Skip to content

Webview captures Gio keyboard events when used with an editor #119

@oligo

Description

@oligo

Affected plugin
webviewer

Describe the bug

Thank you for making this amazing module! I am integrating the webview into my app, the app has a editor and a previewer implemented using webviewer. One serious issue I found is that the webviewer captures some keyboard events and the Gio editor never have a chance to process those keystroke events.

I tried to install a javascript to intercept the key events, but only some of them are propagated to Gio editor, such as arrow keys, pageUp, pageDown.

Expected behavior

  1. The editor should be focused when clicked.
  2. When focused the editor should receive all key events.

Reproducible code

package main

import (
	"image"
	"os"
	"sync"

	"gioui.org/app"
	"gioui.org/f32"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/unit"
	"gioui.org/widget"
	"gioui.org/widget/material"
	"github.com/gioui-plugins/gio-plugins/plugin/gioplugins"
	"github.com/gioui-plugins/gio-plugins/webviewer/giowebview"
)

func main() {
	ops := new(op.Ops)
	w := &app.Window{}
	th := material.NewTheme()

	// Editor state
	var editor widget.Editor
	editor.SetText("Type here after clicking on the editor...\n\nNotice that after clicking on the webview (right side), typing here may not work!")

	webviewTag := new(int)
	initialized := false
	var once sync.Once

	// Split position in dp
	splitDp := 300

	go func() {
		for {
			evt := gioplugins.Hijack(w)

			switch evt := evt.(type) {
			case app.DestroyEvent:
				os.Exit(0)
				return
			case app.FrameEvent:
				gtx := app.NewContext(ops, evt)

				splitPx := float32(gtx.Dp(unit.Dp(splitDp)))

				// Layout: split left (editor), right (webview)
				layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
					layout.Rigid(func(gtx layout.Context) layout.Dimensions {
						gtx.Constraints.Max.X = splitDp
						return material.Editor(th, &editor, "Editor").Layout(gtx)
						//return editor.Layout(gtx, th.Shaper)
					}),
					layout.Rigid(func(gtx layout.Context) layout.Dimensions {
						for {
							_, ok := gioplugins.Event(gtx, giowebview.Filter{Target: webviewTag})
							if !ok {
								break
							}
						}

						webviewWidth := gtx.Constraints.Max.X - splitDp
						webviewHeight := gtx.Constraints.Max.Y

						// Push WebViewOp to create the webview instance (processed at frame end)
						defer giowebview.WebViewOp{Tag: webviewTag}.Push(gtx.Ops).Pop(gtx.Ops)

						// Position webview on the right side
						giowebview.OffsetOp{Point: f32.Pt(splitPx, 0)}.Add(gtx.Ops)
						giowebview.RectOp{Size: f32.Pt(float32(webviewWidth), float32(webviewHeight))}.Add(gtx.Ops)

						if initialized {
							once.Do(func() {
								// Webview exists, we can navigate
								gioplugins.Execute(gtx, giowebview.NavigateCmd{
									View: webviewTag,
									URL:  "https://google.com", // replace the page with other pages with no form, you'll get part of the keystrokes work
								})
							})

						} else {
							initialized = true
							gtx.Execute(op.InvalidateCmd{})
						}

						return layout.Dimensions{Size: image.Point{X: webviewWidth, Y: webviewHeight}}
					}),
				)

				evt.Frame(ops)
			}
		}
	}()

	app.Main()
}

To Reproduce
Run the demo code above, then try to type in the editor, the editor can never be focused.

Desktop :

  • OS: [MacOS]
  • Version [Tahoe 26.2]

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions