uidriver/mobile: Implement keyboard key inputs for gomobile-build

Updates #237
This commit is contained in:
Hajime Hoshi 2020-02-22 02:03:56 +09:00
parent 1dd0c22510
commit a208a026f6
5 changed files with 244 additions and 5 deletions

View File

@ -31,11 +31,13 @@ import (
"text/template"
"github.com/go-gl/glfw/v3.3/glfw"
"golang.org/x/mobile/event/key"
)
var (
nameToGLFWKey map[string]glfw.Key
androidKeyToDriverKeyName map[int]string
gbuildKeyToDriverKeyName map[key.Code]string
driverKeyNameToJSKey map[string]string
edgeKeyCodeToName map[int]string
)
@ -144,6 +146,56 @@ func init() {
161: "KPEqual",
}
gbuildKeyToDriverKeyName = map[key.Code]string{
key.CodeComma: "Comma",
key.CodeFullStop: "Period",
key.CodeLeftAlt: "LeftAlt",
key.CodeRightAlt: "RightAlt",
key.CodeCapsLock: "CapsLock",
key.CodeLeftControl: "LeftControl",
key.CodeRightControl: "RightControl",
key.CodeLeftShift: "LeftShift",
key.CodeRightShift: "RightShift",
key.CodeReturnEnter: "Enter",
key.CodeSpacebar: "Space",
key.CodeTab: "Tab",
key.CodeDeleteForward: "Delete",
key.CodeEnd: "End",
key.CodeHome: "Home",
key.CodeInsert: "Insert",
key.CodePageDown: "PageDown",
key.CodePageUp: "PageUp",
key.CodeDownArrow: "Down",
key.CodeLeftArrow: "Left",
key.CodeRightArrow: "Right",
key.CodeUpArrow: "Up",
key.CodeEscape: "Escape",
key.CodeDeleteBackspace: "Backspace",
key.CodeApostrophe: "Apostrophe",
key.CodeHyphenMinus: "Minus",
key.CodeSlash: "Slash",
key.CodeSemicolon: "Semicolon",
key.CodeEqualSign: "Equal",
key.CodeLeftSquareBracket: "LeftBracket",
key.CodeBackslash: "Backslash",
key.CodeRightSquareBracket: "RightBracket",
key.CodeGraveAccent: "GraveAccent",
key.CodeKeypadNumLock: "NumLock",
key.CodePause: "Pause",
key.CodeKeypadFullStop: "KPDecimal",
key.CodeKeypadSlash: "KPDivide",
key.CodeKeypadAsterisk: "KPMultiply",
key.CodeKeypadHyphenMinus: "KPSubtract",
key.CodeKeypadPlusSign: "KPAdd",
key.CodeKeypadEnter: "KPEnter",
key.CodeKeypadEqualSign: "KPEqual",
// Missing keys:
// driver.KeyPrintScreen
// driver.KeyScrollLock
// driver.KeyMenu
}
driverKeyNameToJSKey = map[string]string{
"Comma": "Comma",
"Period": "Period",
@ -196,12 +248,20 @@ func init() {
for c := '0'; c <= '9'; c++ {
nameToGLFWKey[string(c)] = glfw.Key0 + glfw.Key(c) - '0'
androidKeyToDriverKeyName[7+int(c)-'0'] = string(c)
// Gomobile's key code (= USB HID key codes) has successive key codes for 1, 2, ..., 9, 0
// in this order.
if c == '0' {
gbuildKeyToDriverKeyName[key.Code0] = string(c)
} else {
gbuildKeyToDriverKeyName[key.Code1+key.Code(c)-'1'] = string(c)
}
driverKeyNameToJSKey[string(c)] = "Digit" + string(c)
}
// ASCII: A - Z
for c := 'A'; c <= 'Z'; c++ {
nameToGLFWKey[string(c)] = glfw.KeyA + glfw.Key(c) - 'A'
androidKeyToDriverKeyName[29+int(c)-'A'] = string(c)
gbuildKeyToDriverKeyName[key.CodeA+key.Code(c)-'A'] = string(c)
driverKeyNameToJSKey[string(c)] = "Key" + string(c)
}
// Function keys
@ -209,6 +269,7 @@ func init() {
name := "F" + strconv.Itoa(i)
nameToGLFWKey[name] = glfw.KeyF1 + glfw.Key(i) - 1
androidKeyToDriverKeyName[131+i-1] = name
gbuildKeyToDriverKeyName[key.CodeF1+key.Code(i)-1] = name
driverKeyNameToJSKey[name] = name
}
// Numpad
@ -217,6 +278,13 @@ func init() {
name := "KP" + string(c)
nameToGLFWKey[name] = glfw.KeyKP0 + glfw.Key(c) - '0'
androidKeyToDriverKeyName[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.
if c == '0' {
gbuildKeyToDriverKeyName[key.CodeKeypad0] = name
} else {
gbuildKeyToDriverKeyName[key.CodeKeypad1+key.Code(c)-'1'] = name
}
driverKeyNameToJSKey[name] = "Numpad" + string(c)
}
}
@ -458,6 +526,26 @@ var androidKeyToDriverKeyName = map[int]driver.Key{
}
`
const mobileGBuildKeysTmpl = `{{.License}}
{{.DoNotEdit}}
{{.BuildTag}}
package mobile
import (
"golang.org/x/mobile/event/key"
"github.com/hajimehoshi/ebiten/internal/driver"
)
var gbuildKeyToDriverKey = map[key.Code]driver.Key{
{{range $key, $name := .GBuildKeyToDriverKeyName}}key.{{$key}}: driver.Key{{$name}},
{{end}}
}
`
func digitKey(name string) int {
if len(name) != 1 {
return -1
@ -580,6 +668,7 @@ func main() {
filepath.Join("internal", "driver", "keys.go"): driverKeysTmpl,
filepath.Join("internal", "glfw", "keys.go"): glfwKeysTmpl,
filepath.Join("internal", "uidriver", "glfw", "keys.go"): uidriverGlfwKeysTmpl,
filepath.Join("internal", "uidriver", "mobile", "keys.go"): mobileGBuildKeysTmpl,
filepath.Join("internal", "uidriver", "js", "keys.go"): uidriverJsKeysTmpl,
filepath.Join("keys.go"): ebitenKeysTmpl,
filepath.Join("mobile", "ebitenmobileview", "keys_android.go"): mobileAndroidKeysTmpl,
@ -622,6 +711,7 @@ func main() {
DriverKeyNames []string
NameToGLFWKey map[string]glfw.Key
AndroidKeyToDriverKeyName map[int]string
GBuildKeyToDriverKeyName map[key.Code]string
}{
License: license,
DoNotEdit: doNotEdit,
@ -633,6 +723,7 @@ func main() {
DriverKeyNames: driverKeyNames,
NameToGLFWKey: nameToGLFWKey,
AndroidKeyToDriverKeyName: androidKeyToDriverKeyName,
GBuildKeyToDriverKeyName: gbuildKeyToDriverKeyName,
}); err != nil {
log.Fatal(err)
}

2
go.mod
View File

@ -14,7 +14,7 @@ require (
github.com/jfreymuth/vorbis v1.0.0 // indirect
github.com/kr/pretty v0.1.0 // indirect
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8
golang.org/x/mobile v0.0.0-20200119070023-0c13fd316633
golang.org/x/mobile v0.0.0-20200222142934-3c8601c510d0
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037
golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect

5
go.sum
View File

@ -37,8 +37,8 @@ golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20200119070023-0c13fd316633 h1:TTjgkwwZm6Oiwbjs8Kbc2pyIbLaSxC19uURGsZsLz3s=
golang.org/x/mobile v0.0.0-20200119070023-0c13fd316633/go.mod h1:xVnulspMBrznVIwB4CQrGc712u7ETbNKUJ+GCqGLaEc=
golang.org/x/mobile v0.0.0-20200222142934-3c8601c510d0 h1:nZASbxDuz7CO3227BWCCf0MC6ynyvKh6eMDoLcNXAk0=
golang.org/x/mobile v0.0.0-20200222142934-3c8601c510d0/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@ -57,6 +57,7 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e h1:aZzprAO9/8oim3qStq3wc1Xuxx4QmAGriC4VU4ojemQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9 h1:KOkk4e2xd5OeCDJGwacvr75ICCbCsShrHiqPEdsA9hg=
golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -0,0 +1,126 @@
// Copyright 2013 The Ebiten 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 mobile
import (
"golang.org/x/mobile/event/key"
"github.com/hajimehoshi/ebiten/internal/driver"
)
var gbuildKeyToDriverKey = map[key.Code]driver.Key{
key.CodeA: driver.KeyA,
key.CodeB: driver.KeyB,
key.CodeC: driver.KeyC,
key.CodeD: driver.KeyD,
key.CodeE: driver.KeyE,
key.CodeF: driver.KeyF,
key.CodeG: driver.KeyG,
key.CodeH: driver.KeyH,
key.CodeI: driver.KeyI,
key.CodeJ: driver.KeyJ,
key.CodeK: driver.KeyK,
key.CodeL: driver.KeyL,
key.CodeM: driver.KeyM,
key.CodeN: driver.KeyN,
key.CodeO: driver.KeyO,
key.CodeP: driver.KeyP,
key.CodeQ: driver.KeyQ,
key.CodeR: driver.KeyR,
key.CodeS: driver.KeyS,
key.CodeT: driver.KeyT,
key.CodeU: driver.KeyU,
key.CodeV: driver.KeyV,
key.CodeW: driver.KeyW,
key.CodeX: driver.KeyX,
key.CodeY: driver.KeyY,
key.CodeZ: driver.KeyZ,
key.Code1: driver.Key1,
key.Code2: driver.Key2,
key.Code3: driver.Key3,
key.Code4: driver.Key4,
key.Code5: driver.Key5,
key.Code6: driver.Key6,
key.Code7: driver.Key7,
key.Code8: driver.Key8,
key.Code9: driver.Key9,
key.Code0: driver.Key0,
key.CodeReturnEnter: driver.KeyEnter,
key.CodeEscape: driver.KeyEscape,
key.CodeDeleteBackspace: driver.KeyBackspace,
key.CodeTab: driver.KeyTab,
key.CodeSpacebar: driver.KeySpace,
key.CodeHyphenMinus: driver.KeyMinus,
key.CodeEqualSign: driver.KeyEqual,
key.CodeLeftSquareBracket: driver.KeyLeftBracket,
key.CodeRightSquareBracket: driver.KeyRightBracket,
key.CodeBackslash: driver.KeyBackslash,
key.CodeSemicolon: driver.KeySemicolon,
key.CodeApostrophe: driver.KeyApostrophe,
key.CodeGraveAccent: driver.KeyGraveAccent,
key.CodeComma: driver.KeyComma,
key.CodeFullStop: driver.KeyPeriod,
key.CodeSlash: driver.KeySlash,
key.CodeCapsLock: driver.KeyCapsLock,
key.CodeF1: driver.KeyF1,
key.CodeF2: driver.KeyF2,
key.CodeF3: driver.KeyF3,
key.CodeF4: driver.KeyF4,
key.CodeF5: driver.KeyF5,
key.CodeF6: driver.KeyF6,
key.CodeF7: driver.KeyF7,
key.CodeF8: driver.KeyF8,
key.CodeF9: driver.KeyF9,
key.CodeF10: driver.KeyF10,
key.CodeF11: driver.KeyF11,
key.CodeF12: driver.KeyF12,
key.CodePause: driver.KeyPause,
key.CodeInsert: driver.KeyInsert,
key.CodeHome: driver.KeyHome,
key.CodePageUp: driver.KeyPageUp,
key.CodeDeleteForward: driver.KeyDelete,
key.CodeEnd: driver.KeyEnd,
key.CodePageDown: driver.KeyPageDown,
key.CodeRightArrow: driver.KeyRight,
key.CodeLeftArrow: driver.KeyLeft,
key.CodeDownArrow: driver.KeyDown,
key.CodeUpArrow: driver.KeyUp,
key.CodeKeypadNumLock: driver.KeyNumLock,
key.CodeKeypadSlash: driver.KeyKPDivide,
key.CodeKeypadAsterisk: driver.KeyKPMultiply,
key.CodeKeypadHyphenMinus: driver.KeyKPSubtract,
key.CodeKeypadPlusSign: driver.KeyKPAdd,
key.CodeKeypadEnter: driver.KeyKPEnter,
key.CodeKeypad1: driver.KeyKP1,
key.CodeKeypad2: driver.KeyKP2,
key.CodeKeypad3: driver.KeyKP3,
key.CodeKeypad4: driver.KeyKP4,
key.CodeKeypad5: driver.KeyKP5,
key.CodeKeypad6: driver.KeyKP6,
key.CodeKeypad7: driver.KeyKP7,
key.CodeKeypad8: driver.KeyKP8,
key.CodeKeypad9: driver.KeyKP9,
key.CodeKeypad0: driver.KeyKP0,
key.CodeKeypadFullStop: driver.KeyKPDecimal,
key.CodeKeypadEqualSign: driver.KeyKPEqual,
key.CodeLeftControl: driver.KeyLeftControl,
key.CodeLeftShift: driver.KeyLeftShift,
key.CodeLeftAlt: driver.KeyLeftAlt,
key.CodeRightControl: driver.KeyRightControl,
key.CodeRightShift: driver.KeyRightShift,
key.CodeRightAlt: driver.KeyRightAlt,
}

View File

@ -23,6 +23,7 @@ import (
"sync"
"golang.org/x/mobile/app"
"golang.org/x/mobile/event/key"
"golang.org/x/mobile/event/lifecycle"
"golang.org/x/mobile/event/paint"
"golang.org/x/mobile/event/size"
@ -144,8 +145,13 @@ func deviceScale() float64 {
func (u *UserInterface) appMain(a app.App) {
var glctx gl.Context
var sizeInited bool
touches := map[touch.Sequence]*Touch{}
keys := map[driver.Key]struct{}{}
for e := range a.Events() {
var updateInput bool
switch e := a.Filter(e).(type) {
case lifecycle.Event:
switch e.Crosses(lifecycle.StageVisible) {
@ -195,12 +201,27 @@ func (u *UserInterface) appMain(a app.App) {
case touch.TypeEnd:
delete(touches, e.Sequence)
}
updateInput = true
case key.Event:
k, ok := gbuildKeyToDriverKey[e.Code]
if !ok {
continue
}
switch e.Direction {
case key.DirPress, key.DirNone:
keys[k] = struct{}{}
case key.DirRelease:
delete(keys, k)
}
updateInput = true
}
if updateInput {
ts := []*Touch{}
for _, t := range touches {
ts = append(ts, t)
}
// TODO: Give keyboard keys.
u.input.update(nil, ts)
u.input.update(keys, ts)
}
}
}