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