@@ -12,7 +12,6 @@ import (
12
12
13
13
"github.com/go-flutter-desktop/go-flutter/embedder"
14
14
"github.com/go-flutter-desktop/go-flutter/internal/execpath"
15
- "github.com/go-flutter-desktop/go-flutter/internal/tasker"
16
15
)
17
16
18
17
// Run executes a flutter application with the provided options.
@@ -105,7 +104,7 @@ func (a *Application) Run() error {
105
104
glfw .WindowHint (glfw .OpenGLProfile , glfw .OpenGLCoreProfile )
106
105
glfw .WindowHint (glfw .OpenGLForwardCompatible , glfw .True )
107
106
108
- if a .config .windowInitialLocations .xpos != 0 {
107
+ if a .config .windowInitialLocation .xpos != 0 {
109
108
// To create the window at a specific position, make it initially invisible
110
109
// using the Visible window hint, set its position and then show it.
111
110
glfw .WindowHint (glfw .Visible , glfw .False )
@@ -115,12 +114,11 @@ func (a *Application) Run() error {
115
114
if err != nil {
116
115
return errors .Wrap (err , "creating glfw window" )
117
116
}
118
- glfw .DefaultWindowHints ()
119
117
defer a .window .Destroy ()
118
+ glfw .DefaultWindowHints ()
120
119
121
- if a .config .windowInitialLocations .xpos != 0 {
122
- a .window .SetPos (a .config .windowInitialLocations .xpos ,
123
- a .config .windowInitialLocations .ypos )
120
+ if a .config .windowInitialLocation .xpos != 0 {
121
+ a .window .SetPos (a .config .windowInitialLocation .xpos , a .config .windowInitialLocation .ypos )
124
122
a .window .Show ()
125
123
}
126
124
@@ -157,6 +155,7 @@ func (a *Application) Run() error {
157
155
158
156
a .engine = embedder .NewFlutterEngine ()
159
157
158
+ // Create a messenger and init plugins
160
159
messenger := newMessenger (a .engine )
161
160
for _ , p := range a .config .plugins {
162
161
err = p .InitPlugin (messenger )
@@ -173,6 +172,16 @@ func (a *Application) Run() error {
173
172
}
174
173
}
175
174
175
+ // Create a TextureRegistry
176
+ texturer := newTextureRegistry (a .engine , a .window )
177
+
178
+ // Create a new eventloop
179
+ eventLoop := newEventLoop (
180
+ glfw .PostEmptyEvent , // Wakeup GLFW
181
+ a .engine .RunTask , // Flush tasks
182
+ )
183
+
184
+ // Set configuration values to engine, with fallbacks to sane defaults.
176
185
if a .config .flutterAssetsPath != "" {
177
186
a .engine .AssetsPath = a .config .flutterAssetsPath
178
187
} else {
@@ -182,7 +191,6 @@ func (a *Application) Run() error {
182
191
}
183
192
a .engine .AssetsPath = filepath .Join (filepath .Dir (execPath ), "flutter_assets" )
184
193
}
185
-
186
194
if a .config .icuDataPath != "" {
187
195
a .engine .IcuDataPath = a .config .icuDataPath
188
196
} else {
@@ -193,7 +201,7 @@ func (a *Application) Run() error {
193
201
a .engine .IcuDataPath = filepath .Join (filepath .Dir (execPath ), "icudtl.dat" )
194
202
}
195
203
196
- // Render callbacks
204
+ // Attach GL callback functions onto the engine
197
205
a .engine .GLMakeCurrent = func () bool {
198
206
a .window .MakeContextCurrent ()
199
207
return true
@@ -219,31 +227,36 @@ func (a *Application) Run() error {
219
227
a .engine .GLProcResolver = func (procName string ) unsafe.Pointer {
220
228
return glfw .GetProcAddress (procName )
221
229
}
230
+ a .engine .GLExternalTextureFrameCallback = texturer .handleExternalTexture
222
231
223
- eventLoop := newEventLoop (
224
- glfw .PostEmptyEvent , // Wakeup GLFW
225
- a .engine .RunTask , // Flush tasks
226
- )
232
+ // Attach TaskRunner callback functions onto the engine
227
233
a .engine .TaskRunnerRunOnCurrentThread = eventLoop .RunOnCurrentThread
228
234
a .engine .TaskRunnerPostTask = eventLoop .PostTask
229
235
236
+ // Attach PlatformMessage callback functions onto the engine
230
237
a .engine .PlatfromMessage = messenger .handlePlatformMessage
231
238
232
- texturer := newRegistry (a .engine , a .window )
233
- a .engine .GLExternalTextureFrameCallback = texturer .handleExternalTexture
234
-
235
- texturer .init ()
239
+ // Initialize the texturer
240
+ err = texturer .init ()
241
+ if err != nil {
242
+ fmt .Printf ("go-fluter: Failed to init TextureRegistry: %v\n " , err )
243
+ os .Exit (1 )
244
+ }
236
245
237
246
// Not very nice, but we can only really fix this when there's a pluggable
238
247
// renderer.
239
248
defaultTextinputPlugin .keyboardLayout = a .config .keyboardLayout
240
249
250
+ // Set the glfw window user pointer to point to the FlutterEngine so that
251
+ // callback functions may obtain the FlutterEngine from the glfw window
252
+ // user pointer.
241
253
flutterEnginePointer := uintptr (unsafe .Pointer (a .engine ))
242
254
defer func () {
243
255
runtime .KeepAlive (flutterEnginePointer )
244
256
}()
245
257
a .window .SetUserPointer (unsafe .Pointer (& flutterEnginePointer ))
246
258
259
+ // Start the engine
247
260
result := a .engine .Run (unsafe .Pointer (& flutterEnginePointer ), a .config .vmArguments )
248
261
if result != embedder .ResultSuccess {
249
262
switch result {
@@ -257,40 +270,48 @@ func (a *Application) Run() error {
257
270
os .Exit (1 )
258
271
}
259
272
260
- defaultPlatformPlugin . glfwTasker = tasker . New ()
261
-
262
- m := newWindowManager ()
263
- m . forcedPixelRatio = a . config . forcePixelRatio
264
-
265
- m . glfwRefreshCallback ( a . window )
266
- a .window .SetRefreshCallback (m .glfwRefreshCallback )
267
- a .window .SetPosCallback (m .glfwPosCallback )
273
+ // Setup a new windowManager to handle windows pixel ratio's and pointer
274
+ // devices.
275
+ windowManager := newWindowManager (a . config . forcePixelRatio )
276
+ // force first refresh
277
+ windowManager . glfwRefreshCallback ( a . window )
278
+ // Attach glfw window callbacks for refresh and position changes
279
+ a .window .SetRefreshCallback (windowManager .glfwRefreshCallback )
280
+ a .window .SetPosCallback (windowManager .glfwPosCallback )
268
281
282
+ // TODO: Can this only be done here? Why not in the plugin/glfwPlugin init loop above?
269
283
for _ , p := range a .config .plugins {
270
284
// Extra init call for plugins that satisfy the PluginTexture interface.
271
- if glfwPlugin , ok := p .(PluginTexture ); ok {
272
- err = glfwPlugin .InitPluginTexture (texturer )
285
+ if texturePlugin , ok := p .(PluginTexture ); ok {
286
+ err = texturePlugin .InitPluginTexture (texturer )
273
287
if err != nil {
274
288
return errors .Wrap (err , "failed to initialize texture plugin" + fmt .Sprintf ("%T" , p ))
275
289
}
276
290
}
277
291
}
278
292
293
+ // Attach glfw window callbacks for text input
279
294
a .window .SetKeyCallback (
280
295
func (window * glfw.Window , key glfw.Key , scancode int , action glfw.Action , mods glfw.ModifierKey ) {
281
296
defaultTextinputPlugin .glfwKeyCallback (window , key , scancode , action , mods )
282
297
defaultKeyeventsPlugin .sendKeyEvent (window , key , scancode , action , mods )
283
298
})
284
299
a .window .SetCharCallback (defaultTextinputPlugin .glfwCharCallback )
285
300
301
+ // Attach glfw window callback for iconification
286
302
a .window .SetIconifyCallback (defaultLifecyclePlugin .glfwIconifyCallback )
287
303
288
- a .window .SetCursorEnterCallback (m .glfwCursorEnterCallback )
289
- a .window .SetCursorPosCallback (m .glfwCursorPosCallback )
290
- a .window .SetMouseButtonCallback (m .glfwMouseButtonCallback )
291
- a .window .SetScrollCallback (m .glfwScrollCallback )
304
+ // Attach glfw window callbacks for mouse input
305
+ a .window .SetCursorEnterCallback (windowManager .glfwCursorEnterCallback )
306
+ a .window .SetCursorPosCallback (windowManager .glfwCursorPosCallback )
307
+ a .window .SetMouseButtonCallback (windowManager .glfwMouseButtonCallback )
308
+ a .window .SetScrollCallback (windowManager .glfwScrollCallback )
309
+
310
+ // Shutdown the engine if we return from this function (on purpose or panic)
292
311
defer a .engine .Shutdown ()
293
312
313
+ // Handle events until the window indicates we should stop. An event may tell the window to stop, in which case
314
+ // we'll exit on next iteration.
294
315
for ! a .window .ShouldClose () {
295
316
eventLoop .WaitForEvents (func (duration float64 ) {
296
317
glfw .WaitEventsTimeout (duration )
@@ -299,6 +320,9 @@ func (a *Application) Run() error {
299
320
messenger .engineTasker .ExecuteTasks ()
300
321
}
301
322
323
+ // TODO: What if the window indicates to stop, but there are tasks left on
324
+ // the queue?
325
+
302
326
fmt .Println ("go-flutter: closing application" )
303
327
304
328
return nil
0 commit comments