From e61097b8881bc7e72a5499816cb1199ea274a3ca Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Thu, 7 Oct 2010 22:54:10 +0200 Subject: Rework template meta-magic - No more implicit dependency on Boost.MPL - Better documentation for template magic - Move input handler policies to handler definitions where they belong - Separate out event descriptions from handlers --- src/gui/frame.cpp | 18 +- src/input/CMakeLists.txt | 5 +- src/input/allowLocalOrPrivileged.cpp | 21 ++ src/input/detail/Makefile.autogen | 8 + src/input/detail/gen/gen_policyChain.cpp | 68 +++++ src/input/detail/gen/gen_typeList.cpp | 115 ++++++++ src/input/detail/policyChain.h | 78 ++++++ src/input/detail/policyChain_autogen.h | 8 + src/input/detail/systemTraits.h | 94 +++++++ src/input/detail/typeList.h | 76 ++++++ src/input/detail/typeList_autogen.h | 60 ++++ src/input/inputEvent.cpp | 32 +++ src/input/inputEvent.h | 49 ++-- src/input/inputEventHandler.cpp | 21 +- src/input/inputEventHandler.h | 407 ++++++++++++++-------------- src/input/inputHandlerChain.h | 49 ---- src/input/inputHandlerChains.h | 25 ++ src/input/killX11Handler.cpp | 2 +- src/input/killX11Handler.h | 14 +- src/input/magicSysRqHandler.cpp | 2 +- src/input/magicSysRqHandler.h | 52 +--- src/input/privilegedHandlerForwarder.cpp | 4 +- src/input/privilegedHandlerForwarder.h | 6 +- src/input/privilegedInputHandlerChain.cpp | 30 ++ src/input/pvsPrivInputHandler.cpp | 3 +- src/input/pvsPrivInputHandler.h | 4 +- src/input/rebootSystemHandler.cpp | 2 +- src/input/rebootSystemHandler.h | 10 +- src/input/sayHelloHandler.cpp | 2 +- src/input/sayHelloHandler.h | 11 +- src/input/unprivilegedInputHandlerChain.cpp | 30 ++ src/input/x11FakeKeyboardHandler.cpp | 4 +- src/input/x11FakeKeyboardHandler.h | 8 +- src/input/x11FakeMouseHandler.cpp | 4 +- src/input/x11FakeMouseHandler.h | 14 +- src/pvs.cpp | 7 +- src/pvs.h | 4 +- 37 files changed, 968 insertions(+), 379 deletions(-) create mode 100644 src/input/allowLocalOrPrivileged.cpp create mode 100644 src/input/detail/Makefile.autogen create mode 100644 src/input/detail/gen/gen_policyChain.cpp create mode 100644 src/input/detail/gen/gen_typeList.cpp create mode 100644 src/input/detail/policyChain.h create mode 100644 src/input/detail/policyChain_autogen.h create mode 100644 src/input/detail/systemTraits.h create mode 100644 src/input/detail/typeList.h create mode 100644 src/input/detail/typeList_autogen.h delete mode 100644 src/input/inputHandlerChain.h create mode 100644 src/input/inputHandlerChains.h create mode 100644 src/input/privilegedInputHandlerChain.cpp create mode 100644 src/input/unprivilegedInputHandlerChain.cpp diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp index 1b80c3d..12ce6b5 100644 --- a/src/gui/frame.cpp +++ b/src/gui/frame.cpp @@ -19,7 +19,6 @@ */ #include -#include #include "frame.h" #include #include @@ -434,19 +433,18 @@ 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())); + ConsoleLog writeLine(QString("sendInputEvent(%1) to one").arg(evt.toString())); PVSConnectionManager::getManager()->getServer()->sendToAll(msg); } else { - ConsoleLog writeLine(QString("sendInputEvent(%1) to all").arg(evtStr.c_str())); + ConsoleLog writeLine(QString("sendInputEvent(%1) to all").arg(evt.toString())); _cFrame->getConnection()->sendMessage(msg); } } @@ -592,14 +590,14 @@ void Frame::showSpecialEventMenu() { qDebug("Trying to show menu..."); QMenu* menu = new QMenu(this); - QList specialEvents = privileged_handler_chain::describe(); - QList::iterator iter; + QList specialEvents = SpecialInputEventDescription::describeSpecialEvents(); + QListIterator iter(specialEvents); int i; - for(i = 0, iter = specialEvents.begin(); - iter != specialEvents.end(); - iter++, i++) + for(i = 0; + iter.hasNext(); + i++) { - QAction* act = menu->addAction((*iter).descriptionString); + QAction* act = menu->addAction(iter.next().description); act->setData(i); } QAction* selected = menu->exec(QCursor::pos()); diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index 20fd531..689fd39 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -2,6 +2,8 @@ include(${QT_USE_FILE}) set(pvsinput_SRCS inputEvent.cpp + unprivilegedInputHandlerChain.cpp + inputEventHandler.cpp ) if(UNIX) @@ -23,7 +25,8 @@ if(UNIX) killX11Handler.cpp magicSysRqHandler.cpp sayHelloHandler.cpp - inputEventHandler.cpp + privilegedInputHandlerChain.cpp + allowLocalOrPrivileged.cpp ) set(pvsprivinputd_MOC_HDRS diff --git a/src/input/allowLocalOrPrivileged.cpp b/src/input/allowLocalOrPrivileged.cpp new file mode 100644 index 0000000..ba456dc --- /dev/null +++ b/src/input/allowLocalOrPrivileged.cpp @@ -0,0 +1,21 @@ +/* + * inputHandlerSecurityPolicies.cpp + * + * Created on: Oct 7, 2010 + * Author: brs + */ + +#include "inputEventHandler.h" +#include "pvsCheckPrivileges.h" + +bool input_policy::AllowLocalOrPrivileged::allow(InputEventContext const* ctx) +{ + if(ctx) + { + if(PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::SESSION_LOCAL, ctx)) + return true; + if(PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::USER_PRIVILEGED, ctx)) + return true; + } + return false; +} diff --git a/src/input/detail/Makefile.autogen b/src/input/detail/Makefile.autogen new file mode 100644 index 0000000..6d0bfb3 --- /dev/null +++ b/src/input/detail/Makefile.autogen @@ -0,0 +1,8 @@ +all : policyChain_autogen.h typeList_autogen.h +.PHONY : all + +policyChain_autogen.h : gen/gen_policyChain + gen/gen_policyChain > policyChain_autogen.h + +typeList_autogen.h : gen/gen_typeList + gen/gen_typeList > typeList_autogen.h diff --git a/src/input/detail/gen/gen_policyChain.cpp b/src/input/detail/gen/gen_policyChain.cpp new file mode 100644 index 0000000..3e375ec --- /dev/null +++ b/src/input/detail/gen/gen_policyChain.cpp @@ -0,0 +1,68 @@ +/* + # 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/ + # -------------------------------------------------------------------------- + # detail/gen/gen_policyChain.cpp: + # - generate the input_policy::detail::PolicyChain class + # -------------------------------------------------------------------------- + */ + +#include + +using namespace std; + +#define NUM_POLICIES 8 + +int main(int, char**) +{ + int i; + + cout << "template\nstruct PolicyChain :\npublic P0::template apply_ >\n"; + cout << "{};\n"; + + // Base case: + cout << "template\n"; + cout << "struct PolicyChain : public BaseCase {};\n"; + + // We need the following in macros: + cout << "#define _autogen_POLICY_TEMPLATE_PARAMS "; + for(i = 0; i < NUM_POLICIES; i++) + { + if(i) + cout << ", "; + cout << "typename P" << i; + } + + cout << "\n#define _autogen_POLICY_TEMPLATE_ARGS "; + for(i = 0; i < NUM_POLICIES; i++) + { + if(i) + cout << ", "; + cout << "P" << i; + } + cout << "\n"; + + return 0; +} diff --git a/src/input/detail/gen/gen_typeList.cpp b/src/input/detail/gen/gen_typeList.cpp new file mode 100644 index 0000000..e092b80 --- /dev/null +++ b/src/input/detail/gen/gen_typeList.cpp @@ -0,0 +1,115 @@ +/* + # 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/ + # -------------------------------------------------------------------------- + # detail/gen/gen_policyChain.cpp: + # - generate the input_policy::detail::TypeList class + # -------------------------------------------------------------------------- + */ + +#include + +using namespace std; + +#define NUM_MAX_ENTRIES 16 + +int main(int, char**) +{ + int i; + + cout << "template<"; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "typename T" << i << " = void"; + } + cout << ">\nstruct TypeList {\n"; + cout << "typedef T0 head;\n"; + cout << "typedef TypeList<"; + for(i = 1; i < NUM_MAX_ENTRIES; i++) + { + if(i > 1) + cout << ", "; + cout << "T" << i; + } + cout << ", void > tail;\n"; + cout << "};\n"; + + // Contains: + cout << "template\n" + "struct Contains { static const int index = -1; static const bool value = false; };\n"; + + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + int j; + + cout << "template\nstruct Contains >\n{ static const int index = " << i << "; static const bool value = true; };\n"; + } + + // Empty List: + cout << "typedef TypeList<"; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "void"; + } + cout << " > EmptyList;\n"; + + // Macros: + cout << "#define IMPLICIT_TYPE_LIST_PARAMS(prefix) "; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "typename prefix##" << i << " = void"; + } + cout << "\n"; + + cout << "#define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) "; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "typename prefix##" << i; + } + cout << "\n"; + + cout << "#define IMPLICIT_TYPE_LIST_ARGS(prefix) "; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "prefix##" << i; + } + cout << "\n"; + + cout << "#define IMPLICIT_TYPE_LIST(prefix) ::input_policy::detail::TypeList\n"; + + return 0; +} diff --git a/src/input/detail/policyChain.h b/src/input/detail/policyChain.h new file mode 100644 index 0000000..ae01ff2 --- /dev/null +++ b/src/input/detail/policyChain.h @@ -0,0 +1,78 @@ +/* + # 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/ + # -------------------------------------------------------------------------- + # detail/policyChain.h: + # - Tie together the different bits of policy information a handler may + # give us + # -------------------------------------------------------------------------- + */ + +#ifndef POLICYCHAIN_H_ +#define POLICYCHAIN_H_ + +#include "typeList.h" + +namespace input_policy +{ +namespace detail +{ + +template +struct PolicyChain : public PolicyList::head::template apply_ > +{ +}; + +template +struct PolicyChain : public BaseCase +{ +private: + struct This_Should_Not_Work; +public: + static const int test_value = sizeof(This_Should_Not_Work); +}; + +} +} + +///////////////////////////////////////////////////////////////////////// +// Macros that enable specification of policies: +// A policy is declared like this: +// template< PARAM1, PARAM2, ... > +// BEGIN_POLICY_CLASS(MyPolicy) { +// static const int field1 = 2; +// ... +// } END_POLICY_CLASS(MyPolicy); +///////////////////////////////////////////////////////////////////////// +#define BEGIN_POLICY_CLASS(policyName) \ + struct policyName { \ + template \ + struct apply_ : public NextPolicy +#define END_POLICY_CLASS \ + ; }; + +///////////////////////////////////////////////////////////////////////// +// A macro that enables us to use a template parameter list +// in a class using a policy, like this: +// +// template +// struct MyPolicyBasedClass +// { +// typedef USE_POLICY(baseCase) policy_type; +// }; +// +// now, the following type is valid: +// MyPolicyBasedClass +///////////////////////////////////////////////////////////////////////// +#define POLICY_PARAMS IMPLICIT_TYPE_LIST_PARAMS(Policy) +#define POLICY_PARAMS_LIST IMPLICIT_TYPE_LIST(Policy) +#define USE_POLICY(baseCase) ::input_policy::detail::PolicyChain + +#endif /* POLICYCHAIN_H_ */ diff --git a/src/input/detail/policyChain_autogen.h b/src/input/detail/policyChain_autogen.h new file mode 100644 index 0000000..d9503b8 --- /dev/null +++ b/src/input/detail/policyChain_autogen.h @@ -0,0 +1,8 @@ +template +struct PolicyChain : +public P0::template apply_ > +{}; +template +struct PolicyChain : public BaseCase {}; +#define _autogen_POLICY_TEMPLATE_PARAMS typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7 +#define _autogen_POLICY_TEMPLATE_ARGS P0, P1, P2, P3, P4, P5, P6, P7 diff --git a/src/input/detail/systemTraits.h b/src/input/detail/systemTraits.h new file mode 100644 index 0000000..7f5582f --- /dev/null +++ b/src/input/detail/systemTraits.h @@ -0,0 +1,94 @@ +/* + # 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/ + # -------------------------------------------------------------------------- + # detail/systemTraits.h: + # - Define system traits and provide a way to match against them + # -------------------------------------------------------------------------- + */ + +#ifndef SYSTEMTRAITS_H_ +#define SYSTEMTRAITS_H_ + +#include "typeList.h" + +#define DEFINE_SYSTEM_TRAIT(name) struct name; +#define BEGIN_SYSTEM_TRAITS typedef TypeList< +#define END_SYSTEM_TRAITS > SystemTraits; + +namespace input_policy +{ + +// Trait names are externally visible. +DEFINE_SYSTEM_TRAIT(UnixLike) +DEFINE_SYSTEM_TRAIT(LinuxSystem) +DEFINE_SYSTEM_TRAIT(X11GUI) +DEFINE_SYSTEM_TRAIT(ConsoleKitSupported) + +namespace detail +{ +BEGIN_SYSTEM_TRAITS +#ifdef __linux +UnixLike, +LinuxSystem, +X11GUI, +ConsoleKitSupported +#endif +END_SYSTEM_TRAITS +} + +///////////////////////////////////////////////////////////////////////// +// Boolean logic as applied to system traits +///////////////////////////////////////////////////////////////////////// +template +struct AllOf; + +template +struct AnyOf; + +namespace detail +{ +///////////////////////////////////////////////////////////////////////// +// Does the list of system traits match what we have given? +///////////////////////////////////////////////////////////////////////// +template +struct Matches +{ + // if Needles is neither AnyOf<...> nor AllOf<...> + // then we need to know if the Haystack contains it: + static const bool value = Contains::value; +}; + +template +struct MatchesPredicate +{ + template + struct apply + { + static const bool value = Matches::value; + }; +}; + +template +struct Matches, Haystack> +{ + static const bool value = ForAnyInTypeList, IMPLICIT_TYPE_LIST(T)>::value; +}; + +template +struct Matches, Haystack> +{ + static const bool value = ForAllInTypeList, IMPLICIT_TYPE_LIST(T)>::value; +}; +} + +} + +#endif /* SYSTEMTRAITS_H_ */ diff --git a/src/input/detail/typeList.h b/src/input/detail/typeList.h new file mode 100644 index 0000000..5b915a9 --- /dev/null +++ b/src/input/detail/typeList.h @@ -0,0 +1,76 @@ +/* + # 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/ + # -------------------------------------------------------------------------- + # detail/typeList.h: + # - Compile-time metaprogramming facilities: Type Lists and Member Check + # -------------------------------------------------------------------------- + */ + +#ifndef TYPELIST_H_ +#define TYPELIST_H_ + +namespace input_policy +{ +namespace detail +{ + +///////////////////////////////////////////////////////////////////////// +// TypeList, Contains, EmptyList: +// This class is autogenerated by gen/gen_typeList.cpp +///////////////////////////////////////////////////////////////////////// +#include "typeList_autogen.h" + +///////////////////////////////////////////////////////////////////////// +// Type-level functions that do not need to be autogenerated as they +// do not depend on the maximum number of entries: +// +// ForAnyInTypeList::value == true +// if there is any entry E in List for which +// Predicate::apply::value == true +///////////////////////////////////////////////////////////////////////// +template +struct ForAnyInTypeList +{ + static const bool value = + Predicate::template apply::value || + ForAnyInTypeList::value; +}; + +template +struct ForAnyInTypeList +{ + static const bool value = false; +}; + +///////////////////////////////////////////////////////////////////////// +// ForAllInTypeList::value == true +// if there is not any entry E in List for which +// Predicate::apply::value == false +///////////////////////////////////////////////////////////////////////// +template +struct ForAllInTypeList +{ + static const bool value = + Predicate::template apply::value && + ForAllInTypeList::value; +}; + +template +struct ForAllInTypeList +{ + static const bool value = true; +}; + +} + +} + +#endif /* TYPELIST_H_ */ diff --git a/src/input/detail/typeList_autogen.h b/src/input/detail/typeList_autogen.h new file mode 100644 index 0000000..0f8fdd4 --- /dev/null +++ b/src/input/detail/typeList_autogen.h @@ -0,0 +1,60 @@ +template +struct TypeList { +typedef T0 head; +typedef TypeList tail; +}; +template +struct Contains { static const int index = -1; static const bool value = false; }; +template +struct Contains > +{ static const int index = 0; static const bool value = true; }; +template +struct Contains > +{ static const int index = 1; static const bool value = true; }; +template +struct Contains > +{ static const int index = 2; static const bool value = true; }; +template +struct Contains > +{ static const int index = 3; static const bool value = true; }; +template +struct Contains > +{ static const int index = 4; static const bool value = true; }; +template +struct Contains > +{ static const int index = 5; static const bool value = true; }; +template +struct Contains > +{ static const int index = 6; static const bool value = true; }; +template +struct Contains > +{ static const int index = 7; static const bool value = true; }; +template +struct Contains > +{ static const int index = 8; static const bool value = true; }; +template +struct Contains > +{ static const int index = 9; static const bool value = true; }; +template +struct Contains > +{ static const int index = 10; static const bool value = true; }; +template +struct Contains > +{ static const int index = 11; static const bool value = true; }; +template +struct Contains > +{ static const int index = 12; static const bool value = true; }; +template +struct Contains > +{ static const int index = 13; static const bool value = true; }; +template +struct Contains > +{ static const int index = 14; static const bool value = true; }; +template +struct Contains > +{ static const int index = 15; static const bool value = true; }; +typedef TypeList EmptyList; +#define IMPLICIT_TYPE_LIST_PARAMS(prefix) typename prefix##0 = void, typename prefix##1 = void, typename prefix##2 = void, typename prefix##3 = void, typename prefix##4 = void, typename prefix##5 = void, typename prefix##6 = void, typename prefix##7 = void, typename prefix##8 = void, typename prefix##9 = void, typename prefix##10 = void, typename prefix##11 = void, typename prefix##12 = void, typename prefix##13 = void, typename prefix##14 = void, typename prefix##15 = void +#define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) typename prefix##0, typename prefix##1, typename prefix##2, typename prefix##3, typename prefix##4, typename prefix##5, typename prefix##6, typename prefix##7, typename prefix##8, typename prefix##9, typename prefix##10, typename prefix##11, typename prefix##12, typename prefix##13, typename prefix##14, typename prefix##15 +#define IMPLICIT_TYPE_LIST_ARGS(prefix) prefix##0, prefix##1, prefix##2, prefix##3, prefix##4, prefix##5, prefix##6, prefix##7, prefix##8, prefix##9, prefix##10, prefix##11, prefix##12, prefix##13, prefix##14, prefix##15 +#define IMPLICIT_TYPE_LIST(prefix) ::input_policy::detail::TypeList diff --git a/src/input/inputEvent.cpp b/src/input/inputEvent.cpp index 9b69a3a..f5abf43 100644 --- a/src/input/inputEvent.cpp +++ b/src/input/inputEvent.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -97,3 +98,34 @@ InputEvent InputEvent::keyboardRelease(int key, int mods) return InputEvent(ET_KEY, EC_RELEASE, value); } +#define describe(list, description, type, code, value) \ + list.append(SpecialInputEventDescription(InputEvent::type, InputEvent::code, value, QCoreApplication::translate("InputEvent", description))) + +QList SpecialInputEventDescription::describeSpecialEvents() +{ + QList list; + describe(list, "Say Hello", ET_SPECIAL, EC_SAY_HELLO, 0); + describe(list, "Reboot", ET_SPECIAL, EC_REBOOT, 0); + describe(list, "Kill X Server", ET_SPECIAL, EC_KILL_X, 0); + describe(list, "Reboot immediately", ET_SPECIAL, EC_SYSRQ, 'b'); + describe(list, "Power off immediately", ET_SPECIAL, EC_SYSRQ, 'o'); + describe(list, "Crash System", ET_SPECIAL, EC_SYSRQ, 'c'); + describe(list, "Turn off raw keyboard mode", ET_SPECIAL, EC_SYSRQ, 'r'); + describe(list, "Send SIGTERM to all", ET_SPECIAL, EC_SYSRQ, 'e'); + describe(list, "Send SIGKILL to all", ET_SPECIAL, EC_SYSRQ, 'i'); + describe(list, "Kill all on this terminal", ET_SPECIAL, EC_SYSRQ, 'k'); + describe(list, "Activate OOM killer", ET_SPECIAL, EC_SYSRQ, 'f'); + describe(list, "Make real-time tasks niceable", ET_SPECIAL, EC_SYSRQ, 'n'); + describe(list, "Force-thaw filesystems", ET_SPECIAL, EC_SYSRQ, 'j'); + describe(list, "Sync all mounted filesystems", ET_SPECIAL, EC_SYSRQ, 's'); + describe(list, "Remount all readonly", ET_SPECIAL, EC_SYSRQ, 'u'); + describe(list, "Show all held locks", ET_SPECIAL, EC_SYSRQ, 'd'); + describe(list, "Show stack traces", ET_SPECIAL, EC_SYSRQ, 'l'); + describe(list, "Dump memory info", ET_SPECIAL, EC_SYSRQ, 'm'); + describe(list, "Dump registers and flags", ET_SPECIAL, EC_SYSRQ, 'p'); + describe(list, "Dump timers and clockevents", ET_SPECIAL, EC_SYSRQ, 'q'); + describe(list, "Dump task list", ET_SPECIAL, EC_SYSRQ, 't'); + describe(list, "Dump uninterruptible tasks", ET_SPECIAL, EC_SYSRQ, 'w'); + describe(list, "Dump ftrace buffer", ET_SPECIAL, EC_SYSRQ, 'z'); + return list; +} diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h index 7a64bfc..2f557ce 100644 --- a/src/input/inputEvent.h +++ b/src/input/inputEvent.h @@ -18,9 +18,7 @@ #define INPUTEVENT_H_ #include -#include -#include -#include +#include #ifndef __linux # error "This will only run on a Linux system. Porting is required for other systems." @@ -46,8 +44,13 @@ private: // 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(uint16_t type, uint16_t code, uint32_t value = 0) : type_(type), code_(code), value_(value) + { + } + + InputEvent(InputEvent const& other) : type_(other.type_), code_(other.code_), value_(other.value_) { } @@ -158,7 +161,7 @@ public: return (value_ & 0xffff); } - static std::string typeToString(uint16_t type) + static QString typeToString(uint16_t type) { switch(type) { @@ -171,13 +174,11 @@ public: case ET_SPECIAL: return "SPECIAL"; default: - std::ostringstream s; - s << std::hex << type; - return s.str(); + return QString::number(type, 16); } } - static std::string codeToString(uint16_t code) + static QString codeToString(uint16_t code) { switch(code) { @@ -192,17 +193,13 @@ public: case EC_KILL_X: return "KILL_X"; default: - std::ostringstream s; - s << std::hex << code; - return s.str(); + return QString::number(code, 16); } } - std::string toString() const + QString toString() const { - std::ostringstream s; - s << typeToString(type_) << ':' << codeToString(code_) << ':' << std::hex << value_; - return s.str(); + return QString("%1:%2:%3").arg(typeToString(type_)).arg(codeToString(code_)).arg(value_, 16); } uint32_t qt_keysym() const @@ -216,4 +213,24 @@ public: } }; +struct SpecialInputEventDescription +{ + SpecialInputEventDescription(uint16_t type, uint16_t code, uint32_t value, QString const& description_) + : type(type), code(code), value(value), description(description_) + { + } + + uint16_t type; + uint16_t code; + uint32_t value; + QString description; + + InputEvent toEvent() const + { + return InputEvent(type, code, value); + } + + static QList describeSpecialEvents(); +}; + #endif /* INPUTEVENT_H_ */ diff --git a/src/input/inputEventHandler.cpp b/src/input/inputEventHandler.cpp index c16c358..5298aed 100644 --- a/src/input/inputEventHandler.cpp +++ b/src/input/inputEventHandler.cpp @@ -17,20 +17,17 @@ #include "inputEventHandler.h" #include "pvsCheckPrivileges.h" -bool policy::allowPrivilegedUser(InputEvent const& evt, InputEventContext const* ctx) +InputEventHandlerBase::HandlerStatus InputEventHandlerBase::handle(InputEvent const& evt, InputEventContext const* ctx) { - if(ctx) - return PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::SESSION_UNKNOWN, PVSCheckPrivileges::USER_PRIVILEGED, - ctx); - else - return false; + if(!isApplicable(evt, ctx)) + return HANDLER_NOT_APPLICABLE; + if(!allow(evt, ctx)) + return HANDLER_NOT_ALLOWED; + doHandle(evt, ctx); + return HANDLER_MATCHED; } -bool policy::allowPhysicalSeat(InputEvent const& evt, InputEventContext const* ctx) +bool input_policy::AllowEverybody::allow(InputEventContext const*) { - if(ctx) - return PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::SESSION_LOCAL, PVSCheckPrivileges::USER_UNKNOWN, - ctx); - else - return false; + return true; } diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 52e3338..5b03a90 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -22,274 +22,283 @@ #include #include #include -#include -#include -#include #include +#include "detail/policyChain.h" +#include "detail/systemTraits.h" -#define HANDLER_TYPE_DONT_CARE 0xffff -#define HANDLER_CODE_DONT_CARE 0xffff -#define HANDLER_VALUE_DONT_CARE 0xffffffff - -class InputEventContext -{ -public: - virtual pid_t getSenderPid() const = 0; - virtual uid_t getSenderUid() const = 0; - virtual gid_t getSenderGid() const = 0; -}; - -struct SpecialInputEventDescription +struct InputEventContext { - SpecialInputEventDescription(QString const& d, quint16 t, quint16 c, quint32 v = 0) - : descriptionString(d), evtType(t), evtCode(c), evtValue(v) + InputEventContext() { + hasBeenDenied = false; } - QString descriptionString; - quint16 evtType; - quint16 evtCode; - quint32 evtValue; + virtual pid_t getSenderPid() const = 0; + virtual uid_t getSenderUid() const = 0; + virtual gid_t getSenderGid() const = 0; - InputEvent toEvent() const - { - return InputEvent(evtType, evtCode, evtValue); - } + mutable bool hasBeenDenied; }; -template -class DefaultInputEventHandler { -protected: - static QString tr(char const* string) - { - return QCoreApplication::translate("InputEventHandler", string); - } - -public: - virtual bool matches(InputEvent const& evt, InputEventContext const*) { - if(Type != HANDLER_TYPE_DONT_CARE) { - if(evt.type() != Type) - return false; - } - if(Code != HANDLER_CODE_DONT_CARE) { - if(evt.code() != Code) - return false; - } - if(Value != HANDLER_VALUE_DONT_CARE) { - if(evt.value() != Value) - return false; - } - return true; - } +namespace input_policy +{ - virtual void initialize() +///////////////////////////////////////////////////////////////////////// +// Policy: +// Modifies the behaviour of an input handler class. +// +// There are several kinds of policy: +// - Security Policy (When to allow a certain action) +// - System Requirements (When to enable a certain handler) +// - Applicability (When to consider a certain handler) +// +// Policies are tied together using the detail::PolicyChain class. +///////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////// +// Security Policy: +// At the moment there are two security policies: +// 1. If the user is on a local seat, allow. If the user is privileged, +// allow. Else deny. +// 2. Allow everybody. +// Additional security policies can be added by following the example +// set by AllowLocalOrPrivileged +///////////////////////////////////////////////////////////////////////// +template +BEGIN_POLICY_CLASS(Security) +{ + bool allow(InputEventContext const* context) { + return PolicyImpl::allow(context); } +} +END_POLICY_CLASS - virtual void handle(InputEvent const& evt, InputEventContext const*) = 0; - - static void describeInto(QList& description) - { - } +struct AllowLocalOrPrivileged +{ + static bool allow(InputEventContext const*); }; -namespace policy { - -enum SecurityFlags { - SEC_FREE_FOR_ALL, - SEC_PHYSICAL_OR_PRIVILEGED +struct AllowEverybody +{ + static bool allow(InputEventContext const*); }; -bool allowPhysicalSeat(InputEvent const& evt, InputEventContext const* ctx); -bool allowPrivilegedUser(InputEvent const& evt, InputEventContext const* ctx); +typedef Security Unprivileged; -struct SecurityAllowAny +///////////////////////////////////////////////////////////////////////// +// System Requirements: +// At the moment, this is trivial, as PVS only runs on Linux. But, +// as porting efforts are already underway, we include the necessary +// machinery anyway. +///////////////////////////////////////////////////////////////////////// +template +BEGIN_POLICY_CLASS(Require) { - bool allow(InputEvent const& evt, InputEventContext const* ctx) - { - return true; - } + static const bool areSystemRequirementsFulfilled = + NextPolicy::areSystemRequirementsFulfilled && + detail::Matches::value; +} +END_POLICY_CLASS + +///////////////////////////////////////////////////////////////////////// +// System Requirements: +// At the moment, this is trivial, as PVS only runs on Linux. But, +// as porting efforts are already underway, we include the necessary +// machinery anyway. +///////////////////////////////////////////////////////////////////////// +enum { + HANDLER_CODE_DONT_CARE = 0xffff, + HANDLER_VALUE_DONT_CARE = 0xffffffff }; -struct SecurityAllowPhysicalOrPrivileged +struct T; + +template +BEGIN_POLICY_CLASS(Match) { - bool allow(InputEvent const& evt, InputEventContext const* ctx) + bool isApplicable(InputEvent const& evt) { - if(allowPhysicalSeat(evt, ctx)) - return true; - else if(allowPrivilegedUser(evt, ctx)) - return true; - return false; + if(evt.type() != EventType) + return NextPolicy::isApplicable(evt); + if(EventCode != HANDLER_CODE_DONT_CARE && evt.code() != EventCode) + return NextPolicy::isApplicable(evt); + if(EventValue != HANDLER_VALUE_DONT_CARE && evt.value() != EventValue) + return NextPolicy::isApplicable(evt); + return true; } }; +END_POLICY_CLASS -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 +namespace detail { - typedef boost::mpl::bool_::type enabled_type; - static const bool enabled = enabled_type::value; -}; -} - -template -class HandlerHelper +///////////////////////////////////////////////////////////////////////// +// Base case: If no policies are given: +///////////////////////////////////////////////////////////////////////// +struct InputEventHandlerPolicyBase { -public: - bool handle(InputEvent const& evt, InputEventContext const* context = 0) { - if(!securityPolicy.allow(evt, context)) - { - std::string evtStr = evt.toString(); - qWarning("Input Event %s has been denied by security policy", evtStr.c_str()); - return true; - } - if(delegate.matches(evt, context)) { - delegate.handle(evt, context); - return true; - } else { - return false; - } - } + // The default security policy applies + typedef AllowLocalOrPrivileged DefaultSecurityPolicyImpl; - void initialize() + bool allow(InputEventContext const* context) { - delegate.initialize(); + return DefaultSecurityPolicyImpl::allow(context); } - static void describeInto(QList& list) - { - Delegate::describeInto(list); - } + // A handler that does not specify requirements works + // everywhere + static const bool areSystemRequirementsFulfilled = true; -private: - Delegate delegate; - SecurityPolicy securityPolicy; -}; - -template -class HandlerHelper -{ -public: - bool handle(InputEvent const& evt, InputEventContext const* context = 0) { + // Generate an error when no match policy is given. + bool isApplicable(InputEvent const&) + { return false; } + // If any policy implementation needs an initialization hook: + // Don't forget to call NextPolicy::initialize() in your + // implementation! void initialize() { } - - static void describeInto(QList&) - { - } }; -template -struct Handler : public HandlerHelper -{ -}; +} +} -template -struct ApplyDefaultSecurityPolicy +///////////////////////////////////////////////////////////////////////// +// We want a nice non-generic base so we can make a list of polymorphic +// handlers. +// +// The actual handler class need to provide doHandle and can override +// allow and isApplicable. +///////////////////////////////////////////////////////////////////////// +/* interface */ class InputEventHandlerBase { - typedef HandlerType type; -}; +public: + enum HandlerStatus + { + HANDLER_MATCHED, + HANDLER_NOT_ALLOWED, + HANDLER_NOT_APPLICABLE + }; -template -struct ApplyDefaultSecurityPolicy > -{ - typedef Handler type; + virtual void initialize() = 0; + HandlerStatus handle(InputEvent const& evt, InputEventContext const* context = 0); + +protected: + virtual bool allow(InputEvent const& event, InputEventContext const* context = 0) = 0; + virtual bool isApplicable(InputEvent const& event, InputEventContext const* context = 0) = 0; + virtual void doHandle(InputEvent const& event, InputEventContext const* context = 0) = 0; }; -template -struct InputEventHandlerChainHelper +///////////////////////////////////////////////////////////////////////// +// Now that the machinery is in place, we can finally define what it +// is like to be an input event handler: +///////////////////////////////////////////////////////////////////////// +template +class InputEventHandler : public InputEventHandlerBase { -private: - typedef typename boost::mpl::next::type next_iterator_type; - typedef InputEventHandlerChainHelper next_in_chain; - - typedef typename boost::mpl::deref::type handler_entry_type; - typedef typename ApplyDefaultSecurityPolicy::type handler_type; - - handler_type _handler; - next_in_chain _next; +protected: + typedef USE_POLICY(input_policy::detail::InputEventHandlerPolicyBase) policy_type; + policy_type policy; public: - void handle(InputEvent const& evt, InputEventContext const* context = 0) { - if(!_handler.handle(evt, context)) { - _next.handle(evt, context); - } + void initialize() + { + policy.initialize(); } - void initialize() { - _handler.initialize(); - _next.initialize(); - } + // Export this so the handler chain can decide whether to include this handler + static const bool areSystemRequirementsFulfilled = policy_type::areSystemRequirementsFulfilled; + +protected: + + typedef InputEventHandler super; - static void describeInto(QList& list) + // allow and isApplicable are actually provided by Policy. If the + // handler class wishes to override any of them, the policy implementation + // can be called by means of super. + bool allow(InputEvent const&, InputEventContext const* context = 0) { - handler_type::describeInto(list); - next_in_chain::describeInto(list); + return policy.allow(context); } - static QList describe() + bool isApplicable(InputEvent const& event, InputEventContext const* = 0) { - QList list; - describeInto(list); - return list; + return policy.isApplicable(event); } }; -template -struct InputEventHandlerChainHelper +///////////////////////////////////////////////////////////////////////// +// And we can chain input handlers together: +///////////////////////////////////////////////////////////////////////// +class InputEventHandlerChain { - void handle(InputEvent const&, InputEventContext const* context = 0) { - // do nothing - } +private: + QList handlers; + + ///////////////////////////////////////////////////////////////////////// + // We need to statically dispatch on a static member of HandlerType. + // Unfortunately, we cannot specialize member functions of a template. + // So, we need to make this a class with a static non-template member. + ///////////////////////////////////////////////////////////////////////// + template + struct ConditionallyAppend + { + static void doIt(InputEventHandlerChain* chain) + { + chain->handlers.append(new HandlerType); + } + }; - void initialize() { - // do nothing - } + template + struct ConditionallyAppend + { + static void doIt(InputEventHandlerChain*) + { + } + }; - static void describeInto(QList&) +public: + // Add an event handler to the chain. The argument is only for + // compilers which cannot handle template member functions + // correctly. + template + InputEventHandlerChain& add(HandlerType const* = 0) { - // do nothing + ConditionallyAppend::doIt(this); + return *this; } - static QList describe() + void initialize() { - return QList(); + QListIterator i(handlers); + while(i.hasNext()) + { + i.next()->initialize(); + } } -}; -template -struct InputEventHandlerChain : - public InputEventHandlerChainHelper::type, - typename boost::mpl::end::type> -{ + void handle(InputEvent const& event, InputEventContext const* context = 0) + { + QListIterator i(handlers); + while(i.hasNext()) + { + switch(i.next()->handle(event, context)) + { + case InputEventHandlerBase::HANDLER_MATCHED: + break; + case InputEventHandlerBase::HANDLER_NOT_ALLOWED: + context->hasBeenDenied = true; + case InputEventHandlerBase::HANDLER_NOT_APPLICABLE: + continue; + } + } + } }; #endif /* INPUTEVENTHANDLER_H_ */ diff --git a/src/input/inputHandlerChain.h b/src/input/inputHandlerChain.h deleted file mode 100644 index 3c9446c..0000000 --- a/src/input/inputHandlerChain.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - # 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" -#include "privilegedHandlerForwarder.h" -#include "rebootSystemHandler.h" -#include "sayHelloHandler.h" -#include "killX11Handler.h" -#include "magicSysRqHandler.h" - -typedef boost::mpl::list< - Handler >, - Handler >, - Handler >, - Handler ->::type unprivileged_handler_list; - -typedef InputEventHandlerChain unprivileged_handler_chain; - -typedef boost::mpl::list< - Handler, - Handler >, - Handler >, - Handler > ->::type privileged_handler_list; - -typedef InputEventHandlerChain privileged_handler_chain; - -#endif /* INPUTHANDLERCHAIN_H_ */ diff --git a/src/input/inputHandlerChains.h b/src/input/inputHandlerChains.h new file mode 100644 index 0000000..a91e605 --- /dev/null +++ b/src/input/inputHandlerChains.h @@ -0,0 +1,25 @@ +/* + # 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/ + # -------------------------------------------------------------------------- + # inputHandlerChains.h: + # - Definition of the input handler chains - interface + # -------------------------------------------------------------------------- + */ + +#ifndef INPUTHANDLERCHAIN_H_ +#define INPUTHANDLERCHAIN_H_ + +#include "inputEventHandler.h" + +InputEventHandlerChain makeUnprivilegedInputEventHandlerChain(); +InputEventHandlerChain makePrivilegedInputEventHandlerChain(); + +#endif /* INPUTHANDLERCHAIN_H_ */ diff --git a/src/input/killX11Handler.cpp b/src/input/killX11Handler.cpp index 7ac75a1..572656e 100644 --- a/src/input/killX11Handler.cpp +++ b/src/input/killX11Handler.cpp @@ -25,7 +25,7 @@ using namespace std; -void KillX11Handler::handle(InputEvent const&, InputEventContext const* ctx) +void KillX11Handler::doHandle(InputEvent const&, InputEventContext const* ctx) { // Find out which display device is used: QString displayDevice = PVSCheckPrivileges::instance()->getX11DisplayDevice(ctx); diff --git a/src/input/killX11Handler.h b/src/input/killX11Handler.h index 2f3ef44..8c0d655 100644 --- a/src/input/killX11Handler.h +++ b/src/input/killX11Handler.h @@ -20,15 +20,15 @@ #include #include "inputEventHandler.h" -class KillX11Handler : public DefaultInputEventHandler +class KillX11Handler : public InputEventHandler< + input_policy::Match, + input_policy::Require > > { public: - void handle(InputEvent const&, InputEventContext const*); - - static void describeInto(QList& list) - { - list << SpecialInputEventDescription(tr(QT_TRANSLATE_NOOP("InputEventHandler", "Kill X Server")), InputEvent::ET_SPECIAL, InputEvent::EC_KILL_X); - } + void doHandle(InputEvent const&, InputEventContext const*); }; #endif /* KILLX11HANDLER_H_ */ diff --git a/src/input/magicSysRqHandler.cpp b/src/input/magicSysRqHandler.cpp index 108bfca..7c38216 100644 --- a/src/input/magicSysRqHandler.cpp +++ b/src/input/magicSysRqHandler.cpp @@ -17,7 +17,7 @@ #include #include "magicSysRqHandler.h" -void MagicSysRqHandler::handle(InputEvent const& evt, InputEventContext const*) +void MagicSysRqHandler::doHandle(InputEvent const& evt, InputEventContext const*) { QFile trigger("/proc/sysrq-trigger"); trigger.open(QIODevice::WriteOnly); diff --git a/src/input/magicSysRqHandler.h b/src/input/magicSysRqHandler.h index 563d091..ba02997 100644 --- a/src/input/magicSysRqHandler.h +++ b/src/input/magicSysRqHandler.h @@ -19,54 +19,16 @@ #include "inputEventHandler.h" -class MagicSysRqHandler : public DefaultInputEventHandler +class MagicSysRqHandler : public InputEventHandler< + input_policy::Match, + input_policy::Require > { public: - void handle(InputEvent const& evt, InputEventContext const* ctx); + void doHandle(InputEvent const& evt, InputEventContext const* ctx); - static void describeInto(QList& list) - { - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Reboot immediately"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'b'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Crash system"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'c'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Show all held logs"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'd'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Send SIGTERM to all"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'e'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Activate OOM killer"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'f'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Send SIGKILL to all"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'i'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Force thaw filesystems"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'j'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Kill all on terminal"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'k'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Show stack traces"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'l'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump memory info"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'm'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Make real-time tasks niceable"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'n'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Power off immediately"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'o'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump registers and flags"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'p'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump timers and clockevents"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'q'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Turn off raw keyboard mode"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'r'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Sync all mounted filesystems"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 's'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump task list"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 't'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Remount all read-only"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'u'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump uninterruptible tasks"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'w'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump ftrace buffer"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'z'); - } +// static void describeInto(QList& list) +// { +// } }; #endif /* MAGICSYSRQHANDLER_H_ */ diff --git a/src/input/privilegedHandlerForwarder.cpp b/src/input/privilegedHandlerForwarder.cpp index 3c0b3bd..17c4ab1 100644 --- a/src/input/privilegedHandlerForwarder.cpp +++ b/src/input/privilegedHandlerForwarder.cpp @@ -45,9 +45,9 @@ void PrivilegedHandlerForwarder::initialize() } } -void PrivilegedHandlerForwarder::handle(InputEvent const& evt, InputEventContext const*) +void PrivilegedHandlerForwarder::doHandle(InputEvent const& evt, InputEventContext const*) { - qDebug("Trying to handle %s in PrivilegedHandlerForwarder", evt.toString().c_str()); + qDebug("Trying to handle %s in PrivilegedHandlerForwarder", evt.toString().toLocal8Bit().constData()); if(_socket < 0) { initialize(); diff --git a/src/input/privilegedHandlerForwarder.h b/src/input/privilegedHandlerForwarder.h index 37e8f24..f5a6cc3 100644 --- a/src/input/privilegedHandlerForwarder.h +++ b/src/input/privilegedHandlerForwarder.h @@ -19,10 +19,12 @@ #include "inputEventHandler.h" -class PrivilegedHandlerForwarder : public DefaultInputEventHandler +class PrivilegedHandlerForwarder : public InputEventHandler< + input_policy::Require, + input_policy::Unprivileged> { public: - void handle(InputEvent const& evt, InputEventContext const* = 0); + void doHandle(InputEvent const& evt, InputEventContext const* = 0); void initialize(); private: diff --git a/src/input/privilegedInputHandlerChain.cpp b/src/input/privilegedInputHandlerChain.cpp new file mode 100644 index 0000000..5764728 --- /dev/null +++ b/src/input/privilegedInputHandlerChain.cpp @@ -0,0 +1,30 @@ +/* + # 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/ + # -------------------------------------------------------------------------- + # privilegedInputHandlerChain.cpp + # - Definition of the input handler chains - implementation for privileged + # chain + # -------------------------------------------------------------------------- + */ + +#include "rebootSystemHandler.h" +#include "sayHelloHandler.h" +#include "killX11Handler.h" +#include "magicSysRqHandler.h" +#include "inputHandlerChains.h" + +InputEventHandlerChain makePrivilegedInputEventHandlerChain() +{ + return InputEventHandlerChain().add() + .add() + .add() + .add(); +} diff --git a/src/input/pvsPrivInputHandler.cpp b/src/input/pvsPrivInputHandler.cpp index 70ed1bc..bfa60ce 100644 --- a/src/input/pvsPrivInputHandler.cpp +++ b/src/input/pvsPrivInputHandler.cpp @@ -21,7 +21,7 @@ #include #include #include "inputEvent.h" -#include "inputEventHandler.h" +#include "inputHandlerChains.h" #include "pvsPrivInputSocket.h" #include "pvsPrivInputHandler.h" @@ -63,6 +63,7 @@ PVSPrivInputHandler::PVSPrivInputHandler(int fd, QObject* parent) : _notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); _notifier->setEnabled(true); connect(_notifier, SIGNAL(activated(int)), this, SLOT(canRead())); + _handlerChain = makePrivilegedInputEventHandlerChain(); } PVSPrivInputHandler::~PVSPrivInputHandler() diff --git a/src/input/pvsPrivInputHandler.h b/src/input/pvsPrivInputHandler.h index 9980cdf..e82787b 100644 --- a/src/input/pvsPrivInputHandler.h +++ b/src/input/pvsPrivInputHandler.h @@ -20,7 +20,7 @@ #include #include #include -#include "inputHandlerChain.h" +#include "inputEventHandler.h" class QSocketNotifier; @@ -39,7 +39,7 @@ private: QByteArray _messageAssembly; int _bytes; int _fd; - privileged_handler_chain _handlerChain; + InputEventHandlerChain _handlerChain; }; #endif /* PVSPRIVINPUTHANDLER_H_ */ diff --git a/src/input/rebootSystemHandler.cpp b/src/input/rebootSystemHandler.cpp index b5b8f8a..6c5c63a 100644 --- a/src/input/rebootSystemHandler.cpp +++ b/src/input/rebootSystemHandler.cpp @@ -22,7 +22,7 @@ using namespace std; -void RebootLinuxSystemHandler::handle(InputEvent const& evt, InputEventContext const* ctx) +void RebootLinuxSystemHandler::doHandle(InputEvent const& evt, InputEventContext const* ctx) { // Rebooting a linux system is particulary easy: if(kill(1, SIGINT) < 0) diff --git a/src/input/rebootSystemHandler.h b/src/input/rebootSystemHandler.h index 34fa8ae..4920452 100644 --- a/src/input/rebootSystemHandler.h +++ b/src/input/rebootSystemHandler.h @@ -20,15 +20,11 @@ #include #include "inputEventHandler.h" -class RebootLinuxSystemHandler : public DefaultInputEventHandler +class RebootLinuxSystemHandler : public InputEventHandler< + input_policy::Require > { public: - void handle(InputEvent const&, InputEventContext const*); - - static void describeInto(QList& list) - { - list << SpecialInputEventDescription(tr(QT_TRANSLATE_NOOP("InputEventHandler", "Reboot")), InputEvent::ET_SPECIAL, InputEvent::EC_REBOOT); - } + void doHandle(InputEvent const&, InputEventContext const*); }; #endif /* REBOOTSYSTEMHANDLER_H_ */ diff --git a/src/input/sayHelloHandler.cpp b/src/input/sayHelloHandler.cpp index fc6f668..712963d 100644 --- a/src/input/sayHelloHandler.cpp +++ b/src/input/sayHelloHandler.cpp @@ -19,7 +19,7 @@ using namespace std; -void SayHelloHandler::handle(InputEvent const&, InputEventContext const* ctx) +void SayHelloHandler::doHandle(InputEvent const&, InputEventContext const* ctx) { cerr << "I'm right here! You sent this message from pid " << ctx->getSenderPid() << " as user " << ctx->getSenderUid() << " with gid " << ctx->getSenderGid() << endl; } diff --git a/src/input/sayHelloHandler.h b/src/input/sayHelloHandler.h index b0d4c7e..00463ca 100644 --- a/src/input/sayHelloHandler.h +++ b/src/input/sayHelloHandler.h @@ -20,15 +20,12 @@ #include #include "inputEventHandler.h" -class SayHelloHandler : public DefaultInputEventHandler +class SayHelloHandler : public InputEventHandler< + input_policy::Match, + input_policy::Security > { public: - void handle(InputEvent const&, InputEventContext const*); - - static void describeInto(QList& list) - { - list << SpecialInputEventDescription(tr(QT_TRANSLATE_NOOP("InputEventHandler", "Say Hello")), InputEvent::ET_SPECIAL, InputEvent::EC_SAY_HELLO); - } + void doHandle(InputEvent const&, InputEventContext const*); }; #endif /* SAYHELLOHANDLER_CPP_ */ diff --git a/src/input/unprivilegedInputHandlerChain.cpp b/src/input/unprivilegedInputHandlerChain.cpp new file mode 100644 index 0000000..fbbc770 --- /dev/null +++ b/src/input/unprivilegedInputHandlerChain.cpp @@ -0,0 +1,30 @@ +/* + # 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/ + # -------------------------------------------------------------------------- + # privilegedInputHandlerChain.cpp + # - Definition of the input handler chains - implementation for + # unprivileged chain + # -------------------------------------------------------------------------- + */ + +#include "x11FakeKeyboardHandler.h" +#include "x11FakeMouseHandler.h" +#include "privilegedHandlerForwarder.h" +#include "inputHandlerChains.h" + +InputEventHandlerChain makeUnprivilegedInputEventHandlerChain() +{ + return InputEventHandlerChain().add() + .add() + .add() + .add(); +} + diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index 0c32b66..eab4498 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -807,7 +807,7 @@ void X11FakeKeyboardHandler::initialize() current_modifiers = 0; } -void X11FakeKeyboardHandler::handle(InputEvent const& evt, InputEventContext const*) +void X11FakeKeyboardHandler::doHandle(InputEvent const& evt, InputEventContext const*) { Display* dpy = X11InputUtils::display(); @@ -818,7 +818,7 @@ void X11FakeKeyboardHandler::handle(InputEvent const& evt, InputEventContext con switch(evt.qt_keysym()) { case Qt::Key_Backtab: - handle(InputEvent(evt.type(), evt.code(), evt.qt_modifiers() | Qt::ShiftModifier | Qt::Key_Tab)); + doHandle(InputEvent(evt.type(), evt.code(), evt.qt_modifiers() | Qt::ShiftModifier | Qt::Key_Tab)); break; default: ConsoleLog writeLine(QString("Unknown keysym received: %1").arg(evt.qt_keysym(), 8, 16)); diff --git a/src/input/x11FakeKeyboardHandler.h b/src/input/x11FakeKeyboardHandler.h index 3dde7cc..6c18dce 100644 --- a/src/input/x11FakeKeyboardHandler.h +++ b/src/input/x11FakeKeyboardHandler.h @@ -19,10 +19,14 @@ #include "inputEventHandler.h" -class X11FakeKeyboardHandler : public DefaultInputEventHandler +class X11FakeKeyboardHandler : public InputEventHandler< + input_policy::Match, + input_policy::Match, + input_policy::Require, + input_policy::Unprivileged> { public: - void handle(InputEvent const&, InputEventContext const* = 0); + void doHandle(InputEvent const&, InputEventContext const* = 0); void initialize(); }; diff --git a/src/input/x11FakeMouseHandler.cpp b/src/input/x11FakeMouseHandler.cpp index 58415d5..605fe2c 100644 --- a/src/input/x11FakeMouseHandler.cpp +++ b/src/input/x11FakeMouseHandler.cpp @@ -19,7 +19,7 @@ #include #include "x11InputUtils.h" -void X11FakeMouseButtonHandler::handle(InputEvent const& evt, InputEventContext const*) +void X11FakeMouseButtonHandler::doHandle(InputEvent const& evt, InputEventContext const*) { quint16 pressedButton = evt.pressedButton(); @@ -42,7 +42,7 @@ void X11FakeMouseButtonHandler::handle(InputEvent const& evt, InputEventContext XFlush(dpy); } -void X11FakeMouseMovementHandler::handle(InputEvent const& evt, InputEventContext const*) +void X11FakeMouseMovementHandler::doHandle(InputEvent const& evt, InputEventContext const*) { ConsoleLog writeLine(QString("Received mouse motion event (%1,%2)").arg(evt.xCoord()).arg(evt.yCoord())); Display* dpy = X11InputUtils::display(); diff --git a/src/input/x11FakeMouseHandler.h b/src/input/x11FakeMouseHandler.h index 0e32256..8ff8df4 100644 --- a/src/input/x11FakeMouseHandler.h +++ b/src/input/x11FakeMouseHandler.h @@ -19,16 +19,22 @@ #include "inputEventHandler.h" -class X11FakeMouseButtonHandler : public DefaultInputEventHandler +class X11FakeMouseButtonHandler : public InputEventHandler< + input_policy::Match, + input_policy::Require, + input_policy::Unprivileged> { public: - void handle(InputEvent const&, InputEventContext const* = 0); + void doHandle(InputEvent const&, InputEventContext const* = 0); }; -class X11FakeMouseMovementHandler : public DefaultInputEventHandler +class X11FakeMouseMovementHandler : public InputEventHandler< + input_policy::Match, + input_policy::Require, + input_policy::Unprivileged> { public: - void handle(InputEvent const&, InputEventContext const* = 0); + void doHandle(InputEvent const&, InputEventContext const* = 0); }; #endif /* X11FAKEMOUSEHANDLER_H_ */ diff --git a/src/pvs.cpp b/src/pvs.cpp index eda63f5..96a92ea 100755 --- a/src/pvs.cpp +++ b/src/pvs.cpp @@ -20,7 +20,7 @@ #include "src/net/pvsServiceDiscovery.h" #include "src/net/pvsDiscoveredServer.h" #include "src/input/inputEvent.h" -#include "src/input/inputHandlerChain.h" +#include "src/input/inputHandlerChains.h" #include "src/input/x11InputUtils.h" #include "src/net/mcast/McastConfiguration.h" #include "src/net/pvsOutgoingMulticastTransfer.h" @@ -751,14 +751,15 @@ bool PVS::createMulticastTransfer(QString const& objectPath, quint64& transferID void PVS::handleInputEvent(InputEvent const& evt) { - std::string s = evt.toString(); - ConsoleLog writeLine(QString("Received input event: %1").arg(s.c_str())); + QString s = evt.toString(); + ConsoleLog writeLine(QString("Received input event: %1").arg(s.toLocal8Bit().constData())); _inputEventHandlers.handle(evt); } void PVS::initializeInputEventHandling() { X11InputUtils::setDisplay(X11Info::display()); + _inputEventHandlers = makeUnprivilegedInputEventHandlerChain(); _inputEventHandlers.initialize(); } diff --git a/src/pvs.h b/src/pvs.h index c18e9a3..902fbe7 100755 --- a/src/pvs.h +++ b/src/pvs.h @@ -26,7 +26,7 @@ #include "src/version.h" #include "src/util/consoleLogger.h" #include "src/util/clientGUIUtils.h" -#include "src/input/inputHandlerChain.h" +#include "src/input/inputEventHandler.h" class PVSServiceDiscovery; class PVSDiscoveredServer; @@ -168,7 +168,7 @@ private: int _timerLockDelay; // input event handling: - unprivileged_handler_chain _inputEventHandlers; + InputEventHandlerChain _inputEventHandlers; void handleInputEvent(InputEvent const& evt); void initializeInputEventHandling(); -- cgit v1.2.3-55-g7522 From 66f6a2f189a707e285a1cf24ef57c0587e3ecd51 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 01:44:13 +0200 Subject: It is not necessary to auto-generate policyChain_autogen.h anymore All it did is handled by implicit TypeList parameters. --- src/input/detail/Makefile.autogen | 5 +-- src/input/detail/gen/gen_policyChain.cpp | 68 -------------------------------- src/input/detail/policyChain_autogen.h | 8 ---- 3 files changed, 1 insertion(+), 80 deletions(-) delete mode 100644 src/input/detail/gen/gen_policyChain.cpp delete mode 100644 src/input/detail/policyChain_autogen.h diff --git a/src/input/detail/Makefile.autogen b/src/input/detail/Makefile.autogen index 6d0bfb3..cbd52be 100644 --- a/src/input/detail/Makefile.autogen +++ b/src/input/detail/Makefile.autogen @@ -1,8 +1,5 @@ -all : policyChain_autogen.h typeList_autogen.h +all : typeList_autogen.h .PHONY : all -policyChain_autogen.h : gen/gen_policyChain - gen/gen_policyChain > policyChain_autogen.h - typeList_autogen.h : gen/gen_typeList gen/gen_typeList > typeList_autogen.h diff --git a/src/input/detail/gen/gen_policyChain.cpp b/src/input/detail/gen/gen_policyChain.cpp deleted file mode 100644 index 3e375ec..0000000 --- a/src/input/detail/gen/gen_policyChain.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* - # 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/ - # -------------------------------------------------------------------------- - # detail/gen/gen_policyChain.cpp: - # - generate the input_policy::detail::PolicyChain class - # -------------------------------------------------------------------------- - */ - -#include - -using namespace std; - -#define NUM_POLICIES 8 - -int main(int, char**) -{ - int i; - - cout << "template\nstruct PolicyChain :\npublic P0::template apply_ >\n"; - cout << "{};\n"; - - // Base case: - cout << "template\n"; - cout << "struct PolicyChain : public BaseCase {};\n"; - - // We need the following in macros: - cout << "#define _autogen_POLICY_TEMPLATE_PARAMS "; - for(i = 0; i < NUM_POLICIES; i++) - { - if(i) - cout << ", "; - cout << "typename P" << i; - } - - cout << "\n#define _autogen_POLICY_TEMPLATE_ARGS "; - for(i = 0; i < NUM_POLICIES; i++) - { - if(i) - cout << ", "; - cout << "P" << i; - } - cout << "\n"; - - return 0; -} diff --git a/src/input/detail/policyChain_autogen.h b/src/input/detail/policyChain_autogen.h deleted file mode 100644 index d9503b8..0000000 --- a/src/input/detail/policyChain_autogen.h +++ /dev/null @@ -1,8 +0,0 @@ -template -struct PolicyChain : -public P0::template apply_ > -{}; -template -struct PolicyChain : public BaseCase {}; -#define _autogen_POLICY_TEMPLATE_PARAMS typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7 -#define _autogen_POLICY_TEMPLATE_ARGS P0, P1, P2, P3, P4, P5, P6, P7 -- cgit v1.2.3-55-g7522 From 8ed8f90effab0876a8d8374d787d8c3b6214c531 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Fri, 8 Oct 2010 22:01:39 +0200 Subject: Move the translations for pvsinput into the library where they belong. --- i18n/pvsmgr_ar_JO.ts | 118 ---------------------------- i18n/pvsmgr_de_DE.ts | 118 ---------------------------- i18n/pvsmgr_es_MX.ts | 118 ---------------------------- i18n/pvsmgr_fr_FR.ts | 118 ---------------------------- i18n/pvsmgr_pl_PL.ts | 118 ---------------------------- src/input/CMakeLists.txt | 27 +++++++ src/input/i18n.h | 33 ++++++++ src/input/i18n/pvsinput_ar_JO.ts | 147 ++++++++++++++++++++++++++++++++++ src/input/i18n/pvsinput_de_DE.ts | 165 +++++++++++++++++++++++++++++++++++++++ src/input/i18n/pvsinput_es_MX.ts | 147 ++++++++++++++++++++++++++++++++++ src/input/i18n/pvsinput_fr_FR.ts | 147 ++++++++++++++++++++++++++++++++++ src/input/i18n/pvsinput_pl_PL.ts | 147 ++++++++++++++++++++++++++++++++++ src/input/inputEvent.cpp | 48 ++++++------ src/input/inputEvent.h | 7 ++ src/pvsmgr.cpp | 3 + src/pvsmgrtouch.cpp | 3 + 16 files changed, 850 insertions(+), 614 deletions(-) create mode 100644 src/input/i18n.h create mode 100644 src/input/i18n/pvsinput_ar_JO.ts create mode 100644 src/input/i18n/pvsinput_de_DE.ts create mode 100644 src/input/i18n/pvsinput_es_MX.ts create mode 100644 src/input/i18n/pvsinput_fr_FR.ts create mode 100644 src/input/i18n/pvsinput_pl_PL.ts diff --git a/i18n/pvsmgr_ar_JO.ts b/i18n/pvsmgr_ar_JO.ts index e4ee3cb..d434341 100644 --- a/i18n/pvsmgr_ar_JO.ts +++ b/i18n/pvsmgr_ar_JO.ts @@ -333,124 +333,6 @@ Perform an unprojection or remove remote help to get a target. - - InputEventHandler - - - Kill X Server - - - - - Reboot immediately - - - - - Crash system - - - - - Show all held logs - - - - - Send SIGTERM to all - - - - - Activate OOM killer - - - - - Send SIGKILL to all - - - - - Force thaw filesystems - - - - - Kill all on terminal - - - - - Show stack traces - - - - - Dump memory info - - - - - Make real-time tasks niceable - - - - - Power off immediately - - - - - Dump registers and flags - - - - - Dump timers and clockevents - - - - - Turn off raw keyboard mode - - - - - Sync all mounted filesystems - - - - - Dump task list - - - - - Remount all read-only - - - - - Dump uninterruptible tasks - - - - - Dump ftrace buffer - - - - - Reboot - - - - - Say Hello - - - MainWindow diff --git a/i18n/pvsmgr_de_DE.ts b/i18n/pvsmgr_de_DE.ts index 39e79cd..921b5ba 100644 --- a/i18n/pvsmgr_de_DE.ts +++ b/i18n/pvsmgr_de_DE.ts @@ -333,124 +333,6 @@ Perform an unprojection or remove remote help to get a target. - - InputEventHandler - - - Kill X Server - - - - - Reboot immediately - - - - - Crash system - - - - - Show all held logs - - - - - Send SIGTERM to all - - - - - Activate OOM killer - - - - - Send SIGKILL to all - - - - - Force thaw filesystems - - - - - Kill all on terminal - - - - - Show stack traces - - - - - Dump memory info - - - - - Make real-time tasks niceable - - - - - Power off immediately - - - - - Dump registers and flags - - - - - Dump timers and clockevents - - - - - Turn off raw keyboard mode - - - - - Sync all mounted filesystems - - - - - Dump task list - - - - - Remount all read-only - - - - - Dump uninterruptible tasks - - - - - Dump ftrace buffer - - - - - Reboot - - - - - Say Hello - - - MainWindow diff --git a/i18n/pvsmgr_es_MX.ts b/i18n/pvsmgr_es_MX.ts index 1470448..86a21b8 100644 --- a/i18n/pvsmgr_es_MX.ts +++ b/i18n/pvsmgr_es_MX.ts @@ -333,124 +333,6 @@ Perform an unprojection or remove remote help to get a target. - - InputEventHandler - - - Kill X Server - - - - - Reboot immediately - - - - - Crash system - - - - - Show all held logs - - - - - Send SIGTERM to all - - - - - Activate OOM killer - - - - - Send SIGKILL to all - - - - - Force thaw filesystems - - - - - Kill all on terminal - - - - - Show stack traces - - - - - Dump memory info - - - - - Make real-time tasks niceable - - - - - Power off immediately - - - - - Dump registers and flags - - - - - Dump timers and clockevents - - - - - Turn off raw keyboard mode - - - - - Sync all mounted filesystems - - - - - Dump task list - - - - - Remount all read-only - - - - - Dump uninterruptible tasks - - - - - Dump ftrace buffer - - - - - Reboot - - - - - Say Hello - - - MainWindow diff --git a/i18n/pvsmgr_fr_FR.ts b/i18n/pvsmgr_fr_FR.ts index e4ee3cb..d434341 100644 --- a/i18n/pvsmgr_fr_FR.ts +++ b/i18n/pvsmgr_fr_FR.ts @@ -333,124 +333,6 @@ Perform an unprojection or remove remote help to get a target. - - InputEventHandler - - - Kill X Server - - - - - Reboot immediately - - - - - Crash system - - - - - Show all held logs - - - - - Send SIGTERM to all - - - - - Activate OOM killer - - - - - Send SIGKILL to all - - - - - Force thaw filesystems - - - - - Kill all on terminal - - - - - Show stack traces - - - - - Dump memory info - - - - - Make real-time tasks niceable - - - - - Power off immediately - - - - - Dump registers and flags - - - - - Dump timers and clockevents - - - - - Turn off raw keyboard mode - - - - - Sync all mounted filesystems - - - - - Dump task list - - - - - Remount all read-only - - - - - Dump uninterruptible tasks - - - - - Dump ftrace buffer - - - - - Reboot - - - - - Say Hello - - - MainWindow diff --git a/i18n/pvsmgr_pl_PL.ts b/i18n/pvsmgr_pl_PL.ts index e4ee3cb..d434341 100644 --- a/i18n/pvsmgr_pl_PL.ts +++ b/i18n/pvsmgr_pl_PL.ts @@ -333,124 +333,6 @@ Perform an unprojection or remove remote help to get a target. - - InputEventHandler - - - Kill X Server - - - - - Reboot immediately - - - - - Crash system - - - - - Show all held logs - - - - - Send SIGTERM to all - - - - - Activate OOM killer - - - - - Send SIGKILL to all - - - - - Force thaw filesystems - - - - - Kill all on terminal - - - - - Show stack traces - - - - - Dump memory info - - - - - Make real-time tasks niceable - - - - - Power off immediately - - - - - Dump registers and flags - - - - - Dump timers and clockevents - - - - - Turn off raw keyboard mode - - - - - Sync all mounted filesystems - - - - - Dump task list - - - - - Remount all read-only - - - - - Dump uninterruptible tasks - - - - - Dump ftrace buffer - - - - - Reboot - - - - - Say Hello - - - MainWindow diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index 689fd39..e14cdb4 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -110,8 +110,35 @@ if(UNIX) PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) endif() +set(pvsinput_TSS + i18n/pvsinput_de_DE.ts + i18n/pvsinput_fr_FR.ts + i18n/pvsinput_es_MX.ts + i18n/pvsinput_ar_JO.ts + i18n/pvsinput_pl_PL.ts) + +QT4_CREATE_TRANSLATION(pvsinput_QMS + ${pvsinput_SRCS} + ${pvsprivinputd_SRCS} + ${pvsinput_TSS}) + +# Generate an RCC file for our translations: +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/pvsinput.qrc" + "") +foreach(qm ${pvsinput_QMS}) + file(RELATIVE_PATH qm_rel ${CMAKE_CURRENT_BINARY_DIR} ${qm}) + get_filename_component(qm_basename ${qm} NAME) + file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/pvsinput.qrc" + "${qm_rel}") +endforeach() +file(APPEND "${CMAKE_CURRENT_BINARY_DIR}/pvsinput.qrc" "") + +qt4_add_resources(pvsinput_RCS + "${CMAKE_CURRENT_BINARY_DIR}/pvsinput.qrc") + add_library( pvsinput STATIC ${pvsinput_SRCS} + ${pvsinput_RCS} ) diff --git a/src/input/i18n.h b/src/input/i18n.h new file mode 100644 index 0000000..d64c7cf --- /dev/null +++ b/src/input/i18n.h @@ -0,0 +1,33 @@ +/* + # 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/ + # -------------------------------------------------------------------------- + # i18n.h: + # - For library users: Make sure the translations are linked and registered + # -------------------------------------------------------------------------- + */ + +#ifndef I18N_H_ +#define I18N_H_ + +#include +#include +#include + +#define USE_PVSINPUT_TRANSLATIONS \ + do { \ + Q_INIT_RESOURCE(pvsinput); \ + QTranslator* translator = new QTranslator(QCoreApplication::instance()); \ + translator->load("pvsinput_" + QLocale::system().name(), ":/i18n/pvsinput"); \ + QCoreApplication::instance()->installTranslator(translator); \ + } while(false) + + +#endif /* I18N_H_ */ diff --git a/src/input/i18n/pvsinput_ar_JO.ts b/src/input/i18n/pvsinput_ar_JO.ts new file mode 100644 index 0000000..1040142 --- /dev/null +++ b/src/input/i18n/pvsinput_ar_JO.ts @@ -0,0 +1,147 @@ + + + + + InputEvent + + + Say Hello + + + + + Reboot + + + + + Kill X Server + + + + + Reboot immediately + + + + + Power off immediately + + + + + Crash System + + + + + Turn off raw keyboard mode + + + + + Send SIGTERM to all + + + + + Send SIGKILL to all + + + + + Kill all on this terminal + + + + + Activate OOM killer + + + + + Make real-time tasks niceable + + + + + Force-thaw filesystems + + + + + Sync all mounted filesystems + + + + + Remount all readonly + + + + + Show all held locks + + + + + Show stack traces + + + + + Dump memory info + + + + + Dump registers and flags + + + + + Dump timers and clockevents + + + + + Dump task list + + + + + Dump uninterruptible tasks + + + + + Dump ftrace buffer + + + + + QObject + + + Usage: %1 [--help|-h] [--daemon|-d] [--log=<Logger>|-l<Logger>] + +Options: + --help, -h Show this message + --daemon, -d Run in background + --log=<Logger>, + -l<Logger> Redirect all output to <Logger> + valid values are: + - any file name + - `syslog' to redirect output to the system log + - `null' to discard output (default) + (without quotes) + +Signals: + SIGINT, SIGTERM (or press Ctrl+C when run in foreground) + Quit + SIGHUP Reload configuration and cached user data + + + + + diff --git a/src/input/i18n/pvsinput_de_DE.ts b/src/input/i18n/pvsinput_de_DE.ts new file mode 100644 index 0000000..56ebf26 --- /dev/null +++ b/src/input/i18n/pvsinput_de_DE.ts @@ -0,0 +1,165 @@ + + + + + InputEvent + + + Say Hello + Hallo sagen + + + + Reboot + Neustart + + + + Kill X Server + X-Server töten + + + + Reboot immediately + Sofort neu starten + + + + Power off immediately + Sofort abschalten + + + + Crash System + Systemabsturz + + + + Turn off raw keyboard mode + RAW-Tastatur-Modus abschalten + + + + Send SIGTERM to all + SIGTERM an alle Prozesse senden + + + + Send SIGKILL to all + SIGKILL an alle Prozesse senden + + + + Kill all on this terminal + Alle Prozesse an diesem Terminal töten + + + + Activate OOM killer + OOM-Killer aktivieren + + + + Make real-time tasks niceable + Nice für Echtzeitprozesse ermöglichen + + + + Force-thaw filesystems + + + + + Sync all mounted filesystems + Alle eingebundenen Dateisysteme sync(2)en + + + + Remount all readonly + Alle Dateisysteme nur-lesbar mounten + + + + Show all held locks + Alle gehaltenen Sperren zeigen + + + + Show stack traces + Stacktraces anzigen + + + + Dump memory info + Speicherinfo anzeigen + + + + Dump registers and flags + Register und Flags anzeigen + + + + Dump timers and clockevents + Timer und Clockevents anzeigen + + + + Dump task list + Taskliste anzeigen + + + + Dump uninterruptible tasks + Ununterbrechbare Tasks anzeigen + + + + Dump ftrace buffer + ftrace-Puffer anzeigen + + + + QObject + + + Usage: %1 [--help|-h] [--daemon|-d] [--log=<Logger>|-l<Logger>] + +Options: + --help, -h Show this message + --daemon, -d Run in background + --log=<Logger>, + -l<Logger> Redirect all output to <Logger> + valid values are: + - any file name + - `syslog' to redirect output to the system log + - `null' to discard output (default) + (without quotes) + +Signals: + SIGINT, SIGTERM (or press Ctrl+C when run in foreground) + Quit + SIGHUP Reload configuration and cached user data + + Verwendung: %1 [--help|-h] [--daemon|-d] [--log=<Logger>|-l<Logger>] + +Optionen: + --help, -h Diese Nachricht anzeigen + --daemon, -d Im Hintergrund laufen + --log=<Logger>, + -l<Logger> Alle Ausgaben an <Logger> weiterleiten + Mögliche Werte für <Logger>: + - Ein Dateiname + - `syslog', um Ausgaben an das Systemlog zu leiten + - `null', um Ausgaben zu verwerfen + Standardwert: null + Werte ohne Anführungszeichen eingeben + +Signale: + SIGINT, SIGTERM (oder Strg+C wenn nicht im Hintergrund) + Beenden + SIGHUP Konfiguration und Benutzerdatenbank neu laden + + + + diff --git a/src/input/i18n/pvsinput_es_MX.ts b/src/input/i18n/pvsinput_es_MX.ts new file mode 100644 index 0000000..047c59c --- /dev/null +++ b/src/input/i18n/pvsinput_es_MX.ts @@ -0,0 +1,147 @@ + + + + + InputEvent + + + Say Hello + + + + + Reboot + + + + + Kill X Server + + + + + Reboot immediately + + + + + Power off immediately + + + + + Crash System + + + + + Turn off raw keyboard mode + + + + + Send SIGTERM to all + + + + + Send SIGKILL to all + + + + + Kill all on this terminal + + + + + Activate OOM killer + + + + + Make real-time tasks niceable + + + + + Force-thaw filesystems + + + + + Sync all mounted filesystems + + + + + Remount all readonly + + + + + Show all held locks + + + + + Show stack traces + + + + + Dump memory info + + + + + Dump registers and flags + + + + + Dump timers and clockevents + + + + + Dump task list + + + + + Dump uninterruptible tasks + + + + + Dump ftrace buffer + + + + + QObject + + + Usage: %1 [--help|-h] [--daemon|-d] [--log=<Logger>|-l<Logger>] + +Options: + --help, -h Show this message + --daemon, -d Run in background + --log=<Logger>, + -l<Logger> Redirect all output to <Logger> + valid values are: + - any file name + - `syslog' to redirect output to the system log + - `null' to discard output (default) + (without quotes) + +Signals: + SIGINT, SIGTERM (or press Ctrl+C when run in foreground) + Quit + SIGHUP Reload configuration and cached user data + + + + + diff --git a/src/input/i18n/pvsinput_fr_FR.ts b/src/input/i18n/pvsinput_fr_FR.ts new file mode 100644 index 0000000..8e3e417 --- /dev/null +++ b/src/input/i18n/pvsinput_fr_FR.ts @@ -0,0 +1,147 @@ + + + + + InputEvent + + + Say Hello + + + + + Reboot + + + + + Kill X Server + + + + + Reboot immediately + + + + + Power off immediately + + + + + Crash System + + + + + Turn off raw keyboard mode + + + + + Send SIGTERM to all + + + + + Send SIGKILL to all + + + + + Kill all on this terminal + + + + + Activate OOM killer + + + + + Make real-time tasks niceable + + + + + Force-thaw filesystems + + + + + Sync all mounted filesystems + + + + + Remount all readonly + + + + + Show all held locks + + + + + Show stack traces + + + + + Dump memory info + + + + + Dump registers and flags + + + + + Dump timers and clockevents + + + + + Dump task list + + + + + Dump uninterruptible tasks + + + + + Dump ftrace buffer + + + + + QObject + + + Usage: %1 [--help|-h] [--daemon|-d] [--log=<Logger>|-l<Logger>] + +Options: + --help, -h Show this message + --daemon, -d Run in background + --log=<Logger>, + -l<Logger> Redirect all output to <Logger> + valid values are: + - any file name + - `syslog' to redirect output to the system log + - `null' to discard output (default) + (without quotes) + +Signals: + SIGINT, SIGTERM (or press Ctrl+C when run in foreground) + Quit + SIGHUP Reload configuration and cached user data + + + + + diff --git a/src/input/i18n/pvsinput_pl_PL.ts b/src/input/i18n/pvsinput_pl_PL.ts new file mode 100644 index 0000000..87527d5 --- /dev/null +++ b/src/input/i18n/pvsinput_pl_PL.ts @@ -0,0 +1,147 @@ + + + + + InputEvent + + + Say Hello + + + + + Reboot + + + + + Kill X Server + + + + + Reboot immediately + + + + + Power off immediately + + + + + Crash System + + + + + Turn off raw keyboard mode + + + + + Send SIGTERM to all + + + + + Send SIGKILL to all + + + + + Kill all on this terminal + + + + + Activate OOM killer + + + + + Make real-time tasks niceable + + + + + Force-thaw filesystems + + + + + Sync all mounted filesystems + + + + + Remount all readonly + + + + + Show all held locks + + + + + Show stack traces + + + + + Dump memory info + + + + + Dump registers and flags + + + + + Dump timers and clockevents + + + + + Dump task list + + + + + Dump uninterruptible tasks + + + + + Dump ftrace buffer + + + + + QObject + + + Usage: %1 [--help|-h] [--daemon|-d] [--log=<Logger>|-l<Logger>] + +Options: + --help, -h Show this message + --daemon, -d Run in background + --log=<Logger>, + -l<Logger> Redirect all output to <Logger> + valid values are: + - any file name + - `syslog' to redirect output to the system log + - `null' to discard output (default) + (without quotes) + +Signals: + SIGINT, SIGTERM (or press Ctrl+C when run in foreground) + Quit + SIGHUP Reload configuration and cached user data + + + + + diff --git a/src/input/inputEvent.cpp b/src/input/inputEvent.cpp index f5abf43..fa623e1 100644 --- a/src/input/inputEvent.cpp +++ b/src/input/inputEvent.cpp @@ -99,33 +99,33 @@ InputEvent InputEvent::keyboardRelease(int key, int mods) } #define describe(list, description, type, code, value) \ - list.append(SpecialInputEventDescription(InputEvent::type, InputEvent::code, value, QCoreApplication::translate("InputEvent", description))) + list.append(SpecialInputEventDescription(InputEvent::type, InputEvent::code, value, description)) QList SpecialInputEventDescription::describeSpecialEvents() { QList list; - describe(list, "Say Hello", ET_SPECIAL, EC_SAY_HELLO, 0); - describe(list, "Reboot", ET_SPECIAL, EC_REBOOT, 0); - describe(list, "Kill X Server", ET_SPECIAL, EC_KILL_X, 0); - describe(list, "Reboot immediately", ET_SPECIAL, EC_SYSRQ, 'b'); - describe(list, "Power off immediately", ET_SPECIAL, EC_SYSRQ, 'o'); - describe(list, "Crash System", ET_SPECIAL, EC_SYSRQ, 'c'); - describe(list, "Turn off raw keyboard mode", ET_SPECIAL, EC_SYSRQ, 'r'); - describe(list, "Send SIGTERM to all", ET_SPECIAL, EC_SYSRQ, 'e'); - describe(list, "Send SIGKILL to all", ET_SPECIAL, EC_SYSRQ, 'i'); - describe(list, "Kill all on this terminal", ET_SPECIAL, EC_SYSRQ, 'k'); - describe(list, "Activate OOM killer", ET_SPECIAL, EC_SYSRQ, 'f'); - describe(list, "Make real-time tasks niceable", ET_SPECIAL, EC_SYSRQ, 'n'); - describe(list, "Force-thaw filesystems", ET_SPECIAL, EC_SYSRQ, 'j'); - describe(list, "Sync all mounted filesystems", ET_SPECIAL, EC_SYSRQ, 's'); - describe(list, "Remount all readonly", ET_SPECIAL, EC_SYSRQ, 'u'); - describe(list, "Show all held locks", ET_SPECIAL, EC_SYSRQ, 'd'); - describe(list, "Show stack traces", ET_SPECIAL, EC_SYSRQ, 'l'); - describe(list, "Dump memory info", ET_SPECIAL, EC_SYSRQ, 'm'); - describe(list, "Dump registers and flags", ET_SPECIAL, EC_SYSRQ, 'p'); - describe(list, "Dump timers and clockevents", ET_SPECIAL, EC_SYSRQ, 'q'); - describe(list, "Dump task list", ET_SPECIAL, EC_SYSRQ, 't'); - describe(list, "Dump uninterruptible tasks", ET_SPECIAL, EC_SYSRQ, 'w'); - describe(list, "Dump ftrace buffer", ET_SPECIAL, EC_SYSRQ, 'z'); + describe(list, InputEvent::tr("Say Hello"), ET_SPECIAL, EC_SAY_HELLO, 0); + describe(list, InputEvent::tr("Reboot"), ET_SPECIAL, EC_REBOOT, 0); + describe(list, InputEvent::tr("Kill X Server"), ET_SPECIAL, EC_KILL_X, 0); + describe(list, InputEvent::tr("Reboot immediately"), ET_SPECIAL, EC_SYSRQ, 'b'); + describe(list, InputEvent::tr("Power off immediately"), ET_SPECIAL, EC_SYSRQ, 'o'); + describe(list, InputEvent::tr("Crash System"), ET_SPECIAL, EC_SYSRQ, 'c'); + describe(list, InputEvent::tr("Turn off raw keyboard mode"), ET_SPECIAL, EC_SYSRQ, 'r'); + describe(list, InputEvent::tr("Send SIGTERM to all"), ET_SPECIAL, EC_SYSRQ, 'e'); + describe(list, InputEvent::tr("Send SIGKILL to all"), ET_SPECIAL, EC_SYSRQ, 'i'); + describe(list, InputEvent::tr("Kill all on this terminal"), ET_SPECIAL, EC_SYSRQ, 'k'); + describe(list, InputEvent::tr("Activate OOM killer"), ET_SPECIAL, EC_SYSRQ, 'f'); + describe(list, InputEvent::tr("Make real-time tasks niceable"), ET_SPECIAL, EC_SYSRQ, 'n'); + describe(list, InputEvent::tr("Force-thaw filesystems"), ET_SPECIAL, EC_SYSRQ, 'j'); + describe(list, InputEvent::tr("Sync all mounted filesystems"), ET_SPECIAL, EC_SYSRQ, 's'); + describe(list, InputEvent::tr("Remount all readonly"), ET_SPECIAL, EC_SYSRQ, 'u'); + describe(list, InputEvent::tr("Show all held locks"), ET_SPECIAL, EC_SYSRQ, 'd'); + describe(list, InputEvent::tr("Show stack traces"), ET_SPECIAL, EC_SYSRQ, 'l'); + describe(list, InputEvent::tr("Dump memory info"), ET_SPECIAL, EC_SYSRQ, 'm'); + describe(list, InputEvent::tr("Dump registers and flags"), ET_SPECIAL, EC_SYSRQ, 'p'); + describe(list, InputEvent::tr("Dump timers and clockevents"), ET_SPECIAL, EC_SYSRQ, 'q'); + describe(list, InputEvent::tr("Dump task list"), ET_SPECIAL, EC_SYSRQ, 't'); + describe(list, InputEvent::tr("Dump uninterruptible tasks"), ET_SPECIAL, EC_SYSRQ, 'w'); + describe(list, InputEvent::tr("Dump ftrace buffer"), ET_SPECIAL, EC_SYSRQ, 'z'); return list; } diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h index 2f557ce..82b059c 100644 --- a/src/input/inputEvent.h +++ b/src/input/inputEvent.h @@ -18,6 +18,7 @@ #define INPUTEVENT_H_ #include +#include // for translation #include #ifndef __linux @@ -211,6 +212,12 @@ public: { return value_ & MODIFIER_MASK; } + + // We want to enable InputEvent as a translation context, so we fake the tr method: + static QString tr(const char* string) + { + return QCoreApplication::translate("InputEvent", string); + } }; struct SpecialInputEventDescription diff --git a/src/pvsmgr.cpp b/src/pvsmgr.cpp index dd00c0e..f543c6d 100644 --- a/src/pvsmgr.cpp +++ b/src/pvsmgr.cpp @@ -19,6 +19,7 @@ #include "gui/mainWindow.h" #include "util/consoleLogger.h" #include "util/CertManager.h" +#include "src/input/i18n.h" QApplication *qtApp; @@ -35,6 +36,8 @@ int main(int argc, char** argv) translator.load(":pvsmgr"); qtApp->installTranslator(&translator); + USE_PVSINPUT_TRANSLATIONS; + ConsoleLog setLogName(QString("log.server")); ConsoleLog writeLine(QString("PVS-Server started.")); diff --git a/src/pvsmgrtouch.cpp b/src/pvsmgrtouch.cpp index d14ea56..4a1a97d 100644 --- a/src/pvsmgrtouch.cpp +++ b/src/pvsmgrtouch.cpp @@ -18,6 +18,7 @@ #include #include "util/consoleLogger.h" #include "util/CertManager.h" +#include "src/input/i18n.h" QApplication *qtApp; @@ -34,6 +35,8 @@ int main(int argc, char** argv) translator.load(":pvsmgr"); qtApp->installTranslator(&translator);*/ + USE_PVSINPUT_TRANSLATIONS; + ConsoleLog setLogName(QString("log.server")); ConsoleLog writeLine(QString("PVS-Server started.")); -- cgit v1.2.3-55-g7522 From a3885fdab7f8fd91b27237cb882f623dc046cbb9 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Fri, 8 Oct 2010 22:01:51 +0200 Subject: Actually install pvsprivinputd --- src/input/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index e14cdb4..b7a6511 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -108,6 +108,10 @@ if(UNIX) install(FILES pvsprivinputd.conf DESTINATION /etc PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) + + # Install the daemon + install(TARGETS pvsprivinputd + DESTINATION sbin) endif() set(pvsinput_TSS -- cgit v1.2.3-55-g7522 From 1233d9c40fdf20b2c5157eee89d995817b0c1c3b Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 01:33:59 +0200 Subject: Code cleanup for X11FakeKeyboardHandler.cpp - CamelCase names - Add more comments - Remove unused stuff --- src/input/x11FakeKeyboardHandler.cpp | 409 ++++++++++++++++------------------- 1 file changed, 184 insertions(+), 225 deletions(-) diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index eab4498..a136e45 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -9,7 +9,7 @@ # # General information about OpenSLX can be found at http://openslx.org/ # -------------------------------------------------------------------------- - # x11FakeKeyboardHandler.h: + # x11FakeKeyboardHandler.cpp: # - Handle keyboard events on X11 - interface # -------------------------------------------------------------------------- */ @@ -36,10 +36,10 @@ #include #include "x11InputUtils.h" -//////////////////////// INPUT EVENT TRANSLATION ///////////////////////////////// - -typedef unsigned char xmodifier_type; +// X11 supports 8 modifiers, so a bitmask of modifiers fits into a byte: +typedef unsigned char XModifiers; +// For debugging output, these are the names of modifier keys: char modifiernames[][8] = { "SHIFT", "LOCK", @@ -51,7 +51,7 @@ char modifiernames[][8] = { "MOD5" }; -QString modifiers_to_string(xmodifier_type mods) +QString modifiersToString(XModifiers mods) { QString s; for(int i = 0; i < 8; i++) @@ -66,15 +66,22 @@ QString modifiers_to_string(xmodifier_type mods) return s; } +///////////////////////////////////////////////////////////////////////// +// Input event translation code +///////////////////////////////////////////////////////////////////////// + +// We need to translate between Qt's keycodes and X11's keycodes. +// Unfortunately, there does not seem to be a direct correspondence +// between them, so we are stuck with storing a lookup table: +typedef std::map KeycodeLookupTable; +KeycodeLookupTable keysyms; -typedef std::map lookup_table_type; -typedef lookup_table_type::const_iterator lookup_table_const_iterator; -typedef lookup_table_type::iterator lookup_table_iterator; -lookup_table_type keysyms; -void initialize_keysyms() { +// The following code has been partially autogenerated by +// an insane sed(1) script and then hand-edited to make +// the errors go away. +void initializeKeycodeLookupTable() { keysyms[Qt::Key_Escape] = XK_Escape; keysyms[Qt::Key_Tab] = XK_Tab; -// keysyms[Qt::Key_Backtab] = XK_Backtab; keysyms[Qt::Key_Backspace] = XK_BackSpace; keysyms[Qt::Key_Return] = XK_Return; keysyms[Qt::Key_Enter] = XK_KP_Enter; @@ -140,8 +147,6 @@ void initialize_keysyms() { keysyms[Qt::Key_Hyper_L] = XK_Hyper_L; keysyms[Qt::Key_Hyper_R] = XK_Hyper_R; keysyms[Qt::Key_Help] = XK_Help; -// keysyms[Qt::Key_Direction_L] = XK_Direction_L; -// keysyms[Qt::Key_Direction_R] = XK_Direction_R; keysyms[Qt::Key_Space] = XK_space; keysyms[Qt::Key_Exclam] = XK_exclam; keysyms[Qt::Key_QuoteDbl] = XK_quotedbl; @@ -314,10 +319,8 @@ void initialize_keysyms() { keysyms[Qt::Key_MultipleCandidate] = XK_MultipleCandidate; keysyms[Qt::Key_PreviousCandidate] = XK_PreviousCandidate; keysyms[Qt::Key_Mode_switch] = XK_Mode_switch; -// keysyms[Qt::Key_script_switch] = XK_script_switch; keysyms[Qt::Key_Kanji] = XK_Kanji; keysyms[Qt::Key_Muhenkan] = XK_Muhenkan; -// keysyms[Qt::Key_Henkan_Mode] = XK_Henkan_Mode; keysyms[Qt::Key_Henkan] = XK_Henkan; keysyms[Qt::Key_Romaji] = XK_Romaji; keysyms[Qt::Key_Hiragana] = XK_Hiragana; @@ -332,9 +335,6 @@ void initialize_keysyms() { keysyms[Qt::Key_Kana_Shift] = XK_Kana_Shift; keysyms[Qt::Key_Eisu_Shift] = XK_Eisu_Shift; keysyms[Qt::Key_Eisu_toggle] = XK_Eisu_toggle; -// keysyms[Qt::Key_Kanji_Bangou] = XK_Kanji_Bangou; -// keysyms[Qt::Key_Zen_Koho] = XK_Zen_Koho; -// keysyms[Qt::Key_Mae_Koho] = XK_Mae_Koho; keysyms[Qt::Key_Hangul] = XK_Hangul; keysyms[Qt::Key_Hangul_Hanja] = XK_Hangul_Hanja; keysyms[Qt::Key_Hangul] = XK_Hangul; @@ -343,16 +343,11 @@ void initialize_keysyms() { keysyms[Qt::Key_Hangul_Hanja] = XK_Hangul_Hanja; keysyms[Qt::Key_Hangul_Jamo] = XK_Hangul_Jamo; keysyms[Qt::Key_Hangul_Romaja] = XK_Hangul_Romaja; -// keysyms[Qt::Key_Hangul_Codeinput] = XK_Hangul_Codeinput; keysyms[Qt::Key_Hangul_Jeonja] = XK_Hangul_Jeonja; keysyms[Qt::Key_Hangul_Banja] = XK_Hangul_Banja; keysyms[Qt::Key_Hangul_PreHanja] = XK_Hangul_PreHanja; keysyms[Qt::Key_Hangul_PostHanja] = XK_Hangul_PostHanja; -// keysyms[Qt::Key_Hangul_SingleCandidate] = XK_Hangul_SingleCandidate; -// keysyms[Qt::Key_Hangul_MultipleCandidate] = XK_Hangul_MultipleCandidate; -// keysyms[Qt::Key_Hangul_PreviousCandidate] = XK_Hangul_PreviousCandidate; keysyms[Qt::Key_Hangul_Special] = XK_Hangul_Special; -// keysyms[Qt::Key_Hangul_switch] = XK_Hangul_switch; keysyms[Qt::Key_Dead_Grave] = XK_dead_grave; keysyms[Qt::Key_Dead_Acute] = XK_dead_acute; keysyms[Qt::Key_Dead_Circumflex] = XK_dead_circumflex; @@ -372,94 +367,33 @@ void initialize_keysyms() { keysyms[Qt::Key_Dead_Belowdot] = XK_dead_belowdot; keysyms[Qt::Key_Dead_Hook] = XK_dead_hook; keysyms[Qt::Key_Dead_Horn] = XK_dead_horn; -// keysyms[Qt::Key_Back] = XK_Back; -// keysyms[Qt::Key_Forward] = XK_Forward; -// keysyms[Qt::Key_Stop] = XK_Stop; -// keysyms[Qt::Key_Refresh] = XK_Refresh; -// keysyms[Qt::Key_VolumeDown] = XK_VolumeDown; -// keysyms[Qt::Key_VolumeMute] = XK_VolumeMute; -// keysyms[Qt::Key_VolumeUp] = XK_VolumeUp; -// keysyms[Qt::Key_BassBoost] = XK_BassBoost; -// keysyms[Qt::Key_BassUp] = XK_BassUp; -// keysyms[Qt::Key_BassDown] = XK_BassDown; -// keysyms[Qt::Key_TrebleUp] = XK_TrebleUp; -// keysyms[Qt::Key_TrebleDown] = XK_TrebleDown; -// keysyms[Qt::Key_MediaPlay] = XK_MediaPlay; -// keysyms[Qt::Key_MediaStop] = XK_MediaStop; -// keysyms[Qt::Key_MediaPrevious] = XK_MediaPrevious; -// keysyms[Qt::Key_MediaNext] = XK_MediaNext; -// keysyms[Qt::Key_MediaRecord] = XK_MediaRecord; -// keysyms[Qt::Key_HomePage] = XK_HomePage; -// keysyms[Qt::Key_Favorites] = XK_Favorites; -// keysyms[Qt::Key_Search] = XK_Search; -// keysyms[Qt::Key_Standby] = XK_Standby; -// keysyms[Qt::Key_OpenUrl] = XK_OpenUrl; -// keysyms[Qt::Key_LaunchMail] = XK_LaunchMail; -// keysyms[Qt::Key_LaunchMedia] = XK_LaunchMedia; -// keysyms[Qt::Key_Launch0] = XK_Launch0; -// keysyms[Qt::Key_Launch1] = XK_Launch1; -// keysyms[Qt::Key_Launch2] = XK_Launch2; -// keysyms[Qt::Key_Launch3] = XK_Launch3; -// keysyms[Qt::Key_Launch4] = XK_Launch4; -// keysyms[Qt::Key_Launch5] = XK_Launch5; -// keysyms[Qt::Key_Launch6] = XK_Launch6; -// keysyms[Qt::Key_Launch7] = XK_Launch7; -// keysyms[Qt::Key_Launch8] = XK_Launch8; -// keysyms[Qt::Key_Launch9] = XK_Launch9; -// keysyms[Qt::Key_LaunchA] = XK_LaunchA; -// keysyms[Qt::Key_LaunchB] = XK_LaunchB; -// keysyms[Qt::Key_LaunchC] = XK_LaunchC; -// keysyms[Qt::Key_LaunchD] = XK_LaunchD; -// keysyms[Qt::Key_LaunchE] = XK_LaunchE; -// keysyms[Qt::Key_LaunchF] = XK_LaunchF; -// keysyms[Qt::Key_Display] = XK_Display; -// keysyms[Qt::Key_MediaLast] = XK_MediaLast; keysyms[Qt::Key_Select] = XK_Select; -// keysyms[Qt::Key_Yes] = XK_Yes; -// keysyms[Qt::Key_No] = XK_No; keysyms[Qt::Key_Cancel] = XK_Cancel; -// keysyms[Qt::Key_Printer] = XK_Printer; keysyms[Qt::Key_Execute] = XK_Execute; -// keysyms[Qt::Key_Sleep] = XK_Sleep; -// keysyms[Qt::Key_MediaPlay] = XK_MediaPlay; -// keysyms[Qt::Key_Zoom] = XK_Zoom; -// keysyms[Qt::Key_Jisho] = XK_Jisho; -// keysyms[Qt::Key_Oyayubi_Left] = XK_Oyayubi_Left; -// keysyms[Qt::Key_Oyayubi_Right] = XK_Oyayubi_Right; -// keysyms[Qt::Key_Context1] = XK_Context1; -// keysyms[Qt::Key_Context2] = XK_Context2; -// keysyms[Qt::Key_Context3] = XK_Context3; -// keysyms[Qt::Key_Context4] = XK_Context4; -// keysyms[Qt::Key_Call] = XK_Call; -// keysyms[Qt::Key_Hangup] = XK_Hangup; -// keysyms[Qt::Key_Flip] = XK_Flip; keysyms[Qt::Key_unknown] = XK_VoidSymbol; } -/* Store Keycodes for "normal" Latin1 keys: */ -int basic_keycodes[0x100]; -int basic_modifiers[0x100]; - -int modifier_keycodes[8]; -Qt::KeyboardModifier modifier_meaning[8]; +// every keysym with a value under 256 corresponds +// directly to an ISO-Latin1 Character. We need +// to store how to generate those characters: +int basicKeycodes[0x100]; // What key do we need to press? +int basicModifiers[0x100]; // What modifiers are required? -int xmodifier_from_qtmodifier(Qt::KeyboardModifier m) { - for(int i = 0; i < 8; i++) { - if(m == modifier_meaning[i]) - return i; - } - return -1; -} +// What keys do we need to press to generate the +// modifiers? +int modifierKeycodes[8]; +// How do the X11 modifiers relate to Qt's KeyboardModifiers? +Qt::KeyboardModifier modifierMeaning[8]; -typedef std::map qt_to_xmodifier_type; -typedef std::map x_to_qtmodifier_type; -qt_to_xmodifier_type qt_to_xmodifier; -x_to_qtmodifier_type x_to_qtmodifier; +// How do the X11 modifiers correspond to Qt's KeyboardModifiers? +typedef std::map XToQtModifierMap; +XToQtModifierMap XToQtModifier; -typedef std::multimap modifier_to_keycode_map; -modifier_to_keycode_map modifier_to_keycode; -typedef std::map keycode_to_modifier_map; -keycode_to_modifier_map keycode_to_modifier; +// And how do the modifiers relate to Keycodes? +typedef std::multimap ModifierToKeycodeMap; +ModifierToKeycodeMap ModifierToKeycode; +typedef std::map KeycodeToModifierMap; +KeycodeToModifierMap KeycodeToModifier; // We need to query the input devices, preferrable through XInput2, but // if that is not available we will contend ourselves with XInput1: @@ -491,56 +425,72 @@ keycode_to_modifier_map keycode_to_modifier; } #endif - -void initialize_basic_keycodes() +// Initialize the above data structures: +void initializeBasicKeycodes() { + // Mark everything as unknown initially for(int i = 0; i < 8; i++) { - modifier_keycodes[i] = -1; + modifierKeycodes[i] = -1; } for(int i = 0; i < 0x100; i++) { - basic_keycodes[i] = -1; + basicKeycodes[i] = -1; } Display* dpy = X11InputUtils::display(); - int min_keycode, max_keycode; - XDisplayKeycodes(dpy, &min_keycode, &max_keycode); - - int xkb_opcode, xkb_event, xkb_error, xkb_major, xkb_minor; - bool xkb_present = XkbQueryExtension(dpy, &xkb_opcode, &xkb_event, &xkb_error, &xkb_major, &xkb_minor); - if(!xkb_present) { - int keysyms_per_code; - const int count = max_keycode - min_keycode + 1; - KeySym* mapping = XGetKeyboardMapping(dpy, min_keycode, count, &keysyms_per_code); + + // Find out the valid range of keycodes + int minKeycode, maxKeycode; + XDisplayKeycodes(dpy, &minKeycode, &maxKeycode); + + // Initialize the XKB client-side code, and find out whether + // the XKB extension is present in the server. + int xkbOpcode, xkbEvent, xkbError, xkbMajor, xkbMinor; + bool xkbPresent = XkbQueryExtension(dpy, &xkbOpcode, &xkbEvent, &xkbError, &xkbMajor, &xkbMinor); + + if(!xkbPresent) { + // No XKB. This is probably not a very recent + // system, but we will do the best we can. + // Retrieve the keyboard mapping + int keysymsPerCode; + const int count = maxKeycode - minKeycode + 1; + KeySym* mapping = XGetKeyboardMapping(dpy, minKeycode, count, &keysymsPerCode); + + // and traverse every entry for(int i = 0; i < count; i++) { - for(int j = 0; j < keysyms_per_code; j++) + for(int j = 0; j < keysymsPerCode; j++) { - const int idx = i * keysyms_per_code + j; + const int idx = i * keysymsPerCode + j; const KeySym ks = mapping[idx]; - const int keycode = min_keycode + i; + const int keycode = minKeycode + i; + // to find out if there is a Latin1 character there, if(ks >= ' ' && ks < 0x100) { - if(ks == XK_at) { - ConsoleLog writeLine(QString("Keycode %1 (%2) gives `@' with modifiers `%3', but it is really `%4'").arg(keycode).arg(XKeysymToString(XKeycodeToKeysym(dpy, keycode, 0))).arg(modifiers_to_string(j)).arg(XKeysymToString(XKeycodeToKeysym(dpy, keycode, j)))); - - } - - if(basic_keycodes[ks] != -1) + // that we have not yet found, + if(basicKeycodes[ks] != -1) continue; // already found - basic_keycodes[ks] = keycode; - basic_modifiers[ks] = j; + // and record its keycode and needed modifiers. + basicKeycodes[ks] = keycode; + basicModifiers[ks] = j; } } } + + // We are finished, free the mapping structure. XFree(mapping); } else { - // Try to find out what device XTest will send events on: + // XKB is present. + + // As different input devices can have different keymaps, + // we need to find out what device XTest will send events on: unsigned int xkbDeviceId = XkbUseCoreKbd; Atom xtestDeviceProp = XInternAtom(dpy, "XTEST Device", false); + + // Find the list of input devices: int ndevinfos; XIDeviceInfo* devinfos = XIQueryDevice(dpy, XIAllDevices, &ndevinfos); if(devinfos) @@ -578,6 +528,9 @@ void initialize_basic_keycodes() # undef deviceid #endif } + // at this point, xkbDeviceId contains the identifier + // of the XTEST Device, or xkbUseCoreKbd if none was + // found. // Okay, we know which device to query. Now get its keymap: XkbDescPtr keybDesc = XkbGetKeyboard(dpy, XkbAllComponentsMask, xkbDeviceId); @@ -586,7 +539,9 @@ void initialize_basic_keycodes() qWarning("Unable to retrieve keyboard description for device %d. Falling back to unreliable global mapping", xkbDeviceId); } - for(int i = min_keycode; i <= max_keycode; i++) + // This is basically the same loop as above, it just queries XKB + // instead of the old core Xlib routines. + for(int i = minKeycode; i <= maxKeycode; i++) { for(int j = 0; j <= 0xff; j++) { @@ -605,17 +560,11 @@ void initialize_basic_keycodes() if(ks && (ks < 0x100)) { -// ConsoleLog writeLine(QString("Keycode %1 (%2) seems to give `%3' with modifiers `%4', of which `%5' are unconsumed") -// .arg(i) -// .arg(XKeysymToString(XKeycodeToKeysym(dpy, i, 0))) -// .arg(XKeysymToString(ks)) -// .arg(modifiers_to_string(j)) -// .arg(modifiers_to_string(unconsumed))); - if(basic_keycodes[ks] != -1) + if(basicKeycodes[ks] != -1) continue; - basic_keycodes[ks] = i; - basic_modifiers[ks] = unconsumed & j; + basicKeycodes[ks] = i; + basicModifiers[ks] = unconsumed & j; } } } @@ -631,56 +580,57 @@ void initialize_basic_keycodes() XModifierKeymap* modkm; modkm = XGetModifierMapping(dpy); - const int shift_kc = XKeysymToKeycode(dpy, XK_Shift_L); - const int control_kc = XKeysymToKeycode(dpy, XK_Control_L); - const int alt_kc = XKeysymToKeycode(dpy, XK_Alt_L); - const int meta_kc = XKeysymToKeycode(dpy, XK_Meta_L); - const int switch_kc = XKeysymToKeycode(dpy, XK_Mode_switch); + const int shiftCode = XKeysymToKeycode(dpy, XK_Shift_L); + const int controlCode = XKeysymToKeycode(dpy, XK_Control_L); + const int altCode = XKeysymToKeycode(dpy, XK_Alt_L); + const int metaCode = XKeysymToKeycode(dpy, XK_Meta_L); + const int switchCode = XKeysymToKeycode(dpy, XK_Mode_switch); + // and use this information to find out which + // X11 modifiers correspond to Qt's modifiers: for(int i = 0; i < 8; i++) { for(int j = 0; j < modkm->max_keypermod; j++) { const int idx = i * modkm->max_keypermod + j; const int kc = modkm->modifiermap[idx]; - modifier_to_keycode.insert(std::make_pair((1< int_set_type; -int_set_type pressed_modifier_keys; -xmodifier_type current_modifiers; +// We need to keep track of which modifiers +// are currently active +typedef std::set IntSet; +IntSet pressedModifierKeys; +XModifiers currentModifiers; void trackModifiers(int keycode, bool down) { // is this a modifier key? - const bool is_modifier = keycode_to_modifier.find(keycode) != keycode_to_modifier.end(); + const bool isModifier = KeycodeToModifier.find(keycode) != KeycodeToModifier.end(); - if(!is_modifier) + if(!isModifier) { return; } if(down) { - pressed_modifier_keys.insert(keycode); + pressedModifierKeys.insert(keycode); } else { - pressed_modifier_keys.erase(keycode); + pressedModifierKeys.erase(keycode); } - int_set_type::iterator i, end = pressed_modifier_keys.end(); - xmodifier_type modifs = 0; - for(i = pressed_modifier_keys.begin(); i != end; i++) + IntSet::iterator i, end = pressedModifierKeys.end(); + XModifiers modifs = 0; + for(i = pressedModifierKeys.begin(); i != end; i++) { - keycode_to_modifier_map::iterator found_kc = keycode_to_modifier.find(*i); - if(found_kc != keycode_to_modifier.end()) + KeycodeToModifierMap::iterator foundCode = KeycodeToModifier.find(*i); + if(foundCode != KeycodeToModifier.end()) { - modifs |= (*found_kc).second; + modifs |= (*foundCode).second; } } - current_modifiers = modifs; + currentModifiers = modifs; - ConsoleLog writeLine(QString("[trackModifiers] current modifiers: %1").arg(modifiers_to_string(modifs))); + ConsoleLog writeLine(QString("[trackModifiers] current modifiers: %1").arg(modifiersToString(modifs))); } -typedef std::pair modifier_tweak_type; -typedef std::vector tweak_sequence_type; +// And, if we need to tweak the modifiers to generate +// a particular keysym, we need to keep track of which +// ones we pressed or released. +typedef std::pair ModifierTweak; +typedef std::vector TweakSequence; -void tweakModifiers(Display* dpy, xmodifier_type neededState, xmodifier_type actualState, tweak_sequence_type& tracker) +// Tweak the modifiers to reach the neededState, from actualState +// and record tweaks in the tracker. +void tweakModifiers(Display* dpy, XModifiers neededState, XModifiers actualState, TweakSequence& tracker) { - ConsoleLog writeLine(QString("tweakModifiers: Trying to get to `%1' from `%2'").arg(modifiers_to_string(neededState)).arg(modifiers_to_string(actualState))); + ConsoleLog writeLine(QString("tweakModifiers: Trying to get to `%1' from `%2'").arg(modifiersToString(neededState)).arg(modifiersToString(actualState))); for(int j = 0; j < 8; j++) { - xmodifier_type i = 1<second == i) { + KeycodeToModifierMap::iterator modmapIter = KeycodeToModifier.find(*iter); + if(modmapIter != KeycodeToModifier.end()) { + if(modmapIter->second == i) { kc = *iter; // release this key: @@ -790,29 +746,33 @@ void tweakModifiers(Display* dpy, xmodifier_type neededState, xmodifier_type act } } -void untweakModifiers(Display* dpy, tweak_sequence_type& tracker) +// Undo a recorded sequence of modifier tweaks +void untweakModifiers(Display* dpy, TweakSequence& tracker) { - tweak_sequence_type::iterator i, end = tracker.end(); + TweakSequence::iterator i, end = tracker.end(); for(i = tracker.begin(); i != end; i++) { - modifier_tweak_type& t = *i; + ModifierTweak& t = *i; XTestFakeKeyEvent(dpy, t.first, !t.second, CurrentTime); } } +// initialize the handler void X11FakeKeyboardHandler::initialize() { - initialize_keysyms(); - initialize_basic_keycodes(); - pressed_modifier_keys.clear(); - current_modifiers = 0; + initializeKeycodeLookupTable(); + initializeBasicKeycodes(); + pressedModifierKeys.clear(); + currentModifiers = 0; } +// actually try our best to generate the correct input sequence +// for the event void X11FakeKeyboardHandler::doHandle(InputEvent const& evt, InputEventContext const*) { Display* dpy = X11InputUtils::display(); // find out which keysym caused this event: - lookup_table_const_iterator i = keysyms.find(evt.qt_keysym()); + KeycodeLookupTable::const_iterator i = keysyms.find(evt.qt_keysym()); if(i == keysyms.end()) { // Special cases. We don't know how to directly translate those, so we will try to emulate them. switch(evt.qt_keysym()) @@ -829,44 +789,43 @@ void X11FakeKeyboardHandler::doHandle(InputEvent const& evt, InputEventContext c // is it a "normal" key? if(ks >= ' ' && ks < 0x100) { - if(basic_keycodes[ks] != -1) + if(basicKeycodes[ks] != -1) { if(evt.isPress()) { // Try the simple way first: // Does the keycode with current modifiers yield the requested symbol? - KeySym unmod_ks = XKeycodeToKeysym(dpy, basic_keycodes[ks], current_modifiers); - ConsoleLog writeLine(QString("Pressing the key for %1 would yield %2 right now.").arg(XKeysymToString(ks)).arg(XKeysymToString(unmod_ks))); + KeySym unmodSym = XKeycodeToKeysym(dpy, basicKeycodes[ks], currentModifiers); + ConsoleLog writeLine(QString("Pressing the key for %1 would yield %2 right now.").arg(XKeysymToString(ks)).arg(XKeysymToString(unmodSym))); - if(ks == XKeycodeToKeysym(dpy, basic_keycodes[ks], current_modifiers)) + if(ks == XKeycodeToKeysym(dpy, basicKeycodes[ks], currentModifiers)) { - XTestFakeKeyEvent(dpy, basic_keycodes[ks], 1, CurrentTime); + XTestFakeKeyEvent(dpy, basicKeycodes[ks], 1, CurrentTime); } else { // what modifier keys do we need to press? - xmodifier_type mods = translate_modifiers(evt.qt_modifiers()); + XModifiers mods = translateModifiers(evt.qt_modifiers()); // we may need to press additional modifiers to generate this keysym: if(QChar(ks, 0).isLetter()) { - // but, since we do not differentiate upper and lower case, - // and instead let the sender handle those modifiers, - // we need to AND ShiftModifier and LockModifier out. - mods |= basic_modifiers[ks] & ~(1<>(QDataStream& istrm, InputEvent& evt) { - istrm >> evt.type_ >> evt.code_ >> evt.value_; + istrm >> evt._type >> evt._code >> evt._value; return istrm; } diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h index 82b059c..73b7129 100644 --- a/src/input/inputEvent.h +++ b/src/input/inputEvent.h @@ -39,19 +39,19 @@ private: 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_; + quint16 _type; + quint16 _code; + quint32 _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 = 0) : type_(type), code_(code), value_(value) + InputEvent(quint16 type, quint16 code, quint32 value = 0) : _type(type), _code(code), _value(value) { } - InputEvent(InputEvent const& other) : type_(other.type_), code_(other.code_), value_(other.value_) + InputEvent(InputEvent const& other) : _type(other._type), _code(other._code), _value(other._value) { } @@ -59,110 +59,110 @@ public: { } - static InputEvent mouseMotion(uint16_t x, uint16_t y) + static InputEvent mouseMotion(quint16 x, quint16 y) { - return InputEvent(ET_POINTER, 0, ((uint32_t)x << 16) | y); + return InputEvent(ET_POINTER, 0, ((quint32)x << 16) | y); } - static uint16_t mouseButtonsFromQt(int b); + static quint16 mouseButtonsFromQt(int b); 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; - static const uint16_t ET_POINTER = 2; - static const uint16_t ET_SPECIAL = 3; + static const quint16 ET_KEY = 0; + static const quint16 ET_BUTTON = 1; + static const quint16 ET_POINTER = 2; + static const quint16 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; - static const uint16_t EC_SAY_HELLO = 5; //< for debugging purposes + static const quint16 EC_PRESS = 0; + static const quint16 EC_RELEASE = 1; + static const quint16 EC_REBOOT = 2; + static const quint16 EC_SYSRQ = 3; + static const quint16 EC_KILL_X = 4; + static const quint16 EC_SAY_HELLO = 5; //< for debugging purposes - typedef uint32_t event_key; + typedef quint32 event_key; - typedef uint32_t event_key_modifiers; + typedef quint32 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 quint16 EB_LEFT = 1; + static const quint16 EB_MIDDLE = 2; + static const quint16 EB_RIGHT = 4; - static const uint32_t MODIFIER_MASK = + static const quint32 MODIFIER_MASK = 0x7e000000; - uint16_t type() const + quint16 type() const { - return type_; + return _type; } - uint16_t code() const + quint16 code() const { - return code_; + return _code; } - uint32_t value() const + quint32 value() const { - return value_; + return _value; } bool isKeyboard() const { - return type_ == ET_KEY; + return _type == ET_KEY; } bool isButton() const { - return type_ == ET_BUTTON; + return _type == ET_BUTTON; } bool isPointer() const { - return type_ == ET_POINTER; + return _type == ET_POINTER; } bool isSpecial() const { - return type_ == ET_SPECIAL; + return _type == ET_SPECIAL; } bool isPress() const { - return code_ == EC_PRESS; + return _code == EC_PRESS; } bool isRelease() const { - return code_ == EC_RELEASE; + return _code == EC_RELEASE; } - uint16_t pressedButton() const + quint16 pressedButton() const { - assert(type_ == ET_BUTTON); - return (value_ >> 16); + assert(_type == ET_BUTTON); + return (_value >> 16); } - uint16_t heldButtons() const + quint16 heldButtons() const { - assert(type_ == ET_BUTTON); - return (value_ & 0xffff); + assert(_type == ET_BUTTON); + return (_value & 0xffff); } - uint16_t xCoord() const + quint16 xCoord() const { - assert(type_ == ET_POINTER); - return (value_ >> 16); + assert(_type == ET_POINTER); + return (_value >> 16); } - uint16_t yCoord() const + quint16 yCoord() const { - assert(type_ == ET_POINTER); - return (value_ & 0xffff); + assert(_type == ET_POINTER); + return (_value & 0xffff); } - static QString typeToString(uint16_t type) + static QString typeToString(quint16 type) { switch(type) { @@ -179,7 +179,7 @@ public: } } - static QString codeToString(uint16_t code) + static QString codeToString(quint16 code) { switch(code) { @@ -200,17 +200,17 @@ public: QString toString() const { - return QString("%1:%2:%3").arg(typeToString(type_)).arg(codeToString(code_)).arg(value_, 16); + return QString("%1:%2:%3").arg(typeToString(_type)).arg(codeToString(_code)).arg(_value, 16); } - uint32_t qt_keysym() const + quint32 qtKeysym() const { - return value_ & ~MODIFIER_MASK; + return _value & ~MODIFIER_MASK; } - uint32_t qt_modifiers() const + quint32 qtModifiers() const { - return value_ & MODIFIER_MASK; + return _value & MODIFIER_MASK; } // We want to enable InputEvent as a translation context, so we fake the tr method: @@ -222,14 +222,14 @@ public: struct SpecialInputEventDescription { - SpecialInputEventDescription(uint16_t type, uint16_t code, uint32_t value, QString const& description_) + SpecialInputEventDescription(quint16 type, quint16 code, quint32 value, QString const& description_) : type(type), code(code), value(value), description(description_) { } - uint16_t type; - uint16_t code; - uint32_t value; + quint16 type; + quint16 code; + quint32 value; QString description; InputEvent toEvent() const diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 5b03a90..71a530b 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -176,7 +176,7 @@ struct InputEventHandlerPolicyBase // The actual handler class need to provide doHandle and can override // allow and isApplicable. ///////////////////////////////////////////////////////////////////////// -/* interface */ class InputEventHandlerBase +class InputEventHandlerBase { public: enum HandlerStatus @@ -246,9 +246,15 @@ private: // Unfortunately, we cannot specialize member functions of a template. // So, we need to make this a class with a static non-template member. ///////////////////////////////////////////////////////////////////////// - template + template struct ConditionallyAppend { + ///////////////////////////////////////////////////////////////////////// + // This method will never be instantiated for handlers that are + // not Compatible, thus generating no reference to HandlerType + // and permitting compilation to proceed without + // tedious nested preprocessor conditionals. + ///////////////////////////////////////////////////////////////////////// static void doIt(InputEventHandlerChain* chain) { chain->handlers.append(new HandlerType); diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index a136e45..4e3449a 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -772,16 +772,16 @@ void X11FakeKeyboardHandler::doHandle(InputEvent const& evt, InputEventContext c Display* dpy = X11InputUtils::display(); // find out which keysym caused this event: - KeycodeLookupTable::const_iterator i = keysyms.find(evt.qt_keysym()); + KeycodeLookupTable::const_iterator i = keysyms.find(evt.qtKeysym()); if(i == keysyms.end()) { // Special cases. We don't know how to directly translate those, so we will try to emulate them. - switch(evt.qt_keysym()) + switch(evt.qtKeysym()) { case Qt::Key_Backtab: - doHandle(InputEvent(evt.type(), evt.code(), evt.qt_modifiers() | Qt::ShiftModifier | Qt::Key_Tab)); + doHandle(InputEvent(evt.type(), evt.code(), evt.qtModifiers() | Qt::ShiftModifier | Qt::Key_Tab)); break; default: - ConsoleLog writeLine(QString("Unknown keysym received: %1").arg(evt.qt_keysym(), 8, 16)); + ConsoleLog writeLine(QString("Unknown keysym received: %1").arg(evt.qtKeysym(), 8, 16)); } } else { KeySym ks = (*i).second; @@ -805,7 +805,7 @@ void X11FakeKeyboardHandler::doHandle(InputEvent const& evt, InputEventContext c else { // what modifier keys do we need to press? - XModifiers mods = translateModifiers(evt.qt_modifiers()); + XModifiers mods = translateModifiers(evt.qtModifiers()); // we may need to press additional modifiers to generate this keysym: if(QChar(ks, 0).isLetter()) -- cgit v1.2.3-55-g7522 From 18f16ac568d0c699fe24271c5b77f573b749092e Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 01:40:33 +0200 Subject: Lose the `get' method prefix on InputEventContext since it does not fit in --- src/input/inputEventHandler.h | 6 +++--- src/input/killX11Handler.cpp | 2 +- src/input/pvsCheckPrivileges.h | 6 +++--- src/input/pvsPrivInputHandler.cpp | 6 +++--- src/input/sayHelloHandler.cpp | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 71a530b..735b75c 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -33,9 +33,9 @@ struct InputEventContext hasBeenDenied = false; } - virtual pid_t getSenderPid() const = 0; - virtual uid_t getSenderUid() const = 0; - virtual gid_t getSenderGid() const = 0; + virtual pid_t senderPid() const = 0; + virtual uid_t senderUid() const = 0; + virtual gid_t senderGid() const = 0; mutable bool hasBeenDenied; }; diff --git a/src/input/killX11Handler.cpp b/src/input/killX11Handler.cpp index 572656e..32e5873 100644 --- a/src/input/killX11Handler.cpp +++ b/src/input/killX11Handler.cpp @@ -33,7 +33,7 @@ void KillX11Handler::doHandle(InputEvent const&, InputEventContext const* ctx) if(displayDevice.isNull()) { - qWarning("Can not kill X server for %d,%d,%d: No Display Device", ctx->getSenderPid(), ctx->getSenderUid(), ctx->getSenderGid()); + qWarning("Can not kill X server for %d,%d,%d: No Display Device", ctx->senderPid(), ctx->senderUid(), ctx->senderGid()); return; } diff --git a/src/input/pvsCheckPrivileges.h b/src/input/pvsCheckPrivileges.h index 62b463c..92c68fe 100644 --- a/src/input/pvsCheckPrivileges.h +++ b/src/input/pvsCheckPrivileges.h @@ -32,9 +32,9 @@ struct CachedInputContext { if(source) { - pid = source->getSenderPid(); - uid = source->getSenderUid(); - gid = source->getSenderGid(); + pid = source->senderPid(); + uid = source->senderUid(); + gid = source->senderGid(); } else { diff --git a/src/input/pvsPrivInputHandler.cpp b/src/input/pvsPrivInputHandler.cpp index bfa60ce..84ccbae 100644 --- a/src/input/pvsPrivInputHandler.cpp +++ b/src/input/pvsPrivInputHandler.cpp @@ -35,17 +35,17 @@ public: { } - pid_t getSenderPid() const + pid_t senderPid() const { return _pid; } - uid_t getSenderUid() const + uid_t senderUid() const { return _uid; } - gid_t getSenderGid() const + gid_t senderGid() const { return _gid; } diff --git a/src/input/sayHelloHandler.cpp b/src/input/sayHelloHandler.cpp index 712963d..301709f 100644 --- a/src/input/sayHelloHandler.cpp +++ b/src/input/sayHelloHandler.cpp @@ -21,5 +21,5 @@ using namespace std; void SayHelloHandler::doHandle(InputEvent const&, InputEventContext const* ctx) { - cerr << "I'm right here! You sent this message from pid " << ctx->getSenderPid() << " as user " << ctx->getSenderUid() << " with gid " << ctx->getSenderGid() << endl; + cerr << "I'm right here! You sent this message from pid " << ctx->senderPid() << " as user " << ctx->senderUid() << " with gid " << ctx->senderGid() << endl; } -- cgit v1.2.3-55-g7522 From bdec8a3b34650603b111261cfed0364acf6656b7 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 01:41:25 +0200 Subject: Fix wrong policy: KillX11Handler only works on Linux, due to dependency on the /proc file system's layout. --- src/input/killX11Handler.h | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/input/killX11Handler.h b/src/input/killX11Handler.h index 8c0d655..77d9fdb 100644 --- a/src/input/killX11Handler.h +++ b/src/input/killX11Handler.h @@ -22,10 +22,7 @@ class KillX11Handler : public InputEventHandler< input_policy::Match, - input_policy::Require > > + input_policy::Require > { public: void doHandle(InputEvent const&, InputEventContext const*); -- cgit v1.2.3-55-g7522 From 2d31480bf052e3176edfbdc914ff5a29d54dc46c Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 01:41:48 +0200 Subject: Introduce an implicit logical AND into Require policy --- src/input/inputEventHandler.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 735b75c..46e688c 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -92,12 +92,12 @@ typedef Security Unprivileged; // as porting efforts are already underway, we include the necessary // machinery anyway. ///////////////////////////////////////////////////////////////////////// -template +template BEGIN_POLICY_CLASS(Require) { static const bool areSystemRequirementsFulfilled = - NextPolicy::areSystemRequirementsFulfilled && - detail::Matches::value; + NextPolicy::areSystemRequirementsFulfilled || + detail::Matches, detail::SystemTraits>::value; } END_POLICY_CLASS -- cgit v1.2.3-55-g7522 From e659552d9b4c3889522d018e76c00adbe507d045 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 01:42:18 +0200 Subject: Add some comments to inputEventHandler.h --- src/input/inputEventHandler.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 46e688c..3879b80 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -26,6 +26,11 @@ #include "detail/policyChain.h" #include "detail/systemTraits.h" +///////////////////////////////////////////////////////////////////////// +// InputEventContext: +// For handling access control, this specifies who sent the input event. +// This only makes sense in the privileged input handler chain. +///////////////////////////////////////////////////////////////////////// struct InputEventContext { InputEventContext() @@ -37,6 +42,7 @@ struct InputEventContext virtual uid_t senderUid() const = 0; virtual gid_t senderGid() const = 0; + // Support the generation of meaningful log messages: mutable bool hasBeenDenied; }; @@ -203,6 +209,7 @@ template class InputEventHandler : public InputEventHandlerBase { protected: + // instantiate our policy: typedef USE_POLICY(input_policy::detail::InputEventHandlerPolicyBase) policy_type; policy_type policy; -- cgit v1.2.3-55-g7522 From b4a5c00cd583458a83577e3f0148d33ccaae2794 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 01:42:51 +0200 Subject: Remove input headers from PVSMGR_SRCS in CMakeLists.txt as they do not contribute translatable strings anymore --- CMakeLists.txt | 7 ------- 1 file changed, 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc695ce..4214fd3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,13 +103,6 @@ SET( PVSMGR_SRCS src/util/serviceDiscoveryUtil.cpp src/gui/aboutDialog.cpp src/gui/multicastConfigDialog.cpp - - # We need the following headers for translations. - # They will not be compiled. - src/input/killX11Handler.h - src/input/rebootSystemHandler.h - src/input/sayHelloHandler.h - src/input/magicSysRqHandler.h ) # pvs -- cgit v1.2.3-55-g7522 From f6d1c5346fc3b950fe31f7f6f920699e9835cb62 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 14:31:25 +0200 Subject: Fix bug in logical OR when chaining Require<...> Policy. --- src/input/inputEventHandler.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 3879b80..11e2f4e 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -102,8 +102,10 @@ template BEGIN_POLICY_CLASS(Require) { static const bool areSystemRequirementsFulfilled = - NextPolicy::areSystemRequirementsFulfilled || - detail::Matches, detail::SystemTraits>::value; + (NextPolicy::areSystemRequirementsFulfilled + && !NextPolicy::areSystemRequirementsVacuouslyFulfilled) + || detail::Matches, detail::SystemTraits>::value; + static const bool areSystemRequirementsVacuouslyFulfilled = false; } END_POLICY_CLASS @@ -158,6 +160,9 @@ struct InputEventHandlerPolicyBase // everywhere static const bool areSystemRequirementsFulfilled = true; + // We need this to implement proper logical OR + static const bool areSystemRequirementsVacuouslyFulfilled = true; + // Generate an error when no match policy is given. bool isApplicable(InputEvent const&) { -- cgit v1.2.3-55-g7522 From c8978b46070959273d8ee8d760b2594c18a237a9 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 14:31:49 +0200 Subject: Add an InputEventHandler that is not compatible anywhere. --- src/input/incompatibleHandler.h | 37 +++++++++++++++++++++++++++++ src/input/unprivilegedInputHandlerChain.cpp | 4 +++- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/input/incompatibleHandler.h diff --git a/src/input/incompatibleHandler.h b/src/input/incompatibleHandler.h new file mode 100644 index 0000000..5a92806 --- /dev/null +++ b/src/input/incompatibleHandler.h @@ -0,0 +1,37 @@ +/* + # 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/ + # -------------------------------------------------------------------------- + # incompatibleHandler.h: + # - A handler that is not compatible with any system. + # The presence of this file does no harm whatsoever, + # since there will never be any references generated to the class + # it defines, and allows us to test the claim that + # the Require<...> policy does a better job than the preprocessor. + # -------------------------------------------------------------------------- + */ + +#ifndef INCOMPATIBLEHANDLERTYPE_H_ +#define INCOMPATIBLEHANDLERTYPE_H_ + +#include "inputEventHandler.h" + +namespace incompatible { + struct Incompatible; +} + +class IncompatibleHandler : public InputEventHandler< + input_policy::Require > +{ + void doHandle(InputEvent const&, InputEventContext const*); +}; + + +#endif /* INCOMPATIBLEHANDLERTYPE_H_ */ diff --git a/src/input/unprivilegedInputHandlerChain.cpp b/src/input/unprivilegedInputHandlerChain.cpp index fbbc770..9353321 100644 --- a/src/input/unprivilegedInputHandlerChain.cpp +++ b/src/input/unprivilegedInputHandlerChain.cpp @@ -18,6 +18,7 @@ #include "x11FakeKeyboardHandler.h" #include "x11FakeMouseHandler.h" #include "privilegedHandlerForwarder.h" +#include "incompatibleHandler.h" #include "inputHandlerChains.h" InputEventHandlerChain makeUnprivilegedInputEventHandlerChain() @@ -25,6 +26,7 @@ InputEventHandlerChain makeUnprivilegedInputEventHandlerChain() return InputEventHandlerChain().add() .add() .add() - .add(); + .add() + .add(); // See comments in incompatibleHandler.h } -- cgit v1.2.3-55-g7522 From d76a4ddc26ab17277ae4b5018dfc2aa05b623c73 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 14:32:46 +0200 Subject: Remove leftover code that serves no purpose --- src/input/detail/policyChain.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/input/detail/policyChain.h b/src/input/detail/policyChain.h index ae01ff2..efaf371 100644 --- a/src/input/detail/policyChain.h +++ b/src/input/detail/policyChain.h @@ -33,10 +33,6 @@ struct PolicyChain : public PolicyList::head::template apply_ struct PolicyChain : public BaseCase { -private: - struct This_Should_Not_Work; -public: - static const int test_value = sizeof(This_Should_Not_Work); }; } -- cgit v1.2.3-55-g7522 From 2e072d898609ef8dfb5270a07e3212498648d048 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 17:08:49 +0200 Subject: Code cleanup and simplification for X11FakeKeyboardHandler --- src/input/CMakeLists.txt | 32 +- src/input/x11FakeKeyboardHandler.cpp | 655 ++++++++++++++++++----------------- 2 files changed, 358 insertions(+), 329 deletions(-) diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index b7a6511..d950c67 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -5,16 +5,28 @@ set(pvsinput_SRCS unprivilegedInputHandlerChain.cpp inputEventHandler.cpp ) + +set(feature_DEFS) if(UNIX) find_file(XINPUT2_HDR X11/extensions/XInput2.h) if(XINPUT2_HDR) - set_property(SOURCE x11FakeKeyboardHandler.cpp - APPEND - PROPERTY COMPILE_DEFINITIONS HAVE_XINPUT2_H - ) + list(APPEND feature_DEFS + HAVE_XINPUT2_H) endif() - + + find_file(XINPUT_HDR X11/extensions/XInput.h) + if(XINPUT_HDR) + list(APPEND feature_DEFS + HAVE_XINPUT_H) + endif() + + find_file(XKBLIB_HDR X11/XKBlib.h) + if(XKBLIB_HDR) + list(APPEND feature_DEFS + HAVE_XKBLIB_H) + endif() + set(pvsprivinputd_SRCS pvsprivinputd.cpp pvsPrivInputHandler.cpp @@ -114,6 +126,11 @@ if(UNIX) DESTINATION sbin) endif() +set_property(SOURCE ${pvsinput_SRCS} ${pvsprivinputd_SRCS} + APPEND + PROPERTY COMPILE_DEFINITIONS ${feature_DEFS} +) + set(pvsinput_TSS i18n/pvsinput_de_DE.ts i18n/pvsinput_fr_FR.ts @@ -146,3 +163,8 @@ add_library( ${pvsinput_SRCS} ${pvsinput_RCS} ) + +add_library( + pvsinputtests + STATIC + templateMagicTests.cpp) diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index 4e3449a..fed087e 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -51,6 +51,44 @@ char modifiernames[][8] = { "MOD5" }; +// We generally want to find a key sequence with as few modifiers as +// possible. These are all modifier combinations sorted by number of +// bits set: +char modifierpriority[256] = { + 0, 1, 2, 4, 8, 16, 32, 64, 128, + 3, 5, 6, 9, 10, 12, 17, 18, + 20, 24, 33, 34, 36, 40, 48, 65, + 66, 68, 72, 80, 96, 129, 130, 132, + 136, 144, 160, 192, 7, 11, 13, 14, + 19, 21, 22, 25, 26, 28, 35, 37, + 38, 41, 42, 44, 49, 50, 52, 56, + 67, 69, 70, 73, 74, 76, 81, 82, + 84, 88, 97, 98, 100, 104, 112, 131, + 133, 134, 137, 138, 140, 145, 146, 148, + 152, 161, 162, 164, 168, 176, 193, 194, + 196, 200, 208, 224, 15, 23, 27, 29, + 30, 39, 43, 45, 46, 51, 53, 54, + 57, 58, 60, 71, 75, 77, 78, 83, + 85, 86, 89, 90, 92, 99, 101, 102, + 105, 106, 108, 113, 114, 116, 120, 135, + 139, 141, 142, 147, 149, 150, 153, 154, + 156, 163, 165, 166, 169, 170, 172, 177, + 178, 180, 184, 195, 197, 198, 201, 202, + 204, 209, 210, 212, 216, 225, 226, 228, + 232, 240, 31, 47, 55, 59, 61, 62, + 79, 87, 91, 93, 94, 103, 107, 109, + 110, 115, 117, 118, 121, 122, 124, 143, + 151, 155, 157, 158, 167, 171, 173, 174, + 179, 181, 182, 185, 186, 188, 199, 203, + 205, 206, 211, 213, 214, 217, 218, 220, + 227, 229, 230, 233, 234, 236, 241, 242, + 244, 248, 63, 95, 111, 119, 123, 125, + 126, 159, 175, 183, 187, 189, 190, 207, + 215, 219, 221, 222, 231, 235, 237, 238, + 243, 245, 246, 249, 250, 252, 127, 191, + 223, 239, 247, 251, 253, 254, 255 +}; + QString modifiersToString(XModifiers mods) { QString s; @@ -82,6 +120,7 @@ KeycodeLookupTable keysyms; void initializeKeycodeLookupTable() { keysyms[Qt::Key_Escape] = XK_Escape; keysyms[Qt::Key_Tab] = XK_Tab; + keysyms[Qt::Key_Backtab] = XK_ISO_Left_Tab; keysyms[Qt::Key_Backspace] = XK_BackSpace; keysyms[Qt::Key_Return] = XK_Return; keysyms[Qt::Key_Enter] = XK_KP_Enter; @@ -147,171 +186,13 @@ void initializeKeycodeLookupTable() { keysyms[Qt::Key_Hyper_L] = XK_Hyper_L; keysyms[Qt::Key_Hyper_R] = XK_Hyper_R; keysyms[Qt::Key_Help] = XK_Help; - keysyms[Qt::Key_Space] = XK_space; - keysyms[Qt::Key_Exclam] = XK_exclam; - keysyms[Qt::Key_QuoteDbl] = XK_quotedbl; - keysyms[Qt::Key_NumberSign] = XK_numbersign; - keysyms[Qt::Key_Dollar] = XK_dollar; - keysyms[Qt::Key_Percent] = XK_percent; - keysyms[Qt::Key_Ampersand] = XK_ampersand; - keysyms[Qt::Key_Apostrophe] = XK_apostrophe; - keysyms[Qt::Key_ParenLeft] = XK_parenleft; - keysyms[Qt::Key_ParenRight] = XK_parenright; - keysyms[Qt::Key_Asterisk] = XK_asterisk; - keysyms[Qt::Key_Plus] = XK_plus; - keysyms[Qt::Key_Comma] = XK_comma; - keysyms[Qt::Key_Minus] = XK_minus; - keysyms[Qt::Key_Period] = XK_period; - keysyms[Qt::Key_Slash] = XK_slash; - keysyms[Qt::Key_0] = XK_0; - keysyms[Qt::Key_1] = XK_1; - keysyms[Qt::Key_2] = XK_2; - keysyms[Qt::Key_3] = XK_3; - keysyms[Qt::Key_4] = XK_4; - keysyms[Qt::Key_5] = XK_5; - keysyms[Qt::Key_6] = XK_6; - keysyms[Qt::Key_7] = XK_7; - keysyms[Qt::Key_8] = XK_8; - keysyms[Qt::Key_9] = XK_9; - keysyms[Qt::Key_Colon] = XK_colon; - keysyms[Qt::Key_Semicolon] = XK_semicolon; - keysyms[Qt::Key_Less] = XK_less; - keysyms[Qt::Key_Equal] = XK_equal; - keysyms[Qt::Key_Greater] = XK_greater; - keysyms[Qt::Key_Question] = XK_question; - keysyms[Qt::Key_At] = XK_at; - keysyms[Qt::Key_A] = XK_A; - keysyms[Qt::Key_B] = XK_B; - keysyms[Qt::Key_C] = XK_C; - keysyms[Qt::Key_D] = XK_D; - keysyms[Qt::Key_E] = XK_E; - keysyms[Qt::Key_F] = XK_F; - keysyms[Qt::Key_G] = XK_G; - keysyms[Qt::Key_H] = XK_H; - keysyms[Qt::Key_I] = XK_I; - keysyms[Qt::Key_J] = XK_J; - keysyms[Qt::Key_K] = XK_K; - keysyms[Qt::Key_L] = XK_L; - keysyms[Qt::Key_M] = XK_M; - keysyms[Qt::Key_N] = XK_N; - keysyms[Qt::Key_O] = XK_O; - keysyms[Qt::Key_P] = XK_P; - keysyms[Qt::Key_Q] = XK_Q; - keysyms[Qt::Key_R] = XK_R; - keysyms[Qt::Key_S] = XK_S; - keysyms[Qt::Key_T] = XK_T; - keysyms[Qt::Key_U] = XK_U; - keysyms[Qt::Key_V] = XK_V; - keysyms[Qt::Key_W] = XK_W; - keysyms[Qt::Key_X] = XK_X; - keysyms[Qt::Key_Y] = XK_Y; - keysyms[Qt::Key_Z] = XK_Z; - keysyms[Qt::Key_BracketLeft] = XK_bracketleft; - keysyms[Qt::Key_Backslash] = XK_backslash; - keysyms[Qt::Key_BracketRight] = XK_bracketright; - keysyms[Qt::Key_AsciiCircum] = XK_asciicircum; - keysyms[Qt::Key_Underscore] = XK_underscore; - keysyms[Qt::Key_QuoteLeft] = XK_quoteleft; - keysyms[Qt::Key_BraceLeft] = XK_braceleft; - keysyms[Qt::Key_Bar] = XK_bar; - keysyms[Qt::Key_BraceRight] = XK_braceright; - keysyms[Qt::Key_AsciiTilde] = XK_asciitilde; - keysyms[Qt::Key_nobreakspace] = XK_nobreakspace; - keysyms[Qt::Key_exclamdown] = XK_exclamdown; - keysyms[Qt::Key_cent] = XK_cent; - keysyms[Qt::Key_sterling] = XK_sterling; - keysyms[Qt::Key_currency] = XK_currency; - keysyms[Qt::Key_yen] = XK_yen; - keysyms[Qt::Key_brokenbar] = XK_brokenbar; - keysyms[Qt::Key_section] = XK_section; - keysyms[Qt::Key_diaeresis] = XK_diaeresis; - keysyms[Qt::Key_copyright] = XK_copyright; - keysyms[Qt::Key_ordfeminine] = XK_ordfeminine; - keysyms[Qt::Key_guillemotleft] = XK_guillemotleft; - keysyms[Qt::Key_notsign] = XK_notsign; - keysyms[Qt::Key_hyphen] = XK_hyphen; - keysyms[Qt::Key_registered] = XK_registered; - keysyms[Qt::Key_macron] = XK_macron; - keysyms[Qt::Key_degree] = XK_degree; - keysyms[Qt::Key_plusminus] = XK_plusminus; - keysyms[Qt::Key_twosuperior] = XK_twosuperior; - keysyms[Qt::Key_threesuperior] = XK_threesuperior; - keysyms[Qt::Key_acute] = XK_acute; - keysyms[Qt::Key_mu] = XK_mu; - keysyms[Qt::Key_paragraph] = XK_paragraph; - keysyms[Qt::Key_periodcentered] = XK_periodcentered; - keysyms[Qt::Key_cedilla] = XK_cedilla; - keysyms[Qt::Key_onesuperior] = XK_onesuperior; - keysyms[Qt::Key_masculine] = XK_masculine; - keysyms[Qt::Key_guillemotright] = XK_guillemotright; - keysyms[Qt::Key_onequarter] = XK_onequarter; - keysyms[Qt::Key_onehalf] = XK_onehalf; - keysyms[Qt::Key_threequarters] = XK_threequarters; - keysyms[Qt::Key_questiondown] = XK_questiondown; - keysyms[Qt::Key_Agrave] = XK_Agrave; - keysyms[Qt::Key_Aacute] = XK_Aacute; - keysyms[Qt::Key_Acircumflex] = XK_Acircumflex; - keysyms[Qt::Key_Atilde] = XK_Atilde; - keysyms[Qt::Key_Adiaeresis] = XK_Adiaeresis; - keysyms[Qt::Key_Aring] = XK_Aring; - keysyms[Qt::Key_AE] = XK_AE; - keysyms[Qt::Key_Ccedilla] = XK_Ccedilla; - keysyms[Qt::Key_Egrave] = XK_Egrave; - keysyms[Qt::Key_Eacute] = XK_Eacute; - keysyms[Qt::Key_Ecircumflex] = XK_Ecircumflex; - keysyms[Qt::Key_Ediaeresis] = XK_Ediaeresis; - keysyms[Qt::Key_Igrave] = XK_Igrave; - keysyms[Qt::Key_Iacute] = XK_Iacute; - keysyms[Qt::Key_Icircumflex] = XK_Icircumflex; - keysyms[Qt::Key_Idiaeresis] = XK_Idiaeresis; - keysyms[Qt::Key_ETH] = XK_ETH; - keysyms[Qt::Key_Ntilde] = XK_Ntilde; - keysyms[Qt::Key_Ograve] = XK_Ograve; - keysyms[Qt::Key_Oacute] = XK_Oacute; - keysyms[Qt::Key_Ocircumflex] = XK_Ocircumflex; - keysyms[Qt::Key_Otilde] = XK_Otilde; - keysyms[Qt::Key_Odiaeresis] = XK_Odiaeresis; - keysyms[Qt::Key_multiply] = XK_multiply; - keysyms[Qt::Key_Ooblique] = XK_Ooblique; - keysyms[Qt::Key_Ugrave] = XK_Ugrave; - keysyms[Qt::Key_Uacute] = XK_Uacute; - keysyms[Qt::Key_Ucircumflex] = XK_Ucircumflex; - keysyms[Qt::Key_Udiaeresis] = XK_Udiaeresis; - keysyms[Qt::Key_Yacute] = XK_Yacute; - keysyms[Qt::Key_THORN] = XK_THORN; - keysyms[Qt::Key_ssharp] = XK_ssharp; - keysyms[Qt::Key_Agrave] = XK_Agrave; - keysyms[Qt::Key_Aacute] = XK_Aacute; - keysyms[Qt::Key_Acircumflex] = XK_Acircumflex; - keysyms[Qt::Key_Atilde] = XK_Atilde; - keysyms[Qt::Key_Adiaeresis] = XK_Adiaeresis; - keysyms[Qt::Key_Aring] = XK_Aring; - keysyms[Qt::Key_AE] = XK_AE; - keysyms[Qt::Key_Ccedilla] = XK_Ccedilla; - keysyms[Qt::Key_Egrave] = XK_Egrave; - keysyms[Qt::Key_Eacute] = XK_Eacute; - keysyms[Qt::Key_Ecircumflex] = XK_Ecircumflex; - keysyms[Qt::Key_Ediaeresis] = XK_Ediaeresis; - keysyms[Qt::Key_Igrave] = XK_Igrave; - keysyms[Qt::Key_Iacute] = XK_Iacute; - keysyms[Qt::Key_Icircumflex] = XK_Icircumflex; - keysyms[Qt::Key_Idiaeresis] = XK_Idiaeresis; - keysyms[Qt::Key_ETH] = XK_ETH; - keysyms[Qt::Key_Ntilde] = XK_Ntilde; - keysyms[Qt::Key_Ograve] = XK_Ograve; - keysyms[Qt::Key_Oacute] = XK_Oacute; - keysyms[Qt::Key_Ocircumflex] = XK_Ocircumflex; - keysyms[Qt::Key_Otilde] = XK_Otilde; - keysyms[Qt::Key_Odiaeresis] = XK_Odiaeresis; - keysyms[Qt::Key_division] = XK_division; - keysyms[Qt::Key_Ooblique] = XK_Ooblique; - keysyms[Qt::Key_Ugrave] = XK_Ugrave; - keysyms[Qt::Key_Uacute] = XK_Uacute; - keysyms[Qt::Key_Ucircumflex] = XK_Ucircumflex; - keysyms[Qt::Key_Udiaeresis] = XK_Udiaeresis; - keysyms[Qt::Key_Yacute] = XK_Yacute; - keysyms[Qt::Key_THORN] = XK_THORN; - keysyms[Qt::Key_ydiaeresis] = XK_ydiaeresis; + // Latin1 symbols do directly map to + // Keycodes both in Qt and in X11: + for(int i = 0x20; i < 0x100; i++) + { + keysyms[i] = i; + } + keysyms[Qt::Key_AltGr] = XK_ISO_Level3_Shift; keysyms[Qt::Key_Multi_key] = XK_Multi_key; keysyms[Qt::Key_Codeinput] = XK_Codeinput; @@ -373,11 +254,15 @@ void initializeKeycodeLookupTable() { keysyms[Qt::Key_unknown] = XK_VoidSymbol; } -// every keysym with a value under 256 corresponds -// directly to an ISO-Latin1 Character. We need -// to store how to generate those characters: -int basicKeycodes[0x100]; // What key do we need to press? -int basicModifiers[0x100]; // What modifiers are required? +// We need to store how to generate KeySyms: +struct KeySymInfo +{ + KeyCode keycode; + XModifiers neededModifiers; + XModifiers modifierMask; +}; +typedef std::map KeySymToInfoMap; +KeySymToInfoMap keysymInfos; // What keys do we need to press to generate the // modifiers? @@ -388,6 +273,9 @@ Qt::KeyboardModifier modifierMeaning[8]; // How do the X11 modifiers correspond to Qt's KeyboardModifiers? typedef std::map XToQtModifierMap; XToQtModifierMap XToQtModifier; +typedef std::map QtToXModifierMap; +QtToXModifierMap QtToXModifier; + // And how do the modifiers relate to Keycodes? typedef std::multimap ModifierToKeycodeMap; @@ -395,6 +283,36 @@ ModifierToKeycodeMap ModifierToKeycode; typedef std::map KeycodeToModifierMap; KeycodeToModifierMap KeycodeToModifier; +#ifdef HAVE_XKBLIB_H +void recordModifierMapping(XkbDescPtr keybDesc, int keycode, Qt::KeyboardModifier qtMod) +{ + XModifiers rmod = 0; + if(QtToXModifier.find(qtMod) == QtToXModifier.end()) + { + for(int i = 1; i < 0x100; i <<= 1) + { + if(keybDesc->map->modmap[keycode] == i) + { + rmod = i; + XToQtModifier[rmod] = qtMod; + QtToXModifier[qtMod] = rmod; + } + } + } + else + { + rmod = QtToXModifier[qtMod]; + } + + if(rmod) + { + ModifierToKeycode.insert(std::make_pair(rmod, keycode)); + KeycodeToModifier[keycode] = rmod; + ConsoleLog writeLine(QString("%1 %2 %3 ... generates modifier %4").arg(keycode, 3).arg("", 40).arg("", 40).arg(rmod, 2, 16)); + } +} +#endif + // We need to query the input devices, preferrable through XInput2, but // if that is not available we will contend ourselves with XInput1: #ifndef HAVE_XINPUT2_H @@ -428,13 +346,22 @@ KeycodeToModifierMap KeycodeToModifier; // Initialize the above data structures: void initializeBasicKeycodes() { + // We temporarily need a list of all known KeySyms: + typedef std::set KeySymSet; + KeySymSet knownKeySyms; + + for(KeycodeLookupTable::const_iterator kcIter = keysyms.begin(); + kcIter != keysyms.end(); + kcIter++) + { + knownKeySyms.insert((*kcIter).second); + } + // Mark everything as unknown initially for(int i = 0; i < 8; i++) { modifierKeycodes[i] = -1; } - for(int i = 0; i < 0x100; i++) { - basicKeycodes[i] = -1; - } + keysymInfos.clear(); Display* dpy = X11InputUtils::display(); @@ -445,7 +372,11 @@ void initializeBasicKeycodes() // Initialize the XKB client-side code, and find out whether // the XKB extension is present in the server. int xkbOpcode, xkbEvent, xkbError, xkbMajor, xkbMinor; +#ifdef HAVE_XKBLIB_H bool xkbPresent = XkbQueryExtension(dpy, &xkbOpcode, &xkbEvent, &xkbError, &xkbMajor, &xkbMinor); +#else + bool xkbPresent = false; +#endif if(!xkbPresent) { // No XKB. This is probably not a very recent @@ -458,29 +389,81 @@ void initializeBasicKeycodes() // and traverse every entry for(int i = 0; i < count; i++) { - for(int j = 0; j < keysymsPerCode; j++) + for(int j = 0; j < 0x100; j++) { - const int idx = i * keysymsPerCode + j; + const XModifiers mods = modifierpriority[j]; + if(mods >= keysymsPerCode) + continue; + + const int idx = i * keysymsPerCode + mods; const KeySym ks = mapping[idx]; const int keycode = minKeycode + i; - // to find out if there is a Latin1 character there, - if(ks >= ' ' && ks < 0x100) + // to find out if there is a KeySym there that we know about + if(knownKeySyms.find(ks) != knownKeySyms.end()) { // that we have not yet found, - if(basicKeycodes[ks] != -1) + if(keysymInfos.find(ks) != keysymInfos.end()) continue; // already found // and record its keycode and needed modifiers. - basicKeycodes[ks] = keycode; - basicModifiers[ks] = j; + KeySymInfo info; + info.keycode = keycode; + info.neededModifiers = mods; + info.modifierMask = mods; + keysymInfos[ks] = info; } } } // We are finished, free the mapping structure. XFree(mapping); + + // find out which keycodes cause the modifier state bits: + XModifierKeymap* modkm; + modkm = XGetModifierMapping(dpy); + + const int shiftCode = XKeysymToKeycode(dpy, XK_Shift_L); + const int controlCode = XKeysymToKeycode(dpy, XK_Control_L); + const int altCode = XKeysymToKeycode(dpy, XK_Alt_L); + const int metaCode = XKeysymToKeycode(dpy, XK_Meta_L); + const int switchCode = XKeysymToKeycode(dpy, XK_Mode_switch); + + // and use this information to find out which + // X11 modifiers correspond to Qt's modifiers: + for(int i = 0; i < 8; i++) { + for(int j = 0; j < modkm->max_keypermod; j++) { + const int idx = i * modkm->max_keypermod + j; + const int kc = modkm->modifiermap[idx]; + + ModifierToKeycode.insert(std::make_pair((1<deviceid, devinfo->use, devinfo->name); + for(int i = 0; i < ndevinfos && xkbDeviceId == XkbUseCoreKbd; i++) + { + XIDeviceInfo* devinfo = devinfos + i; + qDebug("Found device %lu of type %d with name %s", (unsigned long)devinfo->deviceid, devinfo->use, devinfo->name); - // We want it to be a keyboard. - if(devinfo->use != XIMasterKeyboard && devinfo->use != XISlaveKeyboard) - continue; + // We want it to be a keyboard. + if(devinfo->use != XIMasterKeyboard && devinfo->use != XISlaveKeyboard) + continue; - int nprops; - Atom* props = getDeviceProperties(dpy, devinfo, &nprops); - if(props) - { - for(int j = 0; j < nprops && xkbDeviceId == XkbUseCoreKbd; j++) + int nprops; + Atom* props = getDeviceProperties(dpy, devinfo, &nprops); + if(props) { - Atom prop = props[j]; - if(prop == xtestDeviceProp) + for(int j = 0; j < nprops && xkbDeviceId == XkbUseCoreKbd; j++) { - // The device is the XTest Keyboard: - xkbDeviceId = devinfo->deviceid; + Atom prop = props[j]; + if(prop == xtestDeviceProp) + { + // The device is the XTest Keyboard: + xkbDeviceId = devinfo->deviceid; + } } + XFree(props); } - XFree(props); } - } - XIFreeDeviceInfo(devinfos); + XIFreeDeviceInfo(devinfos); #ifdef deviceid /* XInput1 */ # undef deviceid #endif + } } +#endif /* HAVE_XINPUT_H || HAVE_XINPUT2_H */ + // at this point, xkbDeviceId contains the identifier // of the XTEST Device, or xkbUseCoreKbd if none was // found. @@ -545,26 +541,64 @@ void initializeBasicKeycodes() { for(int j = 0; j <= 0xff; j++) { + XModifiers mods = modifierpriority[j]; KeySym ks = 0; unsigned int unconsumed; if(keybDesc) { - if(!XkbTranslateKeyCode(keybDesc, i, j, &unconsumed, &ks) || ks == NoSymbol) + if(!XkbTranslateKeyCode(keybDesc, i, mods, &unconsumed, &ks) || ks == NoSymbol) continue; } else { - if(!XkbLookupKeySym(dpy, i, j, &unconsumed, &ks) || ks == NoSymbol) + if(!XkbLookupKeySym(dpy, i, mods, &unconsumed, &ks) || ks == NoSymbol) continue; } - if(ks && (ks < 0x100)) + if(knownKeySyms.find(ks) != knownKeySyms.end()) { - if(basicKeycodes[ks] != -1) + if(j & ~unconsumed) + { + // we would be recording extraneous modifiers + continue; + } + + if(keysymInfos.find(ks) != keysymInfos.end()) continue; - basicKeycodes[ks] = i; - basicModifiers[ks] = unconsumed & j; + KeySymInfo info; + info.keycode = i; + info.neededModifiers = mods & unconsumed; + info.modifierMask = unconsumed; + keysymInfos[ks] = info; + + ConsoleLog writeLine(QString("%1 %2 %3 %4").arg(i, 3).arg(modifiersToString(info.neededModifiers), 40).arg(modifiersToString(info.modifierMask), 40).arg(XKeysymToString(ks))); + } + + if(j == 0) + { + switch(ks) + { + case XK_Shift_L: + case XK_Shift_R: + recordModifierMapping(keybDesc, i, Qt::ShiftModifier); + break; + case XK_Control_L: + case XK_Control_R: + recordModifierMapping(keybDesc, i, Qt::ControlModifier); + break; + case XK_Meta_L: + case XK_Meta_R: + recordModifierMapping(keybDesc, i, Qt::MetaModifier); + break; + case XK_Alt_L: + case XK_Alt_R: + recordModifierMapping(keybDesc, i, Qt::AltModifier); + break; + case XK_ISO_Level3_Shift: + recordModifierMapping(keybDesc, i, Qt::GroupSwitchModifier); + break; + } } } } @@ -575,50 +609,15 @@ void initializeBasicKeycodes() XkbFreeKeyboard(keybDesc, XkbAllComponentsMask, true); } } +#endif /* HAVE_XKBLIB_H */ - // find out which keycodes cause the modifier state bits: - XModifierKeymap* modkm; - modkm = XGetModifierMapping(dpy); - - const int shiftCode = XKeysymToKeycode(dpy, XK_Shift_L); - const int controlCode = XKeysymToKeycode(dpy, XK_Control_L); - const int altCode = XKeysymToKeycode(dpy, XK_Alt_L); - const int metaCode = XKeysymToKeycode(dpy, XK_Meta_L); - const int switchCode = XKeysymToKeycode(dpy, XK_Mode_switch); - - // and use this information to find out which - // X11 modifiers correspond to Qt's modifiers: - for(int i = 0; i < 8; i++) { - for(int j = 0; j < modkm->max_keypermod; j++) { - const int idx = i * modkm->max_keypermod + j; - const int kc = modkm->modifiermap[idx]; - - ModifierToKeycode.insert(std::make_pair((1<first, 2, 16).arg(i->second, 8, 16)); } - - XFreeModifiermap(modkm); } // Translate a Qt KeyboardModifiers flag to @@ -627,7 +626,7 @@ XModifiers translateModifiers(quint32 mods) { XModifiers ret = 0; - for(int j = 1; j < 8; j++) { + for(int j = 0; j < 8; j++) { XModifiers i = 1< IntSet; IntSet pressedModifierKeys; -XModifiers currentModifiers; +XModifiers currentModifiers = 0; void trackModifiers(int keycode, bool down) { @@ -686,13 +685,15 @@ typedef std::vector TweakSequence; // and record tweaks in the tracker. void tweakModifiers(Display* dpy, XModifiers neededState, XModifiers actualState, TweakSequence& tracker) { + if(neededState == actualState) + // nothing to do. + return; + ConsoleLog writeLine(QString("tweakModifiers: Trying to get to `%1' from `%2'").arg(modifiersToString(neededState)).arg(modifiersToString(actualState))); for(int j = 0; j < 8; j++) { XModifiers i = 1<= ' ' && ks < 0x100) + KeySymToInfoMap::const_iterator infoIter = keysymInfos.find(ks); + if(infoIter != keysymInfos.end()) { - if(basicKeycodes[ks] != -1) + KeySymInfo info = infoIter->second; + + if(evt.isPress()) { - if(evt.isPress()) + QString format = "Trying to press the key for %1 with modifiers %2 (X: %3, Qt: %4), while current modifiers are %5 and needed are %6 with mask %7"; + if(ks >= ' ' && ks < 0x100) + { + ConsoleLog writeLine(format + .arg((char)ks) + .arg(modifiersToString(translateModifiers(evt.qtModifiers()))) + .arg(translateModifiers(evt.qtModifiers()), 2, 16) + .arg(evt.qtModifiers(), 8, 16) + .arg(modifiersToString(currentModifiers)) + .arg(modifiersToString(info.neededModifiers)) + .arg(modifiersToString(info.modifierMask))); + } + else { - // Try the simple way first: - // Does the keycode with current modifiers yield the requested symbol? - KeySym unmodSym = XKeycodeToKeysym(dpy, basicKeycodes[ks], currentModifiers); - ConsoleLog writeLine(QString("Pressing the key for %1 would yield %2 right now.").arg(XKeysymToString(ks)).arg(XKeysymToString(unmodSym))); + ConsoleLog writeLine(format + .arg(XKeysymToString(ks)) + .arg(modifiersToString(translateModifiers(evt.qtModifiers()))) + .arg(translateModifiers(evt.qtModifiers()), 2, 16) + .arg(evt.qtModifiers(), 8, 16) + .arg(modifiersToString(currentModifiers)) + .arg(modifiersToString(info.neededModifiers)) + .arg(modifiersToString(info.modifierMask))); + } - if(ks == XKeycodeToKeysym(dpy, basicKeycodes[ks], currentModifiers)) - { - XTestFakeKeyEvent(dpy, basicKeycodes[ks], 1, CurrentTime); - } - else - { - // what modifier keys do we need to press? - XModifiers mods = translateModifiers(evt.qtModifiers()); + // what modifier keys do we need to press? + XModifiers mods = translateModifiers(evt.qtModifiers()); + XModifiers needed = info.neededModifiers; + XModifiers mask = info.modifierMask; + + // This is quite ad-hoc, but we do NOT want to + // mask Alt. + // On some configurations, the F-Keys consume Alt, + // and when we AND it out, we disable Alt+Fn + // combinations. That's just wrong. + // FIXME: Are there situations + // where we actually need to keep Alt masked? + // Hint: I found none. + // If so, how do we determine that? + QtToXModifierMap::const_iterator altIter = QtToXModifier.find(Qt::AltModifier); + if(altIter != QtToXModifier.end()) + { + mask &= ~(altIter->second); + } - // we may need to press additional modifiers to generate this keysym: - if(QChar(ks, 0).isLetter()) - { - // but, since Qt does not differentiate upper and lower case, - // we need to preserve Shift and Lock in their current state. - mods |= basicModifiers[ks] & ~(1<() .add() - .add() + .add() .add() .add(); // See comments in incompatibleHandler.h } diff --git a/src/input/x11FakeMouseHandler.h b/src/input/x11FakeMouseHandler.h index 8ff8df4..9d41c31 100644 --- a/src/input/x11FakeMouseHandler.h +++ b/src/input/x11FakeMouseHandler.h @@ -20,7 +20,7 @@ #include "inputEventHandler.h" class X11FakeMouseButtonHandler : public InputEventHandler< - input_policy::Match, + input_policy::Match, input_policy::Require, input_policy::Unprivileged> { -- cgit v1.2.3-55-g7522 From c53d10b0fdf137ad8157db2f8150c30ca4e814a8 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 21:35:43 +0200 Subject: Fix broken formatting of InputEvent::toString() --- src/input/inputEvent.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h index 73b7129..f9d3225 100644 --- a/src/input/inputEvent.h +++ b/src/input/inputEvent.h @@ -200,7 +200,7 @@ public: QString toString() const { - return QString("%1:%2:%3").arg(typeToString(_type)).arg(codeToString(_code)).arg(_value, 16); + return QString("%1:%2:%3").arg(typeToString(_type)).arg(codeToString(_code)).arg(_value, 8, 16, QLatin1Char('0')); } quint32 qtKeysym() const -- cgit v1.2.3-55-g7522 From d75d1a3e507e6a4cc01367df4d7a77012819b95b Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sun, 10 Oct 2010 22:09:29 +0200 Subject: Fix bug where pressing the closeUp-button sometimes results in no action. --- src/gui/frame.cpp | 29 +++++++++++- src/gui/frame.h | 3 ++ src/gui/mainWindow.cpp | 119 +++++++++++++++++++++++++++++-------------------- src/gui/mainWindow.h | 2 + 4 files changed, 102 insertions(+), 51 deletions(-) diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp index 12ce6b5..b9899d8 100644 --- a/src/gui/frame.cpp +++ b/src/gui/frame.cpp @@ -47,10 +47,12 @@ Frame::Frame(const QString & text, QWidget * parent) : _isLocked = false; _dozent = false; _uy = _ux = 0; + _isCloseUp = false; //QIcon icon; //icon.addFile(QString::fromUtf8(), QSize(), QIcon::Normal, QIcon::Off); button_closeUp = createToolButton(tr("View"), QIcon(":/restore"),SLOT(closeUp())); + button_closeUp->setCheckable(true); button_foto = createToolButton(tr("Foto"), QIcon(":/photos"),SLOT(foto())); button_lock = createToolButton(tr("Lock this client"), QIcon(":/lock"),SLOT(setLock())); //button_unlock = createToolButton(tr("Unlock this client"), QIcon(":/lock"),SLOT(setLock())); @@ -333,7 +335,11 @@ QImage Frame::getImageForFoto() void Frame::closeUp() { emit clicked(); - MainWindow::getWindow()->closeUp(); + + if(_isCloseUp) + MainWindow::getWindow()->unCloseUp(getConFrame()); + else + MainWindow::getWindow()->closeUp(getConFrame()); } void Frame::foto() @@ -377,6 +383,12 @@ void Frame::setDozent() } } +void Frame::setCloseUp(bool value) +{ + _isCloseUp = value; + button_closeUp->setChecked(value); +} + void Frame::remoteControlClicked() { if(_remoteControlEnabled) @@ -517,7 +529,20 @@ void Frame::keyPressEvent(QKeyEvent* event) { // The action of the keyboard may depend on the position of the pointer sendMouseMotionEvent(); - sendInputEvent(InputEvent::keyboardPress(event->key(), event->modifiers())); + + int key = event->key(); + + if(key >= ' ' && key < 0x100) + { + // the key is a Latin1 key. We need to find out the correct code to send. + QString text = event->text(); + if(text.length() == 1 && text.at(0).row() == 0) + { + // We found a Latin1 char and pray it is the correct case. + key = text.at(0).cell(); + } + } + sendInputEvent(InputEvent::keyboardPress(key, event->modifiers())); } } else diff --git a/src/gui/frame.h b/src/gui/frame.h index 8271670..4a3dd11 100644 --- a/src/gui/frame.h +++ b/src/gui/frame.h @@ -74,6 +74,8 @@ public Q_SLOTS: void setLock(); //void unlock(); void setDozent(); + void setCloseUp(bool value); + private Q_SLOTS: void remoteControlClicked(); void remoteControlAllClicked(); @@ -102,6 +104,7 @@ private: bool _isLocked; bool _dozent; int _ux, _uy; + bool _isCloseUp; // for remote control: QPoint _lastRecordedMousePosition; diff --git a/src/gui/mainWindow.cpp b/src/gui/mainWindow.cpp index 0f2fd0e..19b1021 100644 --- a/src/gui/mainWindow.cpp +++ b/src/gui/mainWindow.cpp @@ -98,7 +98,7 @@ MainWindow::MainWindow(QWidget *parent) : #ifdef MAINWINDOW_USE_TOUCHGUI //only used for the touchgui // define the slots we want to use - connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(combobox1(int))); // Combobox 1 verknüpfen mit IndexChangend Signal + connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(combobox1(int))); // Combobox 1 verkn��pfen mit IndexChangend Signal connect(ui->comboBox_touch1, SIGNAL(currentIndexChanged(int)), this, SLOT(setindexback())); connect(ui->pushButton, SIGNAL(clicked()), this, SLOT(createProfile())); // profile button @@ -711,61 +711,82 @@ void MainWindow::closeUp() { std::list* selectedClients = MainWindow::getConnectionList()->getSelectedClients(); - if (!is_closeup) + + if(selectedClients->size() != 1) + // Cannot closeUp zero or more than one frames. + return; + + PVSClient* pvsClient = PVSConnectionManager::getManager()->getClientFromIp(selectedClients->front()); + + closeUp(pvsClient->getConnectionFrame(), pvsClient); +} + +void MainWindow::closeUp(ConnectionFrame* connFrame, PVSClient* pvsClient) +{ + std::list* selectedClients = + MainWindow::getConnectionList()->getSelectedClients(); + + if(selectedClients->size() != 1) + // Cannot closeUp zero or more than one frames. + return; + + if(!pvsClient) + pvsClient = connFrame->getConnection(); + + // Do we already have a closeUp Frame? + ConnectionFrame* closeupFrame = conWin->getCloseupFrame(); + + if(closeupFrame) { - if (selectedClients->size() == 1) - { - PVSClient * pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - selectedClients->front().toStdString().c_str()); - _framePosOnCloseUp = pvsClient->getConnectionFrame()->pos();//get the actualy position before run closeup - if (pvsClient->getVNCConnection()) - { - conWin->setCloseupFrame(pvsClient->getConnectionFrame()); - _updatefreq - = pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->getUpdatefreq(); - pvsClient->getConnectionFrame()->getFrame()->getVNCClientThread()->setUpdatefreq( - 50); - pvsClient->getConnectionFrame()->move(5, 5); - pvsClient->getConnectionFrame()->setWindowFlags( - Qt::WindowStaysOnTopHint); - pvsClient->getConnectionFrame()->raise(); - pvsClient->getConnectionFrame()->paintCloseUp( - ui->widget->width(), ui->widget->height()); - - is_closeup = true; - conWin->setCloseupFrame(pvsClient->getConnectionFrame()); - } - } + // Is it the same as the sender one? + if(connFrame == closeupFrame) + // Then it already is close up. + return; else - { - QString - message = - QString( - tr( - "This operation can only be performed for one selected Client!")); - QMessageBox::information(this, "PVS", message); - } + // We need to un-closeUp the currently selected closeUp-Frame. + unCloseUp(closeupFrame); } - else if (conWin->getCloseupFrame()) + + _framePosOnCloseUp = connFrame->pos();//get the actualy position before run closeup + if (pvsClient->getVNCConnection()) { - /*PVSClient* pvsClient = - PVSConnectionManager::getManager()->getClientFromIp( - selectedClients->front().toStdString().c_str());*/ - conWin->getCloseupFrame()->setWindowFlags(Qt::Widget); - conWin->getCloseupFrame()->paintCloseUp( - conWin->getCloseupFrame()->getPrevWidth(), - conWin->getCloseupFrame()->getPrevHeight()); - conWin->getCloseupFrame()->move(_framePosOnCloseUp);//back to the position before the closeup - if (conWin->getCloseupFrame()->getConnection()->getVNCConnection()) - conWin->getCloseupFrame()->getFrame()->getVNCClientThread()->setUpdatefreq( - _updatefreq); - - is_closeup = false; - conWin->setCloseupFrame(NULL); + conWin->setCloseupFrame(connFrame); + _updatefreq = connFrame->getFrame()->getVNCClientThread()->getUpdatefreq(); + connFrame->getFrame()->getVNCClientThread()->setUpdatefreq( + 50); + connFrame->move(5, 5); + connFrame->setWindowFlags(Qt::WindowStaysOnTopHint); + connFrame->raise(); + connFrame->paintCloseUp(ui->widget->width(), ui->widget->height()); + + conWin->setCloseupFrame(connFrame); + + Frame* frame = connFrame->getFrame(); + if(frame) + frame->setCloseUp(true); } } +void MainWindow::unCloseUp(ConnectionFrame* connFrame) +{ + if(!connFrame) + return; + + connFrame->setWindowFlags(Qt::Widget); + connFrame->paintCloseUp( + connFrame->getPrevWidth(), + connFrame->getPrevHeight()); + connFrame->move(_framePosOnCloseUp);//back to the position before the closeup + if (connFrame->getConnection()->getVNCConnection()) + connFrame->getFrame()->getVNCClientThread()->setUpdatefreq(_updatefreq); + + Frame* frame = connFrame->getFrame(); + if(frame) + frame->setCloseUp(false); + + conWin->setCloseupFrame(NULL); +} + /* Perform some action if actionShowProcesses button was pressed * */ diff --git a/src/gui/mainWindow.h b/src/gui/mainWindow.h index 88756fd..c1f100e 100644 --- a/src/gui/mainWindow.h +++ b/src/gui/mainWindow.h @@ -172,6 +172,8 @@ public slots: void clientlisthide(); void projecttoolbar(); void unprojecttoolbar(); + void closeUp(ConnectionFrame* connFrame, PVSClient* client = 0); + void unCloseUp(ConnectionFrame* connFrame); void closeUp(); void foto(); void backgroundpicture(); -- cgit v1.2.3-55-g7522 From d626b99839eb2cf915d96b4048d31e6622ad00ca Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Mon, 11 Oct 2010 00:52:21 +0200 Subject: Add access control check to input event handling in PVS daemon --- src/pvs.cpp | 13 +++++++++++-- src/pvs.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/pvs.cpp b/src/pvs.cpp index 96a92ea..e0605c2 100755 --- a/src/pvs.cpp +++ b/src/pvs.cpp @@ -199,8 +199,11 @@ void PVS::onCommand(PVSMsg cmdMessage) if (ident.compare("INPUTEVENT") == 0) { InputEvent evt; - eventFromString(message, evt); - handleInputEvent(evt); + if(inputEventsAllowed()) + { + eventFromString(message, evt); + handleInputEvent(evt); + } } if (ident.compare("MCASTFTRETRY") == 0) { @@ -749,6 +752,12 @@ bool PVS::createMulticastTransfer(QString const& objectPath, quint64& transferID // Input handling +bool PVS::inputEventsAllowed() +{ + QString lecturer = getConfigValue("Permissions/vnc_lecturer"); + return r == "rw"; +} + void PVS::handleInputEvent(InputEvent const& evt) { QString s = evt.toString(); diff --git a/src/pvs.h b/src/pvs.h index 902fbe7..27ea2fc 100755 --- a/src/pvs.h +++ b/src/pvs.h @@ -169,6 +169,7 @@ private: // input event handling: InputEventHandlerChain _inputEventHandlers; + bool inputEventsAllowed(); void handleInputEvent(InputEvent const& evt); void initializeInputEventHandling(); -- cgit v1.2.3-55-g7522 From 732b9cfec697e893fcf5b65e1e7c9e5921ea5951 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Mon, 11 Oct 2010 09:02:38 +0200 Subject: Introduce LogNonMatchingHandler --- src/input/CMakeLists.txt | 1 + src/input/logNonMatchingHandler.cpp | 27 +++++++++++++++++++++++ src/input/logNonMatchingHandler.h | 33 +++++++++++++++++++++++++++++ src/input/unprivilegedInputHandlerChain.cpp | 4 +++- 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/input/logNonMatchingHandler.cpp create mode 100644 src/input/logNonMatchingHandler.h diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index d950c67..b4dfa4d 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -4,6 +4,7 @@ set(pvsinput_SRCS inputEvent.cpp unprivilegedInputHandlerChain.cpp inputEventHandler.cpp + logNonMatchingHandler.cpp ) set(feature_DEFS) diff --git a/src/input/logNonMatchingHandler.cpp b/src/input/logNonMatchingHandler.cpp new file mode 100644 index 0000000..dd694fc --- /dev/null +++ b/src/input/logNonMatchingHandler.cpp @@ -0,0 +1,27 @@ +/* +# 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/ +# ----------------------------------------------------------------------------- +# src/input/nonMatchingHandler.cpp: +# - Log events that were not matched by another handler - implementation +# ----------------------------------------------------------------------------- +*/ + +#include "logNonMatchingHandler.h" +#include + +void LogNonMatchingHandler::doHandle(InputEvent const& event, InputEventContext const* context) +{ + // It's not really nonmatched if it has already been denied + if(!context->hasBeenDenied) + { + qWarning("No matching handler found for event %s", event.toString().toLocal8Bit().constData()); + } +} diff --git a/src/input/logNonMatchingHandler.h b/src/input/logNonMatchingHandler.h new file mode 100644 index 0000000..3403640 --- /dev/null +++ b/src/input/logNonMatchingHandler.h @@ -0,0 +1,33 @@ +/* +# 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/ +# ----------------------------------------------------------------------------- +# src/input/nonMatchingHandler.h: +# - Log events that were not matched by another handler - interface +# ----------------------------------------------------------------------------- +*/ + +#ifndef LOGNONMATCHINGHANDLER_H_ +#define LOGNONMATCHINGHANDLER_H_ + +#include "inputEventHandler.h" + +class LogNonMatchingHandler : public InputEventHandler +{ +public: + bool isApplicable(InputEvent const&, InputEventContext const*) + { + return true; + } + + void doHandle(InputEvent const&, InputEventContext const*); +}; + +#endif /* LOGNONMATCHINGHANDLER_H_ */ diff --git a/src/input/unprivilegedInputHandlerChain.cpp b/src/input/unprivilegedInputHandlerChain.cpp index 2df2d77..3f47631 100644 --- a/src/input/unprivilegedInputHandlerChain.cpp +++ b/src/input/unprivilegedInputHandlerChain.cpp @@ -20,6 +20,7 @@ #include "privilegedHandlerForwarder.h" #include "incompatibleHandler.h" #include "inputHandlerChains.h" +#include "logNonMatchingHandler.h" InputEventHandlerChain makeUnprivilegedInputEventHandlerChain() { @@ -27,6 +28,7 @@ InputEventHandlerChain makeUnprivilegedInputEventHandlerChain() .add() .add() .add() - .add(); // See comments in incompatibleHandler.h + .add() // See comments in incompatibleHandler.h + .add(); } -- cgit v1.2.3-55-g7522 From ee5f13df4fa951259f5f4c62274483ee4a5e34a7 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Mon, 11 Oct 2010 09:02:49 +0200 Subject: Fix stupid Typo bug. --- src/pvs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pvs.cpp b/src/pvs.cpp index e0605c2..f582caa 100755 --- a/src/pvs.cpp +++ b/src/pvs.cpp @@ -755,7 +755,7 @@ bool PVS::createMulticastTransfer(QString const& objectPath, quint64& transferID bool PVS::inputEventsAllowed() { QString lecturer = getConfigValue("Permissions/vnc_lecturer"); - return r == "rw"; + return lecturer == "rw"; } void PVS::handleInputEvent(InputEvent const& evt) -- cgit v1.2.3-55-g7522 From 5ba61818d5bdd1b96996eb0fe1a5b3befc16b1a0 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Mon, 11 Oct 2010 09:04:19 +0200 Subject: Log unmatched events in pvsprivinputd, too. --- src/input/privilegedInputHandlerChain.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/input/privilegedInputHandlerChain.cpp b/src/input/privilegedInputHandlerChain.cpp index 5764728..c1e8629 100644 --- a/src/input/privilegedInputHandlerChain.cpp +++ b/src/input/privilegedInputHandlerChain.cpp @@ -20,11 +20,13 @@ #include "killX11Handler.h" #include "magicSysRqHandler.h" #include "inputHandlerChains.h" +#include "logNonMatchingHandler.h" InputEventHandlerChain makePrivilegedInputEventHandlerChain() { return InputEventHandlerChain().add() .add() .add() - .add(); + .add() + .add(); } -- cgit v1.2.3-55-g7522 From bcaa6e3580f5b227ab48693192c459cc72c30224 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Mon, 11 Oct 2010 12:27:27 +0200 Subject: Better error handling for PVSPrivInputHandler --- src/input/pvsPrivInputHandler.cpp | 21 ++++++++++++++++++--- src/input/pvsprivinputd.cpp | 4 +++- 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/src/input/pvsPrivInputHandler.cpp b/src/input/pvsPrivInputHandler.cpp index 84ccbae..d33697a 100644 --- a/src/input/pvsPrivInputHandler.cpp +++ b/src/input/pvsPrivInputHandler.cpp @@ -86,9 +86,24 @@ void PVSPrivInputHandler::canRead() if(!pvsPrivInputRecvMessage(_fd, _messageAssembly.data(), siz, pid, uid, gid, &err)) { - close(_fd); - deleteLater(); - return; + switch(err) + { + case EAGAIN: +#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN) + case EWOULDBLOCK: +#endif + // That's okay. Nothing to do. + break; + case 0: + // We'll survive. There was no actual error, just the library routine + // that decided it did not really want to receive that packet. + break; + default: + qWarning("Something bad just happened, and cannot handle it. Panicking."); + close(_fd); + deleteLater(); + return; + } } else { diff --git a/src/input/pvsprivinputd.cpp b/src/input/pvsprivinputd.cpp index e6ae155..df3acfc 100644 --- a/src/input/pvsprivinputd.cpp +++ b/src/input/pvsprivinputd.cpp @@ -182,7 +182,9 @@ int main(int argc, char** argv) } // Install our main object - PVSPrivInputHandler handler(sock); + PVSPrivInputHandler* handler = new PVSPrivInputHandler(sock, &app); + // When the handler gets deleted, we want to quit the application + QObject::connect(handler, SIGNAL(destroyed(QObject*)), &app, SLOT(quit())); // set up signal handling: if(socketpair(AF_UNIX, SOCK_DGRAM, 0, signalFds) < 0) -- cgit v1.2.3-55-g7522 From 6fcd6c00510d4da9c72d1d44c769bb0d546ca9ef Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 12 Oct 2010 05:16:37 +0200 Subject: Fix InputEventHandler logic bug Entered break instead of return. --- src/input/inputEventHandler.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 11e2f4e..a2e943e 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -309,7 +309,7 @@ public: switch(i.next()->handle(event, context)) { case InputEventHandlerBase::HANDLER_MATCHED: - break; + return; case InputEventHandlerBase::HANDLER_NOT_ALLOWED: context->hasBeenDenied = true; case InputEventHandlerBase::HANDLER_NOT_APPLICABLE: -- cgit v1.2.3-55-g7522 From f74fc506229abb42e0ecd67a4bd0fa3ac68f8149 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 12 Oct 2010 05:17:05 +0200 Subject: Fix segmentation fault in LogNonMatchingHandler Would SIGSEGV if an unmatched event arrived with no context. --- src/input/logNonMatchingHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/logNonMatchingHandler.cpp b/src/input/logNonMatchingHandler.cpp index dd694fc..b0aa93a 100644 --- a/src/input/logNonMatchingHandler.cpp +++ b/src/input/logNonMatchingHandler.cpp @@ -20,7 +20,7 @@ void LogNonMatchingHandler::doHandle(InputEvent const& event, InputEventContext const* context) { // It's not really nonmatched if it has already been denied - if(!context->hasBeenDenied) + if(!context || !context->hasBeenDenied) { qWarning("No matching handler found for event %s", event.toString().toLocal8Bit().constData()); } -- cgit v1.2.3-55-g7522 From c26b6dc30178bd153598d7d4b6a2ce64251596d3 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 12 Oct 2010 05:17:27 +0200 Subject: Fix default PolicyKit policy Admin password is required if user is not local and unprivileged. --- src/input/org.openslx.pvs.input.policy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/input/org.openslx.pvs.input.policy b/src/input/org.openslx.pvs.input.policy index f0de9f2..f4a73e6 100644 --- a/src/input/org.openslx.pvs.input.policy +++ b/src/input/org.openslx.pvs.input.policy @@ -10,8 +10,8 @@ Use privileged input actions in PVS Authentication is required to let PVS use privileged input actions - auth_self_keep - auth_self_keep + auth_admin_keep + auth_admin_keep auth_admin_keep -- cgit v1.2.3-55-g7522 From 09e7427b3715ae8cfeb81bb3489b70a823662d19 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 12 Oct 2010 05:19:30 +0200 Subject: Fix build error. --- src/input/CMakeLists.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index b4dfa4d..4f9eb4d 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -164,8 +164,3 @@ add_library( ${pvsinput_SRCS} ${pvsinput_RCS} ) - -add_library( - pvsinputtests - STATIC - templateMagicTests.cpp) -- cgit v1.2.3-55-g7522 From d81fa20f32d6285731248405d47fc34b8e612073 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 12 Oct 2010 06:12:20 +0200 Subject: Fix control character handling bug. The code to deal with lowercase and uppercase versions of Latin1 characters was overly broad and sent ASCII Control Characters if Ctrl was pressed. --- src/gui/frame.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp index b9899d8..12d49bc 100644 --- a/src/gui/frame.cpp +++ b/src/gui/frame.cpp @@ -538,8 +538,18 @@ void Frame::keyPressEvent(QKeyEvent* event) QString text = event->text(); if(text.length() == 1 && text.at(0).row() == 0) { - // We found a Latin1 char and pray it is the correct case. - key = text.at(0).cell(); + QChar c = text.at(0); + + // The next problem is that it may be a control character. + // This happens when Ctrl is pressed, so we only + // modify keys if they are lowercase or uppercase + // versions of the keycode. + + if(c.toLower().toLatin1() == key || c.toUpper().toLatin1() == key) + { + // We found a Latin1 char and pray it is the correct case. + key = c.cell(); + } } } sendInputEvent(InputEvent::keyboardPress(key, event->modifiers())); -- cgit v1.2.3-55-g7522 From 6f9be93b8e47a5a65a3c56fab0de7e78d150d790 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 12 Oct 2010 09:44:11 +0200 Subject: Document changed requirements --- INSTALL | 2 ++ 1 file changed, 2 insertions(+) diff --git a/INSTALL b/INSTALL index cfb079b..6a7d736 100644 --- a/INSTALL +++ b/INSTALL @@ -6,6 +6,8 @@ The following packages are required: libvncserver-dev libx11-dev + libxi-dev + libxtst-dev libqt4-dev >= 4.5.3 qt4-dev-tools >= 4.5.3 cmake >= 2.4.0 -- cgit v1.2.3-55-g7522 From 2561bfbe4f72bfb2093da2d93b1298caaa4f4497 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Wed, 13 Oct 2010 03:28:43 +0200 Subject: Fix key case comparison bug --- src/gui/frame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp index 12d49bc..561f3ce 100644 --- a/src/gui/frame.cpp +++ b/src/gui/frame.cpp @@ -545,7 +545,7 @@ void Frame::keyPressEvent(QKeyEvent* event) // modify keys if they are lowercase or uppercase // versions of the keycode. - if(c.toLower().toLatin1() == key || c.toUpper().toLatin1() == key) + if(c.toLower().toLatin1() == (char)key || c.toUpper().toLatin1() == (char)key) { // We found a Latin1 char and pray it is the correct case. key = c.cell(); -- cgit v1.2.3-55-g7522 From 45ffedadfb42973e244debdb63300e9aefda5414 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Wed, 13 Oct 2010 03:34:39 +0200 Subject: Introduce init-scripts for pvsprivinputd --- src/input/CMakeLists.txt | 9 ++ src/input/pvsprivinputd.gentooinit.in | 37 +++++++++ src/input/pvsprivinputd.lsbinit.in | 152 ++++++++++++++++++++++++++++++++++ 3 files changed, 198 insertions(+) create mode 100644 src/input/pvsprivinputd.gentooinit.in create mode 100644 src/input/pvsprivinputd.lsbinit.in diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index 4f9eb4d..26eeb64 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -164,3 +164,12 @@ add_library( ${pvsinput_SRCS} ${pvsinput_RCS} ) + +if(EXISTS /etc/gentoo-release) + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pvsprivinputd.gentooinit.in ${CMAKE_CURRENT_BINARY_DIR}/pvsprivinputd.init @ONLY@) +else() + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pvsprivinputd.lsbinit.in ${CMAKE_CURRENT_BINARY_DIR}/pvsprivinputd.init @ONLY@) +endif() +install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/pvsprivinputd.init + DESTINATION /etc/init.d + RENAME pvsprivinputd) diff --git a/src/input/pvsprivinputd.gentooinit.in b/src/input/pvsprivinputd.gentooinit.in new file mode 100644 index 0000000..03ade0f --- /dev/null +++ b/src/input/pvsprivinputd.gentooinit.in @@ -0,0 +1,37 @@ +#!/sbin/runscript +# Copyright (C) 2010 OpenSKX Project, Computer Center of the University of Freiburg, Germany +# This program is free software distributed under the GPL version 2. +# See http://openslx.org/COPYING + +opts="${opts} reload" + +PVSPRIVINPUTD_BINARY="@CMAKE_INSTALL_PREFIX@/sbin/pvsprivinputd" +PVSPRIVINPUTD_PIDFILE="/var/run/pvsprivinputd.pid" + +depend() { + use net + use logger + before dbus +} + +start() { + ebegin "Starting pvsprivinputd" + start-stop-daemon --start --pidfile "${PVSPRIVINPUTD_PIDFILE}" \ + --exec "${PVSPRIVINPUTD_BINARY}" -- \ + -d -lsyslog + eend $? +} + +stop() { + ebegin "Stopping pvsprivinputd" + start-stop-daemon --stop --signal SIGINT --pidfile "${PVSPRIVINPUTD_PIDFILE}" \ + --exec "${PVSPRIVINPUTD_BINARY}" + eend $? +} + +reload() { + ebegin "Realoding pvsprivinputd's configuration" + start-stop-daemon --stop --signal SIGHUP --pidfile "${PVSPRIVINPUTD_PIDFILE}" \ + --oknodo --exec "${PVSPRIVINPUTD_BINARY}" + eend $? +} diff --git a/src/input/pvsprivinputd.lsbinit.in b/src/input/pvsprivinputd.lsbinit.in new file mode 100644 index 0000000..9b4293e --- /dev/null +++ b/src/input/pvsprivinputd.lsbinit.in @@ -0,0 +1,152 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: pvsprivinputd +# Required-Start: $remote_fs $syslog +# Required-Stop: $remote_fs $syslog +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: PVS Privileged Input Daemon +# Description: Support system service for PVS. +### END INIT INFO + +# Author: Sebastien Braun +# +# Please remove the "Author" lines above and replace them +# with your own name if you copy and modify this script. + +# Do NOT "set -e" + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="Support system service for PVS" +NAME=pvsprivinputd +DAEMON=@CMAKE_INSTALL_PREFIX@/sbin/pvsprivinputd +DAEMON_ARGS="-d -lsyslog" +PIDFILE=/var/run/$NAME.pid +SCRIPTNAME=/etc/init.d/$NAME + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/$NAME ] && . /etc/default/$NAME + +# Load the VERBOSE setting and other rcS variables +. /lib/init/vars.sh + +# Define LSB log_* functions. +# Depend on lsb-base (>= 3.0-6) to ensure that this file is present. +. /lib/lsb/init-functions + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \ + || return 1 + start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ + $DAEMON_ARGS \ + || return 2 + # Add code here, if necessary, that waits for the process to be ready + # to handle requests from services started subsequently which depend + # on this one. As a last resort, sleep for some time. +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + # Wait for children to finish too if this is a daemon that forks + # and if the daemon is only ever run from this initscript. + # If the above conditions are not satisfied then add some other code + # that waits for the process to drop all resources that could be + # needed by services started subsequently. A last resort is to + # sleep for some time. + start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON + [ "$?" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f $PIDFILE + return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + # + # If the daemon can reload its configuration without + # restarting (for example, when it is sent a SIGHUP), + # then implement that here. + # + start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME + return 0 +} + +case "$1" in + start) + [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; + 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; + esac + ;; + status) + status_of_proc "$DAEMON" "$NAME" && exit 0 || exit $? + ;; + reload|force-reload) + # + # If do_reload() is not implemented then leave this commented out + # and leave 'force-reload' as an alias for 'restart'. + # + log_daemon_msg "Reloading $DESC" "$NAME" + do_reload + log_end_msg $? + ;; + restart) + log_daemon_msg "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) log_end_msg 0 ;; + 1) log_end_msg 1 ;; # Old process is still running + *) log_end_msg 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + log_end_msg 1 + ;; + esac + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 + exit 3 + ;; +esac + +: -- cgit v1.2.3-55-g7522 From a27b41dfcbf1c73a2eab60e5e32016eee014f816 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Wed, 13 Oct 2010 03:34:59 +0200 Subject: Uncomment killing of X-Server --- src/input/killX11Handler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/killX11Handler.cpp b/src/input/killX11Handler.cpp index 32e5873..8fa8c24 100644 --- a/src/input/killX11Handler.cpp +++ b/src/input/killX11Handler.cpp @@ -85,5 +85,5 @@ void KillX11Handler::doHandle(InputEvent const&, InputEventContext const* ctx) QString exe = QFileInfo(QString("/proc/%1/exe").arg(pids[0])).readLink(); qDebug("Killing X server, PID %d, exe name %s with SIGTERM", pids[0], exe.toLocal8Bit().constData()); -// kill(pids[0], SIGTERM); + kill(pids[0], SIGTERM); } -- cgit v1.2.3-55-g7522 From a576f62d0e3003824832e4730dd42aa16dc1f178 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Wed, 13 Oct 2010 05:07:44 +0200 Subject: Formatting fixes for X11FakeKeyboardHandler --- src/input/x11FakeKeyboardHandler.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index fed087e..333baab 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -186,6 +186,7 @@ void initializeKeycodeLookupTable() { keysyms[Qt::Key_Hyper_L] = XK_Hyper_L; keysyms[Qt::Key_Hyper_R] = XK_Hyper_R; keysyms[Qt::Key_Help] = XK_Help; + // Latin1 symbols do directly map to // Keycodes both in Qt and in X11: for(int i = 0x20; i < 0x100; i++) @@ -572,7 +573,11 @@ void initializeBasicKeycodes() info.modifierMask = unconsumed; keysymInfos[ks] = info; - ConsoleLog writeLine(QString("%1 %2 %3 %4").arg(i, 3).arg(modifiersToString(info.neededModifiers), 40).arg(modifiersToString(info.modifierMask), 40).arg(XKeysymToString(ks))); + ConsoleLog writeLine(QString("%1 %2 %3 %4") + .arg(i, 3) + .arg(modifiersToString(info.neededModifiers), 40) + .arg(modifiersToString(info.modifierMask), 40) + .arg(XKeysymToString(ks))); } if(j == 0) -- cgit v1.2.3-55-g7522 From 3db2c6c566b57fb02bd5529274ab690e7e0b1ffc Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Wed, 13 Oct 2010 05:09:02 +0200 Subject: Fix forgotten change of j to mods in X11FakeKeyboardHandler. --- src/input/x11FakeKeyboardHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index 333baab..f27ea1e 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -558,7 +558,7 @@ void initializeBasicKeycodes() if(knownKeySyms.find(ks) != knownKeySyms.end()) { - if(j & ~unconsumed) + if(mods & ~unconsumed) { // we would be recording extraneous modifiers continue; -- cgit v1.2.3-55-g7522 From 7e3b963e3a0cbbf9391243e72ceb015e9015d630 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Sat, 23 Oct 2010 17:49:12 +0200 Subject: Documentation fixes and code cleanup --- doc/doxconf | 10 +- src/input/detail/gen/gen_typeList.cpp | 3 + src/input/detail/typeList_autogen.h | 2 + src/input/i18n/pvsinput_ar_JO.ts | 46 +++---- src/input/i18n/pvsinput_de_DE.ts | 46 +++---- src/input/i18n/pvsinput_es_MX.ts | 46 +++---- src/input/i18n/pvsinput_fr_FR.ts | 46 +++---- src/input/i18n/pvsinput_pl_PL.ts | 46 +++---- src/input/inputEvent.cpp | 32 ++++- src/input/inputEvent.h | 245 +++++++++++++++++++++++++++------ src/input/inputEventHandler.h | 198 ++++++++++++++++++-------- src/input/inputHandlerChains.h | 15 ++ src/input/killX11Handler.h | 11 ++ src/input/logNonMatchingHandler.h | 3 + src/input/magicSysRqHandler.h | 12 +- src/input/privilegedHandlerForwarder.h | 13 ++ src/input/pvsCheckPrivileges.h | 65 +++++++-- src/input/pvsPrivInputHandler.h | 9 ++ src/input/pvsPrivInputSignalHandler.h | 17 +++ src/input/pvsPrivInputSocket.h | 38 +++++ src/input/pvsSyslog.h | 9 ++ src/input/rebootSystemHandler.h | 6 + src/input/sayHelloHandler.h | 4 + src/input/x11FakeKeyboardHandler.h | 7 + src/input/x11FakeMouseHandler.h | 6 + src/input/x11InputUtils.h | 3 + 26 files changed, 695 insertions(+), 243 deletions(-) diff --git a/doc/doxconf b/doc/doxconf index 50334c7..e3e32a6 100644 --- a/doc/doxconf +++ b/doc/doxconf @@ -564,7 +564,7 @@ WARN_LOGFILE = ./doxwarnlog # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ./pvsClient.h ./pvsClient.cpp ./pvs.h ./pvs.cpp ./pvsDaemon.h ./pvsDaemon.cpp ./src +INPUT = ../pvsClient.h ../pvsClient.cpp ../pvs.h ../pvs.cpp ../pvsDaemon.h ../pvsDaemon.cpp ../src # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -1210,13 +1210,13 @@ ENABLE_PREPROCESSING = YES # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. -MACRO_EXPANSION = NO +MACRO_EXPANSION = YES # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. -EXPAND_ONLY_PREDEF = NO +EXPAND_ONLY_PREDEF = YES # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. @@ -1244,7 +1244,9 @@ INCLUDE_FILE_PATTERNS = # undefined via #undef or recursively expanded use the := operator # instead of the = operator. -PREDEFINED = +PREDEFINED = "DOXYGEN_RUNNING" \ + "BEGIN_POLICY_CLASS(name)=class name" \ + "END_POLICY_CLASS=;" # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. diff --git a/src/input/detail/gen/gen_typeList.cpp b/src/input/detail/gen/gen_typeList.cpp index e092b80..21056f9 100644 --- a/src/input/detail/gen/gen_typeList.cpp +++ b/src/input/detail/gen/gen_typeList.cpp @@ -47,6 +47,8 @@ int main(int, char**) cout << "template\n" "struct Contains { static const int index = -1; static const bool value = false; };\n"; + // specializations: + cout << "#ifndef DOXYGEN_RUNNING\n"; for(i = 0; i < NUM_MAX_ENTRIES; i++) { int j; @@ -70,6 +72,7 @@ int main(int, char**) } cout << "> >\n{ static const int index = " << i << "; static const bool value = true; };\n"; } + cout << "#endif\n"; // Empty List: cout << "typedef TypeList<"; diff --git a/src/input/detail/typeList_autogen.h b/src/input/detail/typeList_autogen.h index 0f8fdd4..79f1335 100644 --- a/src/input/detail/typeList_autogen.h +++ b/src/input/detail/typeList_autogen.h @@ -5,6 +5,7 @@ typedef TypeList struct Contains { static const int index = -1; static const bool value = false; }; +#ifndef DOXYGEN_RUNNING template struct Contains > { static const int index = 0; static const bool value = true; }; @@ -53,6 +54,7 @@ struct Contains struct Contains > { static const int index = 15; static const bool value = true; }; +#endif typedef TypeList EmptyList; #define IMPLICIT_TYPE_LIST_PARAMS(prefix) typename prefix##0 = void, typename prefix##1 = void, typename prefix##2 = void, typename prefix##3 = void, typename prefix##4 = void, typename prefix##5 = void, typename prefix##6 = void, typename prefix##7 = void, typename prefix##8 = void, typename prefix##9 = void, typename prefix##10 = void, typename prefix##11 = void, typename prefix##12 = void, typename prefix##13 = void, typename prefix##14 = void, typename prefix##15 = void #define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) typename prefix##0, typename prefix##1, typename prefix##2, typename prefix##3, typename prefix##4, typename prefix##5, typename prefix##6, typename prefix##7, typename prefix##8, typename prefix##9, typename prefix##10, typename prefix##11, typename prefix##12, typename prefix##13, typename prefix##14, typename prefix##15 diff --git a/src/input/i18n/pvsinput_ar_JO.ts b/src/input/i18n/pvsinput_ar_JO.ts index 1040142..bf25eda 100644 --- a/src/input/i18n/pvsinput_ar_JO.ts +++ b/src/input/i18n/pvsinput_ar_JO.ts @@ -4,117 +4,117 @@ InputEvent - + Say Hello - + Reboot - + Kill X Server - + Reboot immediately - + Power off immediately - + Crash System - + Turn off raw keyboard mode - + Send SIGTERM to all - + Send SIGKILL to all - + Kill all on this terminal - + Activate OOM killer - + Make real-time tasks niceable - + Force-thaw filesystems - + Sync all mounted filesystems - + Remount all readonly - + Show all held locks - + Show stack traces - + Dump memory info - + Dump registers and flags - + Dump timers and clockevents - + Dump task list - + Dump uninterruptible tasks - + Dump ftrace buffer diff --git a/src/input/i18n/pvsinput_de_DE.ts b/src/input/i18n/pvsinput_de_DE.ts index 56ebf26..002016a 100644 --- a/src/input/i18n/pvsinput_de_DE.ts +++ b/src/input/i18n/pvsinput_de_DE.ts @@ -4,117 +4,117 @@ InputEvent - + Say Hello Hallo sagen - + Reboot Neustart - + Kill X Server X-Server töten - + Reboot immediately Sofort neu starten - + Power off immediately Sofort abschalten - + Crash System Systemabsturz - + Turn off raw keyboard mode RAW-Tastatur-Modus abschalten - + Send SIGTERM to all SIGTERM an alle Prozesse senden - + Send SIGKILL to all SIGKILL an alle Prozesse senden - + Kill all on this terminal Alle Prozesse an diesem Terminal töten - + Activate OOM killer OOM-Killer aktivieren - + Make real-time tasks niceable Nice für Echtzeitprozesse ermöglichen - + Force-thaw filesystems - + Sync all mounted filesystems Alle eingebundenen Dateisysteme sync(2)en - + Remount all readonly Alle Dateisysteme nur-lesbar mounten - + Show all held locks Alle gehaltenen Sperren zeigen - + Show stack traces Stacktraces anzigen - + Dump memory info Speicherinfo anzeigen - + Dump registers and flags Register und Flags anzeigen - + Dump timers and clockevents Timer und Clockevents anzeigen - + Dump task list Taskliste anzeigen - + Dump uninterruptible tasks Ununterbrechbare Tasks anzeigen - + Dump ftrace buffer ftrace-Puffer anzeigen diff --git a/src/input/i18n/pvsinput_es_MX.ts b/src/input/i18n/pvsinput_es_MX.ts index 047c59c..d805d0e 100644 --- a/src/input/i18n/pvsinput_es_MX.ts +++ b/src/input/i18n/pvsinput_es_MX.ts @@ -4,117 +4,117 @@ InputEvent - + Say Hello - + Reboot - + Kill X Server - + Reboot immediately - + Power off immediately - + Crash System - + Turn off raw keyboard mode - + Send SIGTERM to all - + Send SIGKILL to all - + Kill all on this terminal - + Activate OOM killer - + Make real-time tasks niceable - + Force-thaw filesystems - + Sync all mounted filesystems - + Remount all readonly - + Show all held locks - + Show stack traces - + Dump memory info - + Dump registers and flags - + Dump timers and clockevents - + Dump task list - + Dump uninterruptible tasks - + Dump ftrace buffer diff --git a/src/input/i18n/pvsinput_fr_FR.ts b/src/input/i18n/pvsinput_fr_FR.ts index 8e3e417..af231ea 100644 --- a/src/input/i18n/pvsinput_fr_FR.ts +++ b/src/input/i18n/pvsinput_fr_FR.ts @@ -4,117 +4,117 @@ InputEvent - + Say Hello - + Reboot - + Kill X Server - + Reboot immediately - + Power off immediately - + Crash System - + Turn off raw keyboard mode - + Send SIGTERM to all - + Send SIGKILL to all - + Kill all on this terminal - + Activate OOM killer - + Make real-time tasks niceable - + Force-thaw filesystems - + Sync all mounted filesystems - + Remount all readonly - + Show all held locks - + Show stack traces - + Dump memory info - + Dump registers and flags - + Dump timers and clockevents - + Dump task list - + Dump uninterruptible tasks - + Dump ftrace buffer diff --git a/src/input/i18n/pvsinput_pl_PL.ts b/src/input/i18n/pvsinput_pl_PL.ts index 87527d5..11365c0 100644 --- a/src/input/i18n/pvsinput_pl_PL.ts +++ b/src/input/i18n/pvsinput_pl_PL.ts @@ -4,117 +4,117 @@ InputEvent - + Say Hello - + Reboot - + Kill X Server - + Reboot immediately - + Power off immediately - + Crash System - + Turn off raw keyboard mode - + Send SIGTERM to all - + Send SIGKILL to all - + Kill all on this terminal - + Activate OOM killer - + Make real-time tasks niceable - + Force-thaw filesystems - + Sync all mounted filesystems - + Remount all readonly - + Show all held locks - + Show stack traces - + Dump memory info - + Dump registers and flags - + Dump timers and clockevents - + Dump task list - + Dump uninterruptible tasks - + Dump ftrace buffer diff --git a/src/input/inputEvent.cpp b/src/input/inputEvent.cpp index b623281..cff1ac8 100644 --- a/src/input/inputEvent.cpp +++ b/src/input/inputEvent.cpp @@ -1,8 +1,17 @@ /* - * inputEvent.cpp - * - * Created on: 06.09.2010 - * Author: brs + # 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 - utility routines + # -------------------------------------------------------------------------- */ #include @@ -16,18 +25,29 @@ #include // We implement operators to serialize and load an event: +/** + * Serialize an input event to a \ref QDataStream. + */ QDataStream& operator <<(QDataStream& ostrm, InputEvent const& evt) { ostrm << evt._type << evt._code << evt._value; return ostrm; } +/** + * Load an input event from a \ref QDataStream. + */ QDataStream& operator >>(QDataStream& istrm, InputEvent& evt) { istrm >> evt._type >> evt._code >> evt._value; return istrm; } +/** + * Produce a string-encodeable representation of an input event. + * This consists of a base64-encoded binary representation as + * generated by \ref{operator<<(QDataStream&, InputEvent const&)}. + */ void eventToString(InputEvent const& evt, QString& str) { QByteArray ba; @@ -38,6 +58,10 @@ void eventToString(InputEvent const& evt, QString& str) str = QString::fromAscii(ba.toBase64()); } +/** + * Decode the string representation of an input-event produced by + * \ref eventToString. + */ bool eventFromString(QString const& str, InputEvent& evt) { // TODO This does not do proper error checking. Only use from trusted sources! diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h index f9d3225..afb33e5 100644 --- a/src/input/inputEvent.h +++ b/src/input/inputEvent.h @@ -21,15 +21,23 @@ #include // for translation #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; +/** + * The inputEvent class represents a single input event. + * An input event is any of: + * - Pressing or releasing a keyboard key, + * - Moving the mouse pointer, + * - Pressing or releasing a mouse button, + * - Special system events like "reboot". + * + * Events are described by the \ref type(), \ref code() + * and \ref value(). Possible values for \ref type() are given by + * the \c ET_* constants, and for \ref code() by the \c EC_* constants. + */ class InputEvent { private: @@ -59,109 +67,229 @@ public: { } - static InputEvent mouseMotion(quint16 x, quint16 y) - { - return InputEvent(ET_POINTER, 0, ((quint32)x << 16) | y); - } - - static quint16 mouseButtonsFromQt(int b); + /** \name Factory Functions */ + /* @{ */ + /** + * Generates an event for a mouse button press or release. + * \param button The button that caused this event, as defined by \ref Qt::MouseButton. + * \param buttons The buttons that were pressed at the moment the event was generated, as defined by \ref Qt::MouseButtons. + * If the event is a button press, this includes the pressed button. If it is a button release, + * it does not include the pressed button. + */ static InputEvent mousePressRelease(int button, int buttons); - static InputEvent keyboardPress(int key, int mods); - static InputEvent keyboardRelease(int key, int mods); - - static const quint16 ET_KEY = 0; - static const quint16 ET_BUTTON = 1; - static const quint16 ET_POINTER = 2; - static const quint16 ET_SPECIAL = 3; - static const quint16 EC_PRESS = 0; - static const quint16 EC_RELEASE = 1; - static const quint16 EC_REBOOT = 2; - static const quint16 EC_SYSRQ = 3; - static const quint16 EC_KILL_X = 4; - static const quint16 EC_SAY_HELLO = 5; //< for debugging purposes + /** + * Generates an event for a keyboard press. + * \param key The key code that generated this event, as defined by \ref Qt::Key. + * \param mods The modificator keys that were pressed at the moment the event was generated, + * as defined by \ref Qt::KeyboardModifiers. + */ + static InputEvent keyboardPress(int key, int mods); - typedef quint32 event_key; + /** + * Generates an event for a keyboard release. + * \param key The key code that generated this event, as defined by \ref Qt::Key. + * \param mods The modificator keys that were pressed at the moment the event was generated, + * as defined by \ref Qt::KeyboardModifiers. + */ + static InputEvent keyboardRelease(int key, int mods); - typedef quint32 event_key_modifiers; + /** + * Generates an event for a mouse pointer movement. + * \param x,y X and Y coordinates of the mouse pointer. + */ + static InputEvent mouseMotion(uint16_t x, uint16_t y) + { + return InputEvent(ET_POINTER, 0, ((uint32_t)x << 16) | y); + } - static const quint16 EB_LEFT = 1; - static const quint16 EB_MIDDLE = 2; - static const quint16 EB_RIGHT = 4; + /* @} */ + + /** \name Event Types */ + /* @{ */ + static const uint16_t ET_KEY = 0; /**< The event is related to the keyboard */ + static const uint16_t ET_BUTTON = 1; /**< The event is related to a mouse button */ + static const uint16_t ET_POINTER = 2; /**< The event is related to the mouse pointer */ + static const uint16_t ET_SPECIAL = 3; /**< The event is a special system event */ + /* @} */ + + /** \name Event Codes */ + /* @{ */ + static const uint16_t EC_PRESS = 0; /**< The event is a press (keyboard or mouse button) */ + static const uint16_t EC_RELEASE = 1; /**< The event is a release (keyboard or mouse button) */ + static const uint16_t EC_REBOOT = 2; /**< The event is a request to reboot (special system event) */ + static const uint16_t EC_SYSRQ = 3; /**< The event is a request to perform a Magic-SysRq function (special system event) */ + static const uint16_t EC_KILL_X = 4; /**< The event is a request to kill the X Server (special system event) */ + static const uint16_t EC_SAY_HELLO = 5; /**< The event is a request to write a line to the log file (special system event) */ + /* @} */ + + /** \name Mouse Button Flags */ + /* @{ */ + static const uint16_t EB_LEFT = 1; /**< The left mouse button */ + static const uint16_t EB_MIDDLE = 2; /**< The middle mouse button */ + static const uint16_t EB_RIGHT = 4; /**< The right mouse button */ + /* @} */ static const quint32 MODIFIER_MASK = 0x7e000000; - quint16 type() const + /** \name Event Decoding Functions */ + /* @{ */ + + /** + * Return the event type, as defined by the \c ET_* constants. + */ + uint16_t type() const { return _type; } - quint16 code() const + /** + * Return the event code, as defined by the \c EC_* constants. + */ + uint16_t code() const { return _code; } - quint32 value() const + /** + * Return the value associated with the event. The interpretation + * differs according to event type and code: + * - If the event type is \c ET_KEY, the value specifies which + * key and modifiers were pressed. + * - If the event type is \c ET_BUTTON, the value specifies which + * buttons were pressed and which button generated the event. + * - If the event type is \c ET_POINTER, the value specifies the + * screen coordinates the mouse has moved to. + * - If the event type is \c ET_SPECIAL, the interpretation + * depends on the event code. + */ + uint32_t value() const { return _value; } + /** + * True if the event is a keyboard event. + */ bool isKeyboard() const { return _type == ET_KEY; } + /** + * True if the event is a mouse button event. + */ bool isButton() const { return _type == ET_BUTTON; } + /** + * True if the event is a mouse pointer event. + */ bool isPointer() const { return _type == ET_POINTER; } + /** + * True if the event is a special system event. + */ bool isSpecial() const { return _type == ET_SPECIAL; } + /** + * True if the event is a keyboard or mouse button press event. + */ bool isPress() const { return _code == EC_PRESS; } + /** + * True if the event is a keyboard or mouse button release event. + */ bool isRelease() const { return _code == EC_RELEASE; } - quint16 pressedButton() const + /** + * The mouse button that generated this event. + * \return one of the \c EB_* constants. + */ + uint16_t pressedButton() const { assert(_type == ET_BUTTON); return (_value >> 16); } - quint16 heldButtons() const + /** + * The mouse buttons that were pressed at the moment the + * event was generated. + * \return a bitwise or of \c EB_* constants. + */ + uint16_t heldButtons() const { assert(_type == ET_BUTTON); return (_value & 0xffff); } - quint16 xCoord() const + /** + * The X coordinate the pointer was moved to. + */ + uint16_t xCoord() const { assert(_type == ET_POINTER); return (_value >> 16); } - quint16 yCoord() const + /** + * The Y coordinate the pointer was moved to. + */ + uint16_t yCoord() const { assert(_type == ET_POINTER); return (_value & 0xffff); } + /** + * The key that generated the event, as defined by \ref Qt::Key. + */ + quint32 qtKeysym() const + { + return _value & ~MODIFIER_MASK; + } + + /** + * The modifier keys that were pressed at the moment the event was generated, + * as defined by \ref Qt::KeyboardModifiers. + */ + quint32 qtModifiers() const + { + return _value & MODIFIER_MASK; + } + /* @} */ + + + /** \name Conversion Functions */ + /* @{ */ + + /** + * Converts mouse buttons from the bit flags defined by \ref Qt::MouseButton + * to their internal representation as defined in \ref "Mouse Button Flags". + * \returns A bitwise or of \c EB_* values. + */ + static uint16_t mouseButtonsFromQt(int b); + + /** + * Converts an event type as given by the \c ET_* constants to + * a string. + */ static QString typeToString(quint16 type) { switch(type) @@ -179,6 +307,10 @@ public: } } + /** + * Converts an event code as given by the \c EC_* constants to + * a string. + */ static QString codeToString(quint16 code) { switch(code) @@ -198,20 +330,15 @@ public: } } + /** + * Convert the event to a human-readable representation. + */ QString toString() const { return QString("%1:%2:%3").arg(typeToString(_type)).arg(codeToString(_code)).arg(_value, 8, 16, QLatin1Char('0')); } - quint32 qtKeysym() const - { - return _value & ~MODIFIER_MASK; - } - - quint32 qtModifiers() const - { - return _value & MODIFIER_MASK; - } + /* @} */ // We want to enable InputEvent as a translation context, so we fake the tr method: static QString tr(const char* string) @@ -220,23 +347,51 @@ public: } }; +/** + * The SpecialInputEventDescription class provides a human-readable + * name for special system events. + * + * To use the translations of these descriptions in your program, + * you need to link to the \c libpvsinput library and + * use the \ref USE_PVSINPUT_TRANSLATIONS macro in your + * \c main function. + */ struct SpecialInputEventDescription { + /** + * Initialize an instance of the SpecialInputEventDescription class. + * This is only meant to be called from describeSpecialEvents(). + * If you need to add more special event descriptions, do so from there. + */ SpecialInputEventDescription(quint16 type, quint16 code, quint32 value, QString const& description_) : type(type), code(code), value(value), description(description_) { } + /** \name InputEvent fields + * \see InputEvent + */ + /* @{ */ quint16 type; quint16 code; quint32 value; - QString description; + /* @} */ + + QString description; /**< Human-readable description for a special input event. Can be translated via the + InputEvent::tr(char const*) method. */ + /** + * Returns an \ref InputEvent corresponding to this description. + */ InputEvent toEvent() const { return InputEvent(type, code, value); } + /** + * Returns a \ref QList of all known special system events with their human-readable + * description. + */ static QList describeSpecialEvents(); }; diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index a2e943e..783640f 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -26,11 +26,10 @@ #include "detail/policyChain.h" #include "detail/systemTraits.h" -///////////////////////////////////////////////////////////////////////// -// InputEventContext: -// For handling access control, this specifies who sent the input event. -// This only makes sense in the privileged input handler chain. -///////////////////////////////////////////////////////////////////////// +/** + * For handling access control, this specifies who sent the input event. + * This only really makes sense in the privileged input handler chain. + */ struct InputEventContext { InputEventContext() @@ -38,11 +37,11 @@ struct InputEventContext hasBeenDenied = false; } - virtual pid_t senderPid() const = 0; - virtual uid_t senderUid() const = 0; - virtual gid_t senderGid() const = 0; + virtual pid_t senderPid() const = 0; /**< PID of the sending process */ + virtual uid_t senderUid() const = 0; /**< UID of the sending process */ + virtual gid_t senderGid() const = 0; /**< GID of the sending process */ - // Support the generation of meaningful log messages: + /** Support the generation of meaningful log messages. */ mutable bool hasBeenDenied; }; @@ -61,15 +60,21 @@ namespace input_policy // Policies are tied together using the detail::PolicyChain class. ///////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////// -// Security Policy: -// At the moment there are two security policies: -// 1. If the user is on a local seat, allow. If the user is privileged, -// allow. Else deny. -// 2. Allow everybody. -// Additional security policies can be added by following the example -// set by AllowLocalOrPrivileged -///////////////////////////////////////////////////////////////////////// +/** + * Security Policy. + * At the moment there are two security policies: + * -* If the user is on a local seat, allow. If the user is privileged, + * allow. Else deny. + * -* Allow everybody. + * + * Additional security policies can be added by following the example + * set by \ref AllowLocalOrPrivileged + * + * \param PolicyImpl The implementation class that security decisions + * should be delegated to. + * \see {AllowLocalOrPrivileged} + * \see {AllowEverybody} + */ template BEGIN_POLICY_CLASS(Security) { @@ -80,25 +85,43 @@ BEGIN_POLICY_CLASS(Security) } END_POLICY_CLASS +/** + * Check the default security model. + */ struct AllowLocalOrPrivileged { static bool allow(InputEventContext const*); }; +/** + * Do not restrict execution. + */ struct AllowEverybody { static bool allow(InputEventContext const*); }; +/** + * Shorthand for unrestricted execution. + */ typedef Security Unprivileged; -///////////////////////////////////////////////////////////////////////// -// System Requirements: -// At the moment, this is trivial, as PVS only runs on Linux. But, -// as porting efforts are already underway, we include the necessary -// machinery anyway. -///////////////////////////////////////////////////////////////////////// +/** + * System Requirements. + * + * At the moment, this is trivial, as PVS only runs on Linux. But, + * as porting efforts are already underway, we include the necessary + * machinery anyway. + * + * \param Trait... a list of system traits that need to be + * present in order for the handler that this policy is applied to + * to run. + */ +#ifdef DOXYGEN_RUNNING +template +#else template +#endif BEGIN_POLICY_CLASS(Require) { static const bool areSystemRequirementsFulfilled = @@ -109,19 +132,27 @@ BEGIN_POLICY_CLASS(Require) } END_POLICY_CLASS -///////////////////////////////////////////////////////////////////////// -// System Requirements: -// At the moment, this is trivial, as PVS only runs on Linux. But, -// as porting efforts are already underway, we include the necessary -// machinery anyway. -///////////////////////////////////////////////////////////////////////// +#ifndef DOXYGEN_RUNNING enum { HANDLER_CODE_DONT_CARE = 0xffff, HANDLER_VALUE_DONT_CARE = 0xffffffff }; - -struct T; - +#endif + +/** + * Event selection. + * + * This policy makes the handler it is applied to applicable if the + * template parameters \c EventType, \c EventCode and \c EventValue + * match the corresponding fields of the incoming \ref InputEvent. + * + * Can be applied multiple times, and will be combined by logical + * OR. + * + * \param EventType Match the \ref InputEvent::type() field. + * \param EventCode (optional:) Match the \ref InputEvent::code() field. + * \param EventValue (optional:) Match the \ref InputEvent::value() field. + */ template @@ -140,6 +171,7 @@ BEGIN_POLICY_CLASS(Match) }; END_POLICY_CLASS +#ifndef DOXYGEN_RUNNING namespace detail { @@ -177,46 +209,71 @@ struct InputEventHandlerPolicyBase } }; -} +} // namespace detail +#endif // DOXYGEN_RUNNING + } -///////////////////////////////////////////////////////////////////////// -// We want a nice non-generic base so we can make a list of polymorphic -// handlers. -// -// The actual handler class need to provide doHandle and can override -// allow and isApplicable. -///////////////////////////////////////////////////////////////////////// +/** + * Base class without template parameters to enable making a list of + * polymorphic event handlers. + * + * The actual handler class needs to provide \ref doHandle and can + * override \ref allow and \ref isApplicable. + * + * \note Do not derive from InputEventHandlerBase to implement + * new event handlers! Derive from InputEventHandler instead. + */ class InputEventHandlerBase { public: enum HandlerStatus { - HANDLER_MATCHED, - HANDLER_NOT_ALLOWED, - HANDLER_NOT_APPLICABLE + HANDLER_MATCHED, /**< The handler matched the input event and was executed. */ + HANDLER_NOT_ALLOWED, /**< Execution of the handler was prevented by security policy. */ + HANDLER_NOT_APPLICABLE /**< The handler did not match the input event. */ }; virtual void initialize() = 0; HandlerStatus handle(InputEvent const& evt, InputEventContext const* context = 0); protected: + /** + * Check security preconditions for the execution of this handler. + * This is normally handled by the \ref input_policy::Security policy. + */ virtual bool allow(InputEvent const& event, InputEventContext const* context = 0) = 0; + + /** + * Check if this handler can handle the incoming input event. + * This is normally handled by the \ref input_policy::Match policy. + */ virtual bool isApplicable(InputEvent const& event, InputEventContext const* context = 0) = 0; + + /** + * Actually handle the incoming event. + * It is assumed that all preconditions have been checked and the handler + * has been initialized at the point where this method is called. + */ virtual void doHandle(InputEvent const& event, InputEventContext const* context = 0) = 0; }; -///////////////////////////////////////////////////////////////////////// -// Now that the machinery is in place, we can finally define what it -// is like to be an input event handler: -///////////////////////////////////////////////////////////////////////// +/** + * Base class for input event handlers. + */ +#ifdef DOXYGEN_RUNNING +template +#else template +#endif class InputEventHandler : public InputEventHandlerBase { +#ifndef DOXYGEN_RUNNING protected: // instantiate our policy: typedef USE_POLICY(input_policy::detail::InputEventHandlerPolicyBase) policy_type; policy_type policy; +#endif public: void initialize() @@ -224,16 +281,11 @@ public: policy.initialize(); } - // Export this so the handler chain can decide whether to include this handler + /** Export this so the handler chain can decide whether to include this handler */ static const bool areSystemRequirementsFulfilled = policy_type::areSystemRequirementsFulfilled; protected: - typedef InputEventHandler super; - - // allow and isApplicable are actually provided by Policy. If the - // handler class wishes to override any of them, the policy implementation - // can be called by means of super. bool allow(InputEvent const&, InputEventContext const* context = 0) { return policy.allow(context); @@ -245,14 +297,19 @@ protected: } }; -///////////////////////////////////////////////////////////////////////// -// And we can chain input handlers together: -///////////////////////////////////////////////////////////////////////// +/** + * Chain \ref InputEventHandler instances together. + * The chain is also responsible for the creation of instances. + * + * \see privilegedInputEventHandlerChain.cpp + * \see unprivilegedInputEventHandlerChain.cpp + */ class InputEventHandlerChain { private: QList handlers; +#ifndef DOXYGEN_RUNNING // Implementation detail ///////////////////////////////////////////////////////////////////////// // We need to statically dispatch on a static member of HandlerType. // Unfortunately, we cannot specialize member functions of a template. @@ -280,18 +337,31 @@ private: { } }; +#endif // DOXYGEN_RUNNING public: - // Add an event handler to the chain. The argument is only for - // compilers which cannot handle template member functions - // correctly. + /** + * Add an event handler to the chain. + * + * \param fake_parameter The parameter is only for + * compilers which cannot handle template member functions + * correctly. + * \return A reference to the receiver, for invocation chaining. + * + * \note Do not pass a value to this function. The function + * handles creation of an instance itself. + */ template - InputEventHandlerChain& add(HandlerType const* = 0) + InputEventHandlerChain& add(HandlerType const* fake_parameter = 0) { ConditionallyAppend::doIt(this); return *this; } + /** + * Call \ref InputEventHandlerBase::initialize() on all + * handlers in the chain. + */ void initialize() { QListIterator i(handlers); @@ -301,6 +371,12 @@ public: } } + /** + * Handle an input event. All handlers in the chain are tried + * in the order they were added, until one handler's + * implementation of InputEventHandlerBase::handle() returns + * InputEventHandlerBase::HANDLER_MATCHED. + */ void handle(InputEvent const& event, InputEventContext const* context = 0) { QListIterator i(handlers); diff --git a/src/input/inputHandlerChains.h b/src/input/inputHandlerChains.h index a91e605..773303b 100644 --- a/src/input/inputHandlerChains.h +++ b/src/input/inputHandlerChains.h @@ -19,7 +19,22 @@ #include "inputEventHandler.h" +/** \defgroup iehc {Input Event Handler Chains} */ +/* @{ */ + +/** + * Make an instance of InputEventHandlerChain that handles + * unprivileged input events, with a PrivilegedInputForwarder + * instance at the end. + */ InputEventHandlerChain makeUnprivilegedInputEventHandlerChain(); + +/** + * Make an instance of InputEventHandlerChain that handles + * privileged events. + */ InputEventHandlerChain makePrivilegedInputEventHandlerChain(); +/* @} */ + #endif /* INPUTHANDLERCHAIN_H_ */ diff --git a/src/input/killX11Handler.h b/src/input/killX11Handler.h index 77d9fdb..6501d5d 100644 --- a/src/input/killX11Handler.h +++ b/src/input/killX11Handler.h @@ -20,11 +20,22 @@ #include #include "inputEventHandler.h" +/** + * Kills the X11 Server on Linux. + */ class KillX11Handler : public InputEventHandler< input_policy::Match, input_policy::Require > { public: + + /** + * Kills the X11 Server on Linux. + * + * The X11-Server is found by asking ConsoleKit for its controlling + * tty. The sole process that has an open file descriptor referencing it + * must be the X Server. It is then sent SIGTERM. + */ void doHandle(InputEvent const&, InputEventContext const*); }; diff --git a/src/input/logNonMatchingHandler.h b/src/input/logNonMatchingHandler.h index 3403640..ab95bce 100644 --- a/src/input/logNonMatchingHandler.h +++ b/src/input/logNonMatchingHandler.h @@ -19,6 +19,9 @@ #include "inputEventHandler.h" +/** + * Send a qWarning() for any InputEvent that does not have a matching handler. + */ class LogNonMatchingHandler : public InputEventHandler { public: diff --git a/src/input/magicSysRqHandler.h b/src/input/magicSysRqHandler.h index ba02997..5afe259 100644 --- a/src/input/magicSysRqHandler.h +++ b/src/input/magicSysRqHandler.h @@ -19,16 +19,20 @@ #include "inputEventHandler.h" +/** + * Emulate the magic SysRq-Key on Linux. + */ class MagicSysRqHandler : public InputEventHandler< input_policy::Match, input_policy::Require > { public: - void doHandle(InputEvent const& evt, InputEventContext const* ctx); -// static void describeInto(QList& list) -// { -// } + /** + * Send the least significant byte of \c evt's InputEvent::value() + * to the magic \c /proc/sysrq-trigger file. + */ + void doHandle(InputEvent const& evt, InputEventContext const* ctx); }; #endif /* MAGICSYSRQHANDLER_H_ */ diff --git a/src/input/privilegedHandlerForwarder.h b/src/input/privilegedHandlerForwarder.h index f5a6cc3..ea3326a 100644 --- a/src/input/privilegedHandlerForwarder.h +++ b/src/input/privilegedHandlerForwarder.h @@ -19,12 +19,25 @@ #include "inputEventHandler.h" +/** + * Forward the incoming InputEvent to \c pvsprivinputd. + */ class PrivilegedHandlerForwarder : public InputEventHandler< input_policy::Require, input_policy::Unprivileged> { public: + + /** + * Forward \c evt to \c pvsprivinputd, taking care that + * the security context is correctly sent. + */ void doHandle(InputEvent const& evt, InputEventContext const* = 0); + + /** + * Read the address of \c pvsprivinputd's listening socket + * from its configuration and connect to it. + */ void initialize(); private: diff --git a/src/input/pvsCheckPrivileges.h b/src/input/pvsCheckPrivileges.h index 92c68fe..37c4c04 100644 --- a/src/input/pvsCheckPrivileges.h +++ b/src/input/pvsCheckPrivileges.h @@ -26,6 +26,9 @@ #include #include "inputEventHandler.h" +/** + * Store the information in an InputEventContext as a plain old datatype. + */ struct CachedInputContext { CachedInputContext(InputEventContext const* source) @@ -69,16 +72,37 @@ uint qHash(CachedInputContext const& p); class QFileSystemWatcher; +/** + * Check user privileges and handle communications with ConsoleKit and PolicyKit. + * This is a singleton class. + */ class PVSCheckPrivileges : public QObject { Q_OBJECT public: + /** + * SessionKind distinguishes between local and remote users. + */ typedef enum { - SESSION_LOCAL, - SESSION_NONLOCAL, - SESSION_LOOKUP_FAILURE, - SESSION_UNKNOWN + SESSION_LOCAL, /**< User is local */ + SESSION_NONLOCAL, /**< User is remote */ + SESSION_LOOKUP_FAILURE, /**< Failure to look up whether the user is local or remote */ + SESSION_UNKNOWN /**< User session kind not (yet) known */ } SessionKind; + + /** + * UserPrivilege distinguishes between privileged and unprivileged users. + */ + typedef enum { + USER_PRIVILEGED, /**< User is privileged */ + USER_UNPRIVILEGED, /**< User is unprivileged */ + USER_LOOKUP_FAILURE, /**< Failure to look up whether the user is privileged or unprivileged */ + USER_UNKNOWN /**< User privilege level not (yet) known */ + } UserPrivilege; + + /** \name Conversion Functions */ + /* @{ */ + static QString toString(SessionKind k) { switch(k) @@ -91,12 +115,6 @@ public: } } - typedef enum { - USER_PRIVILEGED, - USER_UNPRIVILEGED, - USER_LOOKUP_FAILURE, - USER_UNKNOWN - } UserPrivilege; static QString toString(UserPrivilege k) { switch(k) @@ -109,13 +127,40 @@ public: } } + /* @} */ + + /** \name Singleton pattern */ + /* @{ */ + + /** Retrieve the singleton instance. */ static PVSCheckPrivileges* instance(); + + /** Delete the singleton instance. */ static void deleteInstance(); + /* @} */ + + /** \name Privilege Checks */ + /* @{ */ + + /** Check for a minimum SessionKind level. \return true if the requirement is fulfilled. */ bool require(SessionKind sessionKind, CachedInputContext const& sender); + + /** Check for a minimum UserPrivilege level. \return true if the requirement is fulfilled. */ bool require(UserPrivilege userPrivilege, CachedInputContext const& sender); + + /** Check for a minimum SessionKind and UserPrivilege level. \return true if both requirements are fulfilled. */ bool require(SessionKind sessionKind, UserPrivilege userPrivilege, CachedInputContext const& sender); + + /* @} */ + + /** \name Session Information */ + /* @{ */ + + /** Retrieve the name of the user's X session, according to ConsoleKit. */ QString getX11SessionName(CachedInputContext const& sender); + + /** Retrieve the TTY device of the user's X session, according to ConsoleKit. */ QString getX11DisplayDevice(CachedInputContext const& sender); public slots: diff --git a/src/input/pvsPrivInputHandler.h b/src/input/pvsPrivInputHandler.h index e82787b..015dfa1 100644 --- a/src/input/pvsPrivInputHandler.h +++ b/src/input/pvsPrivInputHandler.h @@ -24,10 +24,19 @@ class QSocketNotifier; +/** + * Handle socket communication with instances of the PVS Client Daemon. + * + * \note This runs in the context of a Qt main loop. It does not start + * a handler thread. + */ class PVSPrivInputHandler : public QObject { Q_OBJECT public: + /** + * Listen for InputEvents on file descriptor \c fd. + */ PVSPrivInputHandler(int fd, QObject* parent = 0); virtual ~PVSPrivInputHandler(); diff --git a/src/input/pvsPrivInputSignalHandler.h b/src/input/pvsPrivInputSignalHandler.h index cb75c86..bc549ec 100644 --- a/src/input/pvsPrivInputSignalHandler.h +++ b/src/input/pvsPrivInputSignalHandler.h @@ -19,6 +19,19 @@ #include +/** + * Handle signals. + * + * This class reads \c int values from a file descriptor and dispatches sends + * Qt signals according to the \c SIG... value the integer represents. + * The purpose of this mechanism is to integrate (asynchronous) Unix signal + * handling into the synchronous event-driven Qt main loop. The main() function + * is expected to open a socket pair and install handlers for all relevant signals + * that simply write the number of the signal to that pipe. + * + * If allowUnauthenticatedKilling() has not been called, this class only accepts + * signal numbers that are sent by the same process. + */ class PVSPrivInputSignalHandler : public QObject { Q_OBJECT @@ -28,16 +41,20 @@ public: { } + /** If \c value is \c true, allow sending signal numbers from other processes. */ void allowUnauthenticatedKilling(bool value) { _allowUnauthenticatedKilling = value; } public slots: + /** Connect this slot to a \c QSocketNotifier's \c activated(int) signal. */ void signalReceived(int sigfd); signals: + /** SIGTERM */ void terminate(); + /** SIGHUP */ void reloadConfiguration(); private: diff --git a/src/input/pvsPrivInputSocket.h b/src/input/pvsPrivInputSocket.h index 447360b..a57d730 100644 --- a/src/input/pvsPrivInputSocket.h +++ b/src/input/pvsPrivInputSocket.h @@ -24,14 +24,52 @@ class QSettings; +/** + * Load \c pvsprivinputd's configuration. This keeps a cached copy. + */ QSettings* pvsPrivInputGetSettings(); + +/** + * Update the cached configuration copy kept by pvsPrivInputGetSettings(). + */ QSettings* pvsPrivInputReopenSettings(); + +/** + * Hardcoded to \c /etc/pvsprivinputd.conf + */ QString pvsPrivInputGetSettingsPath(); + +/** + * Retrieve the path at which \c pvsprivinputd listens for datagrams from + * its configuration. + */ QString pvsPrivInputGetSocketAddress(); + +/** + * Enable the receiving of sender credentials on a \c unix(7) socket. + */ bool pvsPrivInputEnableReceiveCredentials(int sock); + +/** + * Make a \c unix(7) socket that is suitable for sending authenticated + * datagrams to \c pvsprivinputd. + */ int pvsPrivInputMakeClientSocket(); + +/** + * Make a listening \c unix(7) socket at the address specified by + * pvsPrivInputGetSocketAddress() that receives sender credentials. + */ int pvsPrivInputMakeServerSocket(); + +/** + * Send an authenticated message on a \c unix(7) socket. + */ bool pvsPrivInputSendMessage(int sock, void* buf, size_t len, int* err = 0); + +/** + * Receive an authenticated message on a \c unix(7) socket. + */ bool pvsPrivInputRecvMessage(int sock, void* buf, size_t& len, pid_t& pid, uid_t& uid, gid_t& gid, int* err = 0); #endif /* PVSPRIVINPUTSOCKET_H_ */ diff --git a/src/input/pvsSyslog.h b/src/input/pvsSyslog.h index 8c9591a..36ee2e0 100644 --- a/src/input/pvsSyslog.h +++ b/src/input/pvsSyslog.h @@ -20,6 +20,9 @@ #include #include +/** + * Listen on a socket or a pipe and redirect input lines to a child class. + */ class PVSLogRedirector : public QObject { Q_OBJECT @@ -33,6 +36,9 @@ private: QByteArray _buf; }; +/** + * Redirect log lines to a Unix syslog service. + */ class PVSSyslogRedirector : public PVSLogRedirector { public: @@ -46,6 +52,9 @@ protected: class QFile; class QTextStream; +/** + * Redirect log lines to a file. + */ class PVSLogfileRedirector : public PVSLogRedirector { public: diff --git a/src/input/rebootSystemHandler.h b/src/input/rebootSystemHandler.h index 4920452..357dcad 100644 --- a/src/input/rebootSystemHandler.h +++ b/src/input/rebootSystemHandler.h @@ -20,10 +20,16 @@ #include #include "inputEventHandler.h" +/** + * Reboot a Linux system. + */ class RebootLinuxSystemHandler : public InputEventHandler< input_policy::Require > { public: + /** + * Send SIGINT to the process with PID 1. + */ void doHandle(InputEvent const&, InputEventContext const*); }; diff --git a/src/input/sayHelloHandler.h b/src/input/sayHelloHandler.h index 00463ca..24118cf 100644 --- a/src/input/sayHelloHandler.h +++ b/src/input/sayHelloHandler.h @@ -20,6 +20,10 @@ #include #include "inputEventHandler.h" +/** + * Write a line to the log stating the PID, UID and GID of the + * PVS Client Daemon. + */ class SayHelloHandler : public InputEventHandler< input_policy::Match, input_policy::Security > diff --git a/src/input/x11FakeKeyboardHandler.h b/src/input/x11FakeKeyboardHandler.h index 6c18dce..7f2d12e 100644 --- a/src/input/x11FakeKeyboardHandler.h +++ b/src/input/x11FakeKeyboardHandler.h @@ -19,6 +19,13 @@ #include "inputEventHandler.h" +/** + * Send keyboard events via the XTest extension. + * This is unbelievably brittle in the face of non-system-standard keyboard + * mappings. Every Linux distribution seems to set up XTest handling in + * a different way. The code goes out of its way to find a usable mapping + * and use it. + */ class X11FakeKeyboardHandler : public InputEventHandler< input_policy::Match, input_policy::Match, diff --git a/src/input/x11FakeMouseHandler.h b/src/input/x11FakeMouseHandler.h index 9d41c31..2700829 100644 --- a/src/input/x11FakeMouseHandler.h +++ b/src/input/x11FakeMouseHandler.h @@ -19,6 +19,9 @@ #include "inputEventHandler.h" +/** + * Send mouse button events via the XTest extension. + */ class X11FakeMouseButtonHandler : public InputEventHandler< input_policy::Match, input_policy::Require, @@ -28,6 +31,9 @@ public: void doHandle(InputEvent const&, InputEventContext const* = 0); }; +/** + * Send mouse pointer events via the XTest extension. + */ class X11FakeMouseMovementHandler : public InputEventHandler< input_policy::Match, input_policy::Require, diff --git a/src/input/x11InputUtils.h b/src/input/x11InputUtils.h index 9c85d09..94b3116 100644 --- a/src/input/x11InputUtils.h +++ b/src/input/x11InputUtils.h @@ -19,6 +19,9 @@ #include +/** + * Store the X11 Display. + */ struct X11InputUtils { static void setDisplay(Display*); static Display* display(); -- cgit v1.2.3-55-g7522 From e6077e7c5f8ddce8d6db0e427ebc6c22cd61c3ce Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Thu, 4 Nov 2010 01:00:19 +0100 Subject: Remove LaTeX build artifacts. They do not belong in the tree and make merging needlessly difficult. --- doc/LaTeX/pvs-doc.aux | 140 ------- doc/LaTeX/pvs-doc.idx | 34 -- doc/LaTeX/pvs-doc.log | 1065 ------------------------------------------------- doc/LaTeX/pvs-doc.out | 56 --- doc/LaTeX/pvs-doc.pdf | Bin 2362812 -> 0 bytes doc/LaTeX/pvs-doc.toc | 65 --- 6 files changed, 1360 deletions(-) delete mode 100644 doc/LaTeX/pvs-doc.aux delete mode 100644 doc/LaTeX/pvs-doc.idx delete mode 100644 doc/LaTeX/pvs-doc.log delete mode 100644 doc/LaTeX/pvs-doc.out delete mode 100644 doc/LaTeX/pvs-doc.pdf delete mode 100644 doc/LaTeX/pvs-doc.toc diff --git a/doc/LaTeX/pvs-doc.aux b/doc/LaTeX/pvs-doc.aux deleted file mode 100644 index 604ccf1..0000000 --- a/doc/LaTeX/pvs-doc.aux +++ /dev/null @@ -1,140 +0,0 @@ -\relax -\catcode`"\active -\ifx\hyper@anchor\@undefined -\global \let \oldcontentsline\contentsline -\gdef \contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}} -\global \let \oldnewlabel\newlabel -\gdef \newlabel#1#2{\newlabelxx{#1}#2} -\gdef \newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} -\AtEndDocument{\let \contentsline\oldcontentsline -\let \newlabel\oldnewlabel} -\else -\global \let \hyper@last\relax -\fi - -\select@language{ngerman} -\@writefile{toc}{\select@language{ngerman}} -\@writefile{lof}{\select@language{ngerman}} -\@writefile{lot}{\select@language{ngerman}} -\@writefile{toc}{\contentsline {chapter}{Inhaltsverzeichnis}{I}{section*.1}} -\@writefile{toc}{\contentsline {part}{I\hspace {1em}Idee und \IeC {\"U}berblick}{1}{part.1}} -\@writefile{toc}{\contentsline {chapter}{\numberline {1}Idee}{3}{chapter.1}} -\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\addvspace {10\p@ }} -\newlabel{einleitung}{{1}{3}{Idee\relax }{chapter.1}{}} -\@writefile{lof}{\contentsline {figure}{\numberline {1.1}{\ignorespaces Student Control Panel des Edubuntu-Pakets, welches im Umfeld von Linux-Terminalservern eingesetzt werden kann.}}{3}{figure.1.1}} -\newlabel{uscp}{{1.1}{3}{Student Control Panel des Edubuntu-Pakets, welches im Umfeld von Linux-Terminalservern eingesetzt werden kann.\label {uscp}\relax }{figure.1.1}{}} -\@writefile{toc}{\contentsline {chapter}{\numberline {2}Funktionen eines Software-Video-Switchs}{5}{chapter.2}} -\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\addvspace {10\p@ }} -\newlabel{funktionen}{{2}{5}{Funktionen eines Software-Video-Switchs\relax }{chapter.2}{}} -\@writefile{toc}{\contentsline {section}{\numberline {2.1}W\IeC {\"u}nschenswerte Basisfunktionen}{5}{section.2.1}} -\@writefile{lof}{\contentsline {figure}{\numberline {2.1}{\ignorespaces Student Control Panel des Edubuntu-Pakets, welches im Umfeld von Linux-Terminalservern eingesetzt werden kann.}}{5}{figure.2.1}} -\newlabel{uscp}{{2.1}{5}{Student Control Panel des Edubuntu-Pakets, welches im Umfeld von Linux-Terminalservern eingesetzt werden kann.\label {uscp}\relax }{figure.2.1}{}} -\@writefile{toc}{\contentsline {section}{\numberline {2.2}Funktionserweiterungen}{5}{section.2.2}} -\@writefile{toc}{\contentsline {chapter}{\numberline {3}Aufbau dieses Handbuchs}{7}{chapter.3}} -\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\addvspace {10\p@ }} -\newlabel{aufbau}{{3}{7}{Aufbau dieses Handbuchs\relax }{chapter.3}{}} -\@writefile{toc}{\contentsline {section}{\numberline {3.1}Heraushebungen und Formatierungen}{7}{section.3.1}} -\@writefile{toc}{\contentsline {part}{II\hspace {1em}Bedienungsanleitung}{9}{part.2}} -\@writefile{toc}{\contentsline {chapter}{\numberline {4}PVS-Steuerkonsole}{11}{chapter.4}} -\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\addvspace {10\p@ }} -\@writefile{toc}{\contentsline {section}{\numberline {4.1}Allgemein}{11}{section.4.1}} -\@writefile{lof}{\contentsline {figure}{\numberline {4.1}{\ignorespaces Die PVS-Steuerkonsole}}{11}{figure.4.1}} -\newlabel{fig:pvsmgra}{{4.1}{11}{Die PVS-Steuerkonsole\relax }{figure.4.1}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.1}Die Client-Liste}{12}{subsection.4.1.1}} -\newlabel{clientliste}{{4.1.1}{12}{Die Client-Liste\relax }{subsection.4.1.1}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.2}Die VNC-Frames}{12}{subsection.4.1.2}} -\@writefile{lof}{\contentsline {figure}{\numberline {4.2}{\ignorespaces Dummy und Nicht Dummy Frames}}{13}{figure.4.2}} -\newlabel{fig:pvsdummy}{{4.2}{13}{Dummy und Nicht Dummy Frames\relax }{figure.4.2}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {4.1.3}Tastenk\IeC {\"u}rzel f\IeC {\"u}r PVS-Server}{14}{subsection.4.1.3}} -\newlabel{Taste}{{4.1.3}{14}{Tastenkürzel für PVS-Server\relax }{subsection.4.1.3}{}} -\@writefile{toc}{\contentsline {chapter}{\numberline {5}PVS-Client}{15}{chapter.5}} -\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\addvspace {10\p@ }} -\@writefile{lof}{\contentsline {figure}{\numberline {5.1}{\ignorespaces Toolbar des PVS-Clients}}{16}{figure.5.1}} -\newlabel{png:toolbar}{{5.1}{16}{Toolbar des PVS-Clients\relax }{figure.5.1}{}} -\@writefile{toc}{\contentsline {section}{\numberline {5.1}Chat}{16}{section.5.1}} -\@writefile{lof}{\contentsline {figure}{\numberline {5.2}{\ignorespaces Chat-Dialog des PVS-Clients}}{17}{figure.5.2}} -\newlabel{png:chat}{{5.2}{17}{Chat-Dialog des PVS-Clients\relax }{figure.5.2}{}} -\@writefile{toc}{\contentsline {section}{\numberline {5.2}Konfiguration}{17}{section.5.2}} -\@writefile{lof}{\contentsline {figure}{\numberline {5.3}{\ignorespaces Konfigurationsdialog des PVS-Clients}}{18}{figure.5.3}} -\newlabel{png:config}{{5.3}{18}{Konfigurationsdialog des PVS-Clients\relax }{figure.5.3}{}} -\@writefile{toc}{\contentsline {part}{III\hspace {1em}Entwicklerdokumentation}{19}{part.3}} -\@writefile{toc}{\contentsline {chapter}{\numberline {6}Erzeugen und Installieren der Applikation}{21}{chapter.6}} -\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\addvspace {10\p@ }} -\@writefile{toc}{\contentsline {section}{\numberline {6.1}Voraussetzungen}{21}{section.6.1}} -\@writefile{toc}{\contentsline {section}{\numberline {6.2}Kompilieren aus Quellen}{22}{section.6.2}} -\@writefile{toc}{\contentsline {section}{\numberline {6.3}Installation}{22}{section.6.3}} -\@writefile{toc}{\contentsline {chapter}{\numberline {7}Eingesetzte GUI-Bibliothek}{25}{chapter.7}} -\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\addvspace {10\p@ }} -\@writefile{toc}{\contentsline {section}{\numberline {7.1}Internationalisierung}{25}{section.7.1}} -\@writefile{toc}{\contentsline {chapter}{\numberline {8}Aufbau und Funktionsweise des PVS}{27}{chapter.8}} -\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\addvspace {10\p@ }} -\@writefile{toc}{\contentsline {section}{\numberline {8.1}Einzelne Komponenten}{27}{section.8.1}} -\@writefile{toc}{\contentsline {subsection}{\numberline {8.1.1}Zuordnung von Konsole und Clients}{27}{subsection.8.1.1}} -\@writefile{toc}{\contentsline {subsubsection}{Absicherung und Verifikation der Identit\IeC {\"a}t}{27}{section*.4}} -\@writefile{toc}{\contentsline {subsubsection}{Generierung von Sitzungsnamen}{28}{section*.5}} -\@writefile{toc}{\contentsline {section}{\numberline {8.2}\IeC {\"U}berblick \IeC {\"u}ber Aktivit\IeC {\"a}ten auf Clients}{29}{section.8.2}} -\@writefile{toc}{\contentsline {subsection}{\numberline {8.2.1}Projektion an Alle}{29}{subsection.8.2.1}} -\@writefile{toc}{\contentsline {subsection}{\numberline {8.2.2}Projektion eines Clients auf dem Beamer}{29}{subsection.8.2.2}} -\@writefile{toc}{\contentsline {subsection}{\numberline {8.2.3}Chat- und Informationskanal}{30}{subsection.8.2.3}} -\@writefile{toc}{\contentsline {section}{\numberline {8.3}Netzwerkkommunikation}{32}{section.8.3}} -\@writefile{toc}{\contentsline {subsection}{\numberline {8.3.1}PVS-Protokoll}{32}{subsection.8.3.1}} -\@writefile{toc}{\contentsline {subsection}{\numberline {8.3.2}PVS-Messages}{33}{subsection.8.3.2}} -\newlabel{pvs-msg-liste}{{8.3.2}{34}{PVS-Messages\relax }{subsection.8.3.2}{}} -\@writefile{lot}{\contentsline {table}{\numberline {8.1}{\ignorespaces Liste der PVS Messages}}{34}{table.8.1}} -\newlabel{tab:messagelist}{{8.1}{34}{Liste der PVS Messages\relax }{table.8.1}{}} -\@writefile{toc}{\contentsline {chapter}{\numberline {9}PVS-Steuerkonsole}{35}{chapter.9}} -\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\addvspace {10\p@ }} -\@writefile{toc}{\contentsline {section}{\numberline {9.1}pvsmgr in Qt}{35}{section.9.1}} -\@writefile{toc}{\contentsline {section}{\numberline {9.2}GUI Server-Konsole}{35}{section.9.2}} -\@writefile{toc}{\contentsline {subsection}{\numberline {9.2.1}Die Architektur}{35}{subsection.9.2.1}} -\@writefile{lof}{\contentsline {figure}{\numberline {9.1}{\ignorespaces pvsmgr-Architektur}}{36}{figure.9.1}} -\newlabel{fig:pvsmgr}{{9.1}{36}{pvsmgr-Architektur\relax }{figure.9.1}{}} -\@writefile{lof}{\contentsline {figure}{\numberline {9.2}{\ignorespaces Abh{\"a}ngigkeitsdiagram: MainWindow}}{37}{figure.9.2}} -\newlabel{fig:mainwindow}{{9.2}{37}{Abh{\"a}ngigkeitsdiagram: MainWindow\relax }{figure.9.2}{}} -\@writefile{toc}{\contentsline {subsubsection}{Clientliste-Ansicht}{38}{section*.6}} -\@writefile{lof}{\contentsline {figure}{\numberline {9.3}{\ignorespaces Abh{\"a}ngigkeitsdiagramm der ConnectionList-Klasse}}{38}{figure.9.3}} -\newlabel{fig:ConnectionList}{{9.3}{38}{Abh{\"a}ngigkeitsdiagramm der ConnectionList-Klasse\relax }{figure.9.3}{}} -\@writefile{toc}{\contentsline {subsubsection}{VNC-Ansicht}{39}{section*.7}} -\@writefile{lof}{\contentsline {figure}{\numberline {9.4}{\ignorespaces Abh{\"a}ngigkeitsdiagramm der ConnectionFrame-Klasse}}{39}{figure.9.4}} -\newlabel{fig:Connectionframe}{{9.4}{39}{Abh{\"a}ngigkeitsdiagramm der ConnectionFrame-Klasse\relax }{figure.9.4}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {9.2.2}Client-Seite}{40}{subsection.9.2.2}} -\@writefile{toc}{\contentsline {subsection}{\numberline {9.2.3}Server-Seite}{40}{subsection.9.2.3}} -\@writefile{toc}{\contentsline {section}{\numberline {9.3}Verbindungsverwaltung und Projektion}{41}{section.9.3}} -\@writefile{toc}{\contentsline {subsection}{\numberline {9.3.1}Projektion}{41}{subsection.9.3.1}} -\newlabel{pvs-console-projection}{{9.3.1}{41}{Projektion\relax }{subsection.9.3.1}{}} -\@writefile{toc}{\contentsline {subsubsection}{Qualit\IeC {\"a}tsoptionen}{42}{section*.8}} -\newlabel{pvs-console-quality}{{9.3.1}{42}{Qualitätsoptionen\relax }{section*.8}{}} -\@writefile{toc}{\contentsline {subsection}{\numberline {9.3.2}Remote Help}{42}{subsection.9.3.2}} -\@writefile{toc}{\contentsline {chapter}{\numberline {10}PVS-Client}{43}{chapter.10}} -\@writefile{lof}{\addvspace {10\p@ }} -\@writefile{lot}{\addvspace {10\p@ }} -\@writefile{lof}{\contentsline {figure}{\numberline {10.1}{\ignorespaces Back- und Frontend des PVS-Clients kommunizieren \IeC {\"u}ber D-Bus}}{43}{figure.10.1}} -\newlabel{pdf:dbus}{{10.1}{43}{Back- und Frontend des PVS-Clients kommunizieren über D-Bus\relax }{figure.10.1}{}} -\@writefile{toc}{\contentsline {section}{\numberline {10.1}Grafische Benutzeroberfl\IeC {\"a}che}{44}{section.10.1}} -\@writefile{toc}{\contentsline {section}{\numberline {10.2}User-Interface f\IeC {\"u}r Benutzerkonfiguration}{45}{section.10.2}} -\@writefile{toc}{\contentsline {section}{\numberline {10.3}Darstellung von VNC-Datenstr\IeC {\"o}men}{45}{section.10.3}} -\newlabel{pvsclient-datenstrom}{{10.3}{45}{Darstellung von VNC-Datenströmen\relax }{section.10.3}{}} -\@writefile{toc}{\contentsline {section}{\numberline {10.4}Chat-Interface}{46}{section.10.4}} -\@writefile{toc}{\contentsline {section}{\numberline {10.5}Datei\IeC {\"u}bertragung und Interface}{46}{section.10.5}} -\@writefile{toc}{\contentsline {section}{\numberline {10.6}VNC Server}{47}{section.10.6}} -\@writefile{toc}{\contentsline {subsection}{\numberline {10.6.1}Vergleich von VNC Servern}{48}{subsection.10.6.1}} -\@writefile{toc}{\contentsline {paragraph}{Vino}{48}{section*.9}} -\@writefile{toc}{\contentsline {paragraph}{Krfb}{48}{section*.10}} -\@writefile{toc}{\contentsline {paragraph}{x11vnc}{49}{section*.11}} -\@writefile{toc}{\contentsline {subsection}{\numberline {10.6.2}VNC Script}{50}{subsection.10.6.2}} -\newlabel{pvs-vnc-script}{{10.6.2}{50}{VNC Script\relax }{subsection.10.6.2}{}} -\@writefile{toc}{\contentsline {section}{\numberline {10.7}VNC Viewer}{50}{section.10.7}} -\@writefile{toc}{\contentsline {subsection}{\numberline {10.7.1}Tastatur und Maussteuerung}{51}{subsection.10.7.1}} -\newlabel{pvsclient-remotehelp}{{10.7.1}{51}{Tastatur und Maussteuerung\relax }{subsection.10.7.1}{}} -\@writefile{toc}{\contentsline {section}{\numberline {10.8}Signalbehandlung}{52}{section.10.8}} -\@writefile{toc}{\contentsline {part}{IV\hspace {1em}Anhang}{53}{part.4}} -\newlabel{png:kd}{{IV}{55}{Anhang\relax }{part.4}{}} diff --git a/doc/LaTeX/pvs-doc.idx b/doc/LaTeX/pvs-doc.idx deleted file mode 100644 index 2548b25..0000000 --- a/doc/LaTeX/pvs-doc.idx +++ /dev/null @@ -1,34 +0,0 @@ -\indexentry{Einleitung|hyperpage}{3} -\indexentry{Video Switch|hyperpage}{3} -\indexentry{Laptop|hyperpage}{3} -\indexentry{VGA|hyperpage}{3} -\indexentry{DVI|hyperpage}{3} -\indexentry{Klassenraum|hyperpage}{3} -\indexentry{Student Control Panel|hyperpage}{3} -\indexentry{Idee|hyperpage}{3} -\indexentry{Funktion|hyperpage}{5} -\indexentry{Schreibweise|hyperpage}{7} -\indexentry{Kommando|hyperpage}{7} -\indexentry{Quelltext|hyperpage}{7} -\indexentry{Konfiguration|hyperpage}{7} -\indexentry{Formatierung|hyperpage}{7} -\indexentry{Verzeichnis|hyperpage}{7} -\indexentry{Dateiname|hyperpage}{7} -\indexentry{Installieren|hyperpage}{21} -\indexentry{Paket!RPM|hyperpage}{22} -\indexentry{Paket!DPKG|hyperpage}{22} -\indexentry{QT|hyperpage}{25} -\indexentry{GUI|hyperpage}{25} -\indexentry{Internationalisierung|hyperpage}{25} -\indexentry{Aufbau|hyperpage}{27} -\indexentry{Funktionsweise|hyperpage}{27} -\indexentry{Konzept|hyperpage}{27} -\indexentry{Komponenten|hyperpage}{27} -\indexentry{Projektion|hyperpage}{29} -\indexentry{Beamer|hyperpage}{29} -\indexentry{Chat|hyperpage}{30} -\indexentry{Netzwerkkommunikation|hyperpage}{32} -\indexentry{Protokoll!PVS|hyperpage}{32} -\indexentry{Protokoll|hyperpage}{32} -\indexentry{Message!PVS|hyperpage}{33} -\indexentry{Message|hyperpage}{33} diff --git a/doc/LaTeX/pvs-doc.log b/doc/LaTeX/pvs-doc.log deleted file mode 100644 index e634d13..0000000 --- a/doc/LaTeX/pvs-doc.log +++ /dev/null @@ -1,1065 +0,0 @@ -This is pdfTeX, Version 3.1415926-1.40.10 (TeX Live 2009/Debian) (format=pdflatex 2010.9.4) 2 OCT 2010 17:01 -entering extended mode - restricted \write18 enabled. - %&-line parsing enabled. -**pvs-doc.tex -(./pvs-doc.tex -LaTeX2e <2009/09/24> -Babel and hyphenation patterns for english, usenglishmax, dumylang, noh -yphenation, loaded. -\@indexfile=\write3 -\openout3 = `pvs-doc.idx'. - -Writing index file pvs-doc.idx -(./mystyle-pdf.tex (/usr/share/texmf-texlive/tex/latex/base/book.cls -Document Class: book 2007/10/19 v1.4h Standard LaTeX document class -(/usr/share/texmf-texlive/tex/latex/base/bk12.clo -File: bk12.clo 2007/10/19 v1.4h Standard LaTeX file (size option) -) -\c@part=\count79 -\c@chapter=\count80 -\c@section=\count81 -\c@subsection=\count82 -\c@subsubsection=\count83 -\c@paragraph=\count84 -\c@subparagraph=\count85 -\c@figure=\count86 -\c@table=\count87 -\abovecaptionskip=\skip41 -\belowcaptionskip=\skip42 -\bibindent=\dimen102 -) -(/usr/share/texmf-texlive/tex/generic/babel/babel.sty -Package: babel 2008/07/06 v3.8l The Babel package - -(/usr/share/texmf-texlive/tex/generic/babel/ngermanb.ldf -Language: ngermanb 2008/07/06 v2.6n new German support from the babel system - -(/usr/share/texmf-texlive/tex/generic/babel/babel.def -File: babel.def 2008/07/06 v3.8l Babel common definitions -\babel@savecnt=\count88 -\U@D=\dimen103 -) - -Package babel Warning: No hyphenation patterns were loaded for -(babel) the language `ngerman' -(babel) I will use the patterns loaded for \language=0 instead. - -\l@ngerman = a dialect from \language0 -\l@naustrian = a dialect from \language\l@ngerman -Package babel Info: Making " an active character on input line 92. -)) (/usr/share/texmf-texlive/tex/latex/ucs/ucs.sty -Package: ucs 2004/10/17 UCS: Unicode input support - -(/usr/share/texmf-texlive/tex/latex/ucs/data/uni-global.def -File: uni-global.def 2004/10/17 UCS: Unicode global data -) -\uc@secondtry=\count89 -\uc@combtoks=\toks14 -\uc@combtoksb=\toks15 -\uc@temptokena=\toks16 -) -(/usr/share/texmf-texlive/tex/latex/base/fontenc.sty -Package: fontenc 2005/09/27 v1.99g Standard LaTeX package - -(/usr/share/texmf-texlive/tex/latex/base/t1enc.def -File: t1enc.def 2005/09/27 v1.99g Standard LaTeX file -LaTeX Font Info: Redeclaring font encoding T1 on input line 43. -)) -(/usr/share/texmf-texlive/tex/latex/base/inputenc.sty -Package: inputenc 2008/03/30 v1.1d Input encoding file -\inpenc@prehook=\toks17 -\inpenc@posthook=\toks18 - -(/usr/share/texmf-texlive/tex/latex/ucs/utf8x.def -File: utf8x.def 2004/10/17 UCS: Input encoding UTF-8 -)) -(/usr/share/texmf-texlive/tex/latex/tools/multicol.sty -Package: multicol 2008/12/05 v1.6h multicolumn formatting (FMi) -\c@tracingmulticols=\count90 -\mult@box=\box26 -\multicol@leftmargin=\dimen104 -\c@unbalance=\count91 -\c@collectmore=\count92 -\doublecol@number=\count93 -\multicoltolerance=\count94 -\multicolpretolerance=\count95 -\full@width=\dimen105 -\page@free=\dimen106 -\premulticols=\dimen107 -\postmulticols=\dimen108 -\multicolsep=\skip43 -\multicolbaselineskip=\skip44 -\partial@page=\box27 -\last@line=\box28 -\mult@rightbox=\box29 -\mult@grightbox=\box30 -\mult@gfirstbox=\box31 -\mult@firstbox=\box32 -\@tempa=\box33 -\@tempa=\box34 -\@tempa=\box35 -\@tempa=\box36 -\@tempa=\box37 -\@tempa=\box38 -\@tempa=\box39 -\@tempa=\box40 -\@tempa=\box41 -\@tempa=\box42 -\@tempa=\box43 -\@tempa=\box44 -\@tempa=\box45 -\@tempa=\box46 -\@tempa=\box47 -\@tempa=\box48 -\@tempa=\box49 -\c@columnbadness=\count96 -\c@finalcolumnbadness=\count97 -\last@try=\dimen109 -\multicolovershoot=\dimen110 -\multicolundershoot=\dimen111 -\mult@nat@firstbox=\box50 -\colbreak@box=\box51 -) -(/usr/share/texmf-texlive/tex/latex/graphics/graphicx.sty -Package: graphicx 1999/02/16 v1.0f Enhanced LaTeX Graphics (DPC,SPQR) - -(/usr/share/texmf-texlive/tex/latex/graphics/keyval.sty -Package: keyval 1999/03/16 v1.13 key=value parser (DPC) -\KV@toks@=\toks19 -) -(/usr/share/texmf-texlive/tex/latex/graphics/graphics.sty -Package: graphics 2009/02/05 v1.0o Standard LaTeX Graphics (DPC,SPQR) - -(/usr/share/texmf-texlive/tex/latex/graphics/trig.sty -Package: trig 1999/03/16 v1.09 sin cos tan (DPC) -) -(/etc/texmf/tex/latex/config/graphics.cfg -File: graphics.cfg 2009/08/28 v1.8 graphics configuration of TeX Live -) -Package graphics Info: Driver file: pdftex.def on input line 91. - -(/usr/share/texmf-texlive/tex/latex/pdftex-def/pdftex.def -File: pdftex.def 2009/08/25 v0.04m Graphics/color for pdfTeX -\Gread@gobject=\count98 -)) -\Gin@req@height=\dimen112 -\Gin@req@width=\dimen113 -) -(/usr/share/texmf-texlive/tex/latex/base/makeidx.sty -Package: makeidx 2000/03/29 v1.0m Standard LaTeX package -) -(/usr/share/texmf-texlive/tex/latex/ltxmisc/ulem.sty -\UL@box=\box52 -\UL@hyphenbox=\box53 -\UL@skip=\skip45 -\UL@hook=\toks20 -\UL@pe=\count99 -\UL@pixel=\dimen114 -\ULC@box=\box54 -Package: ulem 2000/05/26 -\ULdepth=\dimen115 -) -(/usr/share/texmf/tex/latex/xcolor/xcolor.sty -Package: xcolor 2007/01/21 v2.11 LaTeX color extensions (UK) - -(/etc/texmf/tex/latex/config/color.cfg -File: color.cfg 2007/01/18 v1.5 color configuration of teTeX/TeXLive -) -Package xcolor Info: Driver file: pdftex.def on input line 225. -Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1337. -Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1341. -Package xcolor Info: Model `RGB' extended on input line 1353. -Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1355. -Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1356. -Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1357. -Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1358. -Package xcolor Info: Model `Gray' substituted by `gray' on input line 1359. -Package xcolor Info: Model `wave' substituted by `hsb' on input line 1360. -) -(/usr/share/texmf-texlive/tex/latex/moreverb/moreverb.sty -Package: moreverb 2008/06/03 v2.3 `more' verbatim facilities - -(/usr/share/texmf-texlive/tex/latex/tools/verbatim.sty -Package: verbatim 2003/08/22 v1.5q LaTeX2e package for verbatim enhancements -\every@verbatim=\toks21 -\verbatim@line=\toks22 -\verbatim@in@stream=\read1 -) -\verbatim@out=\write4 -\tab@position=\count100 -\tab@size=\count101 -\listing@line=\count102 -) -(/usr/share/texmf-texlive/tex/latex/fancyhdr/fancyhdr.sty -\fancy@headwidth=\skip46 -\f@ncyO@elh=\skip47 -\f@ncyO@erh=\skip48 -\f@ncyO@olh=\skip49 -\f@ncyO@orh=\skip50 -\f@ncyO@elf=\skip51 -\f@ncyO@erf=\skip52 -\f@ncyO@olf=\skip53 -\f@ncyO@orf=\skip54 -) -(/usr/share/texmf-texlive/tex/latex/caption/caption2.sty -Package: caption2 2008/07/01 v2.2c Customising captions (AS) - - -Package caption2 Warning: **************************************************** -(caption2) THIS PACKAGE IS OBSOLETE: -(caption2) This package attempts to provide an `caption2' -(caption2) package v2.0/2.1 author environment so that OLD -(caption2) documents can be successfully processed. It should -(caption2) NOT be used for NEW documents! New documents should -(caption2) use the regular `caption' package v3.x instead. -(caption2) **************************************************** - -(/usr/share/texmf-texlive/tex/latex/caption/caption3.sty -Package: caption3 2009/10/09 v3.1k caption3 kernel (AR) -\captionmargin=\dimen116 -\captionmargin@=\dimen117 -\captionwidth=\dimen118 -\caption@indent=\dimen119 -\caption@parindent=\dimen120 -\caption@hangindent=\dimen121 -) -Package caption2 Info: Running in caption2 v2.0 compatibility mode on input lin -e 209. -\captionlinewidth=\dimen122 -\realcaptionwidth=\dimen123 -)) -(/usr/share/texmf-texlive/tex/latex/hyperref/hyperref.sty -Package: hyperref 2009/10/09 v6.79a Hypertext links for LaTeX - -(/usr/share/texmf-texlive/tex/generic/oberdiek/ifpdf.sty -Package: ifpdf 2009/04/10 v2.0 Provides the ifpdf switch (HO) -Package ifpdf Info: pdfTeX in pdf mode detected. -) -(/usr/share/texmf-texlive/tex/generic/oberdiek/ifvtex.sty -Package: ifvtex 2008/11/04 v1.4 Switches for detecting VTeX and its modes (HO) -Package ifvtex Info: VTeX not detected. -) -(/usr/share/texmf-texlive/tex/generic/ifxetex/ifxetex.sty -Package: ifxetex 2009/01/23 v0.5 Provides ifxetex conditional -) -(/usr/share/texmf-texlive/tex/latex/oberdiek/hycolor.sty -Package: hycolor 2009/10/02 v1.5 Code for color options of hyperref/bookmark (H -O) - -(/usr/share/texmf-texlive/tex/latex/oberdiek/xcolor-patch.sty -Package: xcolor-patch 2009/10/02 xcolor patch -)) -\@linkdim=\dimen124 -\Hy@linkcounter=\count103 -\Hy@pagecounter=\count104 - -(/usr/share/texmf-texlive/tex/latex/hyperref/pd1enc.def -File: pd1enc.def 2009/10/09 v6.79a Hyperref: PDFDocEncoding definition (HO) -) -(/usr/share/texmf-texlive/tex/generic/oberdiek/etexcmds.sty -Package: etexcmds 2007/12/12 v1.2 Prefix for e-TeX command names (HO) - -(/usr/share/texmf-texlive/tex/generic/oberdiek/infwarerr.sty -Package: infwarerr 2007/09/09 v1.2 Providing info/warning/message (HO) -) -Package etexcmds Info: Could not find \expanded. -(etexcmds) That can mean that you are not using pdfTeX 1.50 or -(etexcmds) that some package has redefined \expanded. -(etexcmds) In the latter case, load this package earlier. -) -(/usr/share/texmf-texlive/tex/latex/latexconfig/hyperref.cfg -File: hyperref.cfg 2002/06/06 v1.2 hyperref configuration of TeXLive -) -(/usr/share/texmf-texlive/tex/latex/oberdiek/kvoptions.sty -Package: kvoptions 2009/08/13 v3.4 Keyval support for LaTeX options (HO) - -(/usr/share/texmf-texlive/tex/generic/oberdiek/kvsetkeys.sty -Package: kvsetkeys 2009/07/30 v1.5 Key value parser with default handler suppor -t (HO) -)) -Package hyperref Info: Option `pdfpagelabels' set `true' on input line 2864. -Package hyperref Info: Option `plainpages' set `false' on input line 2864. -Package hyperref Info: Option `colorlinks' set `true' on input line 2864. -Package hyperref Info: Hyper figures OFF on input line 2975. -Package hyperref Info: Link nesting OFF on input line 2980. -Package hyperref Info: Hyper index ON on input line 2983. -Package hyperref Info: Plain pages OFF on input line 2990. -Package hyperref Info: Backreferencing OFF on input line 2995. - -Implicit mode ON; LaTeX internals redefined -Package hyperref Info: Bookmarks ON on input line 3191. -(/usr/share/texmf-texlive/tex/latex/ltxmisc/url.sty -\Urlmuskip=\muskip10 -Package: url 2006/04/12 ver 3.3 Verb mode for urls, etc. -) -LaTeX Info: Redefining \url on input line 3428. - -(/usr/share/texmf-texlive/tex/generic/oberdiek/bitset.sty -Package: bitset 2007/09/28 v1.0 Data type bit set (HO) - -(/usr/share/texmf-texlive/tex/generic/oberdiek/intcalc.sty -Package: intcalc 2007/09/27 v1.1 Expandable integer calculations (HO) -) -(/usr/share/texmf-texlive/tex/generic/oberdiek/bigintcalc.sty -Package: bigintcalc 2007/11/11 v1.1 Expandable big integer calculations (HO) - -(/usr/share/texmf-texlive/tex/generic/oberdiek/pdftexcmds.sty -Package: pdftexcmds 2009/09/23 v0.6 LuaTeX support for pdfTeX utility functions - (HO) - -(/usr/share/texmf-texlive/tex/generic/oberdiek/ifluatex.sty -Package: ifluatex 2009/04/17 v1.2 Provides the ifluatex switch (HO) -Package ifluatex Info: LuaTeX not detected. -) -(/usr/share/texmf-texlive/tex/generic/oberdiek/ltxcmds.sty -Package: ltxcmds 2009/08/05 v1.0 Some LaTeX kernel commands for general use (HO -) -) -Package pdftexcmds Info: LuaTeX not detected. -Package pdftexcmds Info: \pdf@primitive is available. -Package pdftexcmds Info: \pdf@ifprimitive is available. -))) -\Fld@menulength=\count105 -\Field@Width=\dimen125 -\Fld@charsize=\dimen126 -\Field@toks=\toks23 -Package hyperref Info: Hyper figures OFF on input line 4377. -Package hyperref Info: Link nesting OFF on input line 4382. -Package hyperref Info: Hyper index ON on input line 4385. -Package hyperref Info: backreferencing OFF on input line 4392. -Package hyperref Info: Link coloring ON on input line 4395. -Package hyperref Info: Link coloring with OCG OFF on input line 4402. -Package hyperref Info: PDF/A mode OFF on input line 4407. - -(/usr/share/texmf-texlive/tex/generic/oberdiek/atbegshi.sty -Package: atbegshi 2008/07/31 v1.9 At begin shipout hook (HO) -) -\Hy@abspage=\count106 -\c@Item=\count107 -\c@Hfootnote=\count108 -) -*hyperref using driver hpdftex* -(/usr/share/texmf-texlive/tex/latex/hyperref/hpdftex.def -File: hpdftex.def 2009/10/09 v6.79a Hyperref driver for pdfTeX -\Fld@listcount=\count109 -) (./pvs-doc.aux - -LaTeX Warning: Label `uscp' multiply defined. - -) -\openout1 = `pvs-doc.aux'. - -LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 4. -LaTeX Font Info: ... okay on input line 4. -LaTeX Font Info: Try loading font information for T1+cmss on input line 4. - (/usr/share/texmf-texlive/tex/latex/base/t1cmss.fd -File: t1cmss.fd 1999/05/25 v2.5h Standard LaTeX font definitions -) -(/usr/share/texmf-texlive/tex/latex/ucs/ucsencs.def -File: ucsencs.def 2003/11/29 Fixes to fontencodings LGR, T3 -) -(/usr/share/texmf-texlive/tex/context/base/supp-pdf.mkii -[Loading MPS to PDF converter (version 2006.09.02).] -\scratchcounter=\count110 -\scratchdimen=\dimen127 -\scratchbox=\box55 -\nofMPsegments=\count111 -\nofMParguments=\count112 -\everyMPshowfont=\toks24 -\MPscratchCnt=\count113 -\MPscratchDim=\dimen128 -\MPnumerator=\count114 -\everyMPtoPDFconversion=\toks25 -) -Package caption Info: Begin \AtBeginDocument code. -Package caption Info: End \AtBeginDocument code. -Package hyperref Info: Link coloring ON on input line 4. - (/usr/share/texmf-texlive/tex/latex/hyperref/nameref.sty -Package: nameref 2007/05/29 v2.31 Cross-referencing by name of section - -(/usr/share/texmf-texlive/tex/latex/oberdiek/refcount.sty -Package: refcount 2008/08/11 v3.1 Data extraction from references (HO) -) -\c@section@level=\count115 -) -LaTeX Info: Redefining \ref on input line 4. -LaTeX Info: Redefining \pageref on input line 4. - (./pvs-doc.out) -(./pvs-doc.out) -\@outlinefile=\write5 -\openout5 = `pvs-doc.out'. - -\AtBeginShipoutBox=\box56 - (./header.tex - -File: bilder/siegel-neu.jpg Graphic file (type jpg) - - -(/usr/share/texmf-texlive/tex/latex/ucs/data/uni-0.def -File: uni-0.def 2004/10/17 UCS: Unicode data U+0000..U+00FF -) [1 - -{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map} <./bilder/siegel-neu.jpg>] -[2] - -LaTeX Font Warning: Font shape `T1/cmss/m/sc' in size <14.4> not available -(Font) Font shape `T1/cmr/m/sc' tried instead on input line 39. - -[3] -Underfull \hbox (badness 10000) in paragraph at lines 45--52 - - [] - -[4]) - -Package hyperref Warning: No destination for bookmark of \addcontentsline, -(hyperref) destination is added on input line 7. - -(./pvs-doc.toc -LaTeX Font Info: External font `cmex10' loaded for size -(Font) <12> on input line 6. -LaTeX Font Info: External font `cmex10' loaded for size -(Font) <8> on input line 6. -LaTeX Font Info: External font `cmex10' loaded for size -(Font) <6> on input line 6. - - -Package Fancyhdr Warning: \headheight is too small (12.0pt): - Make it at least 25.40292pt. - We now make it that large for the rest of the document. - This may cause the page layout to be inconsistent, however. - -[1 - -]) -\tf@toc=\write6 -\openout6 = `pvs-doc.toc'. - - [2] (./zusfassung.tex [3 - -])pdfTeX warning (ext4): destination with the same identifier (name{page.1}) ha -s been already used, duplicate ignored - - \relax -l.13 \part{Idee und Ãœberblick} - [1 - -]pdfTeX warning (ext4): destination with the same identifier (name{page.2}) has - been already used, duplicate ignored - - \relax -l.13 \part{Idee und Ãœberblick} - [2] (./intro/0000-chapter.tex -Kapitel 1. - -File: bilder/studentctlpanel.png Graphic file (type png) - -pdfTeX warning (ext4): destination with the sam -e identifier (name{page.3}) has been already used, duplicate ignored - - \relax -l.13 D - em soll ein eigener Ansatz entgegengesetzt werden, der die eingangs ge... -[3 - - <./bilder/studentctlpanel.png>] -Overfull \hbox (2.64162pt too wide) in paragraph at lines 13--14 -[]\T1/cmss/m/n/12 Dem soll ein eigen-er Ansatz ent-ge-genge-set-zt wer-den, der - die ein-gangs genan-nten Beschränkun- - [] - -) (./intro/0100-funktionen.texpdfTeX warning (ext4): destination with the same -identifier (name{page.4}) has been already used, duplicate ignored - - \relax -l.1 \chapter - {Funktionen eines Software-Video-Switchs} [4] -Kapitel 2. -File: bilder/studentctlpanel.png Graphic file (type png) -) (./intro/0900-textaufbau.tex [5 - -] [6 - -] -Kapitel 3. -LaTeX Font Info: Try loading font information for T1+cmtt on input line 12. -(/usr/share/texmf-texlive/tex/latex/base/t1cmtt.fd -File: t1cmtt.fd 1999/05/25 v2.5h Standard LaTeX font definitions -)) [7] [8 - -] [9] [10] -(./user/0001-chapter.tex -Kapitel 4. - -File: bilder/pvsmgrAll.jpg Graphic file (type jpg) - - -Underfull \hbox (badness 10000) in paragraph at lines 17--32 - - [] - - -Underfull \vbox (badness 1052) has occurred while \output is active [] - - [11 - - <./bilder/pvsmgrAll.jpg>] -File: bilder/dum.jpg Graphic file (type jpg) - - -Underfull \hbox (badness 10000) in paragraph at lines 34--63 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 34--63 - - [] - - -LaTeX Warning: `h' float specifier changed to `ht'. - -[12] -Underfull \hbox (badness 10000) in paragraph at lines 66--69 - - [] - - -Underfull \vbox (badness 10000) has occurred while \output is active [] - - [13 <./bilder/dum.jpg>] -Underfull \hbox (badness 10000) in paragraph at lines 70--71 - - [] - -) (./user/0000-chapter.tex -Underfull \hbox (badness 10000) in paragraph at lines 72--1 - - [] - -[14] -Kapitel 5. -[15 - -] -File: bilder/clientToolbar.png Graphic file (type png) - - -LaTeX Font Info: Try loading font information for OMS+cmss on input line 20. - -LaTeX Font Info: No file OMScmss.fd. on input line 20. - - -LaTeX Font Warning: Font shape `OMS/cmss/m/n' undefined -(Font) using `OMS/cmsy/m/n' instead -(Font) for symbol `textbullet' on input line 20. - -[16 <./bilder/clientToolbar.png>] - -File: bilder/clientChatDialog.png Graphic file (type png) - - - -File: bilder/clientConfigDialog.png Graphic file (type png) - - - -LaTeX Warning: `h' float specifier changed to `ht'. - -) [17 <./bilder/clientChatDialog.png>] [18 <./bilder/clientConfigDialog.png>] -[19 - -] [20] (./devel/0000-chapter.tex) (./devel/0100-build.tex -Kapitel 6. - -Underfull \hbox (badness 10000) in paragraph at lines 3--4 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 5--7 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 8--10 - - [] - - -Overfull \hbox (6.42374pt too wide) in paragraph at lines 23--25 -\T1/cmss/m/n/12 Eingesetztes Buildsys-tem und der Makefile-Generator. Um dis-tr -i-bu-tion-sspez-i-fis-che Pakete - [] - -[21 - -] -Underfull \hbox (badness 10000) in paragraph at lines 34--35 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 36--40 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 51--53 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 54--60 - - [] - -[22] -Underfull \hbox (badness 10000) in paragraph at lines 61--62 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 63--65 - - [] - -) (./devel/0200-gui-lib.tex [23] [24 - -] -Kapitel 7. -[25]) (./devel/0300-pvs.tex [26] -Kapitel 8. -(./devel/0310-service-discovery.tex [27 - -]) -Underfull \vbox (badness 10000) has occurred while \output is active [] - - [28] -Underfull \hbox (badness 10000) in paragraph at lines 45--58 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 45--58 - - [] - -[29] -Underfull \hbox (badness 10000) in paragraph at lines 67--67 -[]\T1/cmtt/m/n/12 :addCommandHandler("*", this, - [] - -[32] -Underfull \hbox (badness 10000) in paragraph at lines 202--202 -[]\T1/cmss/m/n/12 hostname - [] - - -Underfull \hbox (badness 7558) in paragraph at lines 202--202 -\T1/cmss/m/n/12 port pass- - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 202--202 -\T1/cmss/m/n/12 word - [] - - -Underfull \hbox (badness 4378) in paragraph at lines 205--206 -[]\T1/cmss/m/n/12 Client mit Nachricht - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 210--210 -[]\T1/cmss/m/n/12 ^^RWrong - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 210--211 -[]\T1/cmss/m/n/12 Wird bei falschem - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 220--221 -[]\T1/cmss/m/n/12 Client hinzufü-gen - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 222--223 -[]\T1/cmss/m/n/12 Festgelegter Name - [] - -) (./devel/0400-pvs-console.tex [33] [34] -Kapitel 9. - -Underfull \hbox (badness 10000) in paragraph at lines 3--7 - - [] - - -File: bilder/pvsmgr.jpg Graphic file (type jpg) - - -File: bilder/mainwindow.png Graphic file (type png) - - -Underfull \hbox (badness 10000) in paragraph at lines 21--48 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 21--48 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 21--48 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 21--48 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 21--48 - - [] - -[35 - -] - -LaTeX Warning: `h' float specifier changed to `ht'. - - -Underfull \hbox (badness 10000) in paragraph at lines 49--56 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 57--60 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 57--60 - - [] - -[36 <./bilder/pvsmgr.jpg>] -Underfull \hbox (badness 10000) in paragraph at lines 61--72 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 73--76 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 77--81 - - [] - -[37 <./bilder/mainwindow.png (PNG copy)>] - -LaTeX Warning: Reference `fig:connectionlist' on page 38 undefined on input lin -e 87. - - -File: bilder/ConnectionList.png Graphic file (type png) - - - -File: bilder/connectionframe.png Graphic file (type png) - - - -LaTeX Warning: Reference `connectionframe' on page 38 undefined on input line 1 -20. - - -Underfull \hbox (badness 10000) in paragraph at lines 105--124 - - [] - - -Underfull \vbox (badness 1629) has occurred while \output is active [] - - [38 <./bilder/ConnectionList.png (PNG copy)>] [39 <./bilder/connectionframe.pn -g (PNG copy)>] -Underfull \hbox (badness 10000) in paragraph at lines 130--150 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 153--158 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 159--164 - - [] - -[40] -Overfull \hbox (9.46333pt too wide) in paragraph at lines 171--174 -\T1/cmss/m/n/12 schon in der Liste der Pro-jek-tion-sziele vorhan-den ist. Ist -er nicht vorhan-den, wird ein Auswahldia- - [] - - -Overfull \hbox (2.76924pt too wide) in paragraph at lines 171--174 -\T1/cmtt/m/n/12 MainWindow::getWindow()->getConnectionList()->getTargetToDispla -y(source)\T1/cmss/m/n/12 ). - [] - -[41]) (./devel/0500-pvs-client.tex [42] -Kapitel 10. - -Underfull \hbox (badness 10000) in paragraph at lines 2--3 - - [] - - -File: bilder/DBus.pdf Graphic file (type pdf) - [43 - - <./bilder/DBus.pdf>] [44] -Underfull \hbox (badness 10000) in paragraph at lines 73--74 - - [] - - -Overfull \hbox (5.7754pt too wide) in paragraph at lines 77--78 -\T1/cmss/m/n/12 über den Kon-struk-tor definiert und nach einem Aufruf von \T1/ -cmtt/m/n/12 VNCClientThread::start() - [] - -[45] -Underfull \hbox (badness 10000) in paragraph at lines 88--89 - - [] - -[46] -Underfull \hbox (badness 10000) in paragraph at lines 95--97 - - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 98--101 - - [] - -[47] -Underfull \hbox (badness 2285) in paragraph at lines 117--128 -\T1/cmss/m/it/12 ^^C/.gconf/desktop/gnome/remote_access/%gconf.xml \T1/cmss/m/n -/12 kon-fig-urier-bar. Pa-ram-e-ter kön-nen - [] - - -Underfull \hbox (badness 10000) in paragraph at lines 117--128 -\T1/cmss/m/n/12 durch \T1/cmtt/m/n/12 gconftool-2 -s -t int desktop/gnome/remot -e_access/alternative_port - [] - - -Underfull \hbox (badness 7256) in paragraph at lines 117--128 -\T1/cmtt/m/n/12 \T1/cmss/m/n/12 bzw. das Ein-fü-gen von z.B. \T1/c -mtt/m/n/12 ''/> \T1 -/cmss/m/n/12 in die entsprechende - [] - -[48] [49] -Overfull \hbox (1.44884pt too wide) in paragraph at lines 189--190 -[]\T1/cmss/m/n/12 Um einen Mehrfach-start des VNC Servers zu ver-hin-dern, wird - zunächst im-mer ein \T1/cmtt/m/n/12 pvs-vncsrv - [] - - -Underfull \hbox (badness 1728) in paragraph at lines 197--199 -\T1/cmss/m/n/12 die Eingaben in der Klasse \T1/cmtt/m/n/12 ClientVNCViewer \T1/ -cmss/m/n/12 abge-fan-gen und ve-r-ar-beit-et wer-den. - [] - - -Underfull \hbox (badness 1107) in paragraph at lines 197--199 -\T1/cmss/m/n/12 Dies kann durch Über-schreiben der geerbten Meth-ode \T1/cmtt/m -/n/12 event \T1/cmss/m/n/12 er-re-icht wer-den \T1/cmtt/m/n/12 bool - [] - -[50] -Overfull \hbox (4.18437pt too wide) in paragraph at lines 211--215 -\T1/cmtt/m/n/12 Key-[]enum$[][]\T1/cmss/m/n/12 ) un-ter-schieden wer-den. Die T -astatur- und Mau-seingaben müssen dann entsprechend - [] - - -Overfull \hbox (11.09923pt too wide) in paragraph at lines 211--215 -\T1/cmss/m/n/12 an \T1/cmtt/m/n/12 vncClientThread \T1/cmss/m/n/12 weit-ergelei -t-et wer-den. In der Klasse vnc-Client-Thread wer-den die Eingaben - [] - -[51] -Underfull \hbox (badness 4441) in paragraph at lines 240--243 -[]\T1/cmss/m/n/12 Um Sig-nale ab-fan-gen zu kön-nen, muss nun noch das sigac-ti -on Ob-jekt durch - [] - - -Underfull \hbox (badness 2181) in paragraph at lines 240--243 -\T1/cmtt/m/n/12 sigaction(SIGTERM, &act, 0) \T1/cmss/m/n/12 mit den entsprechen --den Sig-nalen (hi-er SIGTERM) - [] - -) [52] [53 - -] [54] (./appendix/0000-chapter.tex - -File: bilder/Klassendiagramm.pdf Graphic file (type pdf) - - - -LaTeX Warning: `h' float specifier changed to `ht'. - -) -No file pvs-doc.ind. -[55 <./bilder/Klassendiagramm.pdf>] (./pvs-doc.aux) - -LaTeX Font Warning: Some font shapes were not available, defaults substituted. - - -LaTeX Warning: There were undefined references. - - -LaTeX Warning: There were multiply-defined labels. - - ) -Here is how much of TeX's memory you used: - 7300 strings out of 495061 - 103737 string characters out of 1182622 - 191400 words of memory out of 3000000 - 10133 multiletter control sequences out of 15000+50000 - 17588 words of font info for 39 fonts, out of 3000000 for 9000 - 28 hyphenation exceptions out of 8191 - 38i,14n,44p,1625b,576s stack positions out of 5000i,500n,10000p,200000b,50000s - -Output written on pvs-doc.pdf (62 pages, 2362812 bytes). -PDF statistics: - 1429 PDF objects out of 1440 (max. 8388607) - 156 named destinations out of 1000 (max. 500000) - 514 words of extra memory for PDF output out of 10000 (max. 10000000) - diff --git a/doc/LaTeX/pvs-doc.out b/doc/LaTeX/pvs-doc.out deleted file mode 100644 index e311c72..0000000 --- a/doc/LaTeX/pvs-doc.out +++ /dev/null @@ -1,56 +0,0 @@ -\BOOKMARK [0][-]{section*.1}{Inhaltsverzeichnis}{} -\BOOKMARK [-1][-]{part.1}{I Idee und \334berblick}{} -\BOOKMARK [0][-]{chapter.1}{Idee}{part.1} -\BOOKMARK [0][-]{chapter.2}{Funktionen eines Software-Video-Switchs}{part.1} -\BOOKMARK [1][-]{section.2.1}{W\374nschenswerte Basisfunktionen}{chapter.2} -\BOOKMARK [1][-]{section.2.2}{Funktionserweiterungen}{chapter.2} -\BOOKMARK [0][-]{chapter.3}{Aufbau dieses Handbuchs}{part.1} -\BOOKMARK [1][-]{section.3.1}{Heraushebungen und Formatierungen}{chapter.3} -\BOOKMARK [-1][-]{part.2}{II Bedienungsanleitung}{} -\BOOKMARK [0][-]{chapter.4}{PVS-Steuerkonsole}{part.2} -\BOOKMARK [1][-]{section.4.1}{Allgemein}{chapter.4} -\BOOKMARK [2][-]{subsection.4.1.1}{Die Client-Liste}{section.4.1} -\BOOKMARK [2][-]{subsection.4.1.2}{Die VNC-Frames}{section.4.1} -\BOOKMARK [2][-]{subsection.4.1.3}{Tastenk\374rzel f\374r PVS-Server}{section.4.1} -\BOOKMARK [0][-]{chapter.5}{PVS-Client}{part.2} -\BOOKMARK [1][-]{section.5.1}{Chat}{chapter.5} -\BOOKMARK [1][-]{section.5.2}{Konfiguration}{chapter.5} -\BOOKMARK [-1][-]{part.3}{III Entwicklerdokumentation}{} -\BOOKMARK [0][-]{chapter.6}{Erzeugen und Installieren der Applikation}{part.3} -\BOOKMARK [1][-]{section.6.1}{Voraussetzungen}{chapter.6} -\BOOKMARK [1][-]{section.6.2}{Kompilieren aus Quellen}{chapter.6} -\BOOKMARK [1][-]{section.6.3}{Installation}{chapter.6} -\BOOKMARK [0][-]{chapter.7}{Eingesetzte GUI-Bibliothek}{part.3} -\BOOKMARK [1][-]{section.7.1}{Internationalisierung}{chapter.7} -\BOOKMARK [0][-]{chapter.8}{Aufbau und Funktionsweise des PVS}{part.3} -\BOOKMARK [1][-]{section.8.1}{Einzelne Komponenten}{chapter.8} -\BOOKMARK [2][-]{subsection.8.1.1}{Zuordnung von Konsole und Clients}{section.8.1} -\BOOKMARK [1][-]{section.8.2}{\334berblick \374ber Aktivit\344ten auf Clients}{chapter.8} -\BOOKMARK [2][-]{subsection.8.2.1}{Projektion an Alle}{section.8.2} -\BOOKMARK [2][-]{subsection.8.2.2}{Projektion eines Clients auf dem Beamer}{section.8.2} -\BOOKMARK [2][-]{subsection.8.2.3}{Chat- und Informationskanal}{section.8.2} -\BOOKMARK [1][-]{section.8.3}{Netzwerkkommunikation}{chapter.8} -\BOOKMARK [2][-]{subsection.8.3.1}{PVS-Protokoll}{section.8.3} -\BOOKMARK [2][-]{subsection.8.3.2}{PVS-Messages}{section.8.3} -\BOOKMARK [0][-]{chapter.9}{PVS-Steuerkonsole}{part.3} -\BOOKMARK [1][-]{section.9.1}{pvsmgr in Qt}{chapter.9} -\BOOKMARK [1][-]{section.9.2}{GUI Server-Konsole}{chapter.9} -\BOOKMARK [2][-]{subsection.9.2.1}{Die Architektur}{section.9.2} -\BOOKMARK [2][-]{subsection.9.2.2}{Client-Seite}{section.9.2} -\BOOKMARK [2][-]{subsection.9.2.3}{Server-Seite}{section.9.2} -\BOOKMARK [1][-]{section.9.3}{Verbindungsverwaltung und Projektion}{chapter.9} -\BOOKMARK [2][-]{subsection.9.3.1}{Projektion}{section.9.3} -\BOOKMARK [2][-]{subsection.9.3.2}{Remote Help}{section.9.3} -\BOOKMARK [0][-]{chapter.10}{PVS-Client}{part.3} -\BOOKMARK [1][-]{section.10.1}{Grafische Benutzeroberfl\344che}{chapter.10} -\BOOKMARK [1][-]{section.10.2}{User-Interface f\374r Benutzerkonfiguration}{chapter.10} -\BOOKMARK [1][-]{section.10.3}{Darstellung von VNC-Datenstr\366men}{chapter.10} -\BOOKMARK [1][-]{section.10.4}{Chat-Interface}{chapter.10} -\BOOKMARK [1][-]{section.10.5}{Datei\374bertragung und Interface}{chapter.10} -\BOOKMARK [1][-]{section.10.6}{VNC Server}{chapter.10} -\BOOKMARK [2][-]{subsection.10.6.1}{Vergleich von VNC Servern}{section.10.6} -\BOOKMARK [2][-]{subsection.10.6.2}{VNC Script}{section.10.6} -\BOOKMARK [1][-]{section.10.7}{VNC Viewer}{chapter.10} -\BOOKMARK [2][-]{subsection.10.7.1}{Tastatur und Maussteuerung}{section.10.7} -\BOOKMARK [1][-]{section.10.8}{Signalbehandlung}{chapter.10} -\BOOKMARK [-1][-]{part.4}{IV Anhang}{} diff --git a/doc/LaTeX/pvs-doc.pdf b/doc/LaTeX/pvs-doc.pdf deleted file mode 100644 index 2b43baf..0000000 Binary files a/doc/LaTeX/pvs-doc.pdf and /dev/null differ diff --git a/doc/LaTeX/pvs-doc.toc b/doc/LaTeX/pvs-doc.toc deleted file mode 100644 index cfaa531..0000000 --- a/doc/LaTeX/pvs-doc.toc +++ /dev/null @@ -1,65 +0,0 @@ -\select@language {ngerman} -\contentsline {chapter}{Inhaltsverzeichnis}{I}{section*.1} -\contentsline {part}{I\hspace {1em}Idee und \IeC {\"U}berblick}{1}{part.1} -\contentsline {chapter}{\numberline {1}Idee}{3}{chapter.1} -\contentsline {chapter}{\numberline {2}Funktionen eines Software-Video-Switchs}{5}{chapter.2} -\contentsline {section}{\numberline {2.1}W\IeC {\"u}nschenswerte Basisfunktionen}{5}{section.2.1} -\contentsline {section}{\numberline {2.2}Funktionserweiterungen}{5}{section.2.2} -\contentsline {chapter}{\numberline {3}Aufbau dieses Handbuchs}{7}{chapter.3} -\contentsline {section}{\numberline {3.1}Heraushebungen und Formatierungen}{7}{section.3.1} -\contentsline {part}{II\hspace {1em}Bedienungsanleitung}{9}{part.2} -\contentsline {chapter}{\numberline {4}PVS-Steuerkonsole}{11}{chapter.4} -\contentsline {section}{\numberline {4.1}Allgemein}{11}{section.4.1} -\contentsline {subsection}{\numberline {4.1.1}Die Client-Liste}{12}{subsection.4.1.1} -\contentsline {subsection}{\numberline {4.1.2}Die VNC-Frames}{12}{subsection.4.1.2} -\contentsline {subsection}{\numberline {4.1.3}Tastenk\IeC {\"u}rzel f\IeC {\"u}r PVS-Server}{14}{subsection.4.1.3} -\contentsline {chapter}{\numberline {5}PVS-Client}{15}{chapter.5} -\contentsline {section}{\numberline {5.1}Chat}{16}{section.5.1} -\contentsline {section}{\numberline {5.2}Konfiguration}{17}{section.5.2} -\contentsline {part}{III\hspace {1em}Entwicklerdokumentation}{19}{part.3} -\contentsline {chapter}{\numberline {6}Erzeugen und Installieren der Applikation}{21}{chapter.6} -\contentsline {section}{\numberline {6.1}Voraussetzungen}{21}{section.6.1} -\contentsline {section}{\numberline {6.2}Kompilieren aus Quellen}{22}{section.6.2} -\contentsline {section}{\numberline {6.3}Installation}{22}{section.6.3} -\contentsline {chapter}{\numberline {7}Eingesetzte GUI-Bibliothek}{25}{chapter.7} -\contentsline {section}{\numberline {7.1}Internationalisierung}{25}{section.7.1} -\contentsline {chapter}{\numberline {8}Aufbau und Funktionsweise des PVS}{27}{chapter.8} -\contentsline {section}{\numberline {8.1}Einzelne Komponenten}{27}{section.8.1} -\contentsline {subsection}{\numberline {8.1.1}Zuordnung von Konsole und Clients}{27}{subsection.8.1.1} -\contentsline {subsubsection}{Absicherung und Verifikation der Identit\IeC {\"a}t}{27}{section*.4} -\contentsline {subsubsection}{Generierung von Sitzungsnamen}{28}{section*.5} -\contentsline {section}{\numberline {8.2}\IeC {\"U}berblick \IeC {\"u}ber Aktivit\IeC {\"a}ten auf Clients}{29}{section.8.2} -\contentsline {subsection}{\numberline {8.2.1}Projektion an Alle}{29}{subsection.8.2.1} -\contentsline {subsection}{\numberline {8.2.2}Projektion eines Clients auf dem Beamer}{29}{subsection.8.2.2} -\contentsline {subsection}{\numberline {8.2.3}Chat- und Informationskanal}{30}{subsection.8.2.3} -\contentsline {section}{\numberline {8.3}Netzwerkkommunikation}{32}{section.8.3} -\contentsline {subsection}{\numberline {8.3.1}PVS-Protokoll}{32}{subsection.8.3.1} -\contentsline {subsection}{\numberline {8.3.2}PVS-Messages}{33}{subsection.8.3.2} -\contentsline {chapter}{\numberline {9}PVS-Steuerkonsole}{35}{chapter.9} -\contentsline {section}{\numberline {9.1}pvsmgr in Qt}{35}{section.9.1} -\contentsline {section}{\numberline {9.2}GUI Server-Konsole}{35}{section.9.2} -\contentsline {subsection}{\numberline {9.2.1}Die Architektur}{35}{subsection.9.2.1} -\contentsline {subsubsection}{Clientliste-Ansicht}{38}{section*.6} -\contentsline {subsubsection}{VNC-Ansicht}{39}{section*.7} -\contentsline {subsection}{\numberline {9.2.2}Client-Seite}{40}{subsection.9.2.2} -\contentsline {subsection}{\numberline {9.2.3}Server-Seite}{40}{subsection.9.2.3} -\contentsline {section}{\numberline {9.3}Verbindungsverwaltung und Projektion}{41}{section.9.3} -\contentsline {subsection}{\numberline {9.3.1}Projektion}{41}{subsection.9.3.1} -\contentsline {subsubsection}{Qualit\IeC {\"a}tsoptionen}{42}{section*.8} -\contentsline {subsection}{\numberline {9.3.2}Remote Help}{42}{subsection.9.3.2} -\contentsline {chapter}{\numberline {10}PVS-Client}{43}{chapter.10} -\contentsline {section}{\numberline {10.1}Grafische Benutzeroberfl\IeC {\"a}che}{44}{section.10.1} -\contentsline {section}{\numberline {10.2}User-Interface f\IeC {\"u}r Benutzerkonfiguration}{45}{section.10.2} -\contentsline {section}{\numberline {10.3}Darstellung von VNC-Datenstr\IeC {\"o}men}{45}{section.10.3} -\contentsline {section}{\numberline {10.4}Chat-Interface}{46}{section.10.4} -\contentsline {section}{\numberline {10.5}Datei\IeC {\"u}bertragung und Interface}{46}{section.10.5} -\contentsline {section}{\numberline {10.6}VNC Server}{47}{section.10.6} -\contentsline {subsection}{\numberline {10.6.1}Vergleich von VNC Servern}{48}{subsection.10.6.1} -\contentsline {paragraph}{Vino}{48}{section*.9} -\contentsline {paragraph}{Krfb}{48}{section*.10} -\contentsline {paragraph}{x11vnc}{49}{section*.11} -\contentsline {subsection}{\numberline {10.6.2}VNC Script}{50}{subsection.10.6.2} -\contentsline {section}{\numberline {10.7}VNC Viewer}{50}{section.10.7} -\contentsline {subsection}{\numberline {10.7.1}Tastatur und Maussteuerung}{51}{subsection.10.7.1} -\contentsline {section}{\numberline {10.8}Signalbehandlung}{52}{section.10.8} -\contentsline {part}{IV\hspace {1em}Anhang}{53}{part.4} -- cgit v1.2.3-55-g7522 From 1f169bfb3f46814948e132566451289c2e418eae Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Thu, 4 Nov 2010 15:26:55 +0100 Subject: Replace stray uint{16,32}_t references by quint{16,32} --- src/input/inputEvent.h | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h index afb33e5..4e132eb 100644 --- a/src/input/inputEvent.h +++ b/src/input/inputEvent.h @@ -99,36 +99,36 @@ public: * Generates an event for a mouse pointer movement. * \param x,y X and Y coordinates of the mouse pointer. */ - static InputEvent mouseMotion(uint16_t x, uint16_t y) + static InputEvent mouseMotion(quint16 x, quint16 y) { - return InputEvent(ET_POINTER, 0, ((uint32_t)x << 16) | y); + return InputEvent(ET_POINTER, 0, ((quint32)x << 16) | y); } /* @} */ /** \name Event Types */ /* @{ */ - static const uint16_t ET_KEY = 0; /**< The event is related to the keyboard */ - static const uint16_t ET_BUTTON = 1; /**< The event is related to a mouse button */ - static const uint16_t ET_POINTER = 2; /**< The event is related to the mouse pointer */ - static const uint16_t ET_SPECIAL = 3; /**< The event is a special system event */ + static const quint16 ET_KEY = 0; /**< The event is related to the keyboard */ + static const quint16 ET_BUTTON = 1; /**< The event is related to a mouse button */ + static const quint16 ET_POINTER = 2; /**< The event is related to the mouse pointer */ + static const quint16 ET_SPECIAL = 3; /**< The event is a special system event */ /* @} */ /** \name Event Codes */ /* @{ */ - static const uint16_t EC_PRESS = 0; /**< The event is a press (keyboard or mouse button) */ - static const uint16_t EC_RELEASE = 1; /**< The event is a release (keyboard or mouse button) */ - static const uint16_t EC_REBOOT = 2; /**< The event is a request to reboot (special system event) */ - static const uint16_t EC_SYSRQ = 3; /**< The event is a request to perform a Magic-SysRq function (special system event) */ - static const uint16_t EC_KILL_X = 4; /**< The event is a request to kill the X Server (special system event) */ - static const uint16_t EC_SAY_HELLO = 5; /**< The event is a request to write a line to the log file (special system event) */ + static const quint16 EC_PRESS = 0; /**< The event is a press (keyboard or mouse button) */ + static const quint16 EC_RELEASE = 1; /**< The event is a release (keyboard or mouse button) */ + static const quint16 EC_REBOOT = 2; /**< The event is a request to reboot (special system event) */ + static const quint16 EC_SYSRQ = 3; /**< The event is a request to perform a Magic-SysRq function (special system event) */ + static const quint16 EC_KILL_X = 4; /**< The event is a request to kill the X Server (special system event) */ + static const quint16 EC_SAY_HELLO = 5; /**< The event is a request to write a line to the log file (special system event) */ /* @} */ /** \name Mouse Button Flags */ /* @{ */ - static const uint16_t EB_LEFT = 1; /**< The left mouse button */ - static const uint16_t EB_MIDDLE = 2; /**< The middle mouse button */ - static const uint16_t EB_RIGHT = 4; /**< The right mouse button */ + static const quint16 EB_LEFT = 1; /**< The left mouse button */ + static const quint16 EB_MIDDLE = 2; /**< The middle mouse button */ + static const quint16 EB_RIGHT = 4; /**< The right mouse button */ /* @} */ static const quint32 MODIFIER_MASK = @@ -140,7 +140,7 @@ public: /** * Return the event type, as defined by the \c ET_* constants. */ - uint16_t type() const + quint16 type() const { return _type; } @@ -148,7 +148,7 @@ public: /** * Return the event code, as defined by the \c EC_* constants. */ - uint16_t code() const + quint16 code() const { return _code; } @@ -165,7 +165,7 @@ public: * - If the event type is \c ET_SPECIAL, the interpretation * depends on the event code. */ - uint32_t value() const + quint32 value() const { return _value; } @@ -222,7 +222,7 @@ public: * The mouse button that generated this event. * \return one of the \c EB_* constants. */ - uint16_t pressedButton() const + quint16 pressedButton() const { assert(_type == ET_BUTTON); return (_value >> 16); @@ -233,7 +233,7 @@ public: * event was generated. * \return a bitwise or of \c EB_* constants. */ - uint16_t heldButtons() const + quint16 heldButtons() const { assert(_type == ET_BUTTON); return (_value & 0xffff); @@ -242,7 +242,7 @@ public: /** * The X coordinate the pointer was moved to. */ - uint16_t xCoord() const + quint16 xCoord() const { assert(_type == ET_POINTER); return (_value >> 16); @@ -251,7 +251,7 @@ public: /** * The Y coordinate the pointer was moved to. */ - uint16_t yCoord() const + quint16 yCoord() const { assert(_type == ET_POINTER); return (_value & 0xffff); @@ -284,7 +284,7 @@ public: * to their internal representation as defined in \ref "Mouse Button Flags". * \returns A bitwise or of \c EB_* values. */ - static uint16_t mouseButtonsFromQt(int b); + static quint16 mouseButtonsFromQt(int b); /** * Converts an event type as given by the \c ET_* constants to -- cgit v1.2.3-55-g7522 From 2ef394730ec4cd9803d22cd9eb2accd49b522c32 Mon Sep 17 00:00:00 2001 From: Dirk von Suchodoletz Date: Thu, 4 Nov 2010 17:43:37 +0100 Subject: Aktualisierung Projektdoku ... --- doc/LaTeX/devel/0100-build.tex | 6 +- doc/LaTeX/intro/0000-chapter.tex | 2 + doc/LaTeX/intro/0100-funktionen.tex | 7 +- doc/LaTeX/zusfassung.log | 333 ------------------------------------ doc/LaTeX/zusfassung.tex | 2 +- 5 files changed, 11 insertions(+), 339 deletions(-) delete mode 100644 doc/LaTeX/zusfassung.log diff --git a/doc/LaTeX/devel/0100-build.tex b/doc/LaTeX/devel/0100-build.tex index f5cf05e..10f22dc 100644 --- a/doc/LaTeX/devel/0100-build.tex +++ b/doc/LaTeX/devel/0100-build.tex @@ -3,10 +3,10 @@ Um den Pool Video Switch erfolgreich zu kompilieren, müssen zunächst die Quelldateien heruntergeladen werden. Hierzu sollte auf dem Arbeitsrechner ein Subversion-Client installiert sein. Ein Checkout kann in einem beliebigen Terminal erfolgen, wobei es zwei unterschiedliche Arten des Zugriffs gibt.\\ Anonym, nur Leserechte:\\ -\textbf{svn co http://svn.openslx.org/svn/pvs/trunk/pvs}\\ +\textbf{git clone git://git.openslx.org/pvs.git pvs}\\ -Mit Account, auch Schreibrechte (benutzer mit SSH Login ersetzen):\\ -\textbf{svn co svn+ssh://benutzer@openslx.org/srv/svn/pvs}\\ +Mit Account, auch Schreibrechte (hier wird vorausgesetzt, dass der Benutzer vorher seinen öffentlichen SSH-Schlüssel hinterlegt hat):\\ +\textbf{git clone git@openslx.org:pvs.git}\\ \section{Voraussetzungen} diff --git a/doc/LaTeX/intro/0000-chapter.tex b/doc/LaTeX/intro/0000-chapter.tex index 0339907..6b3319b 100644 --- a/doc/LaTeX/intro/0000-chapter.tex +++ b/doc/LaTeX/intro/0000-chapter.tex @@ -13,3 +13,5 @@ Neben den Hardware-basierten Varianten existieren inzwischen eine Reihe von Soft Dem soll ein eigener Ansatz entgegengesetzt werden, der die eingangs genannten Beschränkungen aufhebt und dem Anspruch einer modernen universitären computer-gestützten Lehre entgegenkommt. Das Projekt soll stufenweise von einer einfachen Basislösung in Rückmeldung mit den Lehrenden weiterentwickelt werden. Ein Open-Source-Ansatz gewährleistet zudem eine größere Nachhaltigkeit. Selbst bei einer Projekteinstellung können andere auf den Code weiterhin zurückgreifen und damit einerseits bestehende Installationen aktualisieren und andererseits eigene Entwicklungen schneller vorantreiben. Bei der Entwicklung steht nicht die Neuerfindung bereits vorhandener Technologien, sondern deren intelligente Verknüpfung im Vordergrund. So bieten bereits Techniken wie VNC oder Xorg/X11 viele notwendige Grundlagen, die um pfiffige Werkzeuge mit intuitiven Oberflächen erweitert werden sollen. Eine gute Anschauung bietet beispielsweise die Open Source Software ''Student Control Panel'' des Edubuntu-Linux (\ref{uscp}). + +Eine sehr vergleichbare Applikation ist iTalc. diff --git a/doc/LaTeX/intro/0100-funktionen.tex b/doc/LaTeX/intro/0100-funktionen.tex index 0c4536a..0dbac13 100644 --- a/doc/LaTeX/intro/0100-funktionen.tex +++ b/doc/LaTeX/intro/0100-funktionen.tex @@ -4,14 +4,17 @@ Damit ein Software-Video-Switch Hardwarelösungen ersetzen kann, muss zumindest eine gewisse Grundmenge an Funktionalität bereitgestellt werden. Diese Funktionen lassen sich in weiteren Schritten erweitern und können dabei über die der Hardwareimplementierungen hinausgehen. Gegebenenfalls muss eine Softwarelösung sich um Aspekte kümmern, die bei einer Hardwarelösung kaum ein Problem darstellen. Hierzu zählt das Thema der Abhörsicherheit. -\section{Wünschenswerte Basisfunktionen} +\section{Basisfunktionen} +In der verfügbaren Version wurden eine Reihe von Features realisiert. Hierzu zählt die Anzeige aller Display-Inhalte der Teilnehmerarbeitsplätze in verkleinerter Form auf einem separaten Steuer-PC, die Möglichkeit einzelne Teilnehmerarbeitsplätze auf den Dozenten-PC und damit auf den Beamer zu schalten, per Chat-Interface von der Dozentin Nachrichten auf die Bildschirme einzelner oder aller Teilnehmer zu schicken, die Inhalte des Dozenten-PC auf alle Teilnehmer-Displays zu schalten und das Sperrenvon Maus- und Tastatur der Teilnehmer. \begin{figure}[h] \center \includegraphics[width=11.5cm]{bilder/studentctlpanel.png} \caption{Student Control Panel des Edubuntu-Pakets, welches im Umfeld von Linux-Terminalservern eingesetzt werden kann.\label{uscp}} \end{figure} +Bei der Realisierung wurde einerseits auf die Absicherung der Steuerverbindungen und andererseits auf die Aspekte des Datenschutzes geachtet. Anders als bei vergleichbaren Produkten liegt in der Standardinstallation die Kontrolle bei den Teilnehmern. -\section{Funktionserweiterungen} +\section{Funktionserweiterungen} +In weiteren Schritten wurden Funktionen wie das Ãœbertragen von Dateien zwischen einzelnen Maschinen oder das Senden von Dateien an mehrere Teilnehmer gleichzeitig implementiert (\ref{}). diff --git a/doc/LaTeX/zusfassung.log b/doc/LaTeX/zusfassung.log deleted file mode 100644 index 4924af6..0000000 --- a/doc/LaTeX/zusfassung.log +++ /dev/null @@ -1,333 +0,0 @@ -This is pdfTeX, Version 3.1415926-1.40.10 (TeX Live 2009/Debian) (format=pdflatex 2010.9.4) 2 OCT 2010 17:00 -entering extended mode - restricted \write18 enabled. - %&-line parsing enabled. -**zusfassung.tex -(./zusfassung.tex -LaTeX2e <2009/09/24> -Babel and hyphenation patterns for english, usenglishmax, dumylang, noh -yphenation, loaded. -! Undefined control sequence. -l.2 \small - -? -! Undefined control sequence. -l.3 \section - *{Zusammenfassung} -? - -! LaTeX Error: Missing \begin{document}. - -See the LaTeX manual or LaTeX Companion for explanation. -Type H for immediate help. - ... - -l.3 \section* - {Zusammenfassung} -? -Missing character: There is no * in font nullfont! -Missing character: There is no Z in font nullfont! -Missing character: There is no u in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no a in font nullfont! -Missing character: There is no m in font nullfont! -Missing character: There is no m in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no f in font nullfont! -Missing character: There is no a in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no u in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no g in font nullfont! -Missing character: There is no D in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no P in font nullfont! -Missing character: There is no o in font nullfont! -Missing character: There is no o in font nullfont! -Missing character: There is no l in font nullfont! -Missing character: There is no V in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no d in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no o in font nullfont! -Missing character: There is no S in font nullfont! -Missing character: There is no w in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no c in font nullfont! -Missing character: There is no h in font nullfont! -Missing character: There is no ( in font nullfont! -Missing character: There is no P in font nullfont! -Missing character: There is no V in font nullfont! -Missing character: There is no S in font nullfont! -Missing character: There is no ) in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no A in font nullfont! -Missing character: There is no p in font nullfont! -Missing character: There is no p in font nullfont! -Missing character: There is no l in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no k in font nullfont! -Missing character: There is no a in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no o in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no , in font nullfont! -Missing character: There is no d in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no g in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no Z in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no m in font nullfont! -Missing character: There is no Z in font nullfont! -Missing character: There is no u in font nullfont! -Missing character: There is no g in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no d in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no O in font nullfont! -Missing character: There is no p in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no S in font nullfont! -Missing character: There is no L in font nullfont! -Missing character: There is no X in font nullfont! -Missing character: There is no - in font nullfont! -Missing character: There is no P in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no o in font nullfont! -Missing character: There is no j in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no k in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no a in font nullfont! -Missing character: There is no m in font nullfont! -Missing character: There is no R in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no c in font nullfont! -Missing character: There is no h in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no z in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no u in font nullfont! -Missing character: There is no m in font nullfont! -Missing character: There is no d in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no U in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no v in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no à in font nullfont! -Missing character: There is no ¤ in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no F in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no b in font nullfont! -Missing character: There is no u in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no g in font nullfont! -Missing character: There is no u in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no d in font nullfont! -Missing character: There is no a in font nullfont! -Missing character: There is no m in font nullfont! -Missing character: There is no L in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no h in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no u in font nullfont! -Missing character: There is no h in font nullfont! -Missing character: There is no l in font nullfont! -Missing character: There is no f in font nullfont! -Missing character: There is no à in font nullfont! -Missing character: There is no ¼ in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no K in font nullfont! -Missing character: There is no o in font nullfont! -Missing character: There is no m in font nullfont! -Missing character: There is no m in font nullfont! -Missing character: There is no u in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no k in font nullfont! -Missing character: There is no a in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no o in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no y in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no m in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no w in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no c in font nullfont! -Missing character: There is no k in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no l in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no w in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no d in font nullfont! -Missing character: There is no . in font nullfont! - -Overfull \hbox (20.0pt too wide) in paragraph at lines 3--5 -[] - [] - - -! LaTeX Error: Missing \begin{document}. - -See the LaTeX manual or LaTeX Companion for explanation. -Type H for immediate help. - ... - -l.6 I - nzwischen liegt die Version 3 vor ... -? -Missing character: There is no I in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no z in font nullfont! -Missing character: There is no w in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no c in font nullfont! -Missing character: There is no h in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no l in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no g in font nullfont! -Missing character: There is no t in font nullfont! -Missing character: There is no d in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no V in font nullfont! -Missing character: There is no e in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no s in font nullfont! -Missing character: There is no i in font nullfont! -Missing character: There is no o in font nullfont! -Missing character: There is no n in font nullfont! -Missing character: There is no 3 in font nullfont! -Missing character: There is no v in font nullfont! -Missing character: There is no o in font nullfont! -Missing character: There is no r in font nullfont! -Missing character: There is no . in font nullfont! -Missing character: There is no . in font nullfont! -Missing character: There is no . in font nullfont! - -Overfull \hbox (20.0pt too wide) in paragraph at lines 6--7 -[] - [] - - -! LaTeX Error: The font size command \normalsize is not defined: - there is probably something wrong with the class file. - -See the LaTeX manual or LaTeX Companion for explanation. -Type H for immediate help. - ... - -l.9 \normalsize - -? - -! LaTeX Error: The font size command \normalsize is not defined: - there is probably something wrong with the class file. - -See the LaTeX manual or LaTeX Companion for explanation. -Type H for immediate help. - ... - -l.10 \newpage - -? -[1]) -* -(Please type a command or say `\end') -* -(Please type a command or say `\end') -* -(Please type a command or say `\end') -*q - -! LaTeX Error: Missing \begin{document}. - -See the LaTeX manual or LaTeX Companion for explanation. -Type H for immediate help. - ... - -<*> q - -? \end -Type to proceed, S to scroll future error messages, -R to run without stopping, Q to run quietly, -I to insert something, -1 or ... or 9 to ignore the next 1 to 9 tokens of input, -H for help, X to quit. -? x - -Here is how much of TeX's memory you used: - 8 strings out of 495061 - 296 string characters out of 1182622 - 45108 words of memory out of 3000000 - 3283 multiletter control sequences out of 15000+50000 - 3640 words of font info for 14 fonts, out of 3000000 for 9000 - 28 hyphenation exceptions out of 8191 - 19i,4n,14p,221b,113s stack positions out of 5000i,500n,10000p,200000b,50000s -Output written on zusfassung.pdf (1 page, 914 bytes). -PDF statistics: - 6 PDF objects out of 1000 (max. 8388607) - 0 named destinations out of 1000 (max. 500000) - 1 words of extra memory for PDF output out of 10000 (max. 10000000) - diff --git a/doc/LaTeX/zusfassung.tex b/doc/LaTeX/zusfassung.tex index 213fedd..abc4140 100644 --- a/doc/LaTeX/zusfassung.tex +++ b/doc/LaTeX/zusfassung.tex @@ -3,7 +3,7 @@ \section*{Zusammenfassung} Der Pool Video Switch (PVS) ist eine Applikation, die seit einiger Zeit im Zuge des OpenSLX-Projekts am Rechenzentrum der Universität Freiburg und am Lehrstuhl für Kommunikationssysteme entwickelt wird. -Inzwischen liegt die Version 3 vor ... +Inzwischen liegt die Version 3 vor. \normalsize -- cgit v1.2.3-55-g7522 From ad0c21b66b6d73cba29c4ea90a1137495ff0ef8c Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Thu, 4 Nov 2010 22:16:05 +0100 Subject: Developer documentation for pvsinput --- doc/LaTeX/bilder/menu-key.png | Bin 0 -> 2179 bytes doc/LaTeX/bilder/vnc-frame-buttons.png | Bin 0 -> 7050 bytes doc/LaTeX/bilder/vnc-frame-buttons.xcf | Bin 0 -> 19912 bytes doc/LaTeX/devel/0100-build.tex | 2 + doc/LaTeX/devel/0100-build.tex~ | 69 ++++++ doc/LaTeX/devel/0300-pvs.tex | 158 ++++++++++++++ doc/LaTeX/devel/0300-pvs.tex~ | 384 +++++++++++++++++++++++++++++++++ doc/LaTeX/mystyle-pdf.tex | 2 + doc/LaTeX/user/0000-chapter.tex | 4 +- doc/LaTeX/user/0001-chapter.tex | 34 +++ 10 files changed, 652 insertions(+), 1 deletion(-) create mode 100644 doc/LaTeX/bilder/menu-key.png create mode 100644 doc/LaTeX/bilder/vnc-frame-buttons.png create mode 100644 doc/LaTeX/bilder/vnc-frame-buttons.xcf create mode 100644 doc/LaTeX/devel/0100-build.tex~ create mode 100644 doc/LaTeX/devel/0300-pvs.tex~ diff --git a/doc/LaTeX/bilder/menu-key.png b/doc/LaTeX/bilder/menu-key.png new file mode 100644 index 0000000..8cec826 Binary files /dev/null and b/doc/LaTeX/bilder/menu-key.png differ diff --git a/doc/LaTeX/bilder/vnc-frame-buttons.png b/doc/LaTeX/bilder/vnc-frame-buttons.png new file mode 100644 index 0000000..0a0a69d Binary files /dev/null and b/doc/LaTeX/bilder/vnc-frame-buttons.png differ diff --git a/doc/LaTeX/bilder/vnc-frame-buttons.xcf b/doc/LaTeX/bilder/vnc-frame-buttons.xcf new file mode 100644 index 0000000..faf5261 Binary files /dev/null and b/doc/LaTeX/bilder/vnc-frame-buttons.xcf differ diff --git a/doc/LaTeX/devel/0100-build.tex b/doc/LaTeX/devel/0100-build.tex index f5cf05e..66d94da 100644 --- a/doc/LaTeX/devel/0100-build.tex +++ b/doc/LaTeX/devel/0100-build.tex @@ -22,6 +22,8 @@ Der Pool Video Switch benötigt zum Kompilieren folgende Pakete (und ihre Abhän Dies wird nur benötigt, falls Unterstützung weiterer Sprachen implementiert werden soll, da in diesem Paket das Hilfsprogramm \textbf{linguist} enthalten ist. \item cmake >= 2.4.0\\ Eingesetztes Buildsystem und der Makefile-Generator. Um distributionsspezifische Pakete zu erzeugen wird CPack benutzt. + \item libxtst-dev, libxi-dev\\ + Diese Bibliotheken dienen zur Implementierung der Fernsteuerungsfunktionen. \end{itemize} \section{Kompilieren aus Quellen} diff --git a/doc/LaTeX/devel/0100-build.tex~ b/doc/LaTeX/devel/0100-build.tex~ new file mode 100644 index 0000000..66d94da --- /dev/null +++ b/doc/LaTeX/devel/0100-build.tex~ @@ -0,0 +1,69 @@ +\chapter{Erzeugen und Installieren der Applikation} +\index{Installieren} +Um den Pool Video Switch erfolgreich zu kompilieren, müssen zunächst die Quelldateien heruntergeladen werden. Hierzu sollte auf dem Arbeitsrechner ein Subversion-Client installiert sein. Ein Checkout kann in einem beliebigen Terminal erfolgen, wobei es zwei unterschiedliche Arten des Zugriffs gibt.\\ + +Anonym, nur Leserechte:\\ +\textbf{svn co http://svn.openslx.org/svn/pvs/trunk/pvs}\\ + +Mit Account, auch Schreibrechte (benutzer mit SSH Login ersetzen):\\ +\textbf{svn co svn+ssh://benutzer@openslx.org/srv/svn/pvs}\\ + + +\section{Voraussetzungen} +Der Pool Video Switch benötigt zum Kompilieren folgende Pakete (und ihre Abhängigkeiten): +\begin{itemize} + \item libvncserver-dev >= 0.9.3\\ + Eine angenehm kleine, wenn auch in C geschriebene, Bibliothek für die Erstellung von VNC Servern und Clients. + \item libx11-dev >= 1.3.3\\ + Diese Bibliothek wurde eingesetzt, um ausgewählten oder allen Zielrechnern den Zugriff auf Maus und Tastatur zu entziehen und den Bildschirm schwarz zu schalten. + \item libqt4-dev >= 4.5.3\\ + Sowohl die Server als auch die ClientGUI benutzen das Qt Framework in der Version 4. Ferner wird QtNetwork zur Kommunikation zwischen Server und Client benötigt und QtDbus zur Interprozesskommunikation zwischen Client-Daemon und GUI. + \item qt4-dev-tools >= 4.5.3\\ + Dies wird nur benötigt, falls Unterstützung weiterer Sprachen implementiert werden soll, da in diesem Paket das Hilfsprogramm \textbf{linguist} enthalten ist. + \item cmake >= 2.4.0\\ + Eingesetztes Buildsystem und der Makefile-Generator. Um distributionsspezifische Pakete zu erzeugen wird CPack benutzt. + \item libxtst-dev, libxi-dev\\ + Diese Bibliotheken dienen zur Implementierung der Fernsteuerungsfunktionen. +\end{itemize} + +\section{Kompilieren aus Quellen} +Sobald alle Voraussetzungen erfüllt und die Quellen installiert sind, kann das ausführbare Programm erzeugt werden. Falls gewünscht, kann zusätzlich in der Datei \textit{CMakeLists.txt} der Build-Type eingestellt werden. Gültige Werte sind \texttt{Debug} und \texttt{Release} und ihre Wirkung den zwei weiteren Zeilen zu entnehmen. +\begin{verbatim} +SET(CMAKE_BUILD_TYPE Debug) +SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -Wall") +SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native") +\end{verbatim} +Damit das Wurzelverzeichnis des Projekts weiterhin sauber bleibt (Ãœbersicht beibehalten, Arbeit mit SVN erleichtern), werden wir hier einen Out-Of-Source Build durchführen. Dies bedeutet, dass zum Kompilieren ein seperates Verzeichnis benutzt wird und sämtliche automatisch generierten Dateien sowie das Kompilat selbst hier abgelegt wird. In einem Terminal sollte nun in das Verzeichnis indem sich das Projekt befindet gewechselt werden, um folgende Befehle ausführen zu können:\\ + +\textbf{mkdir -p build}\\ +\textbf{cd build/}\\ +\textbf{cmake ..}\\ +\textbf{make}\\ + +Die verschiedenen Applikationen können nun folgendermaßen (in \textit{build/}) ausgeführt und getestet werden: +\begin{itemize} + \item Den Server starten: \textbf{./pvsmgr} + \item Den Server mit Touchscreenoberfläche starten: \textbf{./pvsmgrtouch} + \item Den ClientDaemon starten: \textbf{./pvs} + \item Die ClientGUI starten: \textbf{./pvsgui} +\end{itemize} + +\section{Installation} +\index{Paket!RPM} \index{Paket!DPKG} +Nachdem das Projekt kompiliert wurde, kann es (als Superuser z.B. root) auf dem lokalen System installiert werden:\\ +\textbf{make install}\\ + +Dabei werden folgende Dateien auf das aktuelle System übertragen:\\ +\textit{/usr/local/bin/pvsmgr}\\ +\textit{/usr/local/bin/pvs}\\ +\textit{/usr/local/bin/pvsgui}\\ +\textit{/usr/local/bin/pvsmgrtouch}\\ +\textit{/usr/local/share/dbus-1/services/org.openslx.pvs.service}\\ + +Ein Vorteil ist, dass nun ein seperates Ausführen des Client-Daemon nicht mehr notwendig ist. Dieser wird ab sofort automatisch gestartet und beendet, sobald die ClientGUI ausgeführt wurde.\\ + +Es ist ebenfalls möglich, distributionsspezifische Pakete zu erstellen (zur Zeit nur .deb):\\ +\textbf{make package}\\ + +Falls erfolgreich, befindet sich nun eine Installationsdatei (pvs--Linux.deb) in \textit{build/} die z.B. auf Debian-Derivaten mit \textbf{dpkg -i} installiert werden kann.\\ +Anmerkung: Falls Pakete für Rechner gebaut werden sollen, die vom Erstellungssystem her verschieden sind, muß der Schalter \texttt{-march=native} in der Datei \textit{CMakeLists.txt} angepasst werden! diff --git a/doc/LaTeX/devel/0300-pvs.tex b/doc/LaTeX/devel/0300-pvs.tex index 92b36f7..44f084f 100644 --- a/doc/LaTeX/devel/0300-pvs.tex +++ b/doc/LaTeX/devel/0300-pvs.tex @@ -175,6 +175,163 @@ erzeugt (siehe Konstruktor) und mittels der Methode \texttt{isCommand} erfährt Falls ja leitet der Dispatche die Nachricht an die Stelle \texttt{PVS::UpdateChatClients} sonst an die Stelle \texttt{PVS::chat\_receive}, wo die Änderungen in der Client-Liste vorgenommen werden oder die Gespräch-Nachricht der GUI abgegeben wird. +\section{Fernsteuerung} + +Die Fernsteuerung eines Clients erfolgt durch den clientseitigen Empfang von \texttt{PVSCOMMAND}-Nachrichten +mit dem Ident \texttt{INPUTEVENT}. +Dieser ist die Base64-kodierte Binärdarstellung eines Eingabeereignisses angehängt, das +clientseitig nachvollzogen werden soll. +\begin{table} + \begin{tabular}{|l|l|p{4cm}|p{4cm}|} + \hline + \textbf{\texttt{type}} & \textbf{\texttt{code}} & \textbf{\texttt{value}} & \textbf{Beschreibung} \\ + \hline + \multirow{2}{*}{\texttt{ET\_KEY}} & + \texttt{EC\_PRESS} & + \multirow{2}{4cm}{Auslösende Taste und gehaltene Modifikatortasten} & + Taste gedrückt \\ + \cline{2-2}\cline{4-4} + & + \texttt{EC\_RELEASE} & + & + Taste losgelassen\newline \\ + \hline + \multirow{2}{*}{\texttt{ET\_BUTTON}} & + \texttt{EC\_PRESS} & + \multirow{2}{4cm}{Auslösende und + gedrückte Maustasten} & + Maustaste gedrückt \\ + \cline{2-2}\cline{4-4} + & + \texttt{EC\_RELEASE} & + & + Maustaste losgelassen \\ + \hline + \texttt{ET\_POINTER} & + --- & + Absolute Koordinaten & + Mauszeiger bewegt \\ + \hline + \multirow{4}{*}{\texttt{ET\_SPECIAL}} & + \texttt{EC\_REBOOT} & + --- & + Systemneustart \\ + \cline{2-4} + & + \texttt{EC\_KILL\_X} & + --- & + X-Server töten \\ + \cline{2-4} + & + \texttt{EC\_SYSRQ} & + Kommando & + Magic-SysRq-Taste \\ + \cline{2-4} + & + \texttt{EC\_SAY\_HELLO} & + --- & + Harmloses Kommando für Funktionstest \\ + \hline + \end{tabular} + \caption{Mögliche Eingabeereignisse\label{tab:input-events}\index{Eingabeereignis!\texttt{InputEvent}}} +\end{table} +Tabelle \ref{tab:input-events} zeigt die möglichen Eingabeereignisse. +Eingabeereignisse werden durch die PVS Input Library (libpvsinput) behandelt, +deren Funktion an dieser Stelle dargestellt werden soll. + +\subsection{Behandlung eines Eingabeereignisses} +\index{Eingabeereignis!Behandlung} + +Ein Eingabeereignis durchläuft die folgenden Stationen: +\begin{enumerate} + \item Die Steuerkonsole generiert ein Eingabeereignis und übergibt dieses an die Netzwerktransportschicht. + \item Der PVS-Client empfängt das Eingabeereignis und übergibt die Behandlung einer Instanz der + Klasse \texttt{InputEventHandlerChain}\index{Klasse!\texttt{InputEventHandlerChain}}. + \item Die Klasse \texttt{InputEventHandlerChain} arbeitet eine Liste von Instanzen der Klasse + \texttt{InputEventHandler}\index{Klasse!\texttt{InputEventHandler}} der Reihe nach ab, um zu sehen, ob eine dieser Instanzen + das Ereignis bearbeiten kann. + \item Falls die betrachtete Instanz das Ereignis bearbeiten kann, wird geprüft, ob der dafür + nötige Sicherheitskontext vorhanden ist. + \item Falls dies ebenfalls der Fall ist, wird die entsprechende Aktion in einer implementierung + der abstrakten Methode \texttt{InputEventHandler::handle} ausgeführt und die weitere Bearbeitung + beendet. + \item Falls keiner der vorherigen Handler das Ereignis behandelt hat, wird es durch + die Klasse \texttt{PrivilegedHandlerForwarder}\index{Klasse!\texttt{PrivilegedHandlerForwarder}} an den zusätzlichen Daemon \texttt{pvsprivinputd} + weitergegeben. + \item Der \texttt{pvsprivinputd}\index{pvsprivinputd} besitzt ebenfalls eine \texttt{InputEventHandlerChain}, die + nach dem gleichen Muster bearbeitet wird. + Falls hierbei kein passender Handler gefunden wird, wird das Ereignis in eine Logdatei geschrieben + und die Bearbeitung aufgegeben. +\end{enumerate} +Ereignishandler sind implementiert für Maus- und Tastatureingaben unter Linux/X11 (mit Hilfe der XTest-Erweiterung), +sowie zur Simulation von Strg+Alt+Entf, Strg+Alt+Rück und Magic SysRq. + +\subsection{Erweiterungen} + +Weitere Eingabehandler lassen sich der libpvsinput hinzufügen. +Dazu muss eine Klasse bereitgestellt werden, die von der Template-Klasse +\texttt{InputEventHandler} erbt. +Diese akzeptiert eine variable Anzahl\footnote{% + Bis zu 16, diese Zahl lässt sich jedoch durch Neugenerierung + der Datei \texttt{src/input/detail/ typelist\_autogen.h} erhöhen. + Ein entsprechendes Programm ist im Quellcode zu finden.} +von Templateparametern, die verschiedene Aspekte der Eingabeereignisbehandlung konfigurieren. + +Durch die Angabe eines Templateparameters \texttt{input\_policy::Match<\textit{typ}, \textit{code}, \textit{wert}>}\index{Klasse!\texttt{input\_policy::Match}}, +wobei \textit{code} und \textit{wert} weggelassen werden können, wird spezifiziert, +dass der betreffende Handler nur für Eingabeereignisse mit den entsprechenden Feldwerten aufgerufen wird. +Wird kein solcher Parameter angegeben, wird der betreffende Handler niemals aufgerufen. +Mehrere \texttt{Match}-Parameter werden mittels logischem ODER verknüpft. + +Ein Templateparameter der Form \texttt{input\_policy::Require<\textit{Merkmal\dots}>}\index{Klasse!\texttt{input\_policy::Require}} +gibt an, dass dieser Handler nur auf einem System lauffähig ist, das die entsprechenden \textit{Merkmale} +aufweist. +Eine Liste von Systemmerkmalen wird in der Datei \texttt{src/input/detail/systemTraits.h} +zentral verwaltet. +Hier lassen sich neue Merkmale mit Hilfe des Makros \texttt{DEFINE\_SYSTEM\_TRAIT} definieren +und mit Hilfe des Präprozessors zwischen den Zeilen \texttt{BEGIN\_SYSTEM\_TRAITS} und +\texttt{END\_SYSTEM\_TRAITS} einfügen. +Diese Vorgehensweise beschränkt die Nutzung des Präprozessors auf eine Datei. +Wird kein \texttt{Require}-Parameter angegeben, so wird der entsprechende Handler als +immer lauffähig eingestuft. +Mehrere \texttt{Require}-Parameter werden mittels logischem ODER verknüpft. + +Weiterhin kann ein Templateparameter der Form \texttt{input\_policy::Security<\textit{Richtlinie}>}\index{Klasse!\texttt{input\_policy::Security}} +angegeben werden. Hierbei stehen für \textit{Richtlinie} die Klassen \texttt{input\_policy::AllowLocal\-OrPrivileged} +oder \texttt{input\_policy::AllowEverybody} zur Verfügung. +Hierdurch wird bestimmt, welche Sicherheitsanforderungen zur Ausführung des Handlers erfüllt sein +müssen. +Die Richtlinie \texttt{input\_policy::AllowLocalOrPrivileged} bestimmt, dass nur Benutzer, +deren Sitzung lokal ist, oder solche, die nach der Konfiguration des pvsprivinputd als privilegiert +gelten, die entsprechende Aktion aufrufen dürfen (hierbei geht es um den Benutzer, der den PVS-Client +ausführt, und nicht den Benutzer, der die Steuerkonsole bedient). +Die Richtlinie \texttt{input\_policy::AllowEverybody} erlaubt die Ausführung der Aktion ohne +besonderen Sicherheitskontext. +Neue Sicherheitsrichtlinien der Form \texttt{input\_policy::Security<\textit{T}>} lassen sich +nutzen, indem eine Klasse \textit{T} eingeführt wird, die eine Methode\\ +\makebox[1cm]{}\texttt{static bool allow(InputEventContext const*)}\\ +besitzt, an die die Entscheidung, ob eine Aktion zuzulassen ist, delegiert wird. + +Der zu implementierende Eingabehandler braucht weiterhin eine Implementierung der abstrakten +Methode\\ +\makebox[1cm]{}\texttt{virtual void handle(InputEvent const\&, InputEventContext const*)},\\ +in der die entsprechende Aktion ausgeführt wird. + +Die Aufnahme des neuen Handlers in die Liste der abzuarbeitenden Handle erfolgt, +je nachdem ob erweiterte Berechtigungen zur Bearbeitung notwendig sind, +in einer der Dateien \texttt{privilegedHandlerChain.cpp} oder \texttt{unprivilegedHandler\-Chain.cpp} +in \texttt{src/input}, wo dem Kettenaufruf eine Zeile der Form\\ +\makebox[1cm]{}\texttt{.add<\textit{Handler}>()}\\ +hinzugefügt wird. +Die Verwendung des Präprozessors zum Ausschluss von Handlern, die auf dem +Zielsystem nicht lauffähig sind, ist an dieser Stelle nicht notwendig und wird durch die +\texttt{Require}-Richtlinie umgesetzt. +Notwendig ist lediglich, die Ãœbersetzung des Handlers auf inkompatiblen Systemen zu verhindern. +Dies kann mit Hilfe des Build-Systems oder durch die Klammerung der gesamten Ãœbersetzungseinheit +in Präprozessorbedingungen geschehen. + +Eine API-Referenz zur libpvsinput (Stand: 4.~November~2010) findet sich im Projektwiki +unter \url{http://lab.openslx.org/projects/pvs/wiki/RemoteKeyMouse}. \section{Netzwerkkommunikation} \index{Netzwerkkommunikation} @@ -216,6 +373,7 @@ PVSCOMMAND & VNC & NO & Verbiete Zugriff \\ PVSCOMMAND & PING & & \\ PVSCOMMAND & VNCREQUEST & & \\ PVSCOMMAND & VNCSRVRESULT & result code & Der Rückgabewert des pvs-vncsrv Skripts \\ +PVSCOMMAND & INPUTEVENT & Base64-kodierte InputEvent-Struktur & Fernsteuerung \\ PVSMESSAGE & BROADCAST & MESSAGE &\\ PVSMESSAGE & clientToAdd & & Client hinzufügen (Chat)\\ PVSMESSAGE & clientToRemove & & Client entfernen (Chat)\\ diff --git a/doc/LaTeX/devel/0300-pvs.tex~ b/doc/LaTeX/devel/0300-pvs.tex~ new file mode 100644 index 0000000..ac88e46 --- /dev/null +++ b/doc/LaTeX/devel/0300-pvs.tex~ @@ -0,0 +1,384 @@ +\chapter{Aufbau und Funktionsweise des PVS} +\index{Aufbau} \index{Funktionsweise} \index{Konzept} + +Generelles Konzept + +\section{Einzelne Komponenten} +\index{Komponenten} + +\subsection{Zuordnung von Konsole und Clients} +\input{devel/0310-service-discovery} + +\section{Ãœberblick über Aktivitäten auf Clients} + +\subsection{Projektion an Alle} +\index{Projektion} +Eine wichtige Eigenschaft des PVS ist die Verwaltung von Projektionen zwischen mehreren Clients. Eine Projektion ist hierbei das Anzeigen des Bildschirminhalts eines Clients - der sogenannten Source oder Quelle - auf einem oder mehreren anderen Clients - den Targets oder Zielen der Projektion. +Die für die Projektion benötigten Verbindungsdaten wie Passwort und IP werden von jedem Client bei der Anmeldung an der Steuerkonsole übermittelt und in einer Liste von PVSConnection Objekten in der Klasse \textit{PVSConnectionManager} gespeichert. Diese zentrale Verwaltung hat mehrere Vorteile: +\begin{itemize} + \item Die Quelle einer Projektion muss keine Aktion ausführen und kann passiv bleiben. + \item Redundanz der Daten wird verhindert, da diese auch in der Steuerkonsole zur Darstellung der Thumbnails benötigt werden. + \item Das Nachrichtenaufkommen wird reduziert, da lediglich eine Nachricht bei der Anmeldung an der Steuerkonsole übermittelt wird. +\end{itemize} + +Bei der Auswahl der Quelle und Ziele ist zu beachten, dass man für jede Projektion jeweils nur eine Quelle jedoch mehrere Ziele auswählen kann. +Quelle und Ziel müssen außerdem verschiedenen Kriterien genügen. +\begin{itemize} + \item Eine Quelle darf nicht gleichzeitig Ziel einer Projektion sein. + \item Ein Ziel einer Projektion darf nicht Ziel einer anderen Projektion sein. + \item Eine Quelle darf mehrfach als Quelle ausgewählt werden. +\end{itemize} +Diese Einschränkungen werden in der Steuerkonsole durchgesetzt, indem im Zielauswahldialog die Zielmenge eingeschränkt wird. +Siehe hierzu auch \ref{pvs-console-projection} Projektion. + +Der Projektionsvorgang an sich besteht aus mehreren Teilen. Wird eine Projektion angefordert, wird überprüft, ob auf der Quelle ein VNC Server gestartet ist. Falls nicht, wird versucht, einen VNC Server zu starten. Ist dies erfolgreich, so sendet die Steuerkonsole das entsprechende Tripel (IP, Passwort und Port der Quelle) an alle ausgewählten Ziele. Clients, welche eine Projektionsaufforderung erhalten, verbinden sich dann mit den Verbindungsdaten zum VNC Server der Quelle. Um die Einstellbarkeit der Qualität einer Projektion zu ermöglichen, kann die Steuerkonsole einen von drei Qualitätswerten an die Zielclients übermitteln. Siehe hierzu auch \ref{pvs-console-quality} Qualitätsoptionen. + + +\subsection{Projektion eines Clients auf dem Beamer} +\index{Beamer} + +Die Projektion eines Clients an den Beamer unterscheidet sich im Wesentlichen nicht von anderen Projektionen. Lediglich ist das Ziel der Projektion hierbei der Dozentenpc bzw. der PC, welcher an den Beamer angeschlossen ist. Eine spezielle Auszeichnung des Beamers erfolgt nicht. Die Anzahl der Ziele wird hierbei nicht beschränkt, da es wünschenswert sein kann, den auf dem Beamer dargestellten Bildschirminhalt auch gleichzeitig auf anderen Clients darzustellen. + +\subsection{Chat- und Informationskanal} +\index{Chat} + +Es gibt 2 Möglichkeiten um Kontakt mit den Clients aufzunehmen. Die erste ist über den Chat, wo Nachrichten sowohl über den offentlichen Kanal als +auch über einen privaten Kanäle verteilt werden können, und die zweite vom PVSManager aus über den Informationskanal. +Der Informationskanal ermöglich das Versenden von Nachrichten, die dringend zu lesen sind, an die Clients. +Im Gegenteil zum Chat erscheinen solche Nachrichten nicht im Chatfenster sondern in einem Pop-Up-Fenster und werden vom Bildschirm entfernt erst wenn man sie +als gelesen markiert durch das Drucken auf dem Knopf \textit{'OK'}. +\\ +\\ +\textbf{Behandlung der Nachrichten im Server} +\\ +\\ +Chat-Nachtichten werden von Server in der Klasse \texttt{PVSConnectionManager} mittels der Methode \texttt{onChat} behandelt. Dort wird aus der Nachrit den Empfänger +und den Absender ausglesen und die Nachricht an beide versendet. So gilt das Empfangen eine eigene Nachricht als Bestätigung, dass die Nachricht ordentlich vom Server +behandelt und versendet wurde. Das Gestalt von solchen Nachrichten sieht folgendermaßen aus + +\begin{center} + PVSMSG +\end{center} +\begin{center} +\begin{tabular}{|l | p{3cm} | p{3cm} | p{3cm}|} +\hline +Type & Ident & Msg & sndID\\ +\hline +\texttt{PVSMESSAGE} & \texttt{} & \texttt{<:} & \texttt{<}\\ +\end{tabular} +\end{center} + +Informationsnachrichten werden ausschließlich vom PVSManager versendet.Dies geschiet in der Klasse \texttt{ConnectionList} mittels der Methode \texttt{on\_Message}. + +\begin{center} + PVSMSG +\end{center} +\begin{center} +\begin{tabular}{|l | l | p{6cm} | p{6cm}} +\hline +Type & Ident & Msg\\ +\hline +\texttt{PVSMESSAGE} & \texttt{BROADCAST} & \texttt{} \\ +\end{tabular} +\end{center} + +Informationnachrichten können außerdem einen oder mehrere Clients sperren, wenn sie den Ident \texttt{LOCKSTATION} enthalten. Sobald ein Client die Nachricht empfängt, +wird diese auf dem Bilschirm angezeigt und 10 Sekunden später wird der Client gesperrt. + +Abgesehen von der Behandlung der Nachrichten muss sich der Server darum kümmern, dass jeder verbunde Client über alle nötige Informationionen verfügt damit er +Nachrichten mit andren Clients austauschen kann. Dies wird folgendermaßen erledigt: +\begin{itemize} + \item \textbf{Einfügen eines Clients:} um die Verwaltung von Clients kümmert sich die Klasse \texttt{PVSConnectionManager}, in der die Methode \texttt{onClientNew} für das Einfügen +von neuen Clients zuständigt ist. Sowald ein neuer Client in der Client-Liste des Servers eingefügt wird, wird an ihn die Liste aller im Server bereits angemeldete +Clients geschickt. Dazu dient die Methode \texttt{sendEventToClients}. + +Bis hier ist der neue Client noch unbekannt für den Rest der Nutzer. Der neuer Client wird erst bekannt gegeben sobald er vom Server einen Benutzername +zugewissen bekommen hat. Da es sein kann, dass den Name, mit dem der neue Client sich beim Server anmelden wollte, +bereits vergeben ist und muss unter Umständen verändert werden. Diese Zuweisung findet in der Methode \texttt{onLoginUsername} statt, +wo nicht nur alle andere Clients sondern auch der neue Client darüber informiert werden. Auch hier kümmert sich die Methoder \texttt{sendEventToClients} +ums Vesenden der entsprechenden Informationen. + + \item \textbf{Entfernen eines Clients:} das Entfernen von Clients wird von der Methode +\\ +\texttt{onClientRemove} erledigt, wo analog wie +Oben alle Clients darüber informiert werden. +\end{itemize} + +Für dei Ãœbermittlung solche Informationen werden Nachrichten mit folgenden Gestal benutzt + +\begin{center} + PVSMSG +\end{center} +\begin{center} +\begin{tabular}{|l | l | p{6cm} |} +\hline +Type & Ident & Msg\\ +\hline +\texttt{PVSMESSAGE} & \texttt{} & \texttt{:} \\ +\end{tabular} +\end{center} + +Es gibt drei unterschiedliche Befehle, die welche Änderung in der localen Client-Liste der Clients vorgenommen werden soll angeben. +\begin{enumerate} + \item \texttt{clientToAdd} +\item \texttt{clientToRemove} +\item \texttt{assignedName} +\end{enumerate} + +Wie es bei Servern gewöhnt ist, werden alle relevante Ereignisse in Log-Dateien protokolliert. Ereignisse werden im Chat-Log mit folgendem +Befehl eingetragen + +\begin{center} +\texttt{ConsoleLog writeChat()} +\end{center} + +\textbf{Chat-Interface der Steuerkonsole} +\\ +\\ +So wie alle Clients ist der PVSManager auch ein Teilnehmer im Chat. Der PVSManager steht wie alle andere Teilnehmer auch in der Nutzer-Liste +jedes Chat-Fenster und kann ebenfalls über private Nachrichten direkt angesprochen werden. Die Arbeitsweise dieser Chat-Interface ist sehr simple. +Da sie sich im Server befindet, müssen einfach alle Ereignise (Nachrichten senden ist die einzige Ausnahme) von der Klasse \texttt{PVSConnectionManager} +an die Klasse \texttt{MainWindow} weitergegeben werden. Dies kümmert sich darum, alle Informationen zu verarbeiten und diesein der Chat-Fenster der +Steuerkonsole anzuzeigen. + +Folgende Methoden der Klasse \texttt{MainWindow} ermöglichen das Anzeigen einer empfangenen Nachricht im Chat-Fenster der Steuerkonsole und Änderungen (Clients einfügen +und entfernen) in der sowohl im Chat-Fenster als auch in der Steuerkonsole angezeigten Client-Liste. +\\ +\\ +\texttt{receiveChatMsg(, , )} +\\ +\texttt{removeConnection(*pvsClient)} +\\ +\texttt{addConnection(*pvsClient)} +\\ +\\ +Alle diese Methoden werden im Gegensatz von der Methode \texttt{sendChatMsg(PVSMsg myMsg)} von der Klasse \texttt{PVSConnectionManager} aus ausgeführt. Da alle durchs +Netz empfangene Nachrichten müssen an die GUI-Weitergegeben werden. Beim Versenden von Nachrichten funktioniert es genau umgekehrt. Die Nachricht wird +vom Nutzer in der GUI eingegeben und muss an die Klasse \texttt{PVSConnectionManager} weitergeleitet werden, damit diese ins Netz gesendet wird. Darum kümmert +sich die Methode in der Klasse \texttt{MainWindow}. +\\ +\\ +\texttt{MainWindow::sendChatMsg(PVSMsg myMsg)} +\\ +\\ +\textbf{Chat-Clients} +\\ +\\ +So weit haben wir die Funtionsweisen des Servers im Bezug auf dem Chat kennengelernt. +Nun wird erläutert wie die einzelnen Clients die Nachrichten bearbeiten. +\\ +\\ +Auf der Client-Seite in der Klasse \texttt{PVSConnectionServer} werden alle Nachrichten des PVS-Protokolls empfangen und gefiltert (Siehe Methode \texttt{handleClientMsg}). +Nachrichten mit dem Ident \texttt{PVSMESSAGE} werden durch den Dispatcher direkt an die Klasse \texttt{PVSChatClient} weitergeleitet, wo die Methode \texttt{receive} feststellen wird, +ob es sich dabei um eine Gespräch-Nachricht oder eine Befehl-Nachricht handelt. Um es feststellen zu können, wird aus der empfangenen Nachricht ein PVSChatMsg-Objekt +erzeugt (siehe Konstruktor) und mittels der Methode \texttt{isCommand} erfährt man ob es sich um einen Befehl handelt oder nicht. +Falls ja leitet der Dispatche die Nachricht an die Stelle \texttt{PVS::UpdateChatClients} sonst an die Stelle \texttt{PVS::chat\_receive}, wo die Änderungen in der Client-Liste +vorgenommen werden oder die Gespräch-Nachricht der GUI abgegeben wird. + +\section{Fernsteuerung} + +Die Fernsteuerung eines Clients erfolgt durch den clientseitigen Empfang von \texttt{PVSCOMMAND}-Nachrichten +mit dem Ident \texttt{INPUTEVENT}. +Dieser ist die Base64-kodierte Binärdarstellung eines Eingabeereignisses angehängt, das +clientseitig nachvollzogen werden soll. +\begin{table} + \begin{tabular}{|l|l|p{4cm}|p{4cm}|} + \hline + \textbf{\texttt{type}} & \textbf{\texttt{code}} & \textbf{\texttt{value}} & \textbf{Beschreibung} \\ + \hline + \multirow{2}{*}{\texttt{ET\_KEY}} & + \texttt{EC\_PRESS} & + \multirow{2}{4cm}{Auslösende Taste und gehaltene Modifikatortasten} & + Taste gedrückt \\ + \cline{2-2}\cline{4-4} + & + \texttt{EC\_RELEASE} & + & + Taste losgelassen\newline \\ + \hline + \multirow{2}{*}{\texttt{ET\_BUTTON}} & + \texttt{EC\_PRESS} & + \multirow{2}{4cm}{Auslösende und + gedrückte Maustasten} & + Maustaste gedrückt \\ + \cline{2-2}\cline{4-4} + & + \texttt{EC\_RELEASE} & + & + Maustaste losgelassen \\ + \hline + \texttt{ET\_POINTER} & + --- & + Absolute Koordinaten & + Mauszeiger bewegt \\ + \hline + \multirow{4}{*}{\texttt{ET\_SPECIAL}} & + \texttt{EC\_REBOOT} & + --- & + Systemneustart \\ + \cline{2-4} + & + \texttt{EC\_KILL\_X} & + --- & + X-Server töten \\ + \cline{2-4} + & + \texttt{EC\_SYSRQ} & + Kommando & + Magic-SysRq-Taste \\ + \cline{2-4} + & + \texttt{EC\_SAY\_HELLO} & + --- & + Harmloses Kommando für Funktionstest \\ + \hline + \end{tabular} + \caption{Mögliche Eingabeereignisse\label{tab:input-events}\index{Eingabeereignis!\texttt{InputEvent}}} +\end{table} +Tabelle \ref{tab:input-events} zeigt die möglichen Eingabeereignisse. +Eingabeereignisse werden durch die PVS Input Library (libpvsinput) behandelt, +deren Funktion an dieser Stelle dargestellt werden soll. + +\subsection{Behandlung eines Eingabeereignisses} +\index{Eingabeereignis!Behandlung} + +Ein Eingabeereignis durchläuft die folgenden Stationen: +\begin{enumerate} + \item Die Steuerkonsole generiert ein Eingabeereignis und übergibt dieses an die Netzwerktransportschicht. + \item Der PVS-Client empfängt das Eingabeereignis und übergibt die Behandlung einer Instanz der + Klasse \texttt{InputEventHandlerChain}\index{Klasse!\texttt{InputEventHandlerChain}}. + \item Die Klasse \texttt{InputEventHandlerChain} arbeitet eine Liste von Instanzen der Klasse + \texttt{InputEventHandler}\index{Klasse!\texttt{InputEventHandler}} der Reihe nach ab, um zu sehen, ob eine dieser Instanzen + das Ereignis bearbeiten kann. + \item Falls die betrachtete Instanz das Ereignis bearbeiten kann, wird geprüft, ob der dafür + nötige Sicherheitskontext vorhanden ist. + \item Falls dies ebenfalls der Fall ist, wird die entsprechende Aktion in einer implementierung + der abstrakten Methode \texttt{InputEventHandler::handle} ausgeführt und die weitere Bearbeitung + beendet. + \item Falls keiner der vorherigen Handler das Ereignis behandelt hat, wird es durch + die Klasse \texttt{PrivilegedHandlerForwarder}\index{Klasse!\texttt{PrivilegedHandlerForwarder}} an den zusätzlichen Daemon \texttt{pvsprivinputd} + weitergegeben. + \item Der \texttt{pvsprivinputd}\index{pvsprivinputd} besitzt ebenfalls eine \texttt{InputEventHandlerChain}, die + nach dem gleichen Muster bearbeitet wird. + Falls hierbei kein passender Handler gefunden wird, wird das Ereignis in eine Logdatei geschrieben + und die Bearbeitung aufgegeben. +\end{enumerate} +Ereignishandler sind implementiert für Maus- und Tastatureingaben unter Linux/X11 (mit Hilfe der XTest-Erweiterung), +sowie zur Simulation von Strg+Alt+Entf, Strg+Alt+Rück und Magic SysRq. + +\subsection{Erweiterungen} + +Weitere Eingabehandler lassen sich der libpvsinput hinzufügen. +Dazu muss eine Klasse bereitgestellt werden, die von der Template-Klasse +\texttt{InputEventHandler} erbt. +Diese akzeptiert eine variable Anzahl\footnote{% + Bis zu 16, diese Zahl lässt sich jedoch durch Neugenerierung + der Datei \texttt{src/input/detail/ typelist\_autogen.h} erhöhen. + Ein entsprechendes Programm ist im Quellcode zu finden.} +von Templateparametern, die verschiedene Aspekte der Eingabeereignisbehandlung konfigurieren. + +Durch die Angabe eines Templateparameters \texttt{input\_policy::Match<\textit{typ}, \textit{code}, \textit{wert}>}\index{Klasse!\texttt{input\_policy::Match}}, +wobei \textit{code} und \textit{wert} weggelassen werden können, wird spezifiziert, +dass der betreffende Handler nur für Eingabeereignisse mit den entsprechenden Feldwerten aufgerufen wird. +Wird kein solcher Parameter angegeben, wird der betreffende Handler niemals aufgerufen. +Mehrere \texttt{Match}-Parameter werden mittels logischem ODER verknüpft. + +Ein Templateparameter der Form \texttt{input\_policy::Require<\textit{Merkmal\dots}>}\index{Klasse!\texttt{input\_policy::Require}} +gibt an, dass dieser Handler nur auf einem System lauffähig ist, das die entsprechenden \textit{Merkmale} +aufweist. +Eine Liste von Systemmerkmalen wird in der Datei \texttt{src/input/detail/systemTraits.h} +zentral verwaltet. +Hier lassen sich neue Merkmale mit Hilfe des Makros \texttt{DEFINE\_SYSTEM\_TRAIT} definieren +und mit Hilfe des Präprozessors zwischen den Zeilen \texttt{BEGIN\_SYSTEM\_TRAITS} und +\texttt{END\_SYSTEM\_TRAITS} einfügen. +Diese Vorgehensweise beschränkt die Nutzung des Präprozessors auf eine Datei. +Wird kein \texttt{Require}-Parameter angegeben, so wird der entsprechende Handler als +immer lauffähig eingestuft. +Mehrere \texttt{Require}-Parameter werden mittels logischem ODER verknüpft. + +Weiterhin kann ein Templateparameter der Form \texttt{input\_policy::Security<\textit{Richtlinie}>}\index{Klasse!\texttt{input\_policy::Security}} +angegeben werden. Hierbei stehen für \textit{Richtlinie} die Klassen \texttt{input\_policy::AllowLocal\-OrPrivileged} +oder \texttt{input\_policy::AllowEverybody} zur Verfügung. +Hierdurch wird bestimmt, welche Sicherheitsanforderungen zur Ausführung des Handlers erfüllt sein +müssen. +Die Richtlinie \texttt{input\_policy::AllowLocalOrPrivileged} bestimmt, dass nur Benutzer, +deren Sitzung lokal ist, oder solche, die nach der Konfiguration des pvsprivinputd als privilegiert +gelten, die entsprechende Aktion aufrufen dürfen (hierbei geht es um den Benutzer, der den PVS-Client +ausführt, und nicht den Benutzer, der die Steuerkonsole bedient). +Die Richtlinie \texttt{input\_policy::AllowEverybody} erlaubt die Ausführung der Aktion ohne +besonderen Sicherheitskontext. +Neue Sicherheitsrichtlinien der Form \texttt{input\_policy::Security<\textit{T}>} lassen sich +nutzen, indem eine Klasse \textit{T} eingeführt wird, die eine Methode\\ +\makebox[1cm]{}\texttt{static bool allow(InputEventContext const*)}\\ +besitzt, an die die Entscheidung, ob eine Aktion zuzulassen ist, delegiert wird. + +Der zu implementierende Eingabehandler braucht weiterhin eine Implementierung der abstrakten +Methode\\ +\makebox[1cm]{}\texttt{virtual void handle(InputEvent const\&, InputEventContext const*)},\\ +in der die entsprechende Aktion ausgeführt wird. + +Die Aufnahme des neuen Handlers in die Liste der abzuarbeitenden Handle erfolgt, +je nachdem ob erweiterte Berechtigungen zur Bearbeitung notwendig sind, +in einer der Dateien \texttt{privilegedHandlerChain.cpp} oder \texttt{unprivilegedHandler\-Chain.cpp} +in \texttt{src/input}, wo dem Kettenaufruf eine Zeile der Form\\ +\makebox[1cm]{}\texttt{.add<\textit{Handler}>()}\\ +hinzugefügt wird. +Die Verwendung des Präprozessors zum Ausschluss von Handlern, die auf dem +Zielsystem nicht lauffähig sind, ist an dieser Stelle nicht notwendig und wird durch die +\texttt{Require}-Richtlinie umgesetzt. +Notwendig ist lediglich, die Ãœbersetzung des Handlers auf inkompatiblen Systemen zu verhindern. +Dies kann mit Hilfe des Build-Systems oder durch die Klammerung der gesamten Ãœbersetzungseinheit +in Präprozessorbedingungen geschehen. + +Eine API-Referenz zur libpvsinput (Stand: 4.~November~2010) findet sich im Projektwiki. + +\section{Netzwerkkommunikation} +\index{Netzwerkkommunikation} + +\subsection{PVS-Protokoll} +\index{Protokoll!PVS} \index{Protokoll} +Im Zuge der Entwicklung des PVS wurde ein sehr einfaches Messagingprotokoll entwickelt. +Die Nachrichten bzw. Messages bestehen dabei aus Header, Nachrichtentyp, Ident und dem eigentlichen Nachrichtentext. Die einzelnen Nachrichtenteile, welche bis auf den Header selbst definiert werden können, werden verknüpft und versendet. Es sind schon Nachrichtentypen vordefiniert, welche sich nur durch unterschiedliche Dispatcher unterscheiden. +Bereits vorhandene Typen sind COMMAND, LOGIN, MESSAGE und UNKNOWN. Die Dispatcher (\_commandDispatcher, \_loginDispatcher und \_chatDispatcher) befinden sich im Client in der Klasse \texttt{ServerConnection}, in der Steuerkonsole in der Klasse \texttt{ClientConnection} bzw. \texttt{ListenServer}. Ein Ident wie z.B. Username, Befehl oder Beschreibung des Nachrichteninhalts dient zur Unterscheidung verschiedener Nachrichten mit demselben Nachrichtentyp, wobei die Nachricht dann den dem Ident entsprechenden Nachrichtentext enthält. +Um eine Funktion zur Behandlung einer bestimmten Nachricht zu definieren, wird diese Funktion als Handler mit dem entsprechenden Dispatcher verknüpft. Im PVS-Client beispielsweise befindet sich der Dispatcher für Nachrichten vom Typ Command in der Klasse \texttt{pvsServerConnection}, daher wird in der Klasse \texttt{pvs} die Funktion \texttt{void PVS::onCommand(PVSMsg cmdMessage)} wie folgt als Handler registriert: +\texttt{\_pvsServerConnection->addCommandHandler("*", this, \&PVS::onCommand)}. Erhält nun der Client eine Nachricht vom Typ COMMAND, so wird die Funktion onCommand mit dem entsprechenden Nachrichtenobjekt aufgerufen. Auf die eigentliche Nachricht kann dann über die Methoden \texttt{getIdent()} und \texttt{getMessage()} des Objektes zugegriffen werden. + +\subsection{PVS-Messages} +\index{Message!PVS} \index{Message} +In Tabelle \ref{tab:messagelist} sind die Messages, die zwischen den einzelnen PVS Komponenenten ausgetauscht werden, aufgelistet. +Der Nachrichtentyp gibt dabei an, welcher Dispatcher die Nachricht behandelt. +Der Ident einer Nachricht wird zur Verarbeitung einer empfangenen Nachricht in der aufzurufenden Funktion benötigt (Unterscheidung von anderen Nachrichten gleichen Typs). + +\begin{table} +\begin{center} +\begin{tabular}{l | l | p{2cm} | p{4cm}} +\label{pvs-msg-liste} +Nachrichtentyp & Nachrichten Ident & Inhalt & Beschreibung \\ +\hline +PVSCOMMAND & PROJECT & hostname port password quality & Hostname, Port, Passwort und Qualität des VNC Servers zu dem verbunden werden soll (durch Space getrennt) \\ +PVSCOMMAND & UNPROJECT & & \\ +PVSCOMMAND & LOCKSTATION & & \\ +PVSCOMMAND & LOCKSTATION & Message & Client mit Nachricht sperren \\ +PVSCOMMAND & UNLOCKSTATION & & \\ +PVSLOGIN & USERNAME & username & Client Benutzername \\ +PVSLOGIN & PASSWORD & password & Serverpasswort \\ +PVSLOGIN & ID & id & \\ +PVSLOGIN & FAILED & "`Wrong Password"' & Wird bei falschem Passwort gesendet \\ +PVSCOMMAND & PORT & port & \\ +PVSCOMMAND & PASSWORD & password & VNC Passwort\\ +PVSCOMMAND & RWPASSWORD & rwpassword & Passwort für den Zugriff auf die Tastatur und Maus \\ +PVSCOMMAND & VNC & YES & Erlaube Zugriff \\ +PVSCOMMAND & VNC & NO & Verbiete Zugriff \\ +PVSCOMMAND & PING & & \\ +PVSCOMMAND & VNCREQUEST & & \\ +PVSCOMMAND & VNCSRVRESULT & result code & Der Rückgabewert des pvs-vncsrv Skripts \\ +PVSCOMMAND & INPUTEVENT & Base64-kodierte InputEvent-Struktur & Fernsteuerung \\ +PVSMESSAGE & BROADCAST & MESSAGE &\\ +PVSMESSAGE & clientToAdd & & Client hinzufügen (Chat)\\ +PVSMESSAGE & clientToRemove & & Client entfernen (Chat)\\ +PVSMESSAGE & assignedName & & Festgelegter Name (Chat)\\ +\end{tabular} +\end{center} +\caption{Liste der PVS Messages} +\label{tab:messagelist} +\end{table} diff --git a/doc/LaTeX/mystyle-pdf.tex b/doc/LaTeX/mystyle-pdf.tex index d2993f4..034ae31 100644 --- a/doc/LaTeX/mystyle-pdf.tex +++ b/doc/LaTeX/mystyle-pdf.tex @@ -108,3 +108,5 @@ % pdftitle={PVS Dokumentation} pdftitle={GZ:if expand("\%") == ""|browse confirm w|else|confirm w|endif} ]{hyperref} + +\usepackage{multirow} \ No newline at end of file diff --git a/doc/LaTeX/user/0000-chapter.tex b/doc/LaTeX/user/0000-chapter.tex index ae9276d..2c570f8 100644 --- a/doc/LaTeX/user/0000-chapter.tex +++ b/doc/LaTeX/user/0000-chapter.tex @@ -50,7 +50,9 @@ Sollte eine Nachricht eingegangen sein obwohl der Chat-Dialog geschlossen ist, s Der Konfigurationsdialog (Abb. \ref{png:config}) erlaubt es dem Benutzer des PVS-Clients diverse Einstellungen vornehmen: \begin{enumerate} \item Mit diesen Reitern kann die Gruppe der zur Verfügung stehenden Optionen gewechselt werden. Unter "`Permissions"' sind Einstellungen zu finden mit denen der Benutzer seine Privatsphäre schützen kann. Unter "`Display"' ist es möglich das Verhalten der Toolbar anzupassen (z.B. die Position selbiger). - \item Hier wird dem Dozenten das Recht erteilt eine VNC-Verbindung aufbauen zu können (z.Z ohne Funktion). + \item Hier wird dem Dozenten das Recht erteilt eine VNC-Verbindung aufbauen zu können. + Durch Auswahl der Option ,,View only'' wird das Ansehen des Bildschirminhalts erlaubt. + Die Wahl ,,Full access'' erlaubt die Fernsteuerung von der Steuerkonsole aus. \item Hier wird allen anderen Benutzern das Recht erteilt eine VNC-Verbindung aufbauen zu können (z.Z ohne Funktion). \item Durch diese zwei Checkboxen kann die Teilnahme am Chat oder das Akzeptieren von Dateiübertragungen aktiviert werden (z.Z ohne Funktion). \end{enumerate} diff --git a/doc/LaTeX/user/0001-chapter.tex b/doc/LaTeX/user/0001-chapter.tex index 35f1128..200ffa5 100644 --- a/doc/LaTeX/user/0001-chapter.tex +++ b/doc/LaTeX/user/0001-chapter.tex @@ -58,6 +58,40 @@ Für die Verbundene Clients besteht die Möglichkeit die VNC-Quality (HIGH, MEDI festlegen, ob die Clients zur Verbindung mit dem pvsmgr ein von System generiertes Passwort eingeben müssen oder nicht. Auf dem Toolbar werden weitere Funktionen wie: Screeshots aufnehmen, Chat mit dem einzelnen Client starten oder alle Clients auf einem Klick zu blockieren. Das Blockieren der Clients schließt natürlich der Dozent-Rechner aus. Der Dozent-Rechner hebt sich von einem anderer verbundenen Machine durch den Rot-Blau Zeichnen neben dem grünen Punkt hervor. +\\ +Befindet sich die Maus über einem VNC-Frame, so ist über dem Bildschirminhalt eine Reihe von +Buttons zu sehen (Siehe Abbildung \ref{png:buttons}). +\begin{figure}[h] + \centering + \includegraphics[scale=1]{bilder/vnc-frame-buttons.png} + \caption{Buttons} + \label{png:buttons} +\end{figure} +Diese erlauben die Ausfürung der folgenden Funktionen: +\begin{enumerate} + \item Anzeige maximieren + \item Bildschirmfoto + \item Bildschirm für den Benutzer sperren + \item Client zum ,,Super-Client'' machen + \item Fernsteuerung aktivieren + \item Fernsteuerung aller Clients +\end{enumerate} +Wird der Button für die Aktivierung der Fernsteuerung gedrückt, werden alle Tastatur- und Mauseingaben, +die getätigt werden, während sich der Mauszeiger über dem Anzeigebereich des VNC-Frames befindet, +an den betreffenden Client gesendet. +So ist es möglich, die Steuerung von Tastatur und Maus eines angeschlossenen Rechners zu übernehmen. +\\ +Davon sind auch Tastenkombinationen wie Alt+Tabulator betroffen. +Um solche Kombinationen am Rechner der Steuerkonsole einzugeben, muss der Mauszeiger von der +Anzeigefläche wegbewegt werden. +\\ +Weiterhin ist auch die Simulation von System-Tastenkombinationen möglich: +Hierzu muss 5 Sekunden lang die Menü-Taste + \includegraphics[height=1.6ex]{bilder/menu-key.png} +gedrückt werden; +es erscheint dann ein Menü, aus dem die gewünschte Aktion ausgewählt werden kann. +{\em Vorsicht:} Die Steuerkonsole fragt vor der Ausführung einer Aktion nicht noch einmal +nach. \\ \\ Im letzten Punkt dieser Abschnitt wollen wir die vorhandenen Tastenkürzel vorstellen. -- cgit v1.2.3-55-g7522 From 08e41e889698024165b051d4d576045e01ea3bb8 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Thu, 4 Nov 2010 22:16:43 +0100 Subject: Doxygen configuration for pvsinput. The rest of the project does not use Doxygen anymore (or so I'm told). However, the vast majority of classes in src/input are annotated with Doxygen comments and it would be a shame not to use them. --- doc/doxconf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/doxconf b/doc/doxconf index e3e32a6..fefbae6 100644 --- a/doc/doxconf +++ b/doc/doxconf @@ -564,7 +564,7 @@ WARN_LOGFILE = ./doxwarnlog # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = ../pvsClient.h ../pvsClient.cpp ../pvs.h ../pvs.cpp ../pvsDaemon.h ../pvsDaemon.cpp ../src +INPUT = ../src/input # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -1341,7 +1341,7 @@ HIDE_UNDOC_RELATIONS = YES # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) -HAVE_DOT = NO +HAVE_DOT = YES # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This -- cgit v1.2.3-55-g7522 From 1b0ca81aa07617eb9764451cf83d04454cd6b0e1 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Fri, 5 Nov 2010 00:51:49 +0100 Subject: Documentation for multicast file transfer. --- doc/LaTeX/devel/0300-pvs.tex | 62 +++++++++++++++++++++++++++++++++++++++++ doc/LaTeX/user/0000-chapter.tex | 21 ++++++++++++-- 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/doc/LaTeX/devel/0300-pvs.tex b/doc/LaTeX/devel/0300-pvs.tex index 92b36f7..5aa5126 100644 --- a/doc/LaTeX/devel/0300-pvs.tex +++ b/doc/LaTeX/devel/0300-pvs.tex @@ -175,6 +175,65 @@ erzeugt (siehe Konstruktor) und mittels der Methode \texttt{isCommand} erfährt Falls ja leitet der Dispatche die Nachricht an die Stelle \texttt{PVS::UpdateChatClients} sonst an die Stelle \texttt{PVS::chat\_receive}, wo die Änderungen in der Client-Liste vorgenommen werden oder die Gespräch-Nachricht der GUI abgegeben wird. +\subsection{Multicast-Dateiversand} +\index{Dateiversand}\index{Multicast} + +Der Multicast-Dateiversand geschieht über die Bibliothek \texttt{OpenPGM}\index{OpenPGM} +(\url{http://code.google.com/p/openpgm/}), die das ,,\textit{Pragmatic General Multicast}''-Protokoll\index{Pragmatic General Multicast} +(PGM)\index{PGM} implementiert. +Darin enthalten ist eine Implementierung der \textit{PGMCC}-Methode zur +Regulierung der Sendebandbreite. +Vorteil der Verwendung einer externen Bibliothek ist, +dass die ,,schwierigen'' Probleme bei der Implementierung einer verlässlichen Datenstrom-orientierten +Multicast-Ãœbertragung bereits von Netzwerkexperten gelöst wurden. + +Die Bibliothek ist in das PVS-System über die interne Bibliothek \texttt{libpvsmcast}\index{libpvsmcast} +eingebunden (der Quellcode findet sich im Verzeichnis \texttt{src/net/mcast}). +Diese stellt mit der Klasse \texttt{McastPGMSocket}\index{Klasse!\texttt{McastPGMSocket}} einen +objektorientierten, ereignisgetriebenen Wrapper zu OpenPGM bereit. +Die Konfigurationsdaten, die zur Einrichtung einer PGM-Verbindung notwendig sind, +sind in der Klasse \texttt{McastConfiguration}\index{Klasse!\texttt{McastConfiguration}} verpackt. + +Auf der nächsten Ebene wird der Versand einer Datei von den Klassen \texttt{McastSender}\index{Klasse!\texttt{McastSender}} +und \texttt{McastReceiver}\index{Klasse!\texttt{McastReceiver}} übernommen. +Diese brechen den Bytestrom der Datei in Pakete auf und formatieren diese wie in Tabelle \ref{tab:mcastpacket} +gezeigt. +\begin{table} +\begin{center} +\begin{tabular}{|l|l|l|} +\hline +\textbf{Format} & \textbf{Feld} & \textbf{Erläuterung} \\ +\hline +\texttt{quint64} & \texttt{magic\_number} & = 0x0x6d60ad83825fb7f9 \\ +\hline +\texttt{quint64} & \texttt{offset} & Position des Datenpaketes in der Datei \\ +\hline +\texttt{QByteArray} & \texttt{data} & Daten \\ +\hline +\texttt{quint64} & \texttt{checksum} & CRC16-CCITT der vorhergehenden Felder \\ +\hline +\end{tabular} +\caption{Paketformat für Multicast-Dateiversand}\label{tab:mcastpacket}\index{Multicast!Paketformat} +\end{center} +\end{table} +Das Paketformat ist mit Hilfe der Qt-eigenen Klasse \texttt{QDataStream} implementiert. +Numerische Felder werden in Netzwerk-Bytereihenfolge übertragen. +Das Ende einer Ãœbertragung wird markiert durch ein Paket, in dessen \texttt{offset} +alle bits gesetzt sind und dessen \texttt{data} die MD5-Prüfsumme der übertragenen Datei +enthält. + +Zur Integration dieser -- prinzipiell von PVS unabhängigen -- Funktionalität +dienen die Klassen \texttt{PVSIncomingMulticastTransfer}\index{Klasse!\texttt{PVSIncomingMulticastTransfer} +und \texttt{PVSOutgoingMulticastTransfer}\index{Klasse!{PVSOutgoingMulticastTransfer}}. +Diese sorgen hauptsächlich für die Konfiguration der Multicast-Funktionalität mit Hilfe der +PVS-Konfiguration und das Generieren der richtigen Signale einerseits in Bezug auf die Benutzerschnittstelle, +sowie andererseits in Bezug zur Netzwerkkomponente des PVS-Systems. + +Ein Client, der eine Datei per Multicast zu versenden wünscht, wählt zufällig einen Port und +kündigt diesen mit der Nachricht MCASTFTANNOUNCE an. +Falls innerhalb einer festgesetzten Zeit (30 Sekunden) keine MCASTFTRETRY-Nachricht eintrifft, +beginnt die Ãœbertragung. +Die Nachricht MCASTFTCONFIG dient zum Setzen netzwerkweiter Parameter von der Steuerkonsole aus. \section{Netzwerkkommunikation} \index{Netzwerkkommunikation} @@ -216,6 +275,9 @@ PVSCOMMAND & VNC & NO & Verbiete Zugriff \\ PVSCOMMAND & PING & & \\ PVSCOMMAND & VNCREQUEST & & \\ PVSCOMMAND & VNCSRVRESULT & result code & Der Rückgabewert des pvs-vncsrv Skripts \\ +PVSCOMMAND & MCASTFTANNOUNCE & sender transferID basename size port & Ankündigung eines Multicast-Transfer \\ +PVSCOMMAND & MCASTFTRETRY & sender transferID & Rückmeldung: Konfiguration des Multicast-Empfängers fehlgeschlagen, bitte auf anderem Port noch einmal versuchen \\ +PVSCOMMAND & MCASTFTCONFIG & blob & Multicast-Konfiguration aus dem angehängten Binärblob neu laden \\ PVSMESSAGE & BROADCAST & MESSAGE &\\ PVSMESSAGE & clientToAdd & & Client hinzufügen (Chat)\\ PVSMESSAGE & clientToRemove & & Client entfernen (Chat)\\ diff --git a/doc/LaTeX/user/0000-chapter.tex b/doc/LaTeX/user/0000-chapter.tex index ae9276d..bf080d3 100644 --- a/doc/LaTeX/user/0000-chapter.tex +++ b/doc/LaTeX/user/0000-chapter.tex @@ -21,7 +21,7 @@ Das Hauptmenü des PVS-Clients besteht aus folgenden Elementen: \item Disconnect: Eine bestehende Verbindung trennen. \item Information: Zeigt in einem Dialog den Namen der aktuell verbundenen Steuerkonsole sowie das zugehörige Passwort. Diese Funktion ist für Dozenten nützlich, um beispielsweise über einen angeschlossenen Projektor die Daten für alle Clients bekannt zu geben. \item Chat: Öffnet den Chat-Dialog. - \item Send File: Ermöglicht das Senden einer Datei an einen Teilnehmer. + \item Send File: Ermöglicht das Senden einer Datei an einen oder alle Teilnehmer. \item Config: Öffnet den Konfigurationsdialog. \item About: Zeigt Versionsinformationen an. \item Quit: Beendet die Applikation sowie das zugehörige Backend. @@ -50,7 +50,9 @@ Sollte eine Nachricht eingegangen sein obwohl der Chat-Dialog geschlossen ist, s Der Konfigurationsdialog (Abb. \ref{png:config}) erlaubt es dem Benutzer des PVS-Clients diverse Einstellungen vornehmen: \begin{enumerate} \item Mit diesen Reitern kann die Gruppe der zur Verfügung stehenden Optionen gewechselt werden. Unter "`Permissions"' sind Einstellungen zu finden mit denen der Benutzer seine Privatsphäre schützen kann. Unter "`Display"' ist es möglich das Verhalten der Toolbar anzupassen (z.B. die Position selbiger). - \item Hier wird dem Dozenten das Recht erteilt eine VNC-Verbindung aufbauen zu können (z.Z ohne Funktion). + \item Hier wird dem Dozenten das Recht erteilt eine VNC-Verbindung aufbauen zu können. + Durch Auswahl der Option ,,View only'' wird das Ansehen des Bildschirminhalts erlaubt. + Die Wahl ,,Full access'' erlaubt die Fernsteuerung von der Steuerkonsole aus. \item Hier wird allen anderen Benutzern das Recht erteilt eine VNC-Verbindung aufbauen zu können (z.Z ohne Funktion). \item Durch diese zwei Checkboxen kann die Teilnahme am Chat oder das Akzeptieren von Dateiübertragungen aktiviert werden (z.Z ohne Funktion). \end{enumerate} @@ -61,3 +63,18 @@ Der Konfigurationsdialog (Abb. \ref{png:config}) erlaubt es dem Benutzer des PVS \label{png:config} \end{center} \end{figure} + +\section{Dateiversand} +Durch anklicken des Menüeintrags ,,Send File'' kann eine Datei versendet werden. +Nach der Auswahl des Menüeintrags erscheint ein Dialogfenster, in dem entweder ein Empfänger +ausgewählt werden (in diesem Fall erhält nur dieser Empfänger die Datei) +oder die Checkbox ,,Send to all'' aktiviert werden kann (dann wird die Datei an alle +angeschlossenen Rechner verschickt). + +Falls die Datei an alle verschickt wird, ist eine kurze Wartezeit vor Beginn des Versands und +nach dem (scheinbaren) Ende des Versands notwendig. +Es ist nicht sinnvoll, den Versand abzubrechen, wenn die Datei bereits vollständig verschickt +wurde und anscheinend nichts mehr passiert, da einzelne Clients eventuell noch verlorengegangene +Stücke der Datei nachfordern müssen. +Das Versandfenster schließt sich automatisch, wenn alle Clients die Datei vollständig +empfangen haben. -- cgit v1.2.3-55-g7522 From a9dd0c503641bf7dd16fc5c2900ad0694253761b Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Fri, 5 Nov 2010 00:55:30 +0100 Subject: Fix typo in documentation --- doc/LaTeX/devel/0300-pvs.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/LaTeX/devel/0300-pvs.tex b/doc/LaTeX/devel/0300-pvs.tex index 5aa5126..a2069de 100644 --- a/doc/LaTeX/devel/0300-pvs.tex +++ b/doc/LaTeX/devel/0300-pvs.tex @@ -223,7 +223,7 @@ alle bits gesetzt sind und dessen \texttt{data} die MD5-Prüfsumme der übertrag enthält. Zur Integration dieser -- prinzipiell von PVS unabhängigen -- Funktionalität -dienen die Klassen \texttt{PVSIncomingMulticastTransfer}\index{Klasse!\texttt{PVSIncomingMulticastTransfer} +dienen die Klassen \texttt{PVSIncomingMulticastTransfer}\index{Klasse!\texttt{PVSIncomingMulticastTransfer}} und \texttt{PVSOutgoingMulticastTransfer}\index{Klasse!{PVSOutgoingMulticastTransfer}}. Diese sorgen hauptsächlich für die Konfiguration der Multicast-Funktionalität mit Hilfe der PVS-Konfiguration und das Generieren der richtigen Signale einerseits in Bezug auf die Benutzerschnittstelle, -- cgit v1.2.3-55-g7522 From fc815ad2b711f0205801ddb04f85c9c776183efd Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Fri, 5 Nov 2010 00:57:04 +0100 Subject: Remove accidentally added backup files --- doc/LaTeX/devel/0100-build.tex~ | 69 -------- doc/LaTeX/devel/0300-pvs.tex~ | 384 ---------------------------------------- 2 files changed, 453 deletions(-) delete mode 100644 doc/LaTeX/devel/0100-build.tex~ delete mode 100644 doc/LaTeX/devel/0300-pvs.tex~ diff --git a/doc/LaTeX/devel/0100-build.tex~ b/doc/LaTeX/devel/0100-build.tex~ deleted file mode 100644 index 66d94da..0000000 --- a/doc/LaTeX/devel/0100-build.tex~ +++ /dev/null @@ -1,69 +0,0 @@ -\chapter{Erzeugen und Installieren der Applikation} -\index{Installieren} -Um den Pool Video Switch erfolgreich zu kompilieren, müssen zunächst die Quelldateien heruntergeladen werden. Hierzu sollte auf dem Arbeitsrechner ein Subversion-Client installiert sein. Ein Checkout kann in einem beliebigen Terminal erfolgen, wobei es zwei unterschiedliche Arten des Zugriffs gibt.\\ - -Anonym, nur Leserechte:\\ -\textbf{svn co http://svn.openslx.org/svn/pvs/trunk/pvs}\\ - -Mit Account, auch Schreibrechte (benutzer mit SSH Login ersetzen):\\ -\textbf{svn co svn+ssh://benutzer@openslx.org/srv/svn/pvs}\\ - - -\section{Voraussetzungen} -Der Pool Video Switch benötigt zum Kompilieren folgende Pakete (und ihre Abhängigkeiten): -\begin{itemize} - \item libvncserver-dev >= 0.9.3\\ - Eine angenehm kleine, wenn auch in C geschriebene, Bibliothek für die Erstellung von VNC Servern und Clients. - \item libx11-dev >= 1.3.3\\ - Diese Bibliothek wurde eingesetzt, um ausgewählten oder allen Zielrechnern den Zugriff auf Maus und Tastatur zu entziehen und den Bildschirm schwarz zu schalten. - \item libqt4-dev >= 4.5.3\\ - Sowohl die Server als auch die ClientGUI benutzen das Qt Framework in der Version 4. Ferner wird QtNetwork zur Kommunikation zwischen Server und Client benötigt und QtDbus zur Interprozesskommunikation zwischen Client-Daemon und GUI. - \item qt4-dev-tools >= 4.5.3\\ - Dies wird nur benötigt, falls Unterstützung weiterer Sprachen implementiert werden soll, da in diesem Paket das Hilfsprogramm \textbf{linguist} enthalten ist. - \item cmake >= 2.4.0\\ - Eingesetztes Buildsystem und der Makefile-Generator. Um distributionsspezifische Pakete zu erzeugen wird CPack benutzt. - \item libxtst-dev, libxi-dev\\ - Diese Bibliotheken dienen zur Implementierung der Fernsteuerungsfunktionen. -\end{itemize} - -\section{Kompilieren aus Quellen} -Sobald alle Voraussetzungen erfüllt und die Quellen installiert sind, kann das ausführbare Programm erzeugt werden. Falls gewünscht, kann zusätzlich in der Datei \textit{CMakeLists.txt} der Build-Type eingestellt werden. Gültige Werte sind \texttt{Debug} und \texttt{Release} und ihre Wirkung den zwei weiteren Zeilen zu entnehmen. -\begin{verbatim} -SET(CMAKE_BUILD_TYPE Debug) -SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -Wall") -SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native") -\end{verbatim} -Damit das Wurzelverzeichnis des Projekts weiterhin sauber bleibt (Ãœbersicht beibehalten, Arbeit mit SVN erleichtern), werden wir hier einen Out-Of-Source Build durchführen. Dies bedeutet, dass zum Kompilieren ein seperates Verzeichnis benutzt wird und sämtliche automatisch generierten Dateien sowie das Kompilat selbst hier abgelegt wird. In einem Terminal sollte nun in das Verzeichnis indem sich das Projekt befindet gewechselt werden, um folgende Befehle ausführen zu können:\\ - -\textbf{mkdir -p build}\\ -\textbf{cd build/}\\ -\textbf{cmake ..}\\ -\textbf{make}\\ - -Die verschiedenen Applikationen können nun folgendermaßen (in \textit{build/}) ausgeführt und getestet werden: -\begin{itemize} - \item Den Server starten: \textbf{./pvsmgr} - \item Den Server mit Touchscreenoberfläche starten: \textbf{./pvsmgrtouch} - \item Den ClientDaemon starten: \textbf{./pvs} - \item Die ClientGUI starten: \textbf{./pvsgui} -\end{itemize} - -\section{Installation} -\index{Paket!RPM} \index{Paket!DPKG} -Nachdem das Projekt kompiliert wurde, kann es (als Superuser z.B. root) auf dem lokalen System installiert werden:\\ -\textbf{make install}\\ - -Dabei werden folgende Dateien auf das aktuelle System übertragen:\\ -\textit{/usr/local/bin/pvsmgr}\\ -\textit{/usr/local/bin/pvs}\\ -\textit{/usr/local/bin/pvsgui}\\ -\textit{/usr/local/bin/pvsmgrtouch}\\ -\textit{/usr/local/share/dbus-1/services/org.openslx.pvs.service}\\ - -Ein Vorteil ist, dass nun ein seperates Ausführen des Client-Daemon nicht mehr notwendig ist. Dieser wird ab sofort automatisch gestartet und beendet, sobald die ClientGUI ausgeführt wurde.\\ - -Es ist ebenfalls möglich, distributionsspezifische Pakete zu erstellen (zur Zeit nur .deb):\\ -\textbf{make package}\\ - -Falls erfolgreich, befindet sich nun eine Installationsdatei (pvs--Linux.deb) in \textit{build/} die z.B. auf Debian-Derivaten mit \textbf{dpkg -i} installiert werden kann.\\ -Anmerkung: Falls Pakete für Rechner gebaut werden sollen, die vom Erstellungssystem her verschieden sind, muß der Schalter \texttt{-march=native} in der Datei \textit{CMakeLists.txt} angepasst werden! diff --git a/doc/LaTeX/devel/0300-pvs.tex~ b/doc/LaTeX/devel/0300-pvs.tex~ deleted file mode 100644 index ac88e46..0000000 --- a/doc/LaTeX/devel/0300-pvs.tex~ +++ /dev/null @@ -1,384 +0,0 @@ -\chapter{Aufbau und Funktionsweise des PVS} -\index{Aufbau} \index{Funktionsweise} \index{Konzept} - -Generelles Konzept - -\section{Einzelne Komponenten} -\index{Komponenten} - -\subsection{Zuordnung von Konsole und Clients} -\input{devel/0310-service-discovery} - -\section{Ãœberblick über Aktivitäten auf Clients} - -\subsection{Projektion an Alle} -\index{Projektion} -Eine wichtige Eigenschaft des PVS ist die Verwaltung von Projektionen zwischen mehreren Clients. Eine Projektion ist hierbei das Anzeigen des Bildschirminhalts eines Clients - der sogenannten Source oder Quelle - auf einem oder mehreren anderen Clients - den Targets oder Zielen der Projektion. -Die für die Projektion benötigten Verbindungsdaten wie Passwort und IP werden von jedem Client bei der Anmeldung an der Steuerkonsole übermittelt und in einer Liste von PVSConnection Objekten in der Klasse \textit{PVSConnectionManager} gespeichert. Diese zentrale Verwaltung hat mehrere Vorteile: -\begin{itemize} - \item Die Quelle einer Projektion muss keine Aktion ausführen und kann passiv bleiben. - \item Redundanz der Daten wird verhindert, da diese auch in der Steuerkonsole zur Darstellung der Thumbnails benötigt werden. - \item Das Nachrichtenaufkommen wird reduziert, da lediglich eine Nachricht bei der Anmeldung an der Steuerkonsole übermittelt wird. -\end{itemize} - -Bei der Auswahl der Quelle und Ziele ist zu beachten, dass man für jede Projektion jeweils nur eine Quelle jedoch mehrere Ziele auswählen kann. -Quelle und Ziel müssen außerdem verschiedenen Kriterien genügen. -\begin{itemize} - \item Eine Quelle darf nicht gleichzeitig Ziel einer Projektion sein. - \item Ein Ziel einer Projektion darf nicht Ziel einer anderen Projektion sein. - \item Eine Quelle darf mehrfach als Quelle ausgewählt werden. -\end{itemize} -Diese Einschränkungen werden in der Steuerkonsole durchgesetzt, indem im Zielauswahldialog die Zielmenge eingeschränkt wird. -Siehe hierzu auch \ref{pvs-console-projection} Projektion. - -Der Projektionsvorgang an sich besteht aus mehreren Teilen. Wird eine Projektion angefordert, wird überprüft, ob auf der Quelle ein VNC Server gestartet ist. Falls nicht, wird versucht, einen VNC Server zu starten. Ist dies erfolgreich, so sendet die Steuerkonsole das entsprechende Tripel (IP, Passwort und Port der Quelle) an alle ausgewählten Ziele. Clients, welche eine Projektionsaufforderung erhalten, verbinden sich dann mit den Verbindungsdaten zum VNC Server der Quelle. Um die Einstellbarkeit der Qualität einer Projektion zu ermöglichen, kann die Steuerkonsole einen von drei Qualitätswerten an die Zielclients übermitteln. Siehe hierzu auch \ref{pvs-console-quality} Qualitätsoptionen. - - -\subsection{Projektion eines Clients auf dem Beamer} -\index{Beamer} - -Die Projektion eines Clients an den Beamer unterscheidet sich im Wesentlichen nicht von anderen Projektionen. Lediglich ist das Ziel der Projektion hierbei der Dozentenpc bzw. der PC, welcher an den Beamer angeschlossen ist. Eine spezielle Auszeichnung des Beamers erfolgt nicht. Die Anzahl der Ziele wird hierbei nicht beschränkt, da es wünschenswert sein kann, den auf dem Beamer dargestellten Bildschirminhalt auch gleichzeitig auf anderen Clients darzustellen. - -\subsection{Chat- und Informationskanal} -\index{Chat} - -Es gibt 2 Möglichkeiten um Kontakt mit den Clients aufzunehmen. Die erste ist über den Chat, wo Nachrichten sowohl über den offentlichen Kanal als -auch über einen privaten Kanäle verteilt werden können, und die zweite vom PVSManager aus über den Informationskanal. -Der Informationskanal ermöglich das Versenden von Nachrichten, die dringend zu lesen sind, an die Clients. -Im Gegenteil zum Chat erscheinen solche Nachrichten nicht im Chatfenster sondern in einem Pop-Up-Fenster und werden vom Bildschirm entfernt erst wenn man sie -als gelesen markiert durch das Drucken auf dem Knopf \textit{'OK'}. -\\ -\\ -\textbf{Behandlung der Nachrichten im Server} -\\ -\\ -Chat-Nachtichten werden von Server in der Klasse \texttt{PVSConnectionManager} mittels der Methode \texttt{onChat} behandelt. Dort wird aus der Nachrit den Empfänger -und den Absender ausglesen und die Nachricht an beide versendet. So gilt das Empfangen eine eigene Nachricht als Bestätigung, dass die Nachricht ordentlich vom Server -behandelt und versendet wurde. Das Gestalt von solchen Nachrichten sieht folgendermaßen aus - -\begin{center} - PVSMSG -\end{center} -\begin{center} -\begin{tabular}{|l | p{3cm} | p{3cm} | p{3cm}|} -\hline -Type & Ident & Msg & sndID\\ -\hline -\texttt{PVSMESSAGE} & \texttt{} & \texttt{<:} & \texttt{<}\\ -\end{tabular} -\end{center} - -Informationsnachrichten werden ausschließlich vom PVSManager versendet.Dies geschiet in der Klasse \texttt{ConnectionList} mittels der Methode \texttt{on\_Message}. - -\begin{center} - PVSMSG -\end{center} -\begin{center} -\begin{tabular}{|l | l | p{6cm} | p{6cm}} -\hline -Type & Ident & Msg\\ -\hline -\texttt{PVSMESSAGE} & \texttt{BROADCAST} & \texttt{} \\ -\end{tabular} -\end{center} - -Informationnachrichten können außerdem einen oder mehrere Clients sperren, wenn sie den Ident \texttt{LOCKSTATION} enthalten. Sobald ein Client die Nachricht empfängt, -wird diese auf dem Bilschirm angezeigt und 10 Sekunden später wird der Client gesperrt. - -Abgesehen von der Behandlung der Nachrichten muss sich der Server darum kümmern, dass jeder verbunde Client über alle nötige Informationionen verfügt damit er -Nachrichten mit andren Clients austauschen kann. Dies wird folgendermaßen erledigt: -\begin{itemize} - \item \textbf{Einfügen eines Clients:} um die Verwaltung von Clients kümmert sich die Klasse \texttt{PVSConnectionManager}, in der die Methode \texttt{onClientNew} für das Einfügen -von neuen Clients zuständigt ist. Sowald ein neuer Client in der Client-Liste des Servers eingefügt wird, wird an ihn die Liste aller im Server bereits angemeldete -Clients geschickt. Dazu dient die Methode \texttt{sendEventToClients}. - -Bis hier ist der neue Client noch unbekannt für den Rest der Nutzer. Der neuer Client wird erst bekannt gegeben sobald er vom Server einen Benutzername -zugewissen bekommen hat. Da es sein kann, dass den Name, mit dem der neue Client sich beim Server anmelden wollte, -bereits vergeben ist und muss unter Umständen verändert werden. Diese Zuweisung findet in der Methode \texttt{onLoginUsername} statt, -wo nicht nur alle andere Clients sondern auch der neue Client darüber informiert werden. Auch hier kümmert sich die Methoder \texttt{sendEventToClients} -ums Vesenden der entsprechenden Informationen. - - \item \textbf{Entfernen eines Clients:} das Entfernen von Clients wird von der Methode -\\ -\texttt{onClientRemove} erledigt, wo analog wie -Oben alle Clients darüber informiert werden. -\end{itemize} - -Für dei Ãœbermittlung solche Informationen werden Nachrichten mit folgenden Gestal benutzt - -\begin{center} - PVSMSG -\end{center} -\begin{center} -\begin{tabular}{|l | l | p{6cm} |} -\hline -Type & Ident & Msg\\ -\hline -\texttt{PVSMESSAGE} & \texttt{} & \texttt{:} \\ -\end{tabular} -\end{center} - -Es gibt drei unterschiedliche Befehle, die welche Änderung in der localen Client-Liste der Clients vorgenommen werden soll angeben. -\begin{enumerate} - \item \texttt{clientToAdd} -\item \texttt{clientToRemove} -\item \texttt{assignedName} -\end{enumerate} - -Wie es bei Servern gewöhnt ist, werden alle relevante Ereignisse in Log-Dateien protokolliert. Ereignisse werden im Chat-Log mit folgendem -Befehl eingetragen - -\begin{center} -\texttt{ConsoleLog writeChat()} -\end{center} - -\textbf{Chat-Interface der Steuerkonsole} -\\ -\\ -So wie alle Clients ist der PVSManager auch ein Teilnehmer im Chat. Der PVSManager steht wie alle andere Teilnehmer auch in der Nutzer-Liste -jedes Chat-Fenster und kann ebenfalls über private Nachrichten direkt angesprochen werden. Die Arbeitsweise dieser Chat-Interface ist sehr simple. -Da sie sich im Server befindet, müssen einfach alle Ereignise (Nachrichten senden ist die einzige Ausnahme) von der Klasse \texttt{PVSConnectionManager} -an die Klasse \texttt{MainWindow} weitergegeben werden. Dies kümmert sich darum, alle Informationen zu verarbeiten und diesein der Chat-Fenster der -Steuerkonsole anzuzeigen. - -Folgende Methoden der Klasse \texttt{MainWindow} ermöglichen das Anzeigen einer empfangenen Nachricht im Chat-Fenster der Steuerkonsole und Änderungen (Clients einfügen -und entfernen) in der sowohl im Chat-Fenster als auch in der Steuerkonsole angezeigten Client-Liste. -\\ -\\ -\texttt{receiveChatMsg(, , )} -\\ -\texttt{removeConnection(*pvsClient)} -\\ -\texttt{addConnection(*pvsClient)} -\\ -\\ -Alle diese Methoden werden im Gegensatz von der Methode \texttt{sendChatMsg(PVSMsg myMsg)} von der Klasse \texttt{PVSConnectionManager} aus ausgeführt. Da alle durchs -Netz empfangene Nachrichten müssen an die GUI-Weitergegeben werden. Beim Versenden von Nachrichten funktioniert es genau umgekehrt. Die Nachricht wird -vom Nutzer in der GUI eingegeben und muss an die Klasse \texttt{PVSConnectionManager} weitergeleitet werden, damit diese ins Netz gesendet wird. Darum kümmert -sich die Methode in der Klasse \texttt{MainWindow}. -\\ -\\ -\texttt{MainWindow::sendChatMsg(PVSMsg myMsg)} -\\ -\\ -\textbf{Chat-Clients} -\\ -\\ -So weit haben wir die Funtionsweisen des Servers im Bezug auf dem Chat kennengelernt. -Nun wird erläutert wie die einzelnen Clients die Nachrichten bearbeiten. -\\ -\\ -Auf der Client-Seite in der Klasse \texttt{PVSConnectionServer} werden alle Nachrichten des PVS-Protokolls empfangen und gefiltert (Siehe Methode \texttt{handleClientMsg}). -Nachrichten mit dem Ident \texttt{PVSMESSAGE} werden durch den Dispatcher direkt an die Klasse \texttt{PVSChatClient} weitergeleitet, wo die Methode \texttt{receive} feststellen wird, -ob es sich dabei um eine Gespräch-Nachricht oder eine Befehl-Nachricht handelt. Um es feststellen zu können, wird aus der empfangenen Nachricht ein PVSChatMsg-Objekt -erzeugt (siehe Konstruktor) und mittels der Methode \texttt{isCommand} erfährt man ob es sich um einen Befehl handelt oder nicht. -Falls ja leitet der Dispatche die Nachricht an die Stelle \texttt{PVS::UpdateChatClients} sonst an die Stelle \texttt{PVS::chat\_receive}, wo die Änderungen in der Client-Liste -vorgenommen werden oder die Gespräch-Nachricht der GUI abgegeben wird. - -\section{Fernsteuerung} - -Die Fernsteuerung eines Clients erfolgt durch den clientseitigen Empfang von \texttt{PVSCOMMAND}-Nachrichten -mit dem Ident \texttt{INPUTEVENT}. -Dieser ist die Base64-kodierte Binärdarstellung eines Eingabeereignisses angehängt, das -clientseitig nachvollzogen werden soll. -\begin{table} - \begin{tabular}{|l|l|p{4cm}|p{4cm}|} - \hline - \textbf{\texttt{type}} & \textbf{\texttt{code}} & \textbf{\texttt{value}} & \textbf{Beschreibung} \\ - \hline - \multirow{2}{*}{\texttt{ET\_KEY}} & - \texttt{EC\_PRESS} & - \multirow{2}{4cm}{Auslösende Taste und gehaltene Modifikatortasten} & - Taste gedrückt \\ - \cline{2-2}\cline{4-4} - & - \texttt{EC\_RELEASE} & - & - Taste losgelassen\newline \\ - \hline - \multirow{2}{*}{\texttt{ET\_BUTTON}} & - \texttt{EC\_PRESS} & - \multirow{2}{4cm}{Auslösende und - gedrückte Maustasten} & - Maustaste gedrückt \\ - \cline{2-2}\cline{4-4} - & - \texttt{EC\_RELEASE} & - & - Maustaste losgelassen \\ - \hline - \texttt{ET\_POINTER} & - --- & - Absolute Koordinaten & - Mauszeiger bewegt \\ - \hline - \multirow{4}{*}{\texttt{ET\_SPECIAL}} & - \texttt{EC\_REBOOT} & - --- & - Systemneustart \\ - \cline{2-4} - & - \texttt{EC\_KILL\_X} & - --- & - X-Server töten \\ - \cline{2-4} - & - \texttt{EC\_SYSRQ} & - Kommando & - Magic-SysRq-Taste \\ - \cline{2-4} - & - \texttt{EC\_SAY\_HELLO} & - --- & - Harmloses Kommando für Funktionstest \\ - \hline - \end{tabular} - \caption{Mögliche Eingabeereignisse\label{tab:input-events}\index{Eingabeereignis!\texttt{InputEvent}}} -\end{table} -Tabelle \ref{tab:input-events} zeigt die möglichen Eingabeereignisse. -Eingabeereignisse werden durch die PVS Input Library (libpvsinput) behandelt, -deren Funktion an dieser Stelle dargestellt werden soll. - -\subsection{Behandlung eines Eingabeereignisses} -\index{Eingabeereignis!Behandlung} - -Ein Eingabeereignis durchläuft die folgenden Stationen: -\begin{enumerate} - \item Die Steuerkonsole generiert ein Eingabeereignis und übergibt dieses an die Netzwerktransportschicht. - \item Der PVS-Client empfängt das Eingabeereignis und übergibt die Behandlung einer Instanz der - Klasse \texttt{InputEventHandlerChain}\index{Klasse!\texttt{InputEventHandlerChain}}. - \item Die Klasse \texttt{InputEventHandlerChain} arbeitet eine Liste von Instanzen der Klasse - \texttt{InputEventHandler}\index{Klasse!\texttt{InputEventHandler}} der Reihe nach ab, um zu sehen, ob eine dieser Instanzen - das Ereignis bearbeiten kann. - \item Falls die betrachtete Instanz das Ereignis bearbeiten kann, wird geprüft, ob der dafür - nötige Sicherheitskontext vorhanden ist. - \item Falls dies ebenfalls der Fall ist, wird die entsprechende Aktion in einer implementierung - der abstrakten Methode \texttt{InputEventHandler::handle} ausgeführt und die weitere Bearbeitung - beendet. - \item Falls keiner der vorherigen Handler das Ereignis behandelt hat, wird es durch - die Klasse \texttt{PrivilegedHandlerForwarder}\index{Klasse!\texttt{PrivilegedHandlerForwarder}} an den zusätzlichen Daemon \texttt{pvsprivinputd} - weitergegeben. - \item Der \texttt{pvsprivinputd}\index{pvsprivinputd} besitzt ebenfalls eine \texttt{InputEventHandlerChain}, die - nach dem gleichen Muster bearbeitet wird. - Falls hierbei kein passender Handler gefunden wird, wird das Ereignis in eine Logdatei geschrieben - und die Bearbeitung aufgegeben. -\end{enumerate} -Ereignishandler sind implementiert für Maus- und Tastatureingaben unter Linux/X11 (mit Hilfe der XTest-Erweiterung), -sowie zur Simulation von Strg+Alt+Entf, Strg+Alt+Rück und Magic SysRq. - -\subsection{Erweiterungen} - -Weitere Eingabehandler lassen sich der libpvsinput hinzufügen. -Dazu muss eine Klasse bereitgestellt werden, die von der Template-Klasse -\texttt{InputEventHandler} erbt. -Diese akzeptiert eine variable Anzahl\footnote{% - Bis zu 16, diese Zahl lässt sich jedoch durch Neugenerierung - der Datei \texttt{src/input/detail/ typelist\_autogen.h} erhöhen. - Ein entsprechendes Programm ist im Quellcode zu finden.} -von Templateparametern, die verschiedene Aspekte der Eingabeereignisbehandlung konfigurieren. - -Durch die Angabe eines Templateparameters \texttt{input\_policy::Match<\textit{typ}, \textit{code}, \textit{wert}>}\index{Klasse!\texttt{input\_policy::Match}}, -wobei \textit{code} und \textit{wert} weggelassen werden können, wird spezifiziert, -dass der betreffende Handler nur für Eingabeereignisse mit den entsprechenden Feldwerten aufgerufen wird. -Wird kein solcher Parameter angegeben, wird der betreffende Handler niemals aufgerufen. -Mehrere \texttt{Match}-Parameter werden mittels logischem ODER verknüpft. - -Ein Templateparameter der Form \texttt{input\_policy::Require<\textit{Merkmal\dots}>}\index{Klasse!\texttt{input\_policy::Require}} -gibt an, dass dieser Handler nur auf einem System lauffähig ist, das die entsprechenden \textit{Merkmale} -aufweist. -Eine Liste von Systemmerkmalen wird in der Datei \texttt{src/input/detail/systemTraits.h} -zentral verwaltet. -Hier lassen sich neue Merkmale mit Hilfe des Makros \texttt{DEFINE\_SYSTEM\_TRAIT} definieren -und mit Hilfe des Präprozessors zwischen den Zeilen \texttt{BEGIN\_SYSTEM\_TRAITS} und -\texttt{END\_SYSTEM\_TRAITS} einfügen. -Diese Vorgehensweise beschränkt die Nutzung des Präprozessors auf eine Datei. -Wird kein \texttt{Require}-Parameter angegeben, so wird der entsprechende Handler als -immer lauffähig eingestuft. -Mehrere \texttt{Require}-Parameter werden mittels logischem ODER verknüpft. - -Weiterhin kann ein Templateparameter der Form \texttt{input\_policy::Security<\textit{Richtlinie}>}\index{Klasse!\texttt{input\_policy::Security}} -angegeben werden. Hierbei stehen für \textit{Richtlinie} die Klassen \texttt{input\_policy::AllowLocal\-OrPrivileged} -oder \texttt{input\_policy::AllowEverybody} zur Verfügung. -Hierdurch wird bestimmt, welche Sicherheitsanforderungen zur Ausführung des Handlers erfüllt sein -müssen. -Die Richtlinie \texttt{input\_policy::AllowLocalOrPrivileged} bestimmt, dass nur Benutzer, -deren Sitzung lokal ist, oder solche, die nach der Konfiguration des pvsprivinputd als privilegiert -gelten, die entsprechende Aktion aufrufen dürfen (hierbei geht es um den Benutzer, der den PVS-Client -ausführt, und nicht den Benutzer, der die Steuerkonsole bedient). -Die Richtlinie \texttt{input\_policy::AllowEverybody} erlaubt die Ausführung der Aktion ohne -besonderen Sicherheitskontext. -Neue Sicherheitsrichtlinien der Form \texttt{input\_policy::Security<\textit{T}>} lassen sich -nutzen, indem eine Klasse \textit{T} eingeführt wird, die eine Methode\\ -\makebox[1cm]{}\texttt{static bool allow(InputEventContext const*)}\\ -besitzt, an die die Entscheidung, ob eine Aktion zuzulassen ist, delegiert wird. - -Der zu implementierende Eingabehandler braucht weiterhin eine Implementierung der abstrakten -Methode\\ -\makebox[1cm]{}\texttt{virtual void handle(InputEvent const\&, InputEventContext const*)},\\ -in der die entsprechende Aktion ausgeführt wird. - -Die Aufnahme des neuen Handlers in die Liste der abzuarbeitenden Handle erfolgt, -je nachdem ob erweiterte Berechtigungen zur Bearbeitung notwendig sind, -in einer der Dateien \texttt{privilegedHandlerChain.cpp} oder \texttt{unprivilegedHandler\-Chain.cpp} -in \texttt{src/input}, wo dem Kettenaufruf eine Zeile der Form\\ -\makebox[1cm]{}\texttt{.add<\textit{Handler}>()}\\ -hinzugefügt wird. -Die Verwendung des Präprozessors zum Ausschluss von Handlern, die auf dem -Zielsystem nicht lauffähig sind, ist an dieser Stelle nicht notwendig und wird durch die -\texttt{Require}-Richtlinie umgesetzt. -Notwendig ist lediglich, die Ãœbersetzung des Handlers auf inkompatiblen Systemen zu verhindern. -Dies kann mit Hilfe des Build-Systems oder durch die Klammerung der gesamten Ãœbersetzungseinheit -in Präprozessorbedingungen geschehen. - -Eine API-Referenz zur libpvsinput (Stand: 4.~November~2010) findet sich im Projektwiki. - -\section{Netzwerkkommunikation} -\index{Netzwerkkommunikation} - -\subsection{PVS-Protokoll} -\index{Protokoll!PVS} \index{Protokoll} -Im Zuge der Entwicklung des PVS wurde ein sehr einfaches Messagingprotokoll entwickelt. -Die Nachrichten bzw. Messages bestehen dabei aus Header, Nachrichtentyp, Ident und dem eigentlichen Nachrichtentext. Die einzelnen Nachrichtenteile, welche bis auf den Header selbst definiert werden können, werden verknüpft und versendet. Es sind schon Nachrichtentypen vordefiniert, welche sich nur durch unterschiedliche Dispatcher unterscheiden. -Bereits vorhandene Typen sind COMMAND, LOGIN, MESSAGE und UNKNOWN. Die Dispatcher (\_commandDispatcher, \_loginDispatcher und \_chatDispatcher) befinden sich im Client in der Klasse \texttt{ServerConnection}, in der Steuerkonsole in der Klasse \texttt{ClientConnection} bzw. \texttt{ListenServer}. Ein Ident wie z.B. Username, Befehl oder Beschreibung des Nachrichteninhalts dient zur Unterscheidung verschiedener Nachrichten mit demselben Nachrichtentyp, wobei die Nachricht dann den dem Ident entsprechenden Nachrichtentext enthält. -Um eine Funktion zur Behandlung einer bestimmten Nachricht zu definieren, wird diese Funktion als Handler mit dem entsprechenden Dispatcher verknüpft. Im PVS-Client beispielsweise befindet sich der Dispatcher für Nachrichten vom Typ Command in der Klasse \texttt{pvsServerConnection}, daher wird in der Klasse \texttt{pvs} die Funktion \texttt{void PVS::onCommand(PVSMsg cmdMessage)} wie folgt als Handler registriert: -\texttt{\_pvsServerConnection->addCommandHandler("*", this, \&PVS::onCommand)}. Erhält nun der Client eine Nachricht vom Typ COMMAND, so wird die Funktion onCommand mit dem entsprechenden Nachrichtenobjekt aufgerufen. Auf die eigentliche Nachricht kann dann über die Methoden \texttt{getIdent()} und \texttt{getMessage()} des Objektes zugegriffen werden. - -\subsection{PVS-Messages} -\index{Message!PVS} \index{Message} -In Tabelle \ref{tab:messagelist} sind die Messages, die zwischen den einzelnen PVS Komponenenten ausgetauscht werden, aufgelistet. -Der Nachrichtentyp gibt dabei an, welcher Dispatcher die Nachricht behandelt. -Der Ident einer Nachricht wird zur Verarbeitung einer empfangenen Nachricht in der aufzurufenden Funktion benötigt (Unterscheidung von anderen Nachrichten gleichen Typs). - -\begin{table} -\begin{center} -\begin{tabular}{l | l | p{2cm} | p{4cm}} -\label{pvs-msg-liste} -Nachrichtentyp & Nachrichten Ident & Inhalt & Beschreibung \\ -\hline -PVSCOMMAND & PROJECT & hostname port password quality & Hostname, Port, Passwort und Qualität des VNC Servers zu dem verbunden werden soll (durch Space getrennt) \\ -PVSCOMMAND & UNPROJECT & & \\ -PVSCOMMAND & LOCKSTATION & & \\ -PVSCOMMAND & LOCKSTATION & Message & Client mit Nachricht sperren \\ -PVSCOMMAND & UNLOCKSTATION & & \\ -PVSLOGIN & USERNAME & username & Client Benutzername \\ -PVSLOGIN & PASSWORD & password & Serverpasswort \\ -PVSLOGIN & ID & id & \\ -PVSLOGIN & FAILED & "`Wrong Password"' & Wird bei falschem Passwort gesendet \\ -PVSCOMMAND & PORT & port & \\ -PVSCOMMAND & PASSWORD & password & VNC Passwort\\ -PVSCOMMAND & RWPASSWORD & rwpassword & Passwort für den Zugriff auf die Tastatur und Maus \\ -PVSCOMMAND & VNC & YES & Erlaube Zugriff \\ -PVSCOMMAND & VNC & NO & Verbiete Zugriff \\ -PVSCOMMAND & PING & & \\ -PVSCOMMAND & VNCREQUEST & & \\ -PVSCOMMAND & VNCSRVRESULT & result code & Der Rückgabewert des pvs-vncsrv Skripts \\ -PVSCOMMAND & INPUTEVENT & Base64-kodierte InputEvent-Struktur & Fernsteuerung \\ -PVSMESSAGE & BROADCAST & MESSAGE &\\ -PVSMESSAGE & clientToAdd & & Client hinzufügen (Chat)\\ -PVSMESSAGE & clientToRemove & & Client entfernen (Chat)\\ -PVSMESSAGE & assignedName & & Festgelegter Name (Chat)\\ -\end{tabular} -\end{center} -\caption{Liste der PVS Messages} -\label{tab:messagelist} -\end{table} -- cgit v1.2.3-55-g7522