From 7ced0d29aba09c4ff95c10bb3746bc71ee1435ac Mon Sep 17 00:00:00 2001 From: Mearaj Date: Tue, 10 May 2022 15:58:48 +0530 Subject: [PATCH] app,widget: use arrow keys for Android navigation Android doesn't distinguish between the arrow keys on a keyboard and the directional keys on a remote control, so there's no way to move the caret in an Editor with arrow keys. This change updates the Android port to map Android's DPAD_* key codes to the arrow key names, fixing caret movement. The change also updates Editor to only request arrow keys that actually move the caret, to keep directional focus movement working. Fixes: https://todo.sr.ht/~eliasnaur/gio/410 Signed-off-by: Mearaj --- app/os_android.go | 8 ++++---- app/window.go | 9 +++++---- widget/editor.go | 17 +++++++++++++++-- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/app/os_android.go b/app/os_android.go index 51bb94c5..58422a07 100644 --- a/app/os_android.go +++ b/app/os_android.go @@ -905,13 +905,13 @@ func convertKeyCode(code C.jint) (string, bool) { case C.AKEYCODE_META_LEFT, C.AKEYCODE_META_RIGHT: n = key.NameSuper case C.AKEYCODE_DPAD_UP: - n = key.NameUp + n = key.NameUpArrow case C.AKEYCODE_DPAD_DOWN: - n = key.NameDown + n = key.NameDownArrow case C.AKEYCODE_DPAD_LEFT: - n = key.NameLeft + n = key.NameLeftArrow case C.AKEYCODE_DPAD_RIGHT: - n = key.NameRight + n = key.NameRightArrow default: return "", false } diff --git a/app/window.go b/app/window.go index 4ef85bbc..86dcf36e 100644 --- a/app/window.go +++ b/app/window.go @@ -855,18 +855,19 @@ func (w *Window) processEvent(d driver, e event.Event) bool { w.updateAnimation(d) } else if e, ok := e.(key.Event); ok && e.State == key.Press { handled = true + isMobile := runtime.GOOS == "ios" || runtime.GOOS == "android" switch { case e.Name == key.NameTab && e.Modifiers == 0: w.moveFocus(router.FocusForward, d) case e.Name == key.NameTab && e.Modifiers == key.ModShift: w.moveFocus(router.FocusBackward, d) - case e.Name == key.NameUp && e.Modifiers == 0: + case e.Name == key.NameUpArrow && e.Modifiers == 0 && isMobile: w.moveFocus(router.FocusUp, d) - case e.Name == key.NameDown && e.Modifiers == 0: + case e.Name == key.NameDownArrow && e.Modifiers == 0 && isMobile: w.moveFocus(router.FocusDown, d) - case e.Name == key.NameLeft && e.Modifiers == 0: + case e.Name == key.NameLeftArrow && e.Modifiers == 0 && isMobile: w.moveFocus(router.FocusLeft, d) - case e.Name == key.NameRight && e.Modifiers == 0: + case e.Name == key.NameRightArrow && e.Modifiers == 0 && isMobile: w.moveFocus(router.FocusRight, d) default: handled = false diff --git a/widget/editor.go b/widget/editor.go index 026f5ee4..c74e6df7 100644 --- a/widget/editor.go +++ b/widget/editor.go @@ -618,8 +618,21 @@ func (e *Editor) layout(gtx layout.Context, content layout.Widget) layout.Dimens defer clip.Rect(image.Rectangle{Max: e.viewSize}).Push(gtx.Ops).Pop() pointer.CursorText.Add(gtx.Ops) - const keyFilter = "(ShortAlt)-(Shift)-[←,→,↑,↓]|(Shift)-[⏎,⌤]|(ShortAlt)-(Shift)-[⌫,⌦]|(Shift)-[⇞,⇟,⇱,⇲]|Short-[C,V,X,A]" - key.InputOp{Tag: &e.eventKey, Hint: e.InputHint, Keys: keyFilter}.Add(gtx.Ops) + const keyFilterNoLeftUp = "(ShortAlt)-(Shift)-[→,↓]|(Shift)-[⏎,⌤]|(ShortAlt)-(Shift)-[⌫,⌦]|(Shift)-[⇞,⇟,⇱,⇲]|Short-[C,V,X,A]" + const keyFilterNoRightDown = "(ShortAlt)-(Shift)-[←,↑]|(Shift)-[⏎,⌤]|(ShortAlt)-(Shift)-[⌫,⌦]|(Shift)-[⇞,⇟,⇱,⇲]|Short-[C,V,X,A]" + const keyFilterNoArrows = "(Shift)-[⏎,⌤]|(ShortAlt)-(Shift)-[⌫,⌦]|(Shift)-[⇞,⇟,⇱,⇲]|Short-[C,V,X,A]" + const keyFilterAllArrows = "(ShortAlt)-(Shift)-[←,→,↑,↓]|(Shift)-[⏎,⌤]|(ShortAlt)-(Shift)-[⌫,⌦]|(Shift)-[⇞,⇟,⇱,⇲]|Short-[C,V,X,A]" + caret := e.closestPosition(combinedPos{runes: e.caret.start}) + switch { + case caret.runes == 0 && caret.runes == e.Len(): + key.InputOp{Tag: &e.eventKey, Hint: e.InputHint, Keys: keyFilterNoArrows}.Add(gtx.Ops) + case caret.runes == 0: + key.InputOp{Tag: &e.eventKey, Hint: e.InputHint, Keys: keyFilterNoLeftUp}.Add(gtx.Ops) + case caret.runes == e.Len(): + key.InputOp{Tag: &e.eventKey, Hint: e.InputHint, Keys: keyFilterNoRightDown}.Add(gtx.Ops) + default: + key.InputOp{Tag: &e.eventKey, Hint: e.InputHint, Keys: keyFilterAllArrows}.Add(gtx.Ops) + } if e.requestFocus { key.FocusOp{Tag: &e.eventKey}.Add(gtx.Ops) key.SoftKeyboardOp{Show: true}.Add(gtx.Ops)