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  }