From a208a026f6f9756b802249ff6ebd9842e9f3c241 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sat, 22 Feb 2020 02:03:56 +0900 Subject: [PATCH] uidriver/mobile: Implement keyboard key inputs for gomobile-build Updates #237 --- genkeys.go | 91 ++++++++++++++++++++++ go.mod | 2 +- go.sum | 5 +- internal/uidriver/mobile/keys.go | 126 +++++++++++++++++++++++++++++++ internal/uidriver/mobile/ui.go | 25 +++++- 5 files changed, 244 insertions(+), 5 deletions(-) create mode 100644 internal/uidriver/mobile/keys.go diff --git a/genkeys.go b/genkeys.go index d1223defa..2381c6c7e 100644 --- a/genkeys.go +++ b/genkeys.go @@ -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) } diff --git a/go.mod b/go.mod index 6727345a9..59ec62c3f 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index fee014878..eb754fcde 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/internal/uidriver/mobile/keys.go b/internal/uidriver/mobile/keys.go new file mode 100644 index 000000000..581f7b194 --- /dev/null +++ b/internal/uidriver/mobile/keys.go @@ -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, +} diff --git a/internal/uidriver/mobile/ui.go b/internal/uidriver/mobile/ui.go index 740e758c8..cfc996a90 100644 --- a/internal/uidriver/mobile/ui.go +++ b/internal/uidriver/mobile/ui.go @@ -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) } } }