gioui.org@v0.6.1-0.20240506124620-7a9ce51988ce/app/app.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package app 4 5 import ( 6 "image" 7 "os" 8 "path/filepath" 9 "strings" 10 "time" 11 12 "gioui.org/io/input" 13 "gioui.org/layout" 14 "gioui.org/op" 15 "gioui.org/unit" 16 ) 17 18 // extraArgs contains extra arguments to append to 19 // os.Args. The arguments are separated with |. 20 // Useful for running programs on mobiles where the 21 // command line is not available. 22 // Set with the go linker flag -X. 23 var extraArgs string 24 25 // ID is the app id exposed to the platform. 26 // 27 // On Android ID is the package property of AndroidManifest.xml, 28 // on iOS ID is the CFBundleIdentifier of the app Info.plist, 29 // on Wayland it is the toplevel app_id, 30 // on X11 it is the X11 XClassHint. 31 // 32 // ID is set by the [gioui.org/cmd/gogio] tool or manually with the -X linker flag. For example, 33 // 34 // go build -ldflags="-X 'gioui.org/app.ID=org.gioui.example.Kitchen'" . 35 // 36 // Note that ID is treated as a constant, and that changing it at runtime 37 // is not supported. The default value of ID is filepath.Base(os.Args[0]). 38 var ID = "" 39 40 // A FrameEvent requests a new frame in the form of a list of 41 // operations that describes the window content. 42 type FrameEvent struct { 43 // Now is the current animation. Use Now instead of time.Now to 44 // synchronize animation and to avoid the time.Now call overhead. 45 Now time.Time 46 // Metric converts device independent dp and sp to device pixels. 47 Metric unit.Metric 48 // Size is the dimensions of the window. 49 Size image.Point 50 // Insets represent the space occupied by system decorations and controls. 51 Insets Insets 52 // Frame completes the FrameEvent by drawing the graphical operations 53 // from ops into the window. 54 Frame func(frame *op.Ops) 55 // Source is the interface between the window and widgets. 56 Source input.Source 57 } 58 59 // ViewEvent provides handles to the underlying window objects for the 60 // current display protocol. 61 type ViewEvent interface { 62 implementsViewEvent() 63 ImplementsEvent() 64 } 65 66 // Insets is the space taken up by 67 // system decoration such as translucent 68 // system bars and software keyboards. 69 type Insets struct { 70 // Values are in pixels. 71 Top, Bottom, Left, Right unit.Dp 72 } 73 74 // NewContext is shorthand for 75 // 76 // layout.Context{ 77 // Ops: ops, 78 // Now: e.Now, 79 // Source: e.Source, 80 // Metric: e.Metric, 81 // Constraints: layout.Exact(e.Size), 82 // } 83 // 84 // NewContext calls ops.Reset and adjusts ops for e.Insets. 85 func NewContext(ops *op.Ops, e FrameEvent) layout.Context { 86 ops.Reset() 87 88 size := e.Size 89 90 if e.Insets != (Insets{}) { 91 left := e.Metric.Dp(e.Insets.Left) 92 top := e.Metric.Dp(e.Insets.Top) 93 op.Offset(image.Point{ 94 X: left, 95 Y: top, 96 }).Add(ops) 97 98 size.X -= left + e.Metric.Dp(e.Insets.Right) 99 size.Y -= top + e.Metric.Dp(e.Insets.Bottom) 100 } 101 102 return layout.Context{ 103 Ops: ops, 104 Now: e.Now, 105 Source: e.Source, 106 Metric: e.Metric, 107 Constraints: layout.Exact(size), 108 } 109 } 110 111 // DataDir returns a path to use for application-specific 112 // configuration data. 113 // On desktop systems, DataDir use os.UserConfigDir. 114 // On iOS NSDocumentDirectory is queried. 115 // For Android Context.getFilesDir is used. 116 // 117 // BUG: DataDir blocks on Android until init functions 118 // have completed. 119 func DataDir() (string, error) { 120 return dataDir() 121 } 122 123 // Main must be called last from the program main function. 124 // On most platforms Main blocks forever, for Android and 125 // iOS it returns immediately to give control of the main 126 // thread back to the system. 127 // 128 // Calling Main is necessary because some operating systems 129 // require control of the main thread of the program for 130 // running windows. 131 func Main() { 132 osMain() 133 } 134 135 func (FrameEvent) ImplementsEvent() {} 136 137 func init() { 138 if extraArgs != "" { 139 args := strings.Split(extraArgs, "|") 140 os.Args = append(os.Args, args...) 141 } 142 if ID == "" { 143 ID = filepath.Base(os.Args[0]) 144 } 145 }