summaryrefslogtreecommitdiffstats
path: root/src/input/inputEvent.h
blob: 4e132ebc2ed5e10ef7f3195a2ddfb30693578fb9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
/*
 # 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_ */