A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using System;
5using Android.Views;
6using osu.Framework.Input.Handlers;
7using osu.Framework.Input.StateChanges;
8using osu.Framework.Platform;
9using osuTK.Input;
10
11namespace osu.Framework.Android.Input
12{
13 public class AndroidKeyboardHandler : InputHandler
14 {
15 private readonly AndroidGameView view;
16
17 public AndroidKeyboardHandler(AndroidGameView view)
18 {
19 this.view = view;
20 view.KeyDown += keyDown;
21 view.KeyUp += keyUp;
22 }
23
24 public override bool IsActive => true;
25
26 public override bool Initialize(GameHost host) => true;
27
28 private void keyDown(Keycode keycode, KeyEvent e)
29 {
30 var key = GetKeyCodeAsKey(keycode);
31
32 if (key != Key.Unknown)
33 PendingInputs.Enqueue(new KeyboardKeyInput(key, true));
34 }
35
36 private void keyUp(Keycode keycode, KeyEvent e)
37 {
38 var key = GetKeyCodeAsKey(keycode);
39
40 if (key != Key.Unknown)
41 PendingInputs.Enqueue(new KeyboardKeyInput(key, false));
42 }
43
44 /// <summary>
45 /// This method maps the <see cref="Xamarin.Android"/> <see cref="Keycode"/> to <see cref="Key"/> from opentk.
46 /// </summary>
47 /// <param name="keyCode">The <see cref="Keycode"/> to be converted into a <see cref="Key"/>.</param>
48 /// <returns>The <see cref="Key"/> that was converted from <see cref="Keycode"/>.</returns>
49 public static Key GetKeyCodeAsKey(Keycode keyCode)
50 {
51 int code = (int)keyCode;
52
53 // number keys
54 const int first_num_key = (int)Keycode.Num0;
55 const int last_num_key = (int)Keycode.Num9;
56 if (code >= first_num_key && code <= last_num_key)
57 return Key.Number0 + code - first_num_key;
58
59 // letters
60 const int first_letter_key = (int)Keycode.A;
61 const int last_letter_key = (int)Keycode.Z;
62 if (code >= first_letter_key && code <= last_letter_key)
63 return Key.A + code - first_letter_key;
64
65 // function keys
66 const int first_funtion_key = (int)Keycode.F1;
67 const int last_function_key = (int)Keycode.F12;
68 if (code >= first_funtion_key && code <= last_function_key)
69 return Key.F1 + code - first_funtion_key;
70
71 // keypad keys
72 const int first_keypad_key = (int)Keycode.Numpad0;
73 const int last_key_pad_key = (int)Keycode.NumpadDot;
74 if (code >= first_keypad_key && code <= last_key_pad_key)
75 return Key.Keypad0 + code - first_keypad_key;
76
77 // direction keys
78 const int first_direction_key = (int)Keycode.DpadUp;
79 const int last_direction_key = (int)Keycode.DpadRight;
80 if (code >= first_direction_key && code <= last_direction_key)
81 return Key.Up + code - first_direction_key;
82
83 // one to one mappings
84 switch (keyCode)
85 {
86 case Keycode.Back:
87 return Key.Escape;
88
89 case Keycode.MediaPlayPause:
90 return Key.PlayPause;
91
92 case Keycode.SoftLeft:
93 return Key.Left;
94
95 case Keycode.SoftRight:
96 return Key.Right;
97
98 case Keycode.Star:
99 return Key.KeypadMultiply;
100
101 case Keycode.Pound:
102 return Key.BackSlash; // english keyboard layout
103
104 case Keycode.Del:
105 return Key.BackSpace;
106
107 case Keycode.ForwardDel:
108 return Key.Delete;
109
110 case Keycode.Power:
111 return Key.Sleep;
112
113 case Keycode.MoveEnd:
114 return Key.End;
115
116 case Keycode.MediaPause:
117 return Key.Pause;
118
119 case Keycode.MediaClose:
120 return Key.Stop;
121
122 case Keycode.LeftBracket:
123 return Key.BracketLeft;
124
125 case Keycode.RightBracket:
126 return Key.BracketRight;
127
128 case Keycode.MediaPrevious:
129 return Key.TrackPrevious;
130
131 case Keycode.MediaNext:
132 return Key.TrackNext;
133
134 case Keycode.CtrlLeft:
135 return Key.ControlLeft;
136
137 case Keycode.CtrlRight:
138 return Key.ControlRight;
139
140 case Keycode.MetaLeft:
141 return Key.WinLeft;
142
143 case Keycode.MetaRight:
144 return Key.WinRight;
145
146 case Keycode.Equals:
147 return Key.Plus;
148
149 case Keycode.At:
150 case Keycode.Apostrophe:
151 return Key.Quote;
152 }
153
154 if (Enum.TryParse(keyCode.ToString(), out Key key))
155 return key;
156
157 // this is the worst case scenario. Please note that the osu-framework keyboard handling cannot cope with Key.Unknown.
158 return Key.Unknown;
159 }
160
161 protected override void Dispose(bool disposing)
162 {
163 view.KeyDown -= keyDown;
164 view.KeyUp -= keyUp;
165 base.Dispose(disposing);
166 }
167 }
168}