mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
cb1e605203
In the early days of Gio, FrameEvent was part of package app. It was moved to package system to enable layout.NewContext be a convenient short-hand for constructing a layout. However, it seems the better design to leave FrameEvent (and Insets) in package app, and move layout.NewContext there as well. More importantly, the move allows us to replace the event.Queue interface with a concrete type. Signed-off-by: Elias Naur <mail@eliasnaur.com>
140 lines
3.6 KiB
Go
140 lines
3.6 KiB
Go
// SPDX-License-Identifier: Unlicense OR MIT
|
|
|
|
package app
|
|
|
|
import (
|
|
"image"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"gioui.org/io/event"
|
|
"gioui.org/layout"
|
|
"gioui.org/op"
|
|
"gioui.org/unit"
|
|
)
|
|
|
|
// extraArgs contains extra arguments to append to
|
|
// os.Args. The arguments are separated with |.
|
|
// Useful for running programs on mobiles where the
|
|
// command line is not available.
|
|
// Set with the go linker flag -X.
|
|
var extraArgs string
|
|
|
|
// ID is the app id exposed to the platform.
|
|
//
|
|
// On Android ID is the package property of AndroidManifest.xml,
|
|
// on iOS ID is the CFBundleIdentifier of the app Info.plist,
|
|
// on Wayland it is the toplevel app_id,
|
|
// on X11 it is the X11 XClassHint
|
|
//
|
|
// ID is set by the gogio tool or manually with the -X linker flag. For example,
|
|
//
|
|
// go build -ldflags="-X 'gioui.org/app.ID=org.gioui.example.Kitchen'" .
|
|
//
|
|
// Note that ID is treated as a constant, and that changing it at runtime
|
|
// is not supported. Default value of ID is filepath.Base(os.Args[0]).
|
|
var ID = ""
|
|
|
|
// A FrameEvent requests a new frame in the form of a list of
|
|
// operations that describes what to display and how to handle
|
|
// input.
|
|
type FrameEvent struct {
|
|
// Now is the current animation. Use Now instead of time.Now to
|
|
// synchronize animation and to avoid the time.Now call overhead.
|
|
Now time.Time
|
|
// Metric converts device independent dp and sp to device pixels.
|
|
Metric unit.Metric
|
|
// Size is the dimensions of the window.
|
|
Size image.Point
|
|
// Insets represent the space occupied by system decorations and controls.
|
|
Insets Insets
|
|
// Frame completes the FrameEvent by drawing the graphical operations
|
|
// from ops into the window.
|
|
Frame func(frame *op.Ops)
|
|
// Queue supplies the events for event handlers.
|
|
Queue event.Queue
|
|
}
|
|
|
|
// Insets is the space taken up by
|
|
// system decoration such as translucent
|
|
// system bars and software keyboards.
|
|
type Insets struct {
|
|
// Values are in pixels.
|
|
Top, Bottom, Left, Right unit.Dp
|
|
}
|
|
|
|
// NewContext is a shorthand for
|
|
//
|
|
// layout.Context{
|
|
// Ops: ops,
|
|
// Now: e.Now,
|
|
// Queue: e.Queue,
|
|
// Config: e.Config,
|
|
// Constraints: layout.Exact(e.Size),
|
|
// }
|
|
//
|
|
// NewContext calls ops.Reset and adjusts ops for e.Insets.
|
|
func NewContext(ops *op.Ops, e FrameEvent) layout.Context {
|
|
ops.Reset()
|
|
|
|
size := e.Size
|
|
|
|
if e.Insets != (Insets{}) {
|
|
left := e.Metric.Dp(e.Insets.Left)
|
|
top := e.Metric.Dp(e.Insets.Top)
|
|
op.Offset(image.Point{
|
|
X: left,
|
|
Y: top,
|
|
}).Add(ops)
|
|
|
|
size.X -= left + e.Metric.Dp(e.Insets.Right)
|
|
size.Y -= top + e.Metric.Dp(e.Insets.Bottom)
|
|
}
|
|
|
|
return layout.Context{
|
|
Ops: ops,
|
|
Now: e.Now,
|
|
Queue: e.Queue,
|
|
Metric: e.Metric,
|
|
Constraints: layout.Exact(size),
|
|
}
|
|
}
|
|
|
|
// DataDir returns a path to use for application-specific
|
|
// configuration data.
|
|
// On desktop systems, DataDir use os.UserConfigDir.
|
|
// On iOS NSDocumentDirectory is queried.
|
|
// For Android Context.getFilesDir is used.
|
|
//
|
|
// BUG: DataDir blocks on Android until init functions
|
|
// have completed.
|
|
func DataDir() (string, error) {
|
|
return dataDir()
|
|
}
|
|
|
|
// Main must be called last from the program main function.
|
|
// On most platforms Main blocks forever, for Android and
|
|
// iOS it returns immediately to give control of the main
|
|
// thread back to the system.
|
|
//
|
|
// Calling Main is necessary because some operating systems
|
|
// require control of the main thread of the program for
|
|
// running windows.
|
|
func Main() {
|
|
osMain()
|
|
}
|
|
|
|
func (FrameEvent) ImplementsEvent() {}
|
|
|
|
func init() {
|
|
if extraArgs != "" {
|
|
args := strings.Split(extraArgs, "|")
|
|
os.Args = append(os.Args, args...)
|
|
}
|
|
if ID == "" {
|
|
ID = filepath.Base(os.Args[0])
|
|
}
|
|
}
|