/*
# Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg
#
# This program is free software distributed under the GPL version 2.
# See http://openslx.org/COPYING
#
# If you have any feedback please consult http://openslx.org/feedback and
# send your suggestions, praise, or complaints to feedback@openslx.org
#
# General information about OpenSLX can be found at http://openslx.org/
# --------------------------------------------------------------------------
# inputEvent.h:
# - Definition of an input event
# --------------------------------------------------------------------------
*/
#ifndef INPUTEVENT_H_
#define INPUTEVENT_H_
#include <cassert>
#include <QCoreApplication> // for translation
#include <QString>
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:
friend QDataStream& operator<<(QDataStream&, InputEvent const&);
friend QDataStream& operator>>(QDataStream&, InputEvent&);
friend void eventToString(InputEvent const& evt, QString& str);
friend bool eventFromString(QString const& str, InputEvent& evt);
quint16 _type;
quint16 _code;
quint32 _value;
// InputEvents are immutable. Prohibit assignment:
InputEvent& operator=(InputEvent const&); // There intentionally is no implementation.
public:
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()
{
}
/** \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);
/**
* 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);
/**
* 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);
/**
* Generates an event for a mouse pointer movement.
* \param x,y X and Y coordinates of the mouse pointer.
*/
static InputEvent mouseMotion(quint16 x, quint16 y)
{
return InputEvent(ET_POINTER, 0, ((quint32)x << 16) | y);
}
/* @} */
/** \name Event Types */
/* @{ */
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 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 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 =
0x7e000000;
/** \name Event Decoding Functions */
/* @{ */
/**
* Return the event type, as defined by the \c ET_* constants.
*/
quint16 type() const
{
return _type;
}
/**
* Return the event code, as defined by the \c EC_* constants.
*/
quint16 code() const
{
return _code;
}
/**
* 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.
*/
quint32 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;
}
/**
* The mouse button that generated this event.
* \return one of the \c EB_* constants.
*/
quint16 pressedButton() const
{
assert(_type == ET_BUTTON);
return (_value >> 16);
}
/**
* The mouse buttons that were pressed at the moment the
* event was generated.
* \return a bitwise or of \c EB_* constants.
*/
quint16 heldButtons() const
{
assert(_type == ET_BUTTON);
return (_value & 0xffff);
}
/**
* The X coordinate the pointer was moved to.
*/
quint16 xCoord() const
{
assert(_type == ET_POINTER);
return (_value >> 16);
}
/**
* The Y coordinate the pointer was moved to.
*/
quint16 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 quint16 mouseButtonsFromQt(int b);
/**
* Converts an event type as given by the \c ET_* constants to
* a string.
*/
static QString typeToString(quint16 type)
{
switch(type)
{
case ET_BUTTON:
return "BUTTON";
case ET_KEY:
return "KEY";
case ET_POINTER:
return "POINTER";
case ET_SPECIAL:
return "SPECIAL";
default:
return QString::number(type, 16);
}
}
/**
* Converts an event code as given by the \c EC_* constants to
* a string.
*/
static QString codeToString(quint16 code)
{
switch(code)
{
case EC_PRESS:
return "PRESS";
case EC_RELEASE:
return "RELEASE";
case EC_SYSRQ:
return "SYSRQ";
case EC_REBOOT:
return "REBOOT";
case EC_KILL_X:
return "KILL_X";
default:
return QString::number(code, 16);
}
}
/**
* 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'));
}
/* @} */
// 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);
}
};
/**
* 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; /**< 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<SpecialInputEventDescription> describeSpecialEvents();
};
#endif /* INPUTEVENT_H_ */