diff --git a/app/internal/wm/Gio.java b/app/Gio.java similarity index 100% rename from app/internal/wm/Gio.java rename to app/Gio.java diff --git a/app/internal/wm/GioActivity.java b/app/GioActivity.java similarity index 100% rename from app/internal/wm/GioActivity.java rename to app/GioActivity.java diff --git a/app/internal/wm/GioView.java b/app/GioView.java similarity index 100% rename from app/internal/wm/GioView.java rename to app/GioView.java diff --git a/app/app.go b/app/app.go index 240b9452..e00298a3 100644 --- a/app/app.go +++ b/app/app.go @@ -5,16 +5,8 @@ package app import ( "os" "strings" - - "gioui.org/app/internal/wm" ) -// ViewEvent carries the platform specific window handles for -// a Window. -// -// ViewEvent is implemented for Android, macOS, Windows. -type ViewEvent = wm.ViewEvent - // extraArgs contains extra arguments to append to // os.Args. The arguments are separated with |. // Useful for running programs on mobiles where the @@ -50,5 +42,5 @@ func DataDir() (string, error) { // require control of the main thread of the program for // running windows. func Main() { - wm.Main() + osMain() } diff --git a/app/app_android.go b/app/app_android.go deleted file mode 100644 index 30a6c675..00000000 --- a/app/app_android.go +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: Unlicense OR MIT - -package app - -import ( - "gioui.org/app/internal/wm" -) - -// JavaVM returns the global JNI JavaVM. -func JavaVM() uintptr { - return wm.JavaVM() -} - -// AppContext returns the global Application context as a JNI -// jobject. -func AppContext() uintptr { - return wm.AppContext() -} diff --git a/app/internal/wm/d3d11_windows.go b/app/d3d11_windows.go similarity index 97% rename from app/internal/wm/d3d11_windows.go rename to app/d3d11_windows.go index 2b89c1f2..8324ed67 100644 --- a/app/internal/wm/d3d11_windows.go +++ b/app/d3d11_windows.go @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Unlicense OR MIT -package wm +package app import ( "fmt" @@ -25,7 +25,7 @@ const debug = false func init() { drivers = append(drivers, gpuAPI{ priority: 1, - initializer: func(w *window) (Context, error) { + initializer: func(w *window) (context, error) { hwnd, _, _ := w.HWND() var flags uint32 if debug { @@ -70,7 +70,7 @@ func (c *d3d11Context) Present() error { // Ignore return nil case d3d11.DXGI_ERROR_DEVICE_RESET, d3d11.DXGI_ERROR_DEVICE_REMOVED, d3d11.D3DDDIERR_DEVICEREMOVED: - return ErrDeviceLost + return errDeviceLost } } return err diff --git a/app/datadir_android.go b/app/datadir_android.go deleted file mode 100644 index c4739e02..00000000 --- a/app/datadir_android.go +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: Unlicense OR MIT - -//go:build android -// +build android - -package app - -import "C" - -import ( - "os" - "path/filepath" - "sync" - - "gioui.org/app/internal/wm" -) - -var ( - dataDirOnce sync.Once - dataPath string -) - -func dataDir() (string, error) { - dataDirOnce.Do(func() { - dataPath = wm.GetDataDir() - // Set XDG_CACHE_HOME to make os.UserCacheDir work. - if _, exists := os.LookupEnv("XDG_CACHE_HOME"); !exists { - cachePath := filepath.Join(dataPath, "cache") - os.Setenv("XDG_CACHE_HOME", cachePath) - } - // Set XDG_CONFIG_HOME to make os.UserConfigDir work. - if _, exists := os.LookupEnv("XDG_CONFIG_HOME"); !exists { - cfgPath := filepath.Join(dataPath, "config") - os.Setenv("XDG_CONFIG_HOME", cfgPath) - } - // Set HOME to make os.UserHomeDir work. - if _, exists := os.LookupEnv("HOME"); !exists { - os.Setenv("HOME", dataPath) - } - }) - return dataPath, nil -} diff --git a/app/internal/wm/egl_android.go b/app/egl_android.go similarity index 70% rename from app/internal/wm/egl_android.go rename to app/egl_android.go index 759620a7..f1f2abc2 100644 --- a/app/internal/wm/egl_android.go +++ b/app/egl_android.go @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Unlicense OR MIT -package wm +package app /* #include @@ -14,27 +14,27 @@ import ( "gioui.org/internal/egl" ) -type context struct { +type androidContext struct { win *window *egl.Context } -func (w *window) NewContext() (Context, error) { +func (w *window) NewContext() (context, error) { ctx, err := egl.NewContext(nil) if err != nil { return nil, err } - return &context{win: w, Context: ctx}, nil + return &androidContext{win: w, Context: ctx}, nil } -func (c *context) Release() { +func (c *androidContext) Release() { if c.Context != nil { c.Context.Release() c.Context = nil } } -func (c *context) Refresh() error { +func (c *androidContext) Refresh() error { c.Context.ReleaseSurface() var ( win *C.ANativeWindow @@ -48,10 +48,10 @@ func (c *context) Refresh() error { return c.Context.CreateSurface(eglSurf, width, height) } -func (c *context) Lock() error { +func (c *androidContext) Lock() error { return c.Context.MakeCurrent() } -func (c *context) Unlock() { +func (c *androidContext) Unlock() { c.Context.ReleaseCurrent() } diff --git a/app/internal/wm/egl_wayland.go b/app/egl_wayland.go similarity index 83% rename from app/internal/wm/egl_wayland.go rename to app/egl_wayland.go index abd92770..05a5fe79 100644 --- a/app/internal/wm/egl_wayland.go +++ b/app/egl_wayland.go @@ -3,7 +3,7 @@ //go:build (linux && !android && !nowayland) || freebsd // +build linux,!android,!nowayland freebsd -package wm +package app import ( "errors" @@ -23,22 +23,22 @@ import ( */ import "C" -type context struct { +type wlContext struct { win *window *egl.Context eglWin *C.struct_wl_egl_window } -func (w *window) NewContext() (Context, error) { +func (w *window) NewContext() (context, error) { disp := egl.NativeDisplayType(unsafe.Pointer(w.display())) ctx, err := egl.NewContext(disp) if err != nil { return nil, err } - return &context{Context: ctx, win: w}, nil + return &wlContext{Context: ctx, win: w}, nil } -func (c *context) Release() { +func (c *wlContext) Release() { if c.Context != nil { c.Context.Release() c.Context = nil @@ -49,7 +49,7 @@ func (c *context) Release() { } } -func (c *context) Refresh() error { +func (c *wlContext) Refresh() error { c.Context.ReleaseSurface() if c.eglWin != nil { C.wl_egl_window_destroy(c.eglWin) @@ -68,10 +68,10 @@ func (c *context) Refresh() error { return c.Context.CreateSurface(eglSurf, width, height) } -func (c *context) Lock() error { +func (c *wlContext) Lock() error { return c.Context.MakeCurrent() } -func (c *context) Unlock() { +func (c *wlContext) Unlock() { c.Context.ReleaseCurrent() } diff --git a/app/internal/wm/egl_windows.go b/app/egl_windows.go similarity index 94% rename from app/internal/wm/egl_windows.go rename to app/egl_windows.go index b2b66ecc..3a95450e 100644 --- a/app/internal/wm/egl_windows.go +++ b/app/egl_windows.go @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Unlicense OR MIT -package wm +package app import ( "golang.org/x/sys/windows" @@ -16,7 +16,7 @@ type glContext struct { func init() { drivers = append(drivers, gpuAPI{ priority: 2, - initializer: func(w *window) (Context, error) { + initializer: func(w *window) (context, error) { disp := egl.NativeDisplayType(w.HDC()) ctx, err := egl.NewContext(disp) if err != nil { diff --git a/app/internal/wm/egl_x11.go b/app/egl_x11.go similarity index 94% rename from app/internal/wm/egl_x11.go rename to app/egl_x11.go index b16ebd7a..763bd965 100644 --- a/app/internal/wm/egl_x11.go +++ b/app/egl_x11.go @@ -3,7 +3,7 @@ //go:build (linux && !android && !nox11) || freebsd || openbsd // +build linux,!android,!nox11 freebsd openbsd -package wm +package app import ( "unsafe" @@ -16,7 +16,7 @@ type x11Context struct { *egl.Context } -func (w *x11Window) NewContext() (Context, error) { +func (w *x11Window) NewContext() (context, error) { disp := egl.NativeDisplayType(unsafe.Pointer(w.display())) ctx, err := egl.NewContext(disp) if err != nil { diff --git a/app/internal/wm/framework_ios.h b/app/framework_ios.h similarity index 100% rename from app/internal/wm/framework_ios.h rename to app/framework_ios.h diff --git a/app/internal/wm/gl_ios.go b/app/gl_ios.go similarity index 99% rename from app/internal/wm/gl_ios.go rename to app/gl_ios.go index 9cf772e9..98c98330 100644 --- a/app/internal/wm/gl_ios.go +++ b/app/gl_ios.go @@ -3,7 +3,7 @@ //go:build darwin && ios && nometal // +build darwin,ios,nometal -package wm +package app /* @import UIKit; diff --git a/app/internal/wm/gl_ios.m b/app/gl_ios.m similarity index 100% rename from app/internal/wm/gl_ios.m rename to app/gl_ios.m diff --git a/app/internal/wm/gl_js.go b/app/gl_js.go similarity index 67% rename from app/internal/wm/gl_js.go rename to app/gl_js.go index 56227235..d76f5bbb 100644 --- a/app/internal/wm/gl_js.go +++ b/app/gl_js.go @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Unlicense OR MIT -package wm +package app import ( "errors" @@ -10,12 +10,12 @@ import ( "gioui.org/internal/gl" ) -type context struct { +type glContext struct { ctx js.Value cnv js.Value } -func newContext(w *window) (*context, error) { +func newContext(w *window) (*glContext, error) { args := map[string]interface{}{ // Enable low latency rendering. // See https://developers.google.com/web/updates/2019/05/desynchronized. @@ -29,41 +29,41 @@ func newContext(w *window) (*context, error) { if ctx.IsNull() { return nil, errors.New("app: webgl is not supported") } - c := &context{ + c := &glContext{ ctx: ctx, cnv: w.cnv, } return c, nil } -func (c *context) RenderTarget() gpu.RenderTarget { +func (c *glContext) RenderTarget() gpu.RenderTarget { return gpu.OpenGLRenderTarget{} } -func (c *context) API() gpu.API { +func (c *glContext) API() gpu.API { return gpu.OpenGL{Context: gl.Context(c.ctx)} } -func (c *context) Release() { +func (c *glContext) Release() { } -func (c *context) Present() error { +func (c *glContext) Present() error { if c.ctx.Call("isContextLost").Bool() { return errors.New("context lost") } return nil } -func (c *context) Lock() error { +func (c *glContext) Lock() error { return nil } -func (c *context) Unlock() {} +func (c *glContext) Unlock() {} -func (c *context) Refresh() error { +func (c *glContext) Refresh() error { return nil } -func (w *window) NewContext() (Context, error) { +func (w *window) NewContext() (context, error) { return newContext(w) } diff --git a/app/internal/wm/gl_macos.go b/app/gl_macos.go similarity index 79% rename from app/internal/wm/gl_macos.go rename to app/gl_macos.go index ad78360c..b6c5924d 100644 --- a/app/internal/wm/gl_macos.go +++ b/app/gl_macos.go @@ -3,7 +3,7 @@ //go:build darwin && !ios && nometal // +build darwin,!ios,nometal -package wm +package app import ( "errors" @@ -28,35 +28,35 @@ __attribute__ ((visibility ("hidden"))) void gio_unlockContext(CFTypeRef ctxRef) */ import "C" -type context struct { +type glContext struct { c *gl.Functions ctx C.CFTypeRef view C.CFTypeRef } -func newContext(w *window) (*context, error) { +func newContext(w *window) (*glContext, error) { view := w.contextView() ctx := C.gio_createGLContext() if ctx == 0 { return nil, errors.New("gl: failed to create NSOpenGLContext") } C.gio_setContextView(ctx, view) - c := &context{ + c := &glContext{ ctx: ctx, view: view, } return c, nil } -func (c *context) RenderTarget() gpu.RenderTarget { +func (c *glContext) RenderTarget() gpu.RenderTarget { return gpu.OpenGLRenderTarget{} } -func (c *context) API() gpu.API { +func (c *glContext) API() gpu.API { return gpu.OpenGL{} } -func (c *context) Release() { +func (c *glContext) Release() { if c.ctx != 0 { C.gio_clearCurrentContext() C.CFRelease(c.ctx) @@ -64,28 +64,28 @@ func (c *context) Release() { } } -func (c *context) Present() error { +func (c *glContext) Present() error { return nil } -func (c *context) Lock() error { +func (c *glContext) Lock() error { C.gio_lockContext(c.ctx) C.gio_makeCurrentContext(c.ctx) return nil } -func (c *context) Unlock() { +func (c *glContext) Unlock() { C.gio_clearCurrentContext() C.gio_unlockContext(c.ctx) } -func (c *context) Refresh() error { +func (c *glContext) Refresh() error { c.Lock() defer c.Unlock() C.gio_updateContext(c.ctx) return nil } -func (w *window) NewContext() (Context, error) { +func (w *window) NewContext() (context, error) { return newContext(w) } diff --git a/app/internal/wm/gl_macos.m b/app/gl_macos.m similarity index 100% rename from app/internal/wm/gl_macos.m rename to app/gl_macos.m diff --git a/app/loop.go b/app/loop.go index 1d388b62..b72a6230 100644 --- a/app/loop.go +++ b/app/loop.go @@ -7,7 +7,6 @@ import ( "image/color" "runtime" - "gioui.org/app/internal/wm" "gioui.org/gpu" "gioui.org/op" ) @@ -17,7 +16,7 @@ type renderLoop struct { drawing bool err error - ctx wm.Context + ctx context frames chan frame results chan frameResult ack chan struct{} @@ -35,7 +34,7 @@ type frameResult struct { err error } -func newLoop(ctx wm.Context) (*renderLoop, error) { +func newLoop(ctx context) (*renderLoop, error) { l := &renderLoop{ ctx: ctx, frames: make(chan frame), @@ -52,7 +51,7 @@ func newLoop(ctx wm.Context) (*renderLoop, error) { return l, nil } -func (l *renderLoop) renderLoop(ctx wm.Context) error { +func (l *renderLoop) renderLoop(ctx context) error { // GL Operations must happen on a single OS thread, so // pass initialization result through a channel. initErr := make(chan error) diff --git a/app/internal/wm/metal_darwin.go b/app/metal_darwin.go similarity index 98% rename from app/internal/wm/metal_darwin.go rename to app/metal_darwin.go index 327a60cc..2dced328 100644 --- a/app/internal/wm/metal_darwin.go +++ b/app/metal_darwin.go @@ -3,7 +3,7 @@ //go:build !nometal // +build !nometal -package wm +package app import ( "errors" @@ -169,6 +169,6 @@ func (c *mtlContext) Refresh() error { return nil } -func (w *window) NewContext() (Context, error) { +func (w *window) NewContext() (context, error) { return newMtlContext(w) } diff --git a/app/internal/wm/metal_ios.go b/app/metal_ios.go similarity index 98% rename from app/internal/wm/metal_ios.go rename to app/metal_ios.go index 5b66136b..860ba1aa 100644 --- a/app/internal/wm/metal_ios.go +++ b/app/metal_ios.go @@ -3,7 +3,7 @@ //go:build !nometal // +build !nometal -package wm +package app /* #cgo CFLAGS: -Werror -xobjective-c -fmodules -fobjc-arc diff --git a/app/internal/wm/metal_macos.go b/app/metal_macos.go similarity index 98% rename from app/internal/wm/metal_macos.go rename to app/metal_macos.go index 570cc84e..7db06a99 100644 --- a/app/internal/wm/metal_macos.go +++ b/app/metal_macos.go @@ -3,7 +3,7 @@ //go:build darwin && !ios && !nometal // +build darwin,!ios,!nometal -package wm +package app /* #cgo CFLAGS: -Werror -xobjective-c -fmodules -fobjc-arc diff --git a/app/internal/wm/window.go b/app/os.go similarity index 61% rename from app/internal/wm/window.go rename to app/os.go index da30a8fb..75d0e03d 100644 --- a/app/internal/wm/window.go +++ b/app/os.go @@ -1,8 +1,8 @@ // SPDX-License-Identifier: Unlicense OR MIT -// package wm implements platform specific windows +// package app implements platform specific windows // and GPU contexts. -package wm +package app import ( "errors" @@ -11,58 +11,52 @@ import ( "gioui.org/io/key" "gioui.org/gpu" - "gioui.org/io/event" "gioui.org/io/pointer" "gioui.org/io/system" "gioui.org/unit" ) -type Size struct { +type size struct { Width unit.Value Height unit.Value } -type Options struct { - Size *Size - MinSize *Size - MaxSize *Size +type config struct { + Size *size + MinSize *size + MaxSize *size Title *string - WindowMode *WindowMode + WindowMode *windowMode StatusColor *color.NRGBA NavigationColor *color.NRGBA - Orientation *Orientation + Orientation *orientation CustomRenderer bool } -type WakeupEvent struct{} +type wakeupEvent struct{} -type WindowMode uint8 +type windowMode uint8 const ( - Windowed WindowMode = iota - Fullscreen + windowed windowMode = iota + fullscreen ) -type Orientation uint8 +type orientation uint8 const ( - AnyOrientation Orientation = iota - LandscapeOrientation - PortraitOrientation + anyOrientation orientation = iota + landscapeOrientation + portraitOrientation ) -type FrameEvent struct { +type frameEvent struct { system.FrameEvent Sync bool } -type Callbacks interface { - SetDriver(d Driver) - Event(e event.Event) -} - -type Context interface { +type context interface { API() gpu.API RenderTarget() gpu.RenderTarget Present() error @@ -72,14 +66,14 @@ type Context interface { Unlock() } -// ErrDeviceLost is returned from Context.Present when +// errDeviceLost is returned from Context.Present when // the underlying GPU device is gone and should be // recreated. -var ErrDeviceLost = errors.New("GPU device lost") +var errDeviceLost = errors.New("GPU device lost") // Driver is the interface for the platform implementation // of a window. -type Driver interface { +type driver interface { // SetAnimating sets the animation flag. When the window is animating, // FrameEvents are delivered as fast as the display can handle them. SetAnimating(anim bool) @@ -89,15 +83,15 @@ type Driver interface { SetInputHint(mode key.InputHint) - NewContext() (Context, error) + NewContext() (context, error) // ReadClipboard requests the clipboard content. ReadClipboard() // WriteClipboard requests a clipboard write. WriteClipboard(s string) - // Option processes option changes. - Option(opts *Options) + // Configure the window. + Configure(cnf *config) // SetCursor updates the current cursor to name. SetCursor(name pointer.CursorName) @@ -109,25 +103,25 @@ type Driver interface { } type windowRendezvous struct { - in chan windowAndOptions - out chan windowAndOptions + in chan windowAndConfig + out chan windowAndConfig errs chan error } -type windowAndOptions struct { - window Callbacks - opts *Options +type windowAndConfig struct { + window *callbacks + cnf *config } func newWindowRendezvous() *windowRendezvous { wr := &windowRendezvous{ - in: make(chan windowAndOptions), - out: make(chan windowAndOptions), + in: make(chan windowAndConfig), + out: make(chan windowAndConfig), errs: make(chan error), } go func() { - var main windowAndOptions - var out chan windowAndOptions + var main windowAndConfig + var out chan windowAndConfig for { select { case w := <-wr.in: @@ -145,4 +139,4 @@ func newWindowRendezvous() *windowRendezvous { return wr } -func (_ WakeupEvent) ImplementsEvent() {} +func (_ wakeupEvent) ImplementsEvent() {} diff --git a/app/internal/wm/os_android.go b/app/os_android.go similarity index 93% rename from app/internal/wm/os_android.go rename to app/os_android.go index 0230c0ac..abca7b3f 100644 --- a/app/internal/wm/os_android.go +++ b/app/os_android.go @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Unlicense OR MIT -package wm +package app /* #cgo CFLAGS: -Werror @@ -111,6 +111,8 @@ import ( "fmt" "image" "image/color" + "os" + "path/filepath" "reflect" "runtime" "runtime/debug" @@ -130,7 +132,7 @@ import ( ) type window struct { - callbacks Callbacks + callbacks *callbacks view C.jobject @@ -195,13 +197,38 @@ var android struct { // view maps from GioView JNI refenreces to windows. var views = make(map[C.jlong]*window) -// windows maps from Callbacks to windows -var windows = make(map[Callbacks]*window) +var windows = make(map[*callbacks]*window) var mainWindow = newWindowRendezvous() var mainFuncs = make(chan func(env *C.JNIEnv), 1) +var ( + dataDirOnce sync.Once + dataPath string +) + +func dataDir() (string, error) { + dataDirOnce.Do(func() { + dataPath = <-dataDirChan + // Set XDG_CACHE_HOME to make os.UserCacheDir work. + if _, exists := os.LookupEnv("XDG_CACHE_HOME"); !exists { + cachePath := filepath.Join(dataPath, "cache") + os.Setenv("XDG_CACHE_HOME", cachePath) + } + // Set XDG_CONFIG_HOME to make os.UserConfigDir work. + if _, exists := os.LookupEnv("XDG_CONFIG_HOME"); !exists { + cfgPath := filepath.Join(dataPath, "config") + os.Setenv("XDG_CONFIG_HOME", cfgPath) + } + // Set HOME to make os.UserHomeDir work. + if _, exists := os.LookupEnv("HOME"); !exists { + os.Setenv("HOME", dataPath) + } + }) + return dataPath, nil +} + func getMethodID(env *C.JNIEnv, class C.jclass, method, sig string) C.jmethodID { m := C.CString(method) defer C.free(unsafe.Pointer(m)) @@ -254,6 +281,7 @@ func initJVM(env *C.JNIEnv, gio C.jclass, ctx C.jobject) { android.mwakeupMainThread = getStaticMethodID(env, gio, "wakeupMainThread", "()V") } +// JavaVM returns the global JNI JavaVM. func JavaVM() uintptr { jvm := javaVM() return uintptr(unsafe.Pointer(jvm)) @@ -265,16 +293,13 @@ func javaVM() *C.JavaVM { return android.jvm } +// AppContext returns the global Application context as a JNI jobject. func AppContext() uintptr { android.mu.Lock() defer android.mu.Unlock() return uintptr(android.appCtx) } -func GetDataDir() string { - return <-dataDirChan -} - //export Java_org_gioui_GioView_onCreateView func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.jobject) C.jlong { gioView.once.Do(func() { @@ -305,7 +330,7 @@ func Java_org_gioui_GioView_onCreateView(env *C.JNIEnv, class C.jclass, view C.j handle := C.jlong(view) views[handle] = w w.loadConfig(env, class) - w.Option(wopts.opts) + w.Configure(wopts.cnf) w.setStage(system.StagePaused) w.callbacks.Event(ViewEvent{View: uintptr(view)}) return handle @@ -476,7 +501,7 @@ func (w *window) draw(sync bool) { } const inchPrDp = 1.0 / 160 ppdp := float32(w.dpi) * inchPrDp - w.callbacks.Event(FrameEvent{ + w.callbacks.Event(frameEvent{ FrameEvent: system.FrameEvent{ Now: time.Now(), Size: image.Point{ @@ -723,11 +748,11 @@ func goString(env *C.JNIEnv, str C.jstring) string { return string(utf8) } -func Main() { +func osMain() { } -func NewWindow(window Callbacks, opts *Options) error { - mainWindow.in <- windowAndOptions{window, opts} +func newWindow(window *callbacks, cnf *config) error { + mainWindow.in <- windowAndConfig{window, cnf} return <-mainWindow.errs } @@ -751,18 +776,18 @@ func (w *window) ReadClipboard() { }) } -func (w *window) Option(opts *Options) { +func (w *window) Configure(cnf *config) { runInJVM(javaVM(), func(env *C.JNIEnv) { - if o := opts.Orientation; o != nil { + if o := cnf.Orientation; o != nil { setOrientation(env, w.view, *o) } - if o := opts.NavigationColor; o != nil { + if o := cnf.NavigationColor; o != nil { setNavigationColor(env, w.view, *o) } - if o := opts.StatusColor; o != nil { + if o := cnf.StatusColor; o != nil { setStatusColor(env, w.view, *o) } - if o := opts.WindowMode; o != nil { + if o := cnf.WindowMode; o != nil { setWindowMode(env, w.view, *o) } }) @@ -776,7 +801,7 @@ func (w *window) SetCursor(name pointer.CursorName) { func (w *window) Wakeup() { runOnMain(func(env *C.JNIEnv) { - w.callbacks.Event(WakeupEvent{}) + w.callbacks.Event(wakeupEvent{}) }) } @@ -803,18 +828,18 @@ func setCursor(env *C.JNIEnv, view C.jobject, name pointer.CursorName) { callVoidMethod(env, view, gioView.setCursor, jvalue(curID)) } -func setOrientation(env *C.JNIEnv, view C.jobject, mode Orientation) { +func setOrientation(env *C.JNIEnv, view C.jobject, mode orientation) { var ( id int idFallback int // Used only for SDK 17 or older. ) // Constants defined at https://developer.android.com/reference/android/content/pm/ActivityInfo. switch mode { - case AnyOrientation: + case anyOrientation: id, idFallback = 2, 2 // SCREEN_ORIENTATION_USER - case LandscapeOrientation: + case landscapeOrientation: id, idFallback = 11, 0 // SCREEN_ORIENTATION_USER_LANDSCAPE (or SCREEN_ORIENTATION_LANDSCAPE) - case PortraitOrientation: + case portraitOrientation: id, idFallback = 12, 1 // SCREEN_ORIENTATION_USER_PORTRAIT (or SCREEN_ORIENTATION_PORTRAIT) } callVoidMethod(env, view, gioView.setOrientation, jvalue(id), jvalue(idFallback)) @@ -834,9 +859,9 @@ func setNavigationColor(env *C.JNIEnv, view C.jobject, color color.NRGBA) { ) } -func setWindowMode(env *C.JNIEnv, view C.jobject, mode WindowMode) { +func setWindowMode(env *C.JNIEnv, view C.jobject, mode windowMode) { switch mode { - case Fullscreen: + case fullscreen: callVoidMethod(env, view, gioView.setFullscreen, C.JNI_TRUE) default: callVoidMethod(env, view, gioView.setFullscreen, C.JNI_FALSE) diff --git a/app/internal/wm/os_darwin.go b/app/os_darwin.go similarity index 99% rename from app/internal/wm/os_darwin.go rename to app/os_darwin.go index 7c170f15..c0554db3 100644 --- a/app/internal/wm/os_darwin.go +++ b/app/os_darwin.go @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Unlicense OR MIT -package wm +package app /* #include @@ -232,6 +232,6 @@ func windowSetCursor(from, to pointer.CursorName) pointer.CursorName { func (w *window) Wakeup() { runOnMain(func() { - w.w.Event(WakeupEvent{}) + w.w.Event(wakeupEvent{}) }) } diff --git a/app/internal/wm/os_darwin.m b/app/os_darwin.m similarity index 100% rename from app/internal/wm/os_darwin.m rename to app/os_darwin.m diff --git a/app/internal/wm/os_ios.go b/app/os_ios.go similarity index 97% rename from app/internal/wm/os_ios.go rename to app/os_ios.go index efe0d23f..7d34b904 100644 --- a/app/internal/wm/os_ios.go +++ b/app/os_ios.go @@ -3,7 +3,7 @@ //go:build darwin && ios // +build darwin,ios -package wm +package app /* #cgo CFLAGS: -DGLES_SILENCE_DEPRECATION -Werror -Wno-deprecated-declarations -fmodules -fobjc-arc -x objective-c @@ -90,7 +90,7 @@ type ViewEvent struct{} type window struct { view C.CFTypeRef - w Callbacks + w *callbacks displayLink *displayLink visible bool @@ -144,7 +144,7 @@ func (w *window) draw(sync bool) { w.w.Event(system.StageEvent{Stage: system.StageRunning}) } const inchPrDp = 1.0 / 163 - w.w.Event(FrameEvent{ + w.w.Event(frameEvent{ FrameEvent: system.FrameEvent{ Now: time.Now(), Size: image.Point{ @@ -268,7 +268,7 @@ func (w *window) WriteClipboard(s string) { C.writeClipboard(chars, C.NSUInteger(len(u16))) } -func (w *window) Option(opts *Options) {} +func (w *window) Configure(cnf *config) {} func (w *window) SetAnimating(anim bool) { v := w.view @@ -329,12 +329,12 @@ func (w *window) SetInputHint(_ key.InputHint) {} // Close the window. Not implemented for iOS. func (w *window) Close() {} -func NewWindow(win Callbacks, opts *Options) error { - mainWindow.in <- windowAndOptions{win, opts} +func newWindow(win *callbacks, cnf *config) error { + mainWindow.in <- windowAndConfig{win, cnf} return <-mainWindow.errs } -func Main() { +func osMain() { } //export gio_runMain diff --git a/app/internal/wm/os_ios.m b/app/os_ios.m similarity index 100% rename from app/internal/wm/os_ios.m rename to app/os_ios.m diff --git a/app/internal/wm/os_js.go b/app/os_js.go similarity index 96% rename from app/internal/wm/os_js.go rename to app/os_js.go index 48962b70..64aa7b1c 100644 --- a/app/internal/wm/os_js.go +++ b/app/os_js.go @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Unlicense OR MIT -package wm +package app import ( "fmt" @@ -31,7 +31,7 @@ type window struct { clipboard js.Value cnv js.Value tarea js.Value - w Callbacks + w *callbacks redraw js.Func clipboardCallback js.Func requestAnimationFrame js.Value @@ -56,7 +56,7 @@ type window struct { wakeups chan struct{} } -func NewWindow(win Callbacks, opts *Options) error { +func newWindow(win *callbacks, cnf *config) error { doc := js.Global().Get("document") cont := getContainer(doc) cnv := createCanvas(doc) @@ -94,7 +94,7 @@ func NewWindow(win Callbacks, opts *Options) error { }) w.addEventListeners() w.addHistory() - w.Option(opts) + w.Configure(cnf) w.w = win go func() { @@ -107,7 +107,7 @@ func NewWindow(win Callbacks, opts *Options) error { for { select { case <-w.wakeups: - w.w.Event(WakeupEvent{}) + w.w.Event(wakeupEvent{}) case <-w.chanAnimation: w.animCallback() case <-w.chanRedraw: @@ -509,17 +509,17 @@ func (w *window) WriteClipboard(s string) { w.clipboard.Call("writeText", s) } -func (w *window) Option(opts *Options) { - if o := opts.Title; o != nil { +func (w *window) Configure(cnf *config) { + if o := cnf.Title; o != nil { w.document.Set("title", *o) } - if o := opts.WindowMode; o != nil { + if o := cnf.WindowMode; o != nil { w.windowMode(*o) } - if o := opts.NavigationColor; o != nil { + if o := cnf.NavigationColor; o != nil { w.navigationColor(*o) } - if o := opts.Orientation; o != nil { + if o := cnf.Orientation; o != nil { w.orientation(*o) } } @@ -581,7 +581,7 @@ func (w *window) draw(sync bool) { return } - w.w.Event(FrameEvent{ + w.w.Event(frameEvent{ FrameEvent: system.FrameEvent{ Now: time.Now(), Size: image.Point{ @@ -605,9 +605,9 @@ func (w *window) config() (int, int, system.Insets, unit.Metric) { } } -func (w *window) windowMode(mode WindowMode) { +func (w *window) windowMode(mode windowMode) { switch mode { - case Windowed: + case windowed: if !w.document.Get("fullscreenElement").Truthy() { return // Browser is already Windowed. } @@ -615,7 +615,7 @@ func (w *window) windowMode(mode WindowMode) { return // Browser doesn't support such feature. } w.document.Call("exitFullscreen") - case Fullscreen: + case fullscreen: elem := w.document.Get("documentElement") if !elem.Get("requestFullscreen").Truthy() { return // Browser doesn't support such feature. @@ -624,17 +624,17 @@ func (w *window) windowMode(mode WindowMode) { } } -func (w *window) orientation(mode Orientation) { +func (w *window) orientation(mode orientation) { if j := w.screenOrientation; !j.Truthy() || !j.Get("unlock").Truthy() || !j.Get("lock").Truthy() { return // Browser don't support Screen Orientation API. } switch mode { - case AnyOrientation: + case anyOrientation: w.screenOrientation.Call("unlock") - case LandscapeOrientation: + case landscapeOrientation: w.screenOrientation.Call("lock", "landscape").Call("then", w.redraw) - case PortraitOrientation: + case portraitOrientation: w.screenOrientation.Call("lock", "portrait").Call("then", w.redraw) } } @@ -650,7 +650,7 @@ func (w *window) navigationColor(c color.NRGBA) { theme.Set("content", fmt.Sprintf("#%06X", []uint8{rgba.R, rgba.G, rgba.B})) } -func Main() { +func osMain() { select {} } diff --git a/app/internal/wm/os_macos.go b/app/os_macos.go similarity index 96% rename from app/internal/wm/os_macos.go rename to app/os_macos.go index 1ab07d81..d74bbd6f 100644 --- a/app/internal/wm/os_macos.go +++ b/app/os_macos.go @@ -3,7 +3,7 @@ //go:build darwin && !ios // +build darwin,!ios -package wm +package app import ( "errors" @@ -147,13 +147,13 @@ type ViewEvent struct { type window struct { view C.CFTypeRef window C.CFTypeRef - w Callbacks + w *callbacks stage system.Stage displayLink *displayLink cursor pointer.CursorName scale float32 - mode WindowMode + mode windowMode } // viewMap is the mapping from Cocoa NSViews to Go windows. @@ -210,47 +210,47 @@ func (w *window) WriteClipboard(s string) { C.writeClipboard(chars, C.NSUInteger(len(u16))) } -func (w *window) Option(opts *Options) { +func (w *window) Configure(cnf *config) { screenScale := float32(C.getScreenBackingScale()) cfg := configFor(screenScale) val := func(v unit.Value) float32 { return float32(cfg.Px(v)) / screenScale } - if o := opts.Size; o != nil { + if o := cnf.Size; o != nil { width := val(o.Width) height := val(o.Height) if width > 0 || height > 0 { C.setSize(w.window, C.CGFloat(width), C.CGFloat(height)) } } - if o := opts.MinSize; o != nil { + if o := cnf.MinSize; o != nil { width := val(o.Width) height := val(o.Height) if width > 0 || height > 0 { C.setMinSize(w.window, C.CGFloat(width), C.CGFloat(height)) } } - if o := opts.MaxSize; o != nil { + if o := cnf.MaxSize; o != nil { width := val(o.Width) height := val(o.Height) if width > 0 || height > 0 { C.setMaxSize(w.window, C.CGFloat(width), C.CGFloat(height)) } } - if o := opts.Title; o != nil { + if o := cnf.Title; o != nil { title := C.CString(*o) defer C.free(unsafe.Pointer(title)) C.setTitle(w.window, title) } - if o := opts.WindowMode; o != nil { + if o := cnf.WindowMode; o != nil { w.SetWindowMode(*o) } } -func (w *window) SetWindowMode(mode WindowMode) { +func (w *window) SetWindowMode(mode windowMode) { switch mode { case w.mode: - case Windowed, Fullscreen: + case windowed, fullscreen: C.toggleFullScreen(w.window) w.mode = mode } @@ -396,7 +396,7 @@ func (w *window) draw() { height := int(hf*w.scale + .5) cfg := configFor(w.scale) w.setStage(system.StageRunning) - w.w.Event(FrameEvent{ + w.w.Event(frameEvent{ FrameEvent: system.FrameEvent{ Now: time.Now(), Size: image.Point{ @@ -461,11 +461,11 @@ func gio_onFinishLaunching() { close(launched) } -func NewWindow(win Callbacks, opts *Options) error { +func newWindow(win *callbacks, cnf *config) error { <-launched errch := make(chan error) runOnMain(func() { - w, err := newWindow(opts) + w, err := newOSWindow() if err != nil { errch <- err return @@ -474,7 +474,7 @@ func NewWindow(win Callbacks, opts *Options) error { w.w = win w.window = C.gio_createWindow(w.view, nil, 0, 0, 0, 0, 0, 0) win.SetDriver(w) - w.Option(opts) + w.Configure(cnf) if nextTopLeft.x == 0 && nextTopLeft.y == 0 { // cascadeTopLeftFromPoint treats (0, 0) as a no-op, // and just returns the offset we need for the first window. @@ -488,7 +488,7 @@ func NewWindow(win Callbacks, opts *Options) error { return <-errch } -func newWindow(opts *Options) (*window, error) { +func newOSWindow() (*window, error) { view := C.gio_createView() if view == 0 { return nil, errors.New("CreateWindow: failed to create view") @@ -512,7 +512,7 @@ func newWindow(opts *Options) (*window, error) { return w, nil } -func Main() { +func osMain() { C.gio_main() } diff --git a/app/internal/wm/os_macos.m b/app/os_macos.m similarity index 100% rename from app/internal/wm/os_macos.m rename to app/os_macos.m diff --git a/app/internal/wm/os_unix.go b/app/os_unix.go similarity index 85% rename from app/internal/wm/os_unix.go rename to app/os_unix.go index 7f92d026..518f912c 100644 --- a/app/internal/wm/os_unix.go +++ b/app/os_unix.go @@ -3,7 +3,7 @@ //go:build (linux && !android) || freebsd || openbsd // +build linux,!android freebsd openbsd -package wm +package app import ( "errors" @@ -17,23 +17,23 @@ type ViewEvent struct { Window uintptr } -func Main() { +func osMain() { select {} } -type windowDriver func(Callbacks, *Options) error +type windowDriver func(*callbacks, *config) error // Instead of creating files with build tags for each combination of wayland +/- x11 // let each driver initialize these variables with their own version of createWindow. var wlDriver, x11Driver windowDriver -func NewWindow(window Callbacks, opts *Options) error { +func newWindow(window *callbacks, cnf *config) error { var errFirst error for _, d := range []windowDriver{x11Driver, wlDriver} { if d == nil { continue } - err := d(window, opts) + err := d(window, cnf) if err == nil { return nil } diff --git a/app/internal/wm/os_wayland.c b/app/os_wayland.c similarity index 100% rename from app/internal/wm/os_wayland.c rename to app/os_wayland.c diff --git a/app/internal/wm/os_wayland.go b/app/os_wayland.go similarity index 98% rename from app/internal/wm/os_wayland.go rename to app/os_wayland.go index 5d7a0b0a..e3c95829 100644 --- a/app/internal/wm/os_wayland.go +++ b/app/os_wayland.go @@ -3,7 +3,7 @@ //go:build (linux && !android && !nowayland) || freebsd // +build linux,!android,!nowayland freebsd -package wm +package app import ( "bytes" @@ -136,7 +136,7 @@ type repeatState struct { delay time.Duration key uint32 - win Callbacks + win *callbacks stopC chan struct{} start time.Duration @@ -146,7 +146,7 @@ type repeatState struct { } type window struct { - w Callbacks + w *callbacks disp *wlDisplay surf *C.struct_wl_surface wmSurf *C.struct_xdg_surface @@ -222,12 +222,12 @@ func init() { wlDriver = newWLWindow } -func newWLWindow(window Callbacks, opts *Options) error { +func newWLWindow(window *callbacks, cnf *config) error { d, err := newWLDisplay() if err != nil { return err } - w, err := d.createNativeWindow(opts) + w, err := d.createNativeWindow(cnf) if err != nil { d.destroy() return err @@ -289,7 +289,7 @@ func (d *wlDisplay) readClipboard() (io.ReadCloser, error) { return r, nil } -func (d *wlDisplay) createNativeWindow(opts *Options) (*window, error) { +func (d *wlDisplay) createNativeWindow(cnf *config) (*window, error) { if d.compositor == nil { return nil, errors.New("wayland: no compositor available") } @@ -356,7 +356,7 @@ func (d *wlDisplay) createNativeWindow(opts *Options) (*window, error) { C.xdg_surface_add_listener(w.wmSurf, &C.gio_xdg_surface_listener, unsafe.Pointer(w.surf)) C.xdg_toplevel_add_listener(w.topLvl, &C.gio_xdg_toplevel_listener, unsafe.Pointer(w.surf)) - w.setOptions(opts) + w.Configure(cnf) if d.decor != nil { // Request server side decorations. @@ -907,17 +907,13 @@ func (w *window) WriteClipboard(s string) { w.disp.writeClipboard([]byte(s)) } -func (w *window) Option(opts *Options) { - w.setOptions(opts) -} - -func (w *window) setOptions(opts *Options) { +func (w *window) Configure(cnf *config) { _, _, cfg := w.config() - if o := opts.Size; o != nil { + if o := cnf.Size; o != nil { w.width = cfg.Px(o.Width) w.height = cfg.Px(o.Height) } - if o := opts.Title; o != nil { + if o := cnf.Title; o != nil { title := C.CString(*o) C.xdg_toplevel_set_title(w.topLvl, title) C.free(unsafe.Pointer(title)) @@ -1134,7 +1130,7 @@ func (w *window) loop() error { } select { case <-w.wakeups: - w.w.Event(WakeupEvent{}) + w.w.Event(wakeupEvent{}) default: } if w.dead { @@ -1423,7 +1419,7 @@ func (w *window) draw(sync bool) { // Use the surface as listener data for gio_onFrameDone. C.wl_callback_add_listener(w.lastFrameCallback, &C.gio_callback_listener, unsafe.Pointer(w.surf)) } - w.w.Event(FrameEvent{ + w.w.Event(frameEvent{ FrameEvent: system.FrameEvent{ Now: time.Now(), Size: image.Point{ diff --git a/app/internal/wm/os_windows.go b/app/os_windows.go similarity index 94% rename from app/internal/wm/os_windows.go rename to app/os_windows.go index 5c0cfaf6..2fcf62a4 100644 --- a/app/internal/wm/os_windows.go +++ b/app/os_windows.go @@ -1,6 +1,6 @@ // SPDX-License-Identifier: Unlicense OR MIT -package wm +package app import ( "errors" @@ -45,7 +45,7 @@ type winDeltas struct { type window struct { hwnd syscall.Handle hdc syscall.Handle - w Callbacks + w *callbacks width int height int stage system.Stage @@ -63,14 +63,14 @@ type window struct { minmax winConstraints deltas winDeltas - opts *Options + cnf *config } const _WM_WAKEUP = windows.WM_USER + iota type gpuAPI struct { priority int - initializer func(w *window) (Context, error) + initializer func(w *window) (context, error) } // drivers is the list of potential Context implementations. @@ -92,11 +92,11 @@ var resources struct { cursor syscall.Handle } -func Main() { +func osMain() { select {} } -func NewWindow(window Callbacks, opts *Options) error { +func newWindow(window *callbacks, cnf *config) error { cerr := make(chan error) go func() { // GetMessage and PeekMessage can filter on a window HWND, but @@ -104,7 +104,7 @@ func NewWindow(window Callbacks, opts *Options) error { // Instead lock the thread so window messages arrive through // unfiltered GetMessage calls. runtime.LockOSThread() - w, err := createNativeWindow(opts) + w, err := createNativeWindow(cnf) if err != nil { cerr <- err return @@ -115,7 +115,7 @@ func NewWindow(window Callbacks, opts *Options) error { w.w = window w.w.SetDriver(w) w.w.Event(ViewEvent{HWND: uintptr(w.hwnd)}) - w.Option(opts) + w.Configure(cnf) windows.ShowWindow(w.hwnd, windows.SW_SHOWDEFAULT) windows.SetForegroundWindow(w.hwnd) windows.SetFocus(w.hwnd) @@ -159,20 +159,20 @@ func initResources() error { return nil } -func getWindowConstraints(cfg unit.Metric, opts *Options) winConstraints { +func getWindowConstraints(cfg unit.Metric, cnf *config) winConstraints { var minmax winConstraints - if o := opts.MinSize; o != nil { + if o := cnf.MinSize; o != nil { minmax.minWidth = int32(cfg.Px(o.Width)) minmax.minHeight = int32(cfg.Px(o.Height)) } - if o := opts.MaxSize; o != nil { + if o := cnf.MaxSize; o != nil { minmax.maxWidth = int32(cfg.Px(o.Width)) minmax.maxHeight = int32(cfg.Px(o.Height)) } return minmax } -func createNativeWindow(opts *Options) (*window, error) { +func createNativeWindow(cnf *config) (*window, error) { var resErr error resources.once.Do(func() { resErr = initResources() @@ -200,8 +200,8 @@ func createNativeWindow(opts *Options) (*window, error) { } w := &window{ hwnd: hwnd, - minmax: getWindowConstraints(cfg, opts), - opts: opts, + minmax: getWindowConstraints(cfg, cnf), + cnf: cnf, } w.hdc, err = windows.GetDC(hwnd) if err != nil { @@ -330,7 +330,7 @@ func windowProc(hwnd syscall.Handle, msg uint32, wParam, lParam uintptr) uintptr return windows.TRUE } case _WM_WAKEUP: - w.w.Event(WakeupEvent{}) + w.w.Event(wakeupEvent{}) } return windows.DefWindowProc(hwnd, msg, wParam, lParam) @@ -458,8 +458,8 @@ func (w *window) draw(sync bool) { } dpi := windows.GetWindowDPI(w.hwnd) cfg := configForDPI(dpi) - w.minmax = getWindowConstraints(cfg, w.opts) - w.w.Event(FrameEvent{ + w.minmax = getWindowConstraints(cfg, w.cnf) + w.w.Event(frameEvent{ FrameEvent: system.FrameEvent{ Now: time.Now(), Size: image.Point{ @@ -472,7 +472,7 @@ func (w *window) draw(sync bool) { }) } -func (w *window) NewContext() (Context, error) { +func (w *window) NewContext() (context, error) { sort.Slice(drivers, func(i, j int) bool { return drivers[i].priority < drivers[j].priority }) @@ -515,9 +515,9 @@ func (w *window) readClipboard() error { return nil } -func (w *window) Option(opts *Options) { - w.opts = opts - if o := opts.Size; o != nil { +func (w *window) Configure(cnf *config) { + w.cnf = cnf + if o := cnf.Size; o != nil { dpi := windows.GetSystemDPI() cfg := configForDPI(dpi) width := int32(cfg.Px(o.Width)) @@ -538,27 +538,27 @@ func (w *window) Option(opts *Options) { w.deltas.width = width - dw w.deltas.height = height - dh - w.opts.Size = o + w.cnf.Size = o windows.MoveWindow(w.hwnd, 0, 0, width, height, true) } - if o := opts.MinSize; o != nil { - w.opts.MinSize = o + if o := cnf.MinSize; o != nil { + w.cnf.MinSize = o } - if o := opts.MaxSize; o != nil { - w.opts.MaxSize = o + if o := cnf.MaxSize; o != nil { + w.cnf.MaxSize = o } - if o := opts.Title; o != nil { - windows.SetWindowText(w.hwnd, *opts.Title) + if o := cnf.Title; o != nil { + windows.SetWindowText(w.hwnd, *cnf.Title) } - if o := opts.WindowMode; o != nil { + if o := cnf.WindowMode; o != nil { w.SetWindowMode(*o) } } -func (w *window) SetWindowMode(mode WindowMode) { +func (w *window) SetWindowMode(mode windowMode) { // https://devblogs.microsoft.com/oldnewthing/20100412-00/?p=14353 switch mode { - case Windowed: + case windowed: if w.placement == nil { return } @@ -570,7 +570,7 @@ func (w *window) SetWindowMode(mode WindowMode) { 0, 0, 0, 0, windows.SWP_NOOWNERZORDER|windows.SWP_FRAMECHANGED, ) - case Fullscreen: + case fullscreen: if w.placement != nil { return } diff --git a/app/internal/wm/os_x11.go b/app/os_x11.go similarity index 97% rename from app/internal/wm/os_x11.go rename to app/os_x11.go index f521d6ba..f3716010 100644 --- a/app/internal/wm/os_x11.go +++ b/app/os_x11.go @@ -3,7 +3,7 @@ //go:build (linux && !android && !nox11) || freebsd || openbsd // +build linux,!android,!nox11 freebsd openbsd -package wm +package app /* #cgo openbsd CFLAGS: -I/usr/X11R6/include -I/usr/local/include @@ -49,7 +49,7 @@ import ( ) type x11Window struct { - w Callbacks + w *callbacks x *C.Display xkb *xkb.Context xkbEventBase C.int @@ -96,7 +96,7 @@ type x11Window struct { content []byte } cursor pointer.CursorName - mode WindowMode + mode windowMode wakeups chan struct{} } @@ -115,14 +115,14 @@ func (w *x11Window) WriteClipboard(s string) { C.XSetSelectionOwner(w.x, w.atoms.clipboard, w.xw, C.CurrentTime) } -func (w *x11Window) Option(opts *Options) { +func (w *x11Window) Configure(cnf *config) { var shints C.XSizeHints - if o := opts.MinSize; o != nil { + if o := cnf.MinSize; o != nil { shints.min_width = C.int(w.cfg.Px(o.Width)) shints.min_height = C.int(w.cfg.Px(o.Height)) shints.flags = C.PMinSize } - if o := opts.MaxSize; o != nil { + if o := cnf.MaxSize; o != nil { shints.max_width = C.int(w.cfg.Px(o.Width)) shints.max_height = C.int(w.cfg.Px(o.Height)) shints.flags = shints.flags | C.PMaxSize @@ -131,12 +131,12 @@ func (w *x11Window) Option(opts *Options) { C.XSetWMNormalHints(w.x, w.xw, &shints) } - if o := opts.Size; o != nil { + if o := cnf.Size; o != nil { C.XResizeWindow(w.x, w.xw, C.uint(w.cfg.Px(o.Width)), C.uint(w.cfg.Px(o.Height))) } var title string - if o := opts.Title; o != nil { + if o := cnf.Title; o != nil { title = *o } ctitle := C.CString(title) @@ -152,7 +152,7 @@ func (w *x11Window) Option(opts *Options) { }, w.atoms.wmName) - if o := opts.WindowMode; o != nil { + if o := cnf.WindowMode; o != nil { w.SetWindowMode(*o) } } @@ -181,13 +181,13 @@ func (w *x11Window) SetCursor(name pointer.CursorName) { C.XDefineCursor(w.x, w.xw, c) } -func (w *x11Window) SetWindowMode(mode WindowMode) { +func (w *x11Window) SetWindowMode(mode windowMode) { switch mode { case w.mode: return - case Windowed: + case windowed: C.XDeleteProperty(w.x, w.xw, w.atoms.wmStateFullscreen) - case Fullscreen: + case fullscreen: C.XChangeProperty(w.x, w.xw, w.atoms.wmState, C.XA_ATOM, 32, C.PropModeReplace, (*C.uchar)(unsafe.Pointer(&w.atoms.wmStateFullscreen)), 1, @@ -322,12 +322,12 @@ loop: } select { case <-w.wakeups: - w.w.Event(WakeupEvent{}) + w.w.Event(wakeupEvent{}) default: } if (anim || syn) && w.width != 0 && w.height != 0 { - w.w.Event(FrameEvent{ + w.w.Event(frameEvent{ FrameEvent: system.FrameEvent{ Now: time.Now(), Size: image.Point{ @@ -582,7 +582,7 @@ func init() { x11Driver = newX11Window } -func newX11Window(gioWin Callbacks, opts *Options) error { +func newX11Window(gioWin *callbacks, cnf *config) error { var err error pipe := make([]int, 2) @@ -632,7 +632,7 @@ func newX11Window(gioWin Callbacks, opts *Options) error { override_redirect: C.False, } var width, height int - if o := opts.Size; o != nil { + if o := cnf.Size; o != nil { width = cfg.Px(o.Width) height = cfg.Px(o.Height) } @@ -683,7 +683,7 @@ func newX11Window(gioWin Callbacks, opts *Options) error { // extensions C.XSetWMProtocols(dpy, win, &w.atoms.evDelWindow, 1) - w.Option(opts) + w.Configure(cnf) // make the window visible on the screen C.XMapWindow(dpy, win) diff --git a/app/internal/wm/runmain.go b/app/runmain.go similarity index 98% rename from app/internal/wm/runmain.go rename to app/runmain.go index 0fa7a6cf..a1c1e3d4 100644 --- a/app/internal/wm/runmain.go +++ b/app/runmain.go @@ -3,7 +3,7 @@ //go:build android || (darwin && ios) // +build android darwin,ios -package wm +package app // Android only supports non-Java programs as c-shared libraries. // Unfortunately, Go does not run a program's main function in diff --git a/app/sigpipe_darwin.go b/app/sigpipe_darwin.go deleted file mode 100644 index 74dd969b..00000000 --- a/app/sigpipe_darwin.go +++ /dev/null @@ -1,19 +0,0 @@ -// SPDX-License-Identifier: Unlicense OR MIT - -//go:build !go1.14 -// +build !go1.14 - -// Work around golang.org/issue/33384, fixed in CL 191785, -// to be released in Go 1.14. - -package app - -import ( - "os" - "os/signal" - "syscall" -) - -func init() { - signal.Notify(make(chan os.Signal), syscall.SIGPIPE) -} diff --git a/app/internal/wm/wayland_text_input.c b/app/wayland_text_input.c similarity index 100% rename from app/internal/wm/wayland_text_input.c rename to app/wayland_text_input.c diff --git a/app/internal/wm/wayland_text_input.h b/app/wayland_text_input.h similarity index 100% rename from app/internal/wm/wayland_text_input.h rename to app/wayland_text_input.h diff --git a/app/internal/wm/wayland_xdg_decoration.c b/app/wayland_xdg_decoration.c similarity index 100% rename from app/internal/wm/wayland_xdg_decoration.c rename to app/wayland_xdg_decoration.c diff --git a/app/internal/wm/wayland_xdg_decoration.h b/app/wayland_xdg_decoration.h similarity index 100% rename from app/internal/wm/wayland_xdg_decoration.h rename to app/wayland_xdg_decoration.h diff --git a/app/internal/wm/wayland_xdg_shell.c b/app/wayland_xdg_shell.c similarity index 100% rename from app/internal/wm/wayland_xdg_shell.c rename to app/wayland_xdg_shell.c diff --git a/app/internal/wm/wayland_xdg_shell.h b/app/wayland_xdg_shell.h similarity index 100% rename from app/internal/wm/wayland_xdg_shell.h rename to app/wayland_xdg_shell.h diff --git a/app/window.go b/app/window.go index 3cbd126b..c7ae5af0 100644 --- a/app/window.go +++ b/app/window.go @@ -18,22 +18,21 @@ import ( "gioui.org/unit" _ "gioui.org/app/internal/log" - "gioui.org/app/internal/wm" ) // Option configures a window. -type Option func(opts *wm.Options) +type Option func(cnf *config) // Window represents an operating system window. type Window struct { - ctx wm.Context + ctx context loop *renderLoop // driverFuncs is a channel of functions to run when // the Window has a valid driver. - driverFuncs chan func(d wm.Driver) + driverFuncs chan func(d driver) // wakeups wakes up the native event loop to send a - // wm.WakeupEvent that flushes driverFuncs. + // WakeupEvent that flushes driverFuncs. wakeups chan struct{} out chan event.Event @@ -62,7 +61,7 @@ type Window struct { type callbacks struct { w *Window - d wm.Driver + d driver } // queue is an event.Queue implementation that distributes system events @@ -73,7 +72,7 @@ type queue struct { // driverEvent is sent when the underlying driver changes. type driverEvent struct { - driver wm.Driver + driver driver } // Pre-allocate the ack event to avoid garbage. @@ -90,13 +89,13 @@ var ackEvent event.Event // Calling NewWindow more than once is not supported on // iOS, Android, WebAssembly. func NewWindow(options ...Option) *Window { - opts := new(wm.Options) + cnf := new(config) // Default options. - Size(unit.Dp(800), unit.Dp(600))(opts) - Title("Gio")(opts) + Size(unit.Dp(800), unit.Dp(600))(cnf) + Title("Gio")(cnf) for _, o := range options { - o(opts) + o(cnf) } w := &Window{ @@ -106,14 +105,14 @@ func NewWindow(options ...Option) *Window { invalidates: make(chan struct{}, 1), frames: make(chan *op.Ops), frameAck: make(chan struct{}), - driverFuncs: make(chan func(d wm.Driver), 1), + driverFuncs: make(chan func(d driver), 1), wakeups: make(chan struct{}, 1), dead: make(chan struct{}), notifyAnimate: make(chan struct{}, 1), - nocontext: opts.CustomRenderer, + nocontext: cnf.CustomRenderer, } w.callbacks.w = w - go w.run(opts) + go w.run(cnf) return w } @@ -122,21 +121,20 @@ func (w *Window) Events() <-chan event.Event { return w.out } -// update updates the wm. Paint operations updates the -// window contents, input operations declare input handlers, -// and so on. The supplied operations list completely replaces -// the window state from previous calls. +// update updates the window contents, input operations declare input handlers, +// and so on. The supplied operations list completely replaces the window state +// from previous calls. func (w *Window) update(frame *op.Ops) { w.frames <- frame <-w.frameAck } -func (w *Window) validateAndProcess(driver wm.Driver, frameStart time.Time, size image.Point, sync bool, frame *op.Ops) error { +func (w *Window) validateAndProcess(d driver, frameStart time.Time, size image.Point, sync bool, frame *op.Ops) error { for { if w.loop != nil { if err := w.loop.Flush(); err != nil { w.destroyGPU() - if err == wm.ErrDeviceLost { + if err == errDeviceLost { continue } return err @@ -145,8 +143,8 @@ func (w *Window) validateAndProcess(driver wm.Driver, frameStart time.Time, size if w.loop == nil && !w.nocontext { var err error if w.ctx == nil { - w.driverRun(func(_ wm.Driver) { - w.ctx, err = driver.NewContext() + w.driverRun(func(_ driver) { + w.ctx, err = d.NewContext() }) if err != nil { return err @@ -160,7 +158,7 @@ func (w *Window) validateAndProcess(driver wm.Driver, frameStart time.Time, size } } if sync && w.ctx != nil { - w.driverRun(func(_ wm.Driver) { + w.driverRun(func(_ driver) { w.ctx.Refresh() }) } @@ -168,7 +166,7 @@ func (w *Window) validateAndProcess(driver wm.Driver, frameStart time.Time, size if sync && w.loop != nil { if err := w.loop.Flush(); err != nil { w.destroyGPU() - if err == wm.ErrDeviceLost { + if err == errDeviceLost { continue } return err @@ -190,12 +188,12 @@ func (w *Window) processFrame(frameStart time.Time, size image.Point, frame *op. w.queue.q.Frame(frame) switch w.queue.q.TextInputState() { case router.TextInputOpen: - go w.driverRun(func(d wm.Driver) { d.ShowTextInput(true) }) + go w.driverRun(func(d driver) { d.ShowTextInput(true) }) case router.TextInputClose: - go w.driverRun(func(d wm.Driver) { d.ShowTextInput(false) }) + go w.driverRun(func(d driver) { d.ShowTextInput(false) }) } if hint, ok := w.queue.q.TextInputHint(); ok { - go w.driverRun(func(d wm.Driver) { d.SetInputHint(hint) }) + go w.driverRun(func(d driver) { d.SetInputHint(hint) }) } if txt, ok := w.queue.q.WriteClipboard(); ok { go w.WriteClipboard(txt) @@ -242,12 +240,12 @@ func (w *Window) Invalidate() { // Option applies the options to the window. func (w *Window) Option(opts ...Option) { - go w.driverRun(func(d wm.Driver) { - o := new(wm.Options) + go w.driverRun(func(d driver) { + c := new(config) for _, opt := range opts { - opt(o) + opt(c) } - d.Option(o) + d.Configure(c) }) } @@ -255,32 +253,32 @@ func (w *Window) Option(opts ...Option) { // of a clipboard.Event. Multiple reads may be coalesced // to a single event. func (w *Window) ReadClipboard() { - go w.driverRun(func(d wm.Driver) { + go w.driverRun(func(d driver) { d.ReadClipboard() }) } // WriteClipboard writes a string to the clipboard. func (w *Window) WriteClipboard(s string) { - go w.driverRun(func(d wm.Driver) { + go w.driverRun(func(d driver) { d.WriteClipboard(s) }) } // SetCursorName changes the current window cursor to name. func (w *Window) SetCursorName(name pointer.CursorName) { - go w.driverRun(func(d wm.Driver) { + go w.driverRun(func(d driver) { d.SetCursor(name) }) } -// Close the wm. The window's event loop should exit when it receives +// Close the window. The window's event loop should exit when it receives // system.DestroyEvent. // // Currently, only macOS, Windows and X11 drivers implement this functionality, // all others are stubbed. func (w *Window) Close() { - go w.driverRun(func(d wm.Driver) { + go w.driverRun(func(d driver) { d.Close() }) } @@ -294,14 +292,14 @@ func (w *Window) Close() { // Note that most programs should not call Run; configuring a Window with // CustomRenderer is a notable exception. func (w *Window) Run(f func()) { - w.driverRun(func(_ wm.Driver) { + w.driverRun(func(_ driver) { f() }) } -func (w *Window) driverRun(f func(d wm.Driver)) { +func (w *Window) driverRun(f func(d driver)) { done := make(chan struct{}) - wrapper := func(d wm.Driver) { + wrapper := func(d driver) { defer close(done) f(d) } @@ -353,7 +351,7 @@ func (w *Window) setNextFrame(at time.Time) { } } -func (c *callbacks) SetDriver(d wm.Driver) { +func (c *callbacks) SetDriver(d driver) { c.d = d c.Event(driverEvent{d}) } @@ -366,7 +364,7 @@ func (c *callbacks) Event(e event.Event) { } } -func (w *Window) runFuncs(d wm.Driver) { +func (w *Window) runFuncs(d driver) { // Don't run driver functions if there's no driver. if d == nil { <-w.ack @@ -446,14 +444,14 @@ func (w *Window) waitFrame() (*op.Ops, bool) { } } -func (w *Window) run(opts *wm.Options) { +func (w *Window) run(cnf *config) { defer close(w.out) defer close(w.dead) - if err := wm.NewWindow(&w.callbacks, opts); err != nil { + if err := newWindow(&w.callbacks, cnf); err != nil { w.out <- system.DestroyEvent{Err: err} return } - var driver wm.Driver + var driver driver for { var wakeups chan struct{} if driver != nil { @@ -487,7 +485,7 @@ func (w *Window) run(opts *wm.Options) { w.updateAnimation() w.out <- e w.waitAck() - case wm.FrameEvent: + case frameEvent: if e2.Size == (image.Point{}) { panic(errors.New("internal error: zero-sized Draw")) } @@ -525,7 +523,7 @@ func (w *Window) run(opts *wm.Options) { case ViewEvent: w.out <- e2 w.waitAck() - case wm.WakeupEvent: + case wakeupEvent: case event.Event: if w.queue.q.Queue(e2) { w.setNextFrame(time.Time{}) @@ -552,42 +550,42 @@ func (q *queue) Events(k event.Tag) []event.Event { var ( // Windowed is the normal window mode with OS specific window decorations. - Windowed Option = windowMode(wm.Windowed) + Windowed Option = modeOption(windowed) // Fullscreen is the full screen window mode. - Fullscreen Option = windowMode(wm.Fullscreen) + Fullscreen Option = modeOption(fullscreen) ) -// windowMode sets the window mode. +// WindowMode sets the window mode. // // Supported platforms are macOS, X11, Windows and JS. -func windowMode(mode wm.WindowMode) Option { - return func(opts *wm.Options) { - opts.WindowMode = &mode +func modeOption(mode windowMode) Option { + return func(cnf *config) { + cnf.WindowMode = &mode } } var ( // AnyOrientation allows the window to be freely orientated. - AnyOrientation Option = orientation(wm.AnyOrientation) + AnyOrientation Option = orientationOption(anyOrientation) // LandscapeOrientation constrains the window to landscape orientations. - LandscapeOrientation Option = orientation(wm.LandscapeOrientation) + LandscapeOrientation Option = orientationOption(landscapeOrientation) // PortraitOrientation constrains the window to portrait orientations. - PortraitOrientation Option = orientation(wm.PortraitOrientation) + PortraitOrientation Option = orientationOption(portraitOrientation) ) // orientation sets the orientation of the app. // // Supported platforms are Android and JS. -func orientation(mode wm.Orientation) Option { - return func(opts *wm.Options) { - opts.Orientation = &mode +func orientationOption(mode orientation) Option { + return func(cnf *config) { + cnf.Orientation = &mode } } // Title sets the title of the window. func Title(t string) Option { - return func(opts *wm.Options) { - opts.Title = &t + return func(cnf *config) { + cnf.Title = &t } } @@ -599,8 +597,8 @@ func Size(w, h unit.Value) Option { if h.V <= 0 { panic("height must be larger than or equal to 0") } - return func(opts *wm.Options) { - opts.Size = &wm.Size{ + return func(cnf *config) { + cnf.Size = &size{ Width: w, Height: h, } @@ -615,8 +613,8 @@ func MaxSize(w, h unit.Value) Option { if h.V <= 0 { panic("height must be larger than or equal to 0") } - return func(opts *wm.Options) { - opts.MaxSize = &wm.Size{ + return func(cnf *config) { + cnf.MaxSize = &size{ Width: w, Height: h, } @@ -631,8 +629,8 @@ func MinSize(w, h unit.Value) Option { if h.V <= 0 { panic("height must be larger than or equal to 0") } - return func(opts *wm.Options) { - opts.MinSize = &wm.Size{ + return func(cnf *config) { + cnf.MinSize = &size{ Width: w, Height: h, } @@ -641,23 +639,23 @@ func MinSize(w, h unit.Value) Option { // StatusColor sets the color of the Android status bar. func StatusColor(color color.NRGBA) Option { - return func(opts *wm.Options) { - opts.StatusColor = &color + return func(cnf *config) { + cnf.StatusColor = &color } } // NavigationColor sets the color of the navigation bar on Android, or the address bar in browsers. func NavigationColor(color color.NRGBA) Option { - return func(opts *wm.Options) { - opts.NavigationColor = &color + return func(cnf *config) { + cnf.NavigationColor = &color } } // CustomRenderer controls whether the the window contents is // rendered by the client. If true, no GPU context is created. func CustomRenderer(custom bool) Option { - return func(opts *wm.Options) { - opts.CustomRenderer = custom + return func(cnf *config) { + cnf.CustomRenderer = custom } } diff --git a/cmd/gogio/androidbuild.go b/cmd/gogio/androidbuild.go index b937c5b6..87486669 100644 --- a/cmd/gogio/androidbuild.go +++ b/cmd/gogio/androidbuild.go @@ -240,7 +240,7 @@ func compileAndroid(tmpDir string, tools *androidTools, bi *buildInfo) (err erro return err }) } - appDir, err := runCmd(exec.Command("go", "list", "-f", "{{.Dir}}", "gioui.org/app/internal/wm")) + appDir, err := runCmd(exec.Command("go", "list", "-f", "{{.Dir}}", "gioui.org/app/")) if err != nil { return err } diff --git a/cmd/gogio/iosbuild.go b/cmd/gogio/iosbuild.go index 858b5697..b75e43cc 100644 --- a/cmd/gogio/iosbuild.go +++ b/cmd/gogio/iosbuild.go @@ -464,7 +464,7 @@ func archiveIOS(tmpDir, target, frameworkRoot string, bi *buildInfo) error { if _, err := runCmd(lipo); err != nil { return err } - appDir, err := runCmd(exec.Command("go", "list", "-f", "{{.Dir}}", "gioui.org/app/internal/wm")) + appDir, err := runCmd(exec.Command("go", "list", "-f", "{{.Dir}}", "gioui.org/app/")) if err != nil { return err }