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 osu.Framework.Input;
5using osu.Framework.Platform.MacOS.Native;
6
7namespace osu.Framework.Platform.MacOS
8{
9 internal class MacOSTextInput : GameWindowTextInput
10 {
11 // Defined as kCGEventFlagMaskAlphaShift in CoreGraphics
12 private const ulong event_flag_mask_alpha_shift = 65536;
13
14 // Defined as kCGEventSourceStateHIDSystemState in CoreGraphics
15 private const int event_source_state_hid_system_state = 1;
16
17 private static bool isCapsLockOn => (Cocoa.CGEventSourceFlagsState(event_source_state_hid_system_state) & event_flag_mask_alpha_shift) != 0;
18
19 public MacOSTextInput(IWindow window)
20 : base(window)
21 {
22 }
23
24 protected override void HandleKeyPress(object sender, osuTK.KeyPressEventArgs e)
25 {
26 // Drop any keypresses if the control, alt, or windows/command key are being held.
27 // This is a workaround for an issue on macOS where osuTK will fire KeyPress events even
28 // if modifier keys are held. This can be reverted when it is fixed on osuTK's side.
29 var state = osuTK.Input.Keyboard.GetState();
30 if (state.IsKeyDown(osuTK.Input.Key.LControl)
31 || state.IsKeyDown(osuTK.Input.Key.RControl)
32 || state.IsKeyDown(osuTK.Input.Key.LAlt)
33 || state.IsKeyDown(osuTK.Input.Key.RAlt)
34 || state.IsKeyDown(osuTK.Input.Key.LWin)
35 || state.IsKeyDown(osuTK.Input.Key.RWin))
36 return;
37
38 // arbitrary choice here, but it caters for any non-printable keys on an A1243 Apple Keyboard
39 if (e.KeyChar > 63000)
40 return;
41
42 // capslock is not correctly handled by osuTK, so force uppercase if capslock is on
43 if (isCapsLockOn)
44 e = new osuTK.KeyPressEventArgs(char.ToUpper(e.KeyChar));
45
46 base.HandleKeyPress(sender, e);
47 }
48 }
49}