Skip to content

Adds comments and renames internals. Also some re-ordering of init code. #235

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Aug 18, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 48 additions & 29 deletions application.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (

"github.com/go-flutter-desktop/go-flutter/embedder"
"github.com/go-flutter-desktop/go-flutter/internal/execpath"
"github.com/go-flutter-desktop/go-flutter/internal/tasker"
)

// Run executes a flutter application with the provided options.
Expand Down Expand Up @@ -105,7 +104,7 @@ func (a *Application) Run() error {
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)

if a.config.windowInitialLocations.xpos != 0 {
if a.config.windowInitialLocation.xpos != 0 {
// To create the window at a specific position, make it initially invisible
// using the Visible window hint, set its position and then show it.
glfw.WindowHint(glfw.Visible, glfw.False)
Expand All @@ -115,12 +114,11 @@ func (a *Application) Run() error {
if err != nil {
return errors.Wrap(err, "creating glfw window")
}
glfw.DefaultWindowHints()
defer a.window.Destroy()
glfw.DefaultWindowHints()

if a.config.windowInitialLocations.xpos != 0 {
a.window.SetPos(a.config.windowInitialLocations.xpos,
a.config.windowInitialLocations.ypos)
if a.config.windowInitialLocation.xpos != 0 {
a.window.SetPos(a.config.windowInitialLocation.xpos, a.config.windowInitialLocation.ypos)
a.window.Show()
}

Expand Down Expand Up @@ -157,6 +155,7 @@ func (a *Application) Run() error {

a.engine = embedder.NewFlutterEngine()

// Create a messenger and init plugins
messenger := newMessenger(a.engine)
for _, p := range a.config.plugins {
err = p.InitPlugin(messenger)
Expand All @@ -173,6 +172,16 @@ func (a *Application) Run() error {
}
}

// Create a TextureRegistry
texturer := newTextureRegistry(a.engine, a.window)

// Create a new eventloop
eventLoop := newEventLoop(
glfw.PostEmptyEvent, // Wakeup GLFW
a.engine.RunTask, // Flush tasks
)

// Set configuration values to engine, with fallbacks to sane defaults.
if a.config.flutterAssetsPath != "" {
a.engine.AssetsPath = a.config.flutterAssetsPath
} else {
Expand All @@ -182,7 +191,6 @@ func (a *Application) Run() error {
}
a.engine.AssetsPath = filepath.Join(filepath.Dir(execPath), "flutter_assets")
}

if a.config.icuDataPath != "" {
a.engine.IcuDataPath = a.config.icuDataPath
} else {
Expand All @@ -193,7 +201,7 @@ func (a *Application) Run() error {
a.engine.IcuDataPath = filepath.Join(filepath.Dir(execPath), "icudtl.dat")
}

// Render callbacks
// Attach GL callback functions onto the engine
a.engine.GLMakeCurrent = func() bool {
a.window.MakeContextCurrent()
return true
Expand All @@ -219,29 +227,29 @@ func (a *Application) Run() error {
a.engine.GLProcResolver = func(procName string) unsafe.Pointer {
return glfw.GetProcAddress(procName)
}
a.engine.GLExternalTextureFrameCallback = texturer.handleExternalTexture

eventLoop := newEventLoop(
glfw.PostEmptyEvent, // Wakeup GLFW
a.engine.RunTask, // Flush tasks
)
// Attach TaskRunner callback functions onto the engine
a.engine.TaskRunnerRunOnCurrentThread = eventLoop.RunOnCurrentThread
a.engine.TaskRunnerPostTask = eventLoop.PostTask

// Attach PlatformMessage callback functions onto the engine
a.engine.PlatfromMessage = messenger.handlePlatformMessage

texturer := newRegistry(a.engine, a.window)
a.engine.GLExternalTextureFrameCallback = texturer.handleExternalTexture

// Not very nice, but we can only really fix this when there's a pluggable
// renderer.
defaultTextinputPlugin.keyboardLayout = a.config.keyboardLayout

// Set the glfw window user pointer to point to the FlutterEngine so that
// callback functions may obtain the FlutterEngine from the glfw window
// user pointer.
flutterEnginePointer := uintptr(unsafe.Pointer(a.engine))
defer func() {
runtime.KeepAlive(flutterEnginePointer)
}()
a.window.SetUserPointer(unsafe.Pointer(&flutterEnginePointer))

// Start the engine
result := a.engine.Run(unsafe.Pointer(&flutterEnginePointer), a.config.vmArguments)
if result != embedder.ResultSuccess {
switch result {
Expand All @@ -255,40 +263,48 @@ func (a *Application) Run() error {
os.Exit(1)
}

defaultPlatformPlugin.glfwTasker = tasker.New()

m := newWindowManager()
m.forcedPixelRatio = a.config.forcePixelRatio

m.glfwRefreshCallback(a.window)
a.window.SetRefreshCallback(m.glfwRefreshCallback)
a.window.SetPosCallback(m.glfwPosCallback)
// Setup a new windowManager to handle windows pixel ratio's and pointer
// devices.
windowManager := newWindowManager(a.config.forcePixelRatio)
// force first refresh
windowManager.glfwRefreshCallback(a.window)
// Attach glfw window callbacks for refresh and position changes
a.window.SetRefreshCallback(windowManager.glfwRefreshCallback)
a.window.SetPosCallback(windowManager.glfwPosCallback)

// TODO: Can this only be done here? Why not in the plugin/glfwPlugin init loop above?
for _, p := range a.config.plugins {
// Extra init call for plugins that satisfy the PluginTexture interface.
if glfwPlugin, ok := p.(PluginTexture); ok {
err = glfwPlugin.InitPluginTexture(texturer)
if texturePlugin, ok := p.(PluginTexture); ok {
err = texturePlugin.InitPluginTexture(texturer)
if err != nil {
return errors.Wrap(err, "failed to initialize texture plugin"+fmt.Sprintf("%T", p))
}
}
}

// Attach glfw window callbacks for text input
a.window.SetKeyCallback(
func(window *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
defaultTextinputPlugin.glfwKeyCallback(window, key, scancode, action, mods)
defaultKeyeventsPlugin.sendKeyEvent(window, key, scancode, action, mods)
})
a.window.SetCharCallback(defaultTextinputPlugin.glfwCharCallback)

// Attach glfw window callback for iconification
a.window.SetIconifyCallback(defaultLifecyclePlugin.glfwIconifyCallback)

a.window.SetCursorEnterCallback(m.glfwCursorEnterCallback)
a.window.SetCursorPosCallback(m.glfwCursorPosCallback)
a.window.SetMouseButtonCallback(m.glfwMouseButtonCallback)
a.window.SetScrollCallback(m.glfwScrollCallback)
// Attach glfw window callbacks for mouse input
a.window.SetCursorEnterCallback(windowManager.glfwCursorEnterCallback)
a.window.SetCursorPosCallback(windowManager.glfwCursorPosCallback)
a.window.SetMouseButtonCallback(windowManager.glfwMouseButtonCallback)
a.window.SetScrollCallback(windowManager.glfwScrollCallback)

// Shutdown the engine if we return from this function (on purpose or panic)
defer a.engine.Shutdown()

// Handle events until the window indicates we should stop. An event may tell the window to stop, in which case
// we'll exit on next iteration.
for !a.window.ShouldClose() {
eventLoop.WaitForEvents(func(duration float64) {
glfw.WaitEventsTimeout(duration)
Expand All @@ -297,6 +313,9 @@ func (a *Application) Run() error {
messenger.engineTasker.ExecuteTasks()
}

// TODO: What if the window indicates to stop, but there are tasks left on
// the queue?

fmt.Println("go-flutter: closing application")

return nil
Expand Down
6 changes: 4 additions & 2 deletions embedder/embedder_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,13 @@ func proxy_gl_proc_resolver(userData unsafe.Pointer, procname *C.char) unsafe.Po
}

//export proxy_gl_external_texture_frame_callback
func proxy_gl_external_texture_frame_callback(userData unsafe.Pointer,
func proxy_gl_external_texture_frame_callback(
userData unsafe.Pointer,
textureID int64,
width C.size_t,
height C.size_t,
texture *C.FlutterOpenGLTexture) C.bool {
texture *C.FlutterOpenGLTexture,
) C.bool {
flutterEnginePointer := *(*uintptr)(userData)
flutterEngine := (*FlutterEngine)(unsafe.Pointer(flutterEnginePointer))
embedderGLTexture := flutterEngine.GLExternalTextureFrameCallback(textureID, int(width), int(height))
Expand Down
20 changes: 14 additions & 6 deletions glfw.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,24 @@ const dpPerInch = 160.0
// glfwRenderer or glfwManager? All the attaching to glfw.Window must be done
// during manager init in that case. Cannot be done by Application.
type windowManager struct {
forcedPixelRatio float64
oncePrintPixelRatioLimit sync.Once
pointerPhase embedder.PointerPhase
// forcedPixelRatio forces the pixelRatio to given value, when value is not zero.
forcedPixelRatio float64

// sync.Once to limit pixelRatio warning messages.
oncePrintPixelRatioLimit sync.Once

// current pointer state
pointerPhase embedder.PointerPhase
pointerButton embedder.PointerButtonMouse
pointerCurrentlyAdded bool

// caching of ppsc to avoid re-calculating every event
pixelsPerScreenCoordinate float64
pointerCurrentlyAdded bool
pointerButton embedder.PointerButtonMouse
}

func newWindowManager() *windowManager {
func newWindowManager(forcedPixelRatio float64) *windowManager {
return &windowManager{
forcedPixelRatio: forcedPixelRatio,
pixelsPerScreenCoordinate: 1.0,
pointerPhase: embedder.PointerPhaseHover,
}
Expand Down
25 changes: 18 additions & 7 deletions option.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ type config struct {
windowInitializerDeprecated func(*glfw.Window) error
windowIconProvider func() ([]image.Image, error)
windowInitialDimensions windowDimensions
windowInitialLocations windowLocations
windowInitialLocation windowLocation
windowDimensionLimits windowDimensionLimits
windowMode windowMode

Expand All @@ -31,7 +31,7 @@ type windowDimensions struct {
height int
}

type windowLocations struct {
type windowLocation struct {
xpos int
ypos int
}
Expand Down Expand Up @@ -102,8 +102,8 @@ func OptionVMArguments(a []string) Option {
//
// Deprecated, please use WindowInitialDimensions(x, y).
func ApplicationWindowDimension(x, y int) Option {
// deprecated on 2019-03-10
fmt.Println("go-flutter: ApplicationWindowDimension is deprecated, use WindowInitialDimensions(x, y).")
// deprecated on 2019-03-10, to be removed 2020-01-01
fmt.Println("go-flutter: ApplicationWindowDimension (singular) is deprecated, use WindowInitialDimensions (plural).")
return WindowInitialDimensions(x, y)
}

Expand All @@ -127,7 +127,18 @@ func WindowInitialDimensions(width, height int) Option {
// WindowInitialLocations specify the startup's position of the window.
// Location, in screen coordinates, of the upper-left corner of the client area
// of the window.
//
// Deprecated, please use WindowInitialLocation(xpos, ypos).
func WindowInitialLocations(xpos, ypos int) Option {
// deprecated on 2019-08-18, to be removed 2020-06-01
fmt.Println("go-flutter: WindowInitialLocations (plural) is deprecated, use WindowInitialLocation (singular).")
return WindowInitialLocation(xpos, ypos)
}

// WindowInitialLocation specify the startup's position of the window.
// Location, in screen coordinates, of the upper-left corner of the client area
// of the window.
func WindowInitialLocation(xpos, ypos int) Option {
if xpos < 1 {
fmt.Println("go-flutter: invalid initial value for xpos location, must be 1 or greater.")
os.Exit(1)
Expand All @@ -138,8 +149,8 @@ func WindowInitialLocations(xpos, ypos int) Option {
}

return func(c *config) {
c.windowInitialLocations.xpos = xpos
c.windowInitialLocations.ypos = ypos
c.windowInitialLocation.xpos = xpos
c.windowInitialLocation.ypos = ypos
}
}

Expand Down Expand Up @@ -175,7 +186,7 @@ func WindowDimensionLimits(minWidth, minHeight, maxWidth, maxHeight int) Option
//
// Deprecated, please use WindowIcon if you'd like to set the window icon.
func OptionWindowInitializer(ini func(*glfw.Window) error) Option {
// deprecated on 2019-03-05
// deprecated on 2019-03-05, to be removed 2020-01-01
fmt.Println("go-flutter: OptionWindowInitializer is deprecated. Please read https://is.gd/gflut_window_init_deprecated")
return func(c *config) {
c.windowInitializerDeprecated = ini
Expand Down
1 change: 1 addition & 0 deletions platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var _ PluginGLFW = &platformPlugin{} // compile-time type check

func (p *platformPlugin) InitPlugin(messenger plugin.BinaryMessenger) error {
p.messenger = messenger
p.glfwTasker = tasker.New()
return nil
}

Expand Down
4 changes: 2 additions & 2 deletions texture-registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type externalTextureHanlder struct {
texture uint32
}

func newRegistry(engine *embedder.FlutterEngine, window *glfw.Window) *TextureRegistry {
func newTextureRegistry(engine *embedder.FlutterEngine, window *glfw.Window) *TextureRegistry {
return &TextureRegistry{
window: window,
engine: engine,
Expand All @@ -45,7 +45,7 @@ func (t *TextureRegistry) init() error {
// Important! Call gl.Init only under the presence of an active OpenGL context,
// i.e., after MakeContextCurrent.
if err := gl.Init(); err != nil {
return errors.Wrap(err, "TextureRegistry gl init")
return errors.Wrap(err, "TextureRegistry gl init failed")
}
return nil
}
Expand Down