[ElmSharp] Fix SetNextFocusObject issue (#401)
[platform/core/csapi/tizenfx.git] / external / src / OpenTK / OpenTK / Input / KeyboardState.cs
1  //
2  // The Open Toolkit Library License
3  //
4  // Copyright (c) 2006 - 2009 the Open Toolkit library.
5  //
6  // Permission is hereby granted, free of charge, to any person obtaining a copy
7  // of this software and associated documentation files (the "Software"), to deal
8  // in the Software without restriction, including without limitation the rights to
9  // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10  // the Software, and to permit persons to whom the Software is furnished to do
11  // so, subject to the following conditions:
12  //
13  // The above copyright notice and this permission notice shall be included in all
14  // copies or substantial portions of the Software.
15  //
16  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18  // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20  // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21  // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  // OTHER DEALINGS IN THE SOFTWARE.
24  //
25
26 using System;
27
28 namespace OpenTK.Input
29 {
30     /// <summary>
31     /// Encapsulates the state of a Keyboard device.
32     /// </summary>
33     public struct KeyboardState : IEquatable<KeyboardState>
34     {
35         // Allocate enough ints to store all keyboard keys
36         private const int IntSize = sizeof(int) * 8;
37
38         private const int NumInts = ((int)Key.LastKey + IntSize - 1) / IntSize;
39         // The following line triggers bogus CS0214 in gmcs 2.0.1, sigh...
40         private unsafe fixed int Keys[NumInts];
41
42         /// <summary>
43         /// Gets a <see cref="System.Boolean"/> indicating whether the specified
44         /// <see cref="OpenTK.Input.Key"/> is pressed.
45         /// </summary>
46         /// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
47         /// <returns>True if key is pressed; false otherwise.</returns>
48         public bool this[Key key]
49         {
50             get { return IsKeyDown(key); }
51             internal set { SetKeyState(key, value); }
52         }
53
54         /// <summary>
55         /// Gets a <see cref="System.Boolean"/> indicating whether the specified
56         /// <see cref="OpenTK.Input.Key"/> is pressed.
57         /// </summary>
58         /// <param name="code">The scancode to check.</param>
59         /// <returns>True if code is pressed; false otherwise.</returns>
60         public bool this[short code]
61         {
62             get { return IsKeyDown((Key)code); }
63         }
64
65         /// <summary>
66         /// Gets a <see cref="System.Boolean"/> indicating whether this key is down.
67         /// </summary>
68         /// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
69         public bool IsKeyDown(Key key)
70         {
71             return ReadBit((int)key);
72         }
73
74         /// <summary>
75         /// Gets a <see cref="System.Boolean"/> indicating whether this scan code is down.
76         /// </summary>
77         /// <param name="code">The scan code to check.</param>
78         public bool IsKeyDown(short code)
79         {
80             return code >= 0 && code < (short)Key.LastKey && ReadBit(code);
81         }
82
83         /// <summary>
84         /// Gets a <see cref="System.Boolean"/> indicating whether this key is up.
85         /// </summary>
86         /// <param name="key">The <see cref="OpenTK.Input.Key"/> to check.</param>
87         public bool IsKeyUp(Key key)
88         {
89             return !ReadBit((int)key);
90         }
91
92         /// <summary>
93         /// Gets a <see cref="System.Boolean"/> indicating whether this scan code is down.
94         /// </summary>
95         /// <param name="code">The scan code to check.</param>
96         public bool IsKeyUp(short code)
97         {
98             return !IsKeyDown(code);
99         }
100
101         /// <summary>
102         /// Gets a value indicating whether any key is down.
103         /// </summary>
104         /// <value><c>true</c> if any key is down; otherwise, <c>false</c>.</value>
105         public bool IsAnyKeyDown
106         {
107             get
108             {
109                 // If any bit is set then a key is down.
110                 unsafe
111                 {
112                     fixed (int* k = Keys)
113                     {
114                         for (int i = 0; i < NumInts; ++i)
115                         {
116                             if (k[i] != 0)
117                             {
118                                 return true;
119                             }
120                         }
121                     }
122                 }
123
124                 return false;
125             }
126         }
127
128         /// <summary>
129         /// Gets a <see cref="System.Boolean"/> indicating whether this keyboard
130         /// is connected.
131         /// </summary>
132         public bool IsConnected { get; internal set; }
133
134 #if false
135         // Disabled until the correct cross-platform API can be determined.
136         public bool IsLedOn(KeyboardLeds led)
137         {
138             return false;
139         }
140
141         public bool IsLedOff(KeyboardLeds led)
142         {
143             return false;
144         }
145 #endif
146
147         /// <summary>
148         /// Checks whether two <see cref="KeyboardState" /> instances are equal.
149         /// </summary>
150         /// <param name="left">
151         /// A <see cref="KeyboardState"/> instance.
152         /// </param>
153         /// <param name="right">
154         /// A <see cref="KeyboardState"/> instance.
155         /// </param>
156         /// <returns>
157         /// True if both left is equal to right; false otherwise.
158         /// </returns>
159         public static bool operator ==(KeyboardState left, KeyboardState right)
160         {
161             return left.Equals(right);
162         }
163
164         /// <summary>
165         /// Checks whether two <see cref="KeyboardState" /> instances are not equal.
166         /// </summary>
167         /// <param name="left">
168         /// A <see cref="KeyboardState"/> instance.
169         /// </param>
170         /// <param name="right">
171         /// A <see cref="KeyboardState"/> instance.
172         /// </param>
173         /// <returns>
174         /// True if both left is not equal to right; false otherwise.
175         /// </returns>
176         public static bool operator !=(KeyboardState left, KeyboardState right)
177         {
178             return !left.Equals(right);
179         }
180
181         /// <summary>
182         /// Compares to an object instance for equality.
183         /// </summary>
184         /// <param name="obj">
185         /// The <see cref="System.Object"/> to compare to.
186         /// </param>
187         /// <returns>
188         /// True if this instance is equal to obj; false otherwise.
189         /// </returns>
190         public override bool Equals(object obj)
191         {
192             if (obj is KeyboardState)
193             {
194                 return this == (KeyboardState)obj;
195             }
196             else
197             {
198                 return false;
199             }
200         }
201
202         /// <summary>
203         /// Generates a hashcode for the current instance.
204         /// </summary>
205         /// <returns>
206         /// A <see cref="System.Int32"/> represting the hashcode for this instance.
207         /// </returns>
208         public override int GetHashCode()
209         {
210             unsafe
211             {
212                 fixed (int* k = Keys)
213                 {
214                     int hashcode = 0;
215                     for (int i = 0; i < NumInts; i++)
216                     {
217                         hashcode ^= (k + i)->GetHashCode();
218                     }
219                     return hashcode;
220                 }
221             }
222         }
223
224         internal void SetKeyState(Key key, bool down)
225         {
226             if (down)
227             {
228                 EnableBit((int)key);
229             }
230             else
231             {
232                 DisableBit((int)key);
233             }
234         }
235
236         internal bool ReadBit(int offset)
237         {
238             ValidateOffset(offset);
239
240             int int_offset = offset / IntSize;
241             int bit_offset = offset % IntSize;
242             unsafe
243             {
244                 fixed (int* k = Keys) { return (*(k + int_offset) & (1 << bit_offset)) != 0u; }
245             }
246         }
247
248         internal void EnableBit(int offset)
249         {
250             ValidateOffset(offset);
251
252             int int_offset = offset / IntSize;
253             int bit_offset = offset % IntSize;
254             unsafe
255             {
256                 fixed (int* k = Keys) { *(k + int_offset) |= 1 << bit_offset; }
257             }
258         }
259
260         internal void DisableBit(int offset)
261         {
262             ValidateOffset(offset);
263
264             int int_offset = offset / IntSize;
265             int bit_offset = offset % IntSize;
266             unsafe
267             {
268                 fixed (int* k = Keys) { *(k + int_offset) &= ~(1 << bit_offset); }
269             }
270         }
271
272         internal void MergeBits(KeyboardState other)
273         {
274             unsafe
275             {
276                 int* k2 = other.Keys;
277                 fixed (int* k1 = Keys)
278                 {
279                     for (int i = 0; i < NumInts; i++)
280                     {
281                         *(k1 + i) |= *(k2 + i);
282                     }
283                 }
284             }
285             IsConnected |= other.IsConnected;
286         }
287
288         internal void SetIsConnected(bool value)
289         {
290             IsConnected = value;
291         }
292
293         private static void ValidateOffset(int offset)
294         {
295             if (offset < 0 || offset >= NumInts * IntSize)
296             {
297                 throw new ArgumentOutOfRangeException();
298             }
299         }
300
301         /// <summary>
302         /// Compares two KeyboardState instances.
303         /// </summary>
304         /// <param name="other">The instance to compare two.</param>
305         /// <returns>True, if both instances are equal; false otherwise.</returns>
306         public bool Equals(KeyboardState other)
307         {
308             bool equal = true;
309             unsafe
310             {
311                 int* k2 = other.Keys;
312                 fixed (int* k1 = Keys)
313                 {
314                     for (int i = 0; equal && i < NumInts; i++)
315                     {
316                         equal &= *(k1 + i) == *(k2 + i);
317                     }
318                 }
319             }
320             return equal;
321         }
322     }
323 }