app.go 3.9 KB

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