fyne-io / fyne

Cross platform GUI toolkit in Go inspired by Material Design
https://fyne.io/
Other
25.2k stars 1.4k forks source link

Android: Tapping Entry with stylus doesn't show virtual keyboard #5255

Open pjanx opened 1 week ago

pjanx commented 1 week ago

Checklist

Describe the bug

On Android devices with a stylus, tapping an Entry with the stylus doesn't show the virtual keyboard.

How to reproduce

Screenshots

No response

Example code

package main

import (
    "net"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/dialog"
    "fyne.io/fyne/v2/driver/mobile"
    "fyne.io/fyne/v2/widget"
)

func main() {
    a := app.New()
    w := a.NewWindow("Bugs")
    w.Resize(fyne.NewSize(640, 480))
    w.SetContent(widget.NewMultiLineEntry())

    connectAddress := widget.NewEntry()
    connectAddress.SetPlaceHolder("host:port")
    connectAddress.Validator = func(text string) error {
        _, _, err := net.SplitHostPort(text)
        return err
    }
    connectAddress.SetText(string([]byte{3, 2, 1, 65, 66, 67, ':', '1'}))
    connectAddress.TypedKey(&fyne.KeyEvent{Name: fyne.KeyPageDown})

    var wConnect *dialog.FormDialog
    wConnect = dialog.NewForm("Connect to relay", "Connect", "Exit",
        []*widget.FormItem{
            {Text: "Address:", Widget: connectAddress},
        }, func(ok bool) {
            if ok {
            } else if _, ok := a.Driver().(mobile.Driver); ok {
                wConnect.Show()
            } else {
                a.Quit()
            }
        }, w)
    wConnect.Show()
    w.ShowAndRun()
}

Fyne version

2.5.2

Go compiler version

1.23.2

Operating system and version

Android

Additional Information

No response

andydotxyz commented 1 week ago

As we don't have access to this device is it possible to debug to find what events are being generated or to pick out appropriate docs for the type of device?

The stylus works as expected on iOS and they should be using the same abstraction.

pjanx commented 23 hours ago

I'm not sure what's going on with the stylus and virtual keyboards. Sometimes it works, then it stops, usually but not always it starts working again after using touch. The Entry likes to get into a perpetual state of selection, which might be a hint (tapping and then just hovering keeps changing the selection).

I haven't succeeded in catching the selection dragging events.

With the example code below, this is after tapping an Entry, and looks the same as touch:

image

package main

import (
    "fmt"

    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/container"
    "fyne.io/fyne/v2/driver/desktop"
    "fyne.io/fyne/v2/driver/mobile"
    "fyne.io/fyne/v2/widget"
)

var logEntry *widget.Entry
var logEnable bool

func log(text string) {
    if logEnable {
        logEntry.Append(text)
    }
}

type observerEntry struct{ widget.Entry }

func newObserverEntry() *observerEntry {
    e := &observerEntry{}
    // Or whatever...
    e.MultiLine = true
    e.Wrapping = fyne.TextWrapWord
    e.ExtendBaseWidget(e)
    return e
}

var _ fyne.Draggable = (*observerEntry)(nil)

func (e *observerEntry) Dragged(ev *fyne.DragEvent) {
    log(fmt.Sprintf("Drag %#v\n", *ev))
    e.Entry.Dragged(ev)
}
func (e *observerEntry) DragEnd() {
    log(fmt.Sprintf("DragEnd\n"))
    e.Entry.DragEnd()
}

var _ fyne.Tappable = (*observerEntry)(nil)

func (e *observerEntry) Tapped(ev *fyne.PointEvent) {
    log(fmt.Sprintf("Tapped %#v\n", *ev))
    e.Entry.Tapped(ev)
}

var _ fyne.DoubleTappable = (*observerEntry)(nil)

func (e *observerEntry) DoubleTapped(ev *fyne.PointEvent) {
    log(fmt.Sprintf("DoubleTapped %#v\n", *ev))
    e.Entry.DoubleTapped(ev)
}

var _ fyne.SecondaryTappable = (*observerEntry)(nil)

func (e *observerEntry) TappedSecondary(ev *fyne.PointEvent) {
    log(fmt.Sprintf("TappedSecondary %#v\n", *ev))
    e.Entry.DoubleTapped(ev)
}

var _ mobile.Keyboardable = (*observerEntry)(nil)

func (e *observerEntry) Keyboard() mobile.KeyboardType {
    log(fmt.Sprintf("Keyboard\n"))
    return e.Entry.Keyboard()
}

var _ mobile.Touchable = (*observerEntry)(nil)

func (e *observerEntry) TouchDown(ev *mobile.TouchEvent) {
    log(fmt.Sprintf("TouchDown %#v\n", *ev))
    e.Entry.TouchDown(ev)
}
func (e *observerEntry) TouchUp(ev *mobile.TouchEvent) {
    log(fmt.Sprintf("TouchUp %#v\n", *ev))
    e.Entry.TouchUp(ev)
}
func (e *observerEntry) TouchCancel(ev *mobile.TouchEvent) {
    log(fmt.Sprintf("TouchCancel %#v\n", *ev))
    e.Entry.TouchCancel(ev)
}

var _ desktop.Mouseable = (*observerEntry)(nil)

func (e *observerEntry) MouseDown(ev *desktop.MouseEvent) {
    log(fmt.Sprintf("MouseDown %#v\n", *ev))
    e.Entry.MouseDown(ev)
}
func (e *observerEntry) MouseUp(ev *desktop.MouseEvent) {
    log(fmt.Sprintf("MouseUp %#v\n", *ev))
    e.Entry.MouseUp(ev)
}

func main() {
    a := app.New()
    w := a.NewWindow("Bugs")
    logEntry = widget.NewMultiLineEntry()
    logEntry.SetMinRowsVisible(25)
    logEntry.Wrapping = fyne.TextWrapWord
    logEntry.OnChanged = func(string) {
        logEntry.TypedKey(&fyne.KeyEvent{Name: fyne.KeyPageDown})
    }
    oe := newObserverEntry()
    oe.SetText("Toy with this here\n")
    w.SetContent(container.NewVBox(
        logEntry,
        widget.NewCheck("Log", func(v bool) { logEnable = v }),
        oe,
    ))
    w.ShowAndRun()
}