1 module iota.controls.keyboard;
2 
3 public import iota.controls.types;
4 
5 version (Windows) {
6 	import core.sys.windows.windows;
7 	import core.sys.windows.wtypes;
8 }
9 /** 
10  * Defines keyboard modifiers.
11  */
12 public enum KeyboardModifiers : ubyte {
13 	init,
14 	Shift	=	1<<0,
15 	Ctrl	=	1<<1,
16 	Alt		=	1<<2,
17 	Meta	=	1<<3,
18 	NumLock	=	1<<4,
19 	CapsLock=	1<<5,
20 	ScrollLock= 1<<6,
21 	Aux		=	1<<7,
22 }
23 /** 
24  * Defines keyboard locklight flags.
25  * Both `Compose` and `Kana` exist within USB HID specifications, however they not necessarily are implemented whithin
26  * OS API. Same with the now obsolete Scroll Lock.
27  */
28 public enum KeyboardLocklights : ubyte {
29 	NumLock	=	1<<0,
30 	CapsLock=	1<<1,
31 	ScrollLock= 1<<2,
32 	Compose	=	1<<3,
33 	Kana	=	1<<4,
34 }
35 /** 
36  * Implements keyboard I/O.
37  */
38 public class Keyboard : InputDevice {
39 	///Defines keyboard-specific flags.
40 	enum KeyboardFlags : ushort {
41 		TextInput		=	1<<8,	///Set if text input is enabled.
42 		IgnoreLLMods	=	1<<9,	///Set if lock light modifiers are to be ignored.
43 	}
44 	package this() nothrow {
45 		_type = InputDeviceType.Keyboard;
46 		status |= StatusFlags.IsConnected;
47 	}
48 	/** 
49 	 * Polls the device for events.
50 	 * Params:
51 	 *   output = InputEvents outputted by the 
52 	 * Returns: 1 if there's still events to be polled, 0 if no events left. Other values are error codes.
53 	 */
54 	public override int poll(ref InputEvent output) @nogc nothrow {
55 		version (Windows) {
56 			//Since Windows is a bit weird when it comes to inputs, so inputs are polled from system.
57 			//This class mainly exists here to provide context and other interfaces
58 			return 0;
59 		} else {
60 			return 0;
61 		}
62 	}
63 	/**
64 	 * Returns true if the text input has been enabled.
65 	 */
66 	public final bool isTextInputEn() @property @nogc @safe pure nothrow const {
67 		return (status & KeyboardFlags.TextInput) != 0;
68 	}
69 	/**
70 	 * Sets whether the text input is enabled or not, then 
71 	 */
72 	public bool setTextInput(bool val) @property @nogc @safe pure nothrow {
73 		if (val)
74 			status |= KeyboardFlags.TextInput;
75 		else
76 			status &= ~KeyboardFlags.TextInput;
77 		return isTextInputEn();
78 	}
79 	public final bool isIgnoringLockLights() @property @nogc @safe pure nothrow const {
80 		return (status & KeyboardFlags.IgnoreLLMods) != 0;
81 	}
82 	public bool setIgnoreLockLights(bool val) @property @nogc @safe pure nothrow {
83 		if (val)
84 			status |= KeyboardFlags.IgnoreLLMods;
85 		else
86 			status &= ~KeyboardFlags.IgnoreLLMods;
87 		return isIgnoringLockLights();
88 	}
89 	public ubyte getModifiers() @nogc nothrow {
90 		ubyte result;
91 		version (Windows) {
92 			if (GetKeyState(VK_SHIFT))
93 				result |= KeyboardModifiers.Shift;
94 			if (GetKeyState(VK_CONTROL))
95 				result |= KeyboardModifiers.Ctrl;
96 			if (GetKeyState(VK_MENU))
97 				result |= KeyboardModifiers.Alt;
98 			if (GetKeyState(VK_LWIN) | GetKeyState(VK_RWIN))
99 				result |= KeyboardModifiers.Meta;
100 			if (!isIgnoringLockLights()) {
101 				if (GetKeyState(VK_NUMLOCK))
102 					result |= KeyboardModifiers.NumLock;
103 				if (GetKeyState(VK_CAPITAL))
104 					result |= KeyboardModifiers.CapsLock;
105 				if (GetKeyState(VK_SCROLL))
106 					result |= KeyboardModifiers.ScrollLock;
107 			}
108 		}
109 		return result;
110 	}
111 }