1 //------------------------------------------------------------------------------
2 // emInput.h
3 //
4 // Copyright (C) 2005-2012,2014-2015,2018 Oliver Hamann.
5 //
6 // Homepage: http://eaglemode.sourceforge.net/
7 //
8 // This program is free software: you can redistribute it and/or modify it under
9 // the terms of the GNU General Public License version 3 as published by the
10 // Free Software Foundation.
11 //
12 // This program is distributed in the hope that it will be useful, but WITHOUT
13 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
14 // FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
15 // more details.
16 //
17 // You should have received a copy of the GNU General Public License version 3
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //------------------------------------------------------------------------------
20 
21 #ifndef emInput_h
22 #define emInput_h
23 
24 #ifndef emStd2_h
25 #include <emCore/emStd2.h>
26 #endif
27 
28 #ifndef emArray_h
29 #include <emCore/emArray.h>
30 #endif
31 
32 
33 //==============================================================================
34 //================================= emInputKey =================================
35 //==============================================================================
36 
37 enum emInputKey {
38 
39 	// None:
40 	EM_KEY_NONE           = 0x00,
41 
42 	// Mouse buttons and wheel:
43 	EM_KEY_LEFT_BUTTON    = 0xF0,
44 	EM_KEY_MIDDLE_BUTTON  = 0xF1,
45 	EM_KEY_RIGHT_BUTTON   = 0xF2,
46 	EM_KEY_WHEEL_UP       = 0xF3,
47 	EM_KEY_WHEEL_DOWN     = 0xF4,
48 	EM_KEY_WHEEL_LEFT     = 0xF5,
49 	EM_KEY_WHEEL_RIGHT    = 0xF6,
50 	EM_KEY_BACK_BUTTON    = 0xF7,
51 	EM_KEY_FORWARD_BUTTON = 0xF8,
52 
53 	// Screen touch:
54 	EM_KEY_TOUCH          = 0xEF,
55 
56 	// Keyboard keys:
57 	EM_KEY_SHIFT          = 0x81,
58 	EM_KEY_CTRL           = 0x82,
59 	EM_KEY_ALT            = 0x83,
60 	EM_KEY_META           = 0x84,
61 	EM_KEY_ALT_GR         = 0x85,
62 	EM_KEY_CURSOR_UP      = 0x91,
63 	EM_KEY_CURSOR_DOWN    = 0x92,
64 	EM_KEY_CURSOR_LEFT    = 0x93,
65 	EM_KEY_CURSOR_RIGHT   = 0x94,
66 	EM_KEY_PAGE_UP        = 0x95,
67 	EM_KEY_PAGE_DOWN      = 0x96,
68 	EM_KEY_HOME           = 0x97,
69 	EM_KEY_END            = 0x98,
70 	EM_KEY_PRINT          = 0x99,
71 	EM_KEY_PAUSE          = 0x9A,
72 	EM_KEY_MENU           = 0x9B,
73 	EM_KEY_INSERT         = 0x9F,
74 	EM_KEY_DELETE         = 0x7F,
75 	EM_KEY_BACKSPACE      = 0x08,
76 	EM_KEY_TAB            = 0x09,
77 	EM_KEY_ENTER          = 0x0D,
78 	EM_KEY_ESCAPE         = 0x1B,
79 	EM_KEY_SPACE          = 0x20,
80 	EM_KEY_0              = 0x30,
81 	EM_KEY_1              = 0x31,
82 	EM_KEY_2              = 0x32,
83 	EM_KEY_3              = 0x33,
84 	EM_KEY_4              = 0x34,
85 	EM_KEY_5              = 0x35,
86 	EM_KEY_6              = 0x36,
87 	EM_KEY_7              = 0x37,
88 	EM_KEY_8              = 0x38,
89 	EM_KEY_9              = 0x39,
90 	EM_KEY_A              = 0x41,
91 	EM_KEY_B              = 0x42,
92 	EM_KEY_C              = 0x43,
93 	EM_KEY_D              = 0x44,
94 	EM_KEY_E              = 0x45,
95 	EM_KEY_F              = 0x46,
96 	EM_KEY_G              = 0x47,
97 	EM_KEY_H              = 0x48,
98 	EM_KEY_I              = 0x49,
99 	EM_KEY_J              = 0x4A,
100 	EM_KEY_K              = 0x4B,
101 	EM_KEY_L              = 0x4C,
102 	EM_KEY_M              = 0x4D,
103 	EM_KEY_N              = 0x4E,
104 	EM_KEY_O              = 0x4F,
105 	EM_KEY_P              = 0x50,
106 	EM_KEY_Q              = 0x51,
107 	EM_KEY_R              = 0x52,
108 	EM_KEY_S              = 0x53,
109 	EM_KEY_T              = 0x54,
110 	EM_KEY_U              = 0x55,
111 	EM_KEY_V              = 0x56,
112 	EM_KEY_W              = 0x57,
113 	EM_KEY_X              = 0x58,
114 	EM_KEY_Y              = 0x59,
115 	EM_KEY_Z              = 0x5A,
116 	EM_KEY_F1             = 0xA1,
117 	EM_KEY_F2             = 0xA2,
118 	EM_KEY_F3             = 0xA3,
119 	EM_KEY_F4             = 0xA4,
120 	EM_KEY_F5             = 0xA5,
121 	EM_KEY_F6             = 0xA6,
122 	EM_KEY_F7             = 0xA7,
123 	EM_KEY_F8             = 0xA8,
124 	EM_KEY_F9             = 0xA9,
125 	EM_KEY_F10            = 0xAA,
126 	EM_KEY_F11            = 0xAB,
127 	EM_KEY_F12            = 0xAC
128 };
129 
130 
131 bool emIsMouseInputKey(emInputKey key);
132 	// True for mouse buttons and mouse wheel.
133 
134 bool emIsTouchInputKey(emInputKey key);
135 	// True screen touch.
136 
137 bool emIsKeyboardInputKey(emInputKey key);
138 	// True for all keyboard keys, including modifiers.
139 
140 bool emIsModifierInputKey(emInputKey key);
141 	// True for shift, ctrl, alt and meta.
142 
143 const char * emInputKeyToString(emInputKey key);
144 emInputKey emStringToInputKey(const char * str);
145 	// Convert an input key to and from string representation.
146 
147 
148 //==============================================================================
149 //================================ emInputEvent ================================
150 //==============================================================================
151 
152 class emInputEvent : public emUncopyable {
153 
154 public:
155 
156 	// Class for an input event. Such an event consists of an input key
157 	// (mouse buttons and wheel are even "keys" here), which has changed
158 	// from non-pressed to pressed state. Instead of a key, or in addition
159 	// to the key, a translation into text characters may be provided. It is
160 	// possible that an original event comes through two input events: one
161 	// with the input key, and one with the translated text characters (at
162 	// the time of writing this, it is so with emWndsWindowPort, but not
163 	// with emX11WindowPort).
164 
165 	emInputEvent();
166 		// Construct an event which is initially empty.
167 
168 	void Setup(emInputKey key, const emString & chars, int repeat,
169 	           int variant);
170 		// Set-up the event.
171 		// Arguments:
172 		//   key     - see GetKey().
173 		//   chars   - see GetChars().
174 		//   repeat  - see GetRepeat().
175 		//   variant - see GetVariant().
176 
177 	emInputKey GetKey() const;
178 		// Get the key. This is EM_KEY_NONE if the event is empty or if
179 		// the event provides characters only (see GetChars()).
180 
181 	const emString & GetChars() const;
182 		// Get the translated text characters. This should be at most
183 		// one text character, but possibly encoded as a multi-byte
184 		// sequence (e.g. UTF-8). This is an empty string if the event
185 		// is empty, or if the key could not be translated.
186 
187 	int GetRepeat() const;
188 		// Get number of event repetitions. For example, 1 means
189 		// double-click for mouse buttons.
190 
191 	int GetVariant() const;
192 		// Get variant of the event source. If the key is on the numeric
193 		// key pad, or if it is the right shift, right ctrl or right alt
194 		// key, then this should be 1. Otherwise this should be 0.
195 
196 	void Eat();
197 		// Eat this event (make it an empty event).
198 
199 	bool IsEmpty() const;
200 	bool IsMouseEvent() const;
201 	bool IsTouchEvent() const;
202 	bool IsKeyboardEvent() const;
203 		// Ask for the type of event. One of these returns true.
204 
205 	bool IsKey(emInputKey key) const;
206 		// Like GetKey()==key.
207 
208 	bool IsLeftButton() const;
209 	bool IsMiddleButton() const;
210 	bool IsRightButton() const;
211 		// Like GetKey()==EM_KEY_LEFT_BUTTON and so on.
212 
213 private:
214 	emInputKey Key;
215 	emString Chars;
216 	int Repeat,Variant;
217 };
218 
219 
220 //==============================================================================
221 //================================ emInputState ================================
222 //==============================================================================
223 
224 class emInputState {
225 
226 public:
227 
228 	// Class for the state of keyboard and mouse. The state consists of the
229 	// mouse pointer position, and which keys are pressed. (Mouse buttons
230 	// are even keys)
231 
232 	emInputState();
233 		// Construct without having any key pressed.
234 
235 	emInputState(const emInputState & inputState);
236 		// Construct a copy of an input state.
237 
238 	emInputState & operator = (const emInputState & inputState);
239 		// Copy another input state to this input state.
240 
241 	bool operator == (const emInputState & inputState) const;
242 	bool operator != (const emInputState & inputState) const;
243 		// Comparison operators.
244 
245 	double GetMouseX() const;
246 	double GetMouseY() const;
247 	void SetMouse(double mouseX, double mouseY);
248 		// Get or set the mouse position in pixel coordinates of the
249 		// view.
250 
251 	int GetTouchCount() const;
252 		// Get number of touches.
253 
254 	int SearchTouch(emUInt64 id) const;
255 		// Search a touch by id. Returns the index or -1 if not found.
256 
257 	emUInt64 GetTouchId(int index) const;
258 		// Get the id of a touch. A touch may get another index over the
259 		// time, but it should keep its id.
260 
261 	double GetTouchX(int index) const;
262 	double GetTouchY(int index) const;
263 		// Get position of a touch in pixel coordinates of the view.
264 
265 	void AddTouch(emUInt64 id, double x, double y);
266 		// Add a touch.
267 
268 	void SetTouch(int index, emUInt64 id, double x, double y);
269 		// Modify an existing touch.
270 
271 	void RemoveTouch(int index);
272 		// Remove a touch.
273 
274 	void ClearTouches();
275 		// Remove all touches.
276 
277 	bool Get(emInputKey key) const;
278 	void Set(emInputKey key, bool pressed);
279 		// Get or set the state of a particular key. It is true if the
280 		// key or button is pressed, false otherwise. EM_KEY_WHEEL_UP
281 		// and EM_KEY_WHEEL_DOWN should never be set here.
282 
283 	bool GetLeftButton() const;
284 	bool GetMiddleButton() const;
285 	bool GetRightButton() const;
286 	bool GetShift() const;
287 	bool GetCtrl() const;
288 	bool GetAlt() const;
289 	bool GetMeta() const;
290 		// These are just some abbreviations. It's like
291 		// Get(EM_KEY_LEFT_BUTTON) and so on.
292 
293 	bool IsNoMod() const;
294 	bool IsShiftMod() const;
295 	bool IsShiftCtrlMod() const;
296 	bool IsShiftCtrlAltMod() const;
297 	bool IsShiftCtrlAltMetaMod() const;
298 	bool IsShiftCtrlMetaMod() const;
299 	bool IsShiftAltMod() const;
300 	bool IsShiftAltMetaMod() const;
301 	bool IsShiftMetaMod() const;
302 	bool IsCtrlMod() const;
303 	bool IsCtrlAltMod() const;
304 	bool IsCtrlAltMetaMod() const;
305 	bool IsCtrlMetaMod() const;
306 	bool IsAltMod() const;
307 	bool IsAltMetaMod() const;
308 	bool IsMetaMod() const;
309 		// Test the four modifier keys at once. For example,
310 		// IsShiftMetaMod() is like (GetShift() && !GetCtrl() &&
311 		// !GetAlt() && GetMeta()).
312 
313 	bool ClearKeyStates();
314 		// Set all keys to non-pressed state. Returns true if something
315 		// was pressed.
316 
317 	const unsigned char * GetKeyStates() const;
318 	unsigned char * GetKeyStates();
319 		// Get a pointer to the states of all keyboard keys and mouse
320 		// buttons, even for modification. The size of the returned
321 		// array is 32 bytes. A key is pressed if
322 		// GetKeyStates()[key>>3]&(1<<(key&7)) is non-zero.
323 
324 private:
325 
326 	struct Touch {
327 		emUInt64 Id;
328 		double X, Y;
329 	};
330 
331 	double MouseX, MouseY;
332 	unsigned char KeyStates[32];
333 	emArray<Touch> Touches;
334 };
335 
336 
337 //==============================================================================
338 //=============================== emInputHotkey ================================
339 //==============================================================================
340 
341 class emInputHotkey {
342 
343 public:
344 
345 	// Class for a hotkey. It is a combination of modifier keys and a
346 	// non-modifier keyboard key.
347 
348 	emInputHotkey();
349 		// Construct an invalid hotkey.
350 
351 	emInputHotkey(const emInputHotkey & hotkey);
352 		// Copy constructor.
353 
354 	emInputHotkey(emInputKey key);
355 	emInputHotkey(emInputKey modifier, emInputKey key);
356 	emInputHotkey(emInputKey modifier1, emInputKey modifier2,
357 	              emInputKey key);
358 	emInputHotkey(emInputKey modifier1, emInputKey modifier2,
359 	              emInputKey modifier3, emInputKey key);
360 	emInputHotkey(emInputKey modifier1, emInputKey modifier2,
361 	              emInputKey modifier3, emInputKey modifier4,
362 	              emInputKey key);
363 		// Construct a valid hotkey. The last argument must be a
364 		// non-modifier keyboard key, the other arguments must be
365 		// modifier keys.
366 
367 	emInputHotkey(const emInputEvent & event, const emInputState & state);
368 		// Construct form an input event and an input state. The hotkey
369 		// gets invalid if the event is not a non-modifier keyboard key.
370 
371 	emInputHotkey & operator = (const emInputHotkey & hotkey);
372 		// Copy operator.
373 
374 	bool operator == (const emInputHotkey & hotkey) const;
375 	bool operator != (const emInputHotkey & hotkey) const;
376 		// Comparison operators.
377 
378 	void TryParse(const char * str);
379 		// Try to set this hotkey from a human-readable string
380 		// representation (e.g. "Ctrl+C"). On failure, the hotkey is set
381 		// invalid and an error message is thrown.
382 
383 	emString GetString() const;
384 	void GetString(char * buf, int bufSize) const;
385 		// Create a human-readable string representation (e.g.
386 		// "Ctrl+C"). If the hotkey is invalid, an empty string is
387 		// returned.
388 
389 	bool IsValid() const;
390 		// Whether this is a valid hotkey.
391 
392 	bool GetShift() const;
393 	bool GetCtrl() const;
394 	bool GetAlt() const;
395 	bool GetMeta() const;
396 		// Whether the respective modifier key is part of this hotkey.
397 
398 	emInputKey GetKey() const;
399 		// Get the event key. Returns EM_KEY_NONE if the hotkey is not
400 		// valid.
401 
402 	bool Match(const emInputEvent & event, const emInputState & state) const;
403 		// Ask whether the input event and input state matches this
404 		// hotkey.
405 
406 	void ClearModifiers();
407 		// Remove all modifiers.
408 
409 	void AddModifier(emInputKey modifier);
410 		// Add a modifier.
411 
412 	void SetKey(emInputKey key);
413 		// Set the event key. Must be a non-modifier keyboard key or the
414 		// hotkey gets invalid.
415 
416 private:
417 
418 	static const char * Key2Name(emInputKey key);
419 	static emInputKey Name2Key(const char * name, int len);
420 
421 	enum {
422 		MF_SHIFT=(1<<0),
423 		MF_CTRL =(1<<1),
424 		MF_ALT  =(1<<2),
425 		MF_META =(1<<3)
426 	};
427 
428 	union {
429 		emUInt16 Packed;
430 		struct {
431 			emByte MFlags;
432 			emByte Key;
433 		} Data;
434 	};
435 };
436 
437 
438 //==============================================================================
439 //=========================== Inline Implementations ===========================
440 //==============================================================================
441 
emIsMouseInputKey(emInputKey key)442 inline bool emIsMouseInputKey(emInputKey key)
443 {
444 	return key>=EM_KEY_LEFT_BUTTON;
445 }
446 
emIsTouchInputKey(emInputKey key)447 inline bool emIsTouchInputKey(emInputKey key)
448 {
449 	return key==EM_KEY_TOUCH;
450 }
451 
emIsKeyboardInputKey(emInputKey key)452 inline bool emIsKeyboardInputKey(emInputKey key)
453 {
454 	return key && key<EM_KEY_TOUCH;
455 }
456 
emIsModifierInputKey(emInputKey key)457 inline bool emIsModifierInputKey(emInputKey key)
458 {
459 	return (((int)key)&0xF8)==0x80;
460 }
461 
GetKey()462 inline emInputKey emInputEvent::GetKey() const
463 {
464 	return Key;
465 }
466 
GetChars()467 inline const emString & emInputEvent::GetChars() const
468 {
469 	return Chars;
470 }
471 
GetRepeat()472 inline int emInputEvent::GetRepeat() const
473 {
474 	return Repeat;
475 }
476 
GetVariant()477 inline int emInputEvent::GetVariant() const
478 {
479 	return Variant;
480 }
481 
IsEmpty()482 inline bool emInputEvent::IsEmpty() const
483 {
484 	return Key==EM_KEY_NONE && Chars.IsEmpty();
485 }
486 
IsMouseEvent()487 inline bool emInputEvent::IsMouseEvent() const
488 {
489 	return emIsMouseInputKey(Key);
490 }
491 
IsTouchEvent()492 inline bool emInputEvent::IsTouchEvent() const
493 {
494 	return emIsTouchInputKey(Key);
495 }
496 
IsKeyboardEvent()497 inline bool emInputEvent::IsKeyboardEvent() const
498 {
499 	return emIsKeyboardInputKey(Key) || !Chars.IsEmpty();
500 }
501 
IsKey(emInputKey key)502 inline bool emInputEvent::IsKey(emInputKey key) const
503 {
504 	return Key==key;
505 }
506 
IsLeftButton()507 inline bool emInputEvent::IsLeftButton() const
508 {
509 	return Key==EM_KEY_LEFT_BUTTON;
510 }
511 
IsMiddleButton()512 inline bool emInputEvent::IsMiddleButton() const
513 {
514 	return Key==EM_KEY_MIDDLE_BUTTON;
515 }
516 
IsRightButton()517 inline bool emInputEvent::IsRightButton() const
518 {
519 	return Key==EM_KEY_RIGHT_BUTTON;
520 }
521 
GetMouseX()522 inline double emInputState::GetMouseX() const
523 {
524 	return MouseX;
525 }
526 
GetMouseY()527 inline double emInputState::GetMouseY() const
528 {
529 	return MouseY;
530 }
531 
SetMouse(double mouseX,double mouseY)532 inline void emInputState::SetMouse(double mouseX, double mouseY)
533 {
534 	MouseX=mouseX;
535 	MouseY=mouseY;
536 }
537 
GetTouchCount()538 inline int emInputState::GetTouchCount() const
539 {
540 	return Touches.GetCount();
541 }
542 
GetTouchId(int index)543 inline emUInt64 emInputState::GetTouchId(int index) const
544 {
545 	return Touches[index].Id;
546 }
547 
GetTouchX(int index)548 inline double emInputState::GetTouchX(int index) const
549 {
550 	return Touches[index].X;
551 }
552 
GetTouchY(int index)553 inline double emInputState::GetTouchY(int index) const
554 {
555 	return Touches[index].Y;
556 }
557 
GetLeftButton()558 inline bool emInputState::GetLeftButton() const
559 {
560 	return (KeyStates[EM_KEY_LEFT_BUTTON>>3]&(1<<(EM_KEY_LEFT_BUTTON&7)))!=0;
561 }
562 
GetMiddleButton()563 inline bool emInputState::GetMiddleButton() const
564 {
565 	return (KeyStates[EM_KEY_MIDDLE_BUTTON>>3]&(1<<(EM_KEY_MIDDLE_BUTTON&7)))!=0;
566 }
567 
GetRightButton()568 inline bool emInputState::GetRightButton() const
569 {
570 	return (KeyStates[EM_KEY_RIGHT_BUTTON>>3]&(1<<(EM_KEY_RIGHT_BUTTON&7)))!=0;
571 }
572 
GetShift()573 inline bool emInputState::GetShift() const
574 {
575 	return (KeyStates[EM_KEY_SHIFT>>3]&(1<<(EM_KEY_SHIFT&7)))!=0;
576 }
577 
GetCtrl()578 inline bool emInputState::GetCtrl() const
579 {
580 	return (KeyStates[EM_KEY_CTRL>>3]&(1<<(EM_KEY_CTRL&7)))!=0;
581 }
582 
GetAlt()583 inline bool emInputState::GetAlt() const
584 {
585 	return (KeyStates[EM_KEY_ALT>>3]&(1<<(EM_KEY_ALT&7)))!=0;
586 }
587 
GetMeta()588 inline bool emInputState::GetMeta() const
589 {
590 	return (KeyStates[EM_KEY_META>>3]&(1<<(EM_KEY_META&7)))!=0;
591 }
592 
GetKeyStates()593 inline const unsigned char * emInputState::GetKeyStates() const
594 {
595 	return KeyStates;
596 }
597 
GetKeyStates()598 inline unsigned char * emInputState::GetKeyStates()
599 {
600 	return KeyStates;
601 }
602 
emInputHotkey()603 inline emInputHotkey::emInputHotkey()
604 {
605 	Packed=0;
606 }
607 
emInputHotkey(const emInputHotkey & hotkey)608 inline emInputHotkey::emInputHotkey(const emInputHotkey & hotkey)
609 {
610 	Packed=hotkey.Packed;
611 }
612 
613 inline emInputHotkey & emInputHotkey::operator = (const emInputHotkey & hotkey)
614 {
615 	Packed=hotkey.Packed;
616 	return *this;
617 }
618 
619 inline bool emInputHotkey::operator == (const emInputHotkey & hotkey) const
620 {
621 	return Packed==hotkey.Packed;
622 }
623 
624 inline bool emInputHotkey::operator != (const emInputHotkey & hotkey) const
625 {
626 	return Packed!=hotkey.Packed;
627 }
628 
IsValid()629 inline bool emInputHotkey::IsValid() const
630 {
631 	return Data.Key!=(emByte)EM_KEY_NONE;
632 }
633 
GetShift()634 inline bool emInputHotkey::GetShift() const
635 {
636 	return (Data.MFlags&MF_SHIFT)!=0;
637 }
638 
GetCtrl()639 inline bool emInputHotkey::GetCtrl() const
640 {
641 	return (Data.MFlags&MF_CTRL)!=0;
642 }
643 
GetAlt()644 inline bool emInputHotkey::GetAlt() const
645 {
646 	return (Data.MFlags&MF_ALT)!=0;
647 }
648 
GetMeta()649 inline bool emInputHotkey::GetMeta() const
650 {
651 	return (Data.MFlags&MF_META)!=0;
652 }
653 
GetKey()654 inline emInputKey emInputHotkey::GetKey() const
655 {
656 	return (emInputKey)Data.Key;
657 }
658 
ClearModifiers()659 inline void emInputHotkey::ClearModifiers()
660 {
661 	Data.MFlags=0;
662 }
663 
664 
665 #endif
666