~eliasnaur/gio-example

3f0fb596da18f96efb92dcb2eea822bdce47a295 — Chris Waldon 5 months ago b74c795
deps,7gui/*,life,gophers: update gio and global keyboard shortcut example

This commit updates to the latest gio and adapts all of the global keyboard
shortcut handling examples to the recent changes in Gio's keyboard event
processing.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
7 files changed, 127 insertions(+), 75 deletions(-)

M 7gui/counter/main.go
M 7gui/temperature/main.go
M 7gui/timer/main.go
M go.mod
M go.sum
M gophers/main.go
M life/main.go
M 7gui/counter/main.go => 7gui/counter/main.go +25 -14
@@ 5,12 5,13 @@ import (
	"os"
	"strconv"

	"gioui.org/app"             // app contains Window handling.
	"gioui.org/font/gofont"     // gofont is used for loading the default font.
	"gioui.org/io/key"          // key is used for keyboard events.
	"gioui.org/io/system"       // system is used for system events (e.g. closing the window).
	"gioui.org/layout"          // layout is used for layouting widgets.
	"gioui.org/op"              // op is used for recording different operations.
	"gioui.org/app"         // app contains Window handling.
	"gioui.org/font/gofont" // gofont is used for loading the default font.
	"gioui.org/io/key"      // key is used for keyboard events.
	"gioui.org/io/system"   // system is used for system events (e.g. closing the window).
	"gioui.org/layout"      // layout is used for layouting widgets.
	"gioui.org/op"          // op is used for recording different operations.
	"gioui.org/op/clip"
	"gioui.org/unit"            // unit is used to define pixel-independent sizes
	"gioui.org/widget"          // widget contains state handling for widgets.
	"gioui.org/widget/material" // material contains material design widgets.


@@ 70,19 71,29 @@ func (ui *UI) Run(w *app.Window) error {
		case system.FrameEvent:
			// gtx is used to pass around rendering and event information.
			gtx := layout.NewContext(&ops, e)

			// register a global key listener for the escape key wrapping our entire UI.
			area := clip.Rect{Max: gtx.Constraints.Max}.Push(gtx.Ops)
			key.InputOp{
				Tag:  w,
				Keys: key.NameEscape,
			}.Add(gtx.Ops)

			// check for presses of the escape key and close the window if we find them.
			for _, event := range gtx.Events(w) {
				switch event := event.(type) {
				case key.Event:
					if event.Name == key.NameEscape {
						return nil
					}
				}
			}
			// render and handle UI.
			ui.Layout(gtx)
			area.Pop()
			// render and handle the operations from the UI.
			e.Frame(gtx.Ops)

		// handle a global key press.
		case key.Event:
			switch e.Name {
			// when we click escape, let's close the window.
			case key.NameEscape:
				return nil
			}

		// this is sent when the application is closed.
		case system.DestroyEvent:
			return e.Err

M 7gui/temperature/main.go => 7gui/temperature/main.go +24 -14
@@ 6,12 6,13 @@ import (
	"os"
	"strconv"

	"gioui.org/app"             // app contains Window handling.
	"gioui.org/font/gofont"     // gofont is used for loading the default font.
	"gioui.org/io/key"          // key is used for keyboard events.
	"gioui.org/io/system"       // system is used for system events (e.g. closing the window).
	"gioui.org/layout"          // layout is used for layouting widgets.
	"gioui.org/op"              // op is used for recording different operations.
	"gioui.org/app"         // app contains Window handling.
	"gioui.org/font/gofont" // gofont is used for loading the default font.
	"gioui.org/io/key"      // key is used for keyboard events.
	"gioui.org/io/system"   // system is used for system events (e.g. closing the window).
	"gioui.org/layout"      // layout is used for layouting widgets.
	"gioui.org/op"          // op is used for recording different operations.
	"gioui.org/op/clip"
	"gioui.org/unit"            // unit is used to define pixel-independent sizes
	"gioui.org/widget"          // widget contains state handling for widgets.
	"gioui.org/widget/material" // material contains material design widgets.


@@ 73,19 74,28 @@ func (ui *UI) Run(w *app.Window) error {
		case system.FrameEvent:
			// gtx is used to pass around rendering and event information.
			gtx := layout.NewContext(&ops, e)
			// register a global key listener for the escape key wrapping our entire UI.
			area := clip.Rect{Max: gtx.Constraints.Max}.Push(gtx.Ops)
			key.InputOp{
				Tag:  w,
				Keys: key.NameEscape,
			}.Add(gtx.Ops)

			// check for presses of the escape key and close the window if we find them.
			for _, event := range gtx.Events(w) {
				switch event := event.(type) {
				case key.Event:
					if event.Name == key.NameEscape {
						return nil
					}
				}
			}
			// render and handle UI.
			ui.Layout(gtx)
			area.Pop()
			// render and handle the operations from the UI.
			e.Frame(gtx.Ops)

		// handle a global key press.
		case key.Event:
			switch e.Name {
			// when we click escape, let's close the window.
			case key.NameEscape:
				return nil
			}

		// this is sent when the application is closed.
		case system.DestroyEvent:
			return e.Err

M 7gui/timer/main.go => 7gui/timer/main.go +24 -14
@@ 5,12 5,13 @@ import (
	"os"
	"time"

	"gioui.org/app"             // app contains Window handling.
	"gioui.org/font/gofont"     // gofont is used for loading the default font.
	"gioui.org/io/key"          // key is used for keyboard events.
	"gioui.org/io/system"       // system is used for system events (e.g. closing the window).
	"gioui.org/layout"          // layout is used for layouting widgets.
	"gioui.org/op"              // op is used for recording different operations.
	"gioui.org/app"         // app contains Window handling.
	"gioui.org/font/gofont" // gofont is used for loading the default font.
	"gioui.org/io/key"      // key is used for keyboard events.
	"gioui.org/io/system"   // system is used for system events (e.g. closing the window).
	"gioui.org/layout"      // layout is used for layouting widgets.
	"gioui.org/op"          // op is used for recording different operations.
	"gioui.org/op/clip"
	"gioui.org/unit"            // unit is used to define pixel-independent sizes
	"gioui.org/widget"          // widget contains state handling for widgets.
	"gioui.org/widget/material" // material contains material design widgets.


@@ 87,19 88,28 @@ func (ui *UI) Run(w *app.Window) error {
			case system.FrameEvent:
				// gtx is used to pass around rendering and event information.
				gtx := layout.NewContext(&ops, e)
				// register a global key listener for the escape key wrapping our entire UI.
				area := clip.Rect{Max: gtx.Constraints.Max}.Push(gtx.Ops)
				key.InputOp{
					Tag:  w,
					Keys: key.NameEscape,
				}.Add(gtx.Ops)

				// check for presses of the escape key and close the window if we find them.
				for _, event := range gtx.Events(w) {
					switch event := event.(type) {
					case key.Event:
						if event.Name == key.NameEscape {
							return nil
						}
					}
				}
				// render and handle UI.
				ui.Layout(gtx)
				area.Pop()
				// render and handle the operations from the UI.
				e.Frame(gtx.Ops)

			// handle a global key press.
			case key.Event:
				switch e.Name {
				// when we click escape, let's close the window.
				case key.NameEscape:
					return nil
				}

			// this is sent when the application is closed.
			case system.DestroyEvent:
				return e.Err

M go.mod => go.mod +1 -2
@@ 3,7 3,7 @@ module gioui.org/example
go 1.16

require (
	gioui.org v0.0.0-20220331105829-a1b5ff059c07
	gioui.org v0.0.0-20220425071242-aa14056350d6
	gioui.org/cmd v0.0.0-20211103131231-1d0769ae89a5
	gioui.org/x v0.0.0-20220318131752-bc7801f4bd03
	github.com/go-gl/gl v0.0.0-20210315015930-ae072cafe09d


@@ 13,6 13,5 @@ require (
	golang.org/x/exp v0.0.0-20210722180016-6781d3edade3
	golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
	golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013
	golang.org/x/text v0.3.7 // indirect
	gonum.org/v1/gonum v0.8.2
)

M go.sum => go.sum +4 -3
@@ 38,8 38,8 @@ eliasnaur.com/font v0.0.0-20220124212145-832bb8fc08c3/go.mod h1:OYVuxibdk9OSLX8v
gioui.org v0.0.0-20210910062418-d5d0a75a9bcb/go.mod h1:BTldRXnY5mrUrYZCdWyDwyMzyUzpfZN1cF4MMRrOt9w=
gioui.org v0.0.0-20211103131231-1d0769ae89a5/go.mod h1:yoWOxPng6WkDpsud+NRmkoftmyWn3rkKsYGEcWHpjTI=
gioui.org v0.0.0-20220318070519-8833a6738a3b/go.mod h1:STpXvjqWkldjsUG7qy4sQTHz+QegDh6jTdmkaQuriq0=
gioui.org v0.0.0-20220331105829-a1b5ff059c07 h1:9BdOhoKqRiItOl87wZfQUL2YZNm+6Yyp1f1iEiJUh+U=
gioui.org v0.0.0-20220331105829-a1b5ff059c07/go.mod h1:b8vBukexG6eYuXZa14asjLAWJ+JjbZ/ophEnS2FjYUg=
gioui.org v0.0.0-20220425071242-aa14056350d6 h1:IOBG1/6CNzMhaPLLsPFgAVIC2ttGpbr15k3K3YnyreE=
gioui.org v0.0.0-20220425071242-aa14056350d6/go.mod h1:A0rb8LTFy1Hhi6/2zppz6CRiGJLAk0akcD1p+77l+fg=
gioui.org/cmd v0.0.0-20211103131231-1d0769ae89a5 h1:745EIA9yw5pYHXNPS6hv+gX7UKhoQUIR0X4rrhYXaqo=
gioui.org/cmd v0.0.0-20211103131231-1d0769ae89a5/go.mod h1:qrH3h4nt/PyIqx/XabL/eJ5cXQnQ0ERHqC3VEXx/Rmg=
gioui.org/cpu v0.0.0-20210808092351-bfe733dd3334/go.mod h1:A8M0Cn5o+vY5LTMlnRoK3O5kG+rH0kWfJjeKd9QpBmQ=


@@ 171,8 171,9 @@ github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-text/typesetting v0.0.0-20220112121102-58fe93c84506 h1:1TPz/Gn/MsXwJ6bEtI9wdkPcQYr2X3V9I+wz4wPYUdY=
github.com/go-text/typesetting v0.0.0-20220112121102-58fe93c84506/go.mod h1:R0mlTNeyszZ/tKQhbZA7SRGjx+OHsmNzgN2jTV7yZcs=
github.com/go-text/typesetting v0.0.0-20220411150340-35994bc27a7b h1:WINlj3ANt+CVrO2B4NGDHRlPvEWZPxjhb7z+JKypwXI=
github.com/go-text/typesetting v0.0.0-20220411150340-35994bc27a7b/go.mod h1:ZNYu5saGoMOqtkVH5T8onTwhzenDUVszI+5WFHJRaxQ=
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 h1:qZNfIGkIANxGv/OqtnntR4DfOY2+BgwR60cAcu/i3SE=
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4/go.mod h1:kW3HQ4UdaAyrUCSSDR4xUzBKW6O2iA4uHhk7AtyYp10=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=

M gophers/main.go => gophers/main.go +30 -19
@@ 21,6 21,7 @@ import (
	"gioui.org/io/system"
	"gioui.org/layout"
	"gioui.org/op"
	"gioui.org/op/clip"
	"gioui.org/unit"

	"github.com/google/go-github/v24/github"


@@ 91,16 92,6 @@ func (a *App) run() error {
			a.w.Invalidate()
		case e := <-a.w.Events():
			switch e := e.(type) {
			case key.Event:
				switch e.Name {
				case key.NameEscape:
					os.Exit(0)
				case "P":
					if e.Modifiers.Contain(key.ModShortcut) {
						a.ui.profiling = !a.ui.profiling
						a.w.Invalidate()
					}
				}
			case system.DestroyEvent:
				return e.Err
			case system.StageEvent:


@@ 117,18 108,38 @@ func (a *App) run() error {
						a.ctxCancel = nil
					}
				}
			case *system.CommandEvent:
				switch e.Type {
				case system.CommandBack:
					if a.ui.selectedUser != nil {
						a.ui.selectedUser = nil
						e.Cancel = true
						a.w.Invalidate()
					}
				}
			case system.FrameEvent:
				gtx := layout.NewContext(&ops, e)

				// register a global key listener for the escape key wrapping our entire UI.
				area := clip.Rect{Max: gtx.Constraints.Max}.Push(gtx.Ops)
				key.InputOp{
					Tag:  a.w,
					Keys: key.NameEscape + `|Short-P|` + key.NameBack,
				}.Add(gtx.Ops)

				// check for presses of global keyboard shortcuts and process them.
				for _, event := range gtx.Events(a.w) {
					switch event := event.(type) {
					case key.Event:
						switch event.Name {
						case key.NameEscape:
							return nil
						case key.NameBack:
							if a.ui.selectedUser != nil {
								a.ui.selectedUser = nil
								a.w.Invalidate()
							}
						case "P":
							if event.Modifiers.Contain(key.ModShortcut) && event.State == key.Press {
								a.ui.profiling = !a.ui.profiling
								a.w.Invalidate()
							}
						}
					}
				}
				a.ui.Layout(gtx)
				area.Pop()
				e.Frame(gtx.Ops)
			}
		}

M life/main.go => life/main.go +19 -9
@@ 13,7 13,8 @@ import (
	"gioui.org/io/system" // system is used for system events (e.g. closing the window).
	"gioui.org/layout"    // layout is used for layouting widgets.
	"gioui.org/op"        // op is used for recording different operations.
	"gioui.org/unit"      // unit is used to define pixel-independent sizes
	"gioui.org/op/clip"
	"gioui.org/unit" // unit is used to define pixel-independent sizes
)

var (


@@ 82,19 83,28 @@ func (ui *UI) Run(w *app.Window) error {
			case system.FrameEvent:
				// gtx is used to pass around rendering and event information.
				gtx := layout.NewContext(&ops, e)
				// register a global key listener for the escape key wrapping our entire UI.
				area := clip.Rect{Max: gtx.Constraints.Max}.Push(gtx.Ops)
				key.InputOp{
					Tag:  w,
					Keys: key.NameEscape,
				}.Add(gtx.Ops)

				// check for presses of the escape key and close the window if we find them.
				for _, event := range gtx.Events(w) {
					switch event := event.(type) {
					case key.Event:
						if event.Name == key.NameEscape {
							return nil
						}
					}
				}
				// render and handle UI.
				ui.Layout(gtx)
				area.Pop()
				// render and handle the operations from the UI.
				e.Frame(gtx.Ops)

			// handle a global key press.
			case key.Event:
				switch e.Name {
				// when we click escape, let's close the window.
				case key.NameEscape:
					return nil
				}

			// this is sent when the application is closed.
			case system.DestroyEvent:
				return e.Err