mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
mobile/ebitenmobileview: add iOS Keyboard support. (#2678)
Closes #1090
This commit is contained in:
parent
b96aea70f1
commit
1789f509e1
@ -259,6 +259,28 @@
|
||||
[self updateTouches:touches];
|
||||
}
|
||||
|
||||
- (void)updatePresses:(NSSet<UIPress *> *)presses {
|
||||
if (@available(iOS 13.4, *)) {
|
||||
// Note: before iOS 13.4, this just can return UIPressType, which is
|
||||
// insufficient for games.
|
||||
for (UIPress *press in presses) {
|
||||
UIKey *key = press.key;
|
||||
if (key == nil) {
|
||||
continue;
|
||||
}
|
||||
EbitenmobileviewUpdatePressesOnIOS(press.phase, key.keyCode, key.characters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
|
||||
[self updatePresses:presses];
|
||||
}
|
||||
|
||||
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
|
||||
[self updatePresses:presses];
|
||||
}
|
||||
|
||||
- (void)suspendGame {
|
||||
NSAssert(started_, @"suspendGame must not be called before viewDidLoad is called");
|
||||
|
||||
|
119
genkeys.go
119
genkeys.go
@ -35,6 +35,7 @@ var (
|
||||
glfwKeyNameToGLFWKey map[string]glfw.Key
|
||||
uiKeyNameToGLFWKeyName map[string]string
|
||||
androidKeyToUIKeyName map[int]string
|
||||
iosKeyToUIKeyName map[int]string
|
||||
gbuildKeyToUIKeyName map[key.Code]string
|
||||
uiKeyNameToJSKey map[string]string
|
||||
oldEbitengineKeyNameToUIKeyName map[string]string
|
||||
@ -196,6 +197,90 @@ func init() {
|
||||
118: "MetaRight",
|
||||
}
|
||||
|
||||
// https://developer.apple.com/documentation/uikit/uikeyboardhidusage?language=objc
|
||||
iosKeyToUIKeyName = map[int]string{
|
||||
0xE2: "AltLeft",
|
||||
0xE6: "AltRight",
|
||||
0x51: "ArrowDown",
|
||||
0x50: "ArrowLeft",
|
||||
0x4F: "ArrowRight",
|
||||
0x52: "ArrowUp",
|
||||
0x35: "Backquote",
|
||||
|
||||
// These three keys are:
|
||||
// - US backslash-pipe key (above return),
|
||||
// - non-US backslash key (next to left shift; on German layout this is the <>| key), and
|
||||
// - non-US hashmark key (bottom left of return; on German layout, this is the #' key).
|
||||
// On US layout configurations, they all map to the same characters - the backslash.
|
||||
//
|
||||
// See also: https://www.w3.org/TR/uievents-code/#keyboard-102
|
||||
0x31: "Backslash", // UIKeyboardHIDUsageKeyboardBackslash
|
||||
0x64: "Backslash", // UIKeyboardHIDUsageKeyboardNonUSBackslash
|
||||
0x32: "Backslash", // UIKeyboardHIDUsageKeyboardNonUSPound
|
||||
|
||||
0x2A: "Backspace",
|
||||
0x2F: "BracketLeft",
|
||||
0x30: "BracketRight",
|
||||
|
||||
// Caps Lock can either be a normal key or a hardware toggle.
|
||||
0x39: "CapsLock", // UIKeyboardHIDUsageKeyboardCapsLock
|
||||
0x82: "CapsLock", // UIKeyboardHIDUsageKeyboardLockingCapsLock
|
||||
|
||||
0x36: "Comma",
|
||||
0xE0: "ControlLeft",
|
||||
0xE4: "ControlRight",
|
||||
0x4C: "Delete",
|
||||
0x4D: "End",
|
||||
0x28: "Enter",
|
||||
0x2E: "Equal",
|
||||
0x29: "Escape",
|
||||
0x4A: "Home",
|
||||
0x49: "Insert",
|
||||
0x76: "ContextMenu",
|
||||
0xE3: "MetaLeft",
|
||||
0xE7: "MetaRight",
|
||||
0x2D: "Minus",
|
||||
|
||||
// Num Lock can either be a normal key or a hardware toggle.
|
||||
0x53: "NumLock", // UIKeyboardHIDUsageKeyboardNumLock
|
||||
0x83: "NumLock", // UIKeyboardHIDUsageKeyboardLockingNumLock
|
||||
|
||||
0x57: "NumpadAdd",
|
||||
|
||||
// Some keyboard layouts have a comma, some a period on the numeric pad.
|
||||
// They are the same key, though.
|
||||
0x63: "NumpadDecimal", // UIKeyboardHIDUsageKeypadPeriod
|
||||
0x85: "NumpadDecimal", // UIKeyboardHIDUsageKeypadComma
|
||||
|
||||
0x54: "NumpadDivide",
|
||||
0x58: "NumpadEnter",
|
||||
|
||||
// Some numeric keypads also have an equals sign.
|
||||
// There appear to be two separate keycodes for that.
|
||||
0x67: "NumpadEqual", // UIKeyboardHIDUsageKeypadEqualSign
|
||||
0x86: "NumpadEqual", // UIKeyboardHIDUsageKeypadEqualSignAS400
|
||||
|
||||
0x55: "NumpadMultiply",
|
||||
0x56: "NumpadSubtract",
|
||||
0x4E: "PageDown",
|
||||
0x4B: "PageUp",
|
||||
0x48: "Pause",
|
||||
0x37: "Period",
|
||||
0x46: "PrintScreen",
|
||||
0x34: "Quote",
|
||||
|
||||
// Scroll Lock can either be a normal key or a hardware toggle.
|
||||
0x47: "ScrollLock", // UIKeyboardHIDUsageKeyboardScrollLock
|
||||
0x84: "ScrollLock", // UIKeyboardHIDUsageKeyboardLockingScrollLock
|
||||
|
||||
0x33: "Semicolon",
|
||||
0xE1: "ShiftLeft",
|
||||
0xE5: "ShiftRight",
|
||||
0x38: "Slash",
|
||||
0x2C: "Space",
|
||||
0x2B: "Tab",
|
||||
}
|
||||
|
||||
gbuildKeyToUIKeyName = map[key.Code]string{
|
||||
key.CodeComma: "Comma",
|
||||
key.CodeFullStop: "Period",
|
||||
@ -306,19 +391,23 @@ func init() {
|
||||
uiKeyNameToGLFWKeyName[name] = string(c)
|
||||
androidKeyToUIKeyName[7+int(c)-'0'] = name
|
||||
// Gomobile's key code (= USB HID key codes) has successive key codes for 1, 2, ..., 9, 0
|
||||
// in this order.
|
||||
// in this order. Same for iOS.
|
||||
if c == '0' {
|
||||
iosKeyToUIKeyName[0x27] = name
|
||||
gbuildKeyToUIKeyName[key.Code0] = name
|
||||
} else {
|
||||
iosKeyToUIKeyName[0x1E+int(c)-'1'] = name
|
||||
gbuildKeyToUIKeyName[key.Code1+key.Code(c)-'1'] = name
|
||||
}
|
||||
uiKeyNameToJSKey[name] = name
|
||||
|
||||
}
|
||||
// ASCII: A - Z
|
||||
for c := 'A'; c <= 'Z'; c++ {
|
||||
glfwKeyNameToGLFWKey[string(c)] = glfw.KeyA + glfw.Key(c) - 'A'
|
||||
uiKeyNameToGLFWKeyName[string(c)] = string(c)
|
||||
androidKeyToUIKeyName[29+int(c)-'A'] = string(c)
|
||||
iosKeyToUIKeyName[0x04+int(c)-'A'] = string(c)
|
||||
gbuildKeyToUIKeyName[key.CodeA+key.Code(c)-'A'] = string(c)
|
||||
uiKeyNameToJSKey[string(c)] = "Key" + string(c)
|
||||
}
|
||||
@ -328,6 +417,9 @@ func init() {
|
||||
glfwKeyNameToGLFWKey[name] = glfw.KeyF1 + glfw.Key(i) - 1
|
||||
uiKeyNameToGLFWKeyName[name] = name
|
||||
androidKeyToUIKeyName[131+i-1] = name
|
||||
// Note: iOS keys go up to F24 (with F13 being 0x68 and increasing from there),
|
||||
// but Ebitengine currently only goes to F12.
|
||||
iosKeyToUIKeyName[0x3A+i-1] = name
|
||||
gbuildKeyToUIKeyName[key.CodeF1+key.Code(i)-1] = name
|
||||
uiKeyNameToJSKey[name] = name
|
||||
}
|
||||
@ -339,10 +431,12 @@ func init() {
|
||||
uiKeyNameToGLFWKeyName[name] = "KP" + string(c)
|
||||
androidKeyToUIKeyName[144+int(c)-'0'] = name
|
||||
// Gomobile's key code (= USB HID key codes) has successive key codes for 1, 2, ..., 9, 0
|
||||
// in this order.
|
||||
// in this order. Same for iOS.
|
||||
if c == '0' {
|
||||
iosKeyToUIKeyName[0x62] = name
|
||||
gbuildKeyToUIKeyName[key.CodeKeypad0] = name
|
||||
} else {
|
||||
iosKeyToUIKeyName[0x59+int(c)-'1'] = name
|
||||
gbuildKeyToUIKeyName[key.CodeKeypad1+key.Code(c)-'1'] = name
|
||||
}
|
||||
uiKeyNameToJSKey[name] = name
|
||||
@ -583,6 +677,24 @@ var androidKeyToUIKey = map[int]ui.Key{
|
||||
}
|
||||
`
|
||||
|
||||
const mobileIOSKeysTmpl = `{{.License}}
|
||||
|
||||
{{.DoNotEdit}}
|
||||
|
||||
{{.BuildTag}}
|
||||
|
||||
package ebitenmobileview
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||
)
|
||||
|
||||
var iosKeyToUIKey = map[int]ui.Key{
|
||||
{{range $key, $name := .IOSKeyToUIKeyName}}{{$key}}: ui.Key{{$name}},
|
||||
{{end}}
|
||||
}
|
||||
`
|
||||
|
||||
const uiMobileKeysTmpl = `{{.License}}
|
||||
|
||||
{{.DoNotEdit}}
|
||||
@ -725,6 +837,7 @@ func main() {
|
||||
filepath.Join("internal", "ui", "keys_js.go"): uiJSKeysTmpl,
|
||||
filepath.Join("keys.go"): ebitengineKeysTmpl,
|
||||
filepath.Join("mobile", "ebitenmobileview", "keys_android.go"): mobileAndroidKeysTmpl,
|
||||
filepath.Join("mobile", "ebitenmobileview", "keys_ios.go"): mobileIOSKeysTmpl,
|
||||
} {
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
@ -764,6 +877,7 @@ func main() {
|
||||
UIKeyNames []string
|
||||
UIKeyNameToGLFWKeyName map[string]string
|
||||
AndroidKeyToUIKeyName map[int]string
|
||||
IOSKeyToUIKeyName map[int]string
|
||||
GBuildKeyToUIKeyName map[key.Code]string
|
||||
OldEbitengineKeyNameToUIKeyName map[string]string
|
||||
}{
|
||||
@ -778,6 +892,7 @@ func main() {
|
||||
UIKeyNames: uiKeyNames,
|
||||
UIKeyNameToGLFWKeyName: uiKeyNameToGLFWKeyName,
|
||||
AndroidKeyToUIKeyName: androidKeyToUIKeyName,
|
||||
IOSKeyToUIKeyName: iosKeyToUIKeyName,
|
||||
GBuildKeyToUIKeyName: gbuildKeyToUIKeyName,
|
||||
OldEbitengineKeyNameToUIKeyName: oldEbitengineKeyNameToUIKeyName,
|
||||
}); err != nil {
|
||||
|
4
input.go
4
input.go
@ -35,8 +35,6 @@ import (
|
||||
// AppendInputChars is concurrent-safe.
|
||||
//
|
||||
// On Android (ebitenmobile), EbitenView must be focusable to enable to handle keyboard keys.
|
||||
//
|
||||
// Keyboards don't work on iOS yet (#1090).
|
||||
func AppendInputChars(runes []rune) []rune {
|
||||
return theInputState.appendInputChars(runes)
|
||||
}
|
||||
@ -64,8 +62,6 @@ func InputChars() []rune {
|
||||
// IsKeyPressed is concurrent-safe.
|
||||
//
|
||||
// On Android (ebitenmobile), EbitenView must be focusable to enable to handle keyboard keys.
|
||||
//
|
||||
// Keyboards don't work on iOS yet (#1090).
|
||||
func IsKeyPressed(key Key) bool {
|
||||
return theInputState.isKeyPressed(key)
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ package ebitenmobileview
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||
)
|
||||
@ -48,11 +49,40 @@ func UpdateTouchesOnIOS(phase int, ptr int64, x, y int) {
|
||||
case C.UITouchPhaseBegan, C.UITouchPhaseMoved, C.UITouchPhaseStationary:
|
||||
id := getIDFromPtr(ptr)
|
||||
touches[ui.TouchID(id)] = position{x, y}
|
||||
runes = nil
|
||||
updateInput()
|
||||
case C.UITouchPhaseEnded, C.UITouchPhaseCancelled:
|
||||
id := getIDFromPtr(ptr)
|
||||
delete(ptrToID, ptr)
|
||||
delete(touches, ui.TouchID(id))
|
||||
runes = nil
|
||||
updateInput()
|
||||
default:
|
||||
panic(fmt.Sprintf("ebitenmobileview: invalid phase: %d", phase))
|
||||
}
|
||||
}
|
||||
|
||||
func UpdatePressesOnIOS(phase int, keyCode int, keyString string) {
|
||||
switch phase {
|
||||
case C.UITouchPhaseBegan, C.UITouchPhaseMoved, C.UITouchPhaseStationary:
|
||||
if key, ok := iosKeyToUIKey[keyCode]; ok {
|
||||
keys[key] = struct{}{}
|
||||
}
|
||||
runes = nil
|
||||
if phase == C.UITouchPhaseBegan {
|
||||
for _, r := range keyString {
|
||||
if !unicode.IsPrint(r) {
|
||||
continue
|
||||
}
|
||||
runes = append(runes, r)
|
||||
}
|
||||
}
|
||||
updateInput()
|
||||
case C.UITouchPhaseEnded, C.UITouchPhaseCancelled:
|
||||
if key, ok := iosKeyToUIKey[keyCode]; ok {
|
||||
delete(keys, key)
|
||||
}
|
||||
runes = nil
|
||||
updateInput()
|
||||
default:
|
||||
panic(fmt.Sprintf("ebitenmobileview: invalid phase: %d", phase))
|
||||
|
136
mobile/ebitenmobileview/keys_ios.go
Normal file
136
mobile/ebitenmobileview/keys_ios.go
Normal file
@ -0,0 +1,136 @@
|
||||
// Copyright 2013 The Ebitengine Authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Code generated by genkeys.go using 'go generate'. DO NOT EDIT.
|
||||
|
||||
package ebitenmobileview
|
||||
|
||||
import (
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/ui"
|
||||
)
|
||||
|
||||
var iosKeyToUIKey = map[int]ui.Key{
|
||||
4: ui.KeyA,
|
||||
5: ui.KeyB,
|
||||
6: ui.KeyC,
|
||||
7: ui.KeyD,
|
||||
8: ui.KeyE,
|
||||
9: ui.KeyF,
|
||||
10: ui.KeyG,
|
||||
11: ui.KeyH,
|
||||
12: ui.KeyI,
|
||||
13: ui.KeyJ,
|
||||
14: ui.KeyK,
|
||||
15: ui.KeyL,
|
||||
16: ui.KeyM,
|
||||
17: ui.KeyN,
|
||||
18: ui.KeyO,
|
||||
19: ui.KeyP,
|
||||
20: ui.KeyQ,
|
||||
21: ui.KeyR,
|
||||
22: ui.KeyS,
|
||||
23: ui.KeyT,
|
||||
24: ui.KeyU,
|
||||
25: ui.KeyV,
|
||||
26: ui.KeyW,
|
||||
27: ui.KeyX,
|
||||
28: ui.KeyY,
|
||||
29: ui.KeyZ,
|
||||
30: ui.KeyDigit1,
|
||||
31: ui.KeyDigit2,
|
||||
32: ui.KeyDigit3,
|
||||
33: ui.KeyDigit4,
|
||||
34: ui.KeyDigit5,
|
||||
35: ui.KeyDigit6,
|
||||
36: ui.KeyDigit7,
|
||||
37: ui.KeyDigit8,
|
||||
38: ui.KeyDigit9,
|
||||
39: ui.KeyDigit0,
|
||||
40: ui.KeyEnter,
|
||||
41: ui.KeyEscape,
|
||||
42: ui.KeyBackspace,
|
||||
43: ui.KeyTab,
|
||||
44: ui.KeySpace,
|
||||
45: ui.KeyMinus,
|
||||
46: ui.KeyEqual,
|
||||
47: ui.KeyBracketLeft,
|
||||
48: ui.KeyBracketRight,
|
||||
49: ui.KeyBackslash,
|
||||
50: ui.KeyBackslash,
|
||||
51: ui.KeySemicolon,
|
||||
52: ui.KeyQuote,
|
||||
53: ui.KeyBackquote,
|
||||
54: ui.KeyComma,
|
||||
55: ui.KeyPeriod,
|
||||
56: ui.KeySlash,
|
||||
57: ui.KeyCapsLock,
|
||||
58: ui.KeyF1,
|
||||
59: ui.KeyF2,
|
||||
60: ui.KeyF3,
|
||||
61: ui.KeyF4,
|
||||
62: ui.KeyF5,
|
||||
63: ui.KeyF6,
|
||||
64: ui.KeyF7,
|
||||
65: ui.KeyF8,
|
||||
66: ui.KeyF9,
|
||||
67: ui.KeyF10,
|
||||
68: ui.KeyF11,
|
||||
69: ui.KeyF12,
|
||||
70: ui.KeyPrintScreen,
|
||||
71: ui.KeyScrollLock,
|
||||
72: ui.KeyPause,
|
||||
73: ui.KeyInsert,
|
||||
74: ui.KeyHome,
|
||||
75: ui.KeyPageUp,
|
||||
76: ui.KeyDelete,
|
||||
77: ui.KeyEnd,
|
||||
78: ui.KeyPageDown,
|
||||
79: ui.KeyArrowRight,
|
||||
80: ui.KeyArrowLeft,
|
||||
81: ui.KeyArrowDown,
|
||||
82: ui.KeyArrowUp,
|
||||
83: ui.KeyNumLock,
|
||||
84: ui.KeyNumpadDivide,
|
||||
85: ui.KeyNumpadMultiply,
|
||||
86: ui.KeyNumpadSubtract,
|
||||
87: ui.KeyNumpadAdd,
|
||||
88: ui.KeyNumpadEnter,
|
||||
89: ui.KeyNumpad1,
|
||||
90: ui.KeyNumpad2,
|
||||
91: ui.KeyNumpad3,
|
||||
92: ui.KeyNumpad4,
|
||||
93: ui.KeyNumpad5,
|
||||
94: ui.KeyNumpad6,
|
||||
95: ui.KeyNumpad7,
|
||||
96: ui.KeyNumpad8,
|
||||
97: ui.KeyNumpad9,
|
||||
98: ui.KeyNumpad0,
|
||||
99: ui.KeyNumpadDecimal,
|
||||
100: ui.KeyBackslash,
|
||||
103: ui.KeyNumpadEqual,
|
||||
118: ui.KeyContextMenu,
|
||||
130: ui.KeyCapsLock,
|
||||
131: ui.KeyNumLock,
|
||||
132: ui.KeyScrollLock,
|
||||
133: ui.KeyNumpadDecimal,
|
||||
134: ui.KeyNumpadEqual,
|
||||
224: ui.KeyControlLeft,
|
||||
225: ui.KeyShiftLeft,
|
||||
226: ui.KeyAltLeft,
|
||||
227: ui.KeyMetaLeft,
|
||||
228: ui.KeyControlRight,
|
||||
229: ui.KeyShiftRight,
|
||||
230: ui.KeyAltRight,
|
||||
231: ui.KeyMetaRight,
|
||||
}
|
Loading…
Reference in New Issue
Block a user