mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
app: merge app/internal/wm into package app
The app and app/internal/wm packages are tightly coupled, requiring quite a bit of forwarding types, values and constants from the internal package to export it. Further, no other package imports package wm. This change merges the two packages. While here, drop the pre-Go 1.14 SIGPIPE workaround. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+1
-9
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
package wm
|
||||
package app
|
||||
|
||||
/*
|
||||
#include <android/native_window_jni.h>
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -3,7 +3,7 @@
|
||||
//go:build darwin && ios && nometal
|
||||
// +build darwin,ios,nometal
|
||||
|
||||
package wm
|
||||
package app
|
||||
|
||||
/*
|
||||
@import UIKit;
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
+3
-4
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
//go:build !nometal
|
||||
// +build !nometal
|
||||
|
||||
package wm
|
||||
package app
|
||||
|
||||
/*
|
||||
#cgo CFLAGS: -Werror -xobjective-c -fmodules -fobjc-arc
|
||||
@@ -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
|
||||
@@ -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() {}
|
||||
@@ -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)
|
||||
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
package wm
|
||||
package app
|
||||
|
||||
/*
|
||||
#include <Foundation/Foundation.h>
|
||||
@@ -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{})
|
||||
})
|
||||
}
|
||||
@@ -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
|
||||
@@ -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 {}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -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{
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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)
|
||||
}
|
||||
+70
-72
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user