Files
gio/app/internal/wm/window.go
T
Elias Naur 8611894b4b app,app/internal/wm: introduce app.Window.Run and use it internally
app.Window implements a method for safely running functions against the
underlying native window through the driverFuncs channel. However, the
functions still run in a different goroutine than the one driving the
native event loop, which forces the implementations in package wm to do
complicated synchronization.

A previous change added a mechanism to run functions in the native event
loop thread. The macOS port needed this functionality, but with some
care it can be generalized. That's what this change does through the
new Run method.

The advantage is that the thread switch dance is now confined to
app.Window, with the help of a generic wm.Driver.Wakeup method. All
other Driver methods can then assume they run on their event loop
threads.

Run is exported because it is also needed for programs that use
Windows configured with CustomRenderer to control their own rendering.

Signed-off-by: Elias Naur <mail@eliasnaur.com>
2021-05-18 19:59:01 +01:00

146 lines
2.8 KiB
Go

// SPDX-License-Identifier: Unlicense OR MIT
// package wm implements platform specific windows
// and GPU contexts.
package wm
import (
"errors"
"image/color"
"gioui.org/gpu"
"gioui.org/io/event"
"gioui.org/io/pointer"
"gioui.org/io/system"
"gioui.org/unit"
)
type Size struct {
Width unit.Value
Height unit.Value
}
type Options struct {
Size *Size
MinSize *Size
MaxSize *Size
Title *string
WindowMode *WindowMode
StatusColor *color.NRGBA
NavigationColor *color.NRGBA
Orientation *Orientation
CustomRenderer bool
}
type WakeupEvent struct{}
type WindowMode uint8
const (
Windowed WindowMode = iota
Fullscreen
)
type Orientation uint8
const (
AnyOrientation Orientation = iota
LandscapeOrientation
PortraitOrientation
)
type FrameEvent struct {
system.FrameEvent
Sync bool
}
type Callbacks interface {
SetDriver(d Driver)
Event(e event.Event)
// Func runs a function during an Event. This is required for platforms
// that require coordination between the rendering goroutine and the system
// main thread.
Run(f func())
}
type Context interface {
API() gpu.API
Present() error
MakeCurrent() error
Release()
Lock()
Unlock()
}
// ErrDeviceLost is returned from Context.Present when
// the underlying GPU device is gone and should be
// recreated.
var ErrDeviceLost = errors.New("GPU device lost")
// Driver is the interface for the platform implementation
// of a window.
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)
// ShowTextInput updates the virtual keyboard state.
ShowTextInput(show bool)
NewContext() (Context, error)
// ReadClipboard requests the clipboard content.
ReadClipboard()
// WriteClipboard requests a clipboard write.
WriteClipboard(s string)
// Option processes option changes.
Option(opts *Options)
// SetCursor updates the current cursor to name.
SetCursor(name pointer.CursorName)
// Close the window.
Close()
// Wakeup wakes up the event loop and sends a WakeupEvent.
Wakeup()
}
type windowRendezvous struct {
in chan windowAndOptions
out chan windowAndOptions
errs chan error
}
type windowAndOptions struct {
window Callbacks
opts *Options
}
func newWindowRendezvous() *windowRendezvous {
wr := &windowRendezvous{
in: make(chan windowAndOptions),
out: make(chan windowAndOptions),
errs: make(chan error),
}
go func() {
var main windowAndOptions
var out chan windowAndOptions
for {
select {
case w := <-wr.in:
var err error
if main.window != nil {
err = errors.New("multiple windows are not supported")
}
wr.errs <- err
main = w
out = wr.out
case out <- main:
}
}
}()
return wr
}
func (_ WakeupEvent) ImplementsEvent() {}