11
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
// See the License for the specific language governing permissions and
13
13
// limitations under the License.
14
- #include < flutter_desktop_embedding/linux/embedder.h>
15
14
16
- #include < X11/Xlib.h>
17
- #include < assert.h>
18
- #include < gtk/gtk.h>
15
+ #include " library/include/flutter_desktop_embedding/glfw/embedder.h"
19
16
17
+ #include < assert.h>
20
18
#include < algorithm>
21
19
#include < chrono>
22
20
#include < cstdlib>
23
21
#include < iostream>
24
- #include < memory>
25
- #include < string>
26
22
27
23
#include < flutter_embedder.h>
28
24
31
27
#include " library/common/glfw/text_input_plugin.h"
32
28
#include " library/common/internal/plugin_handler.h"
33
29
30
+ #ifdef __linux__
31
+ // For plugin-compatible event handling (e.g., modal windows).
32
+ #include < X11/Xlib.h>
33
+ #include < gtk/gtk.h>
34
+ #endif
35
+
34
36
// GLFW_TRUE & GLFW_FALSE are introduced since libglfw-3.3,
35
37
// add definitions here to compile under the old versions.
36
38
#ifndef GLFW_TRUE
@@ -51,67 +53,22 @@ struct FlutterEmbedderState {
51
53
// deleted from the heap.
52
54
std::vector<flutter_desktop_embedding::KeyboardHookHandler *>
53
55
keyboard_hook_handlers;
56
+
54
57
// Handles raw key interactions from GLFW.
55
- // TODO: Move key_event_handler once
56
- // https://github.com/google/flutter-desktop-embedding/issues/102 is resolved.
58
+ // TODO: Revisit ownership model once Issue #102 is resolved.
57
59
std::unique_ptr<flutter_desktop_embedding::KeyEventHandler> key_event_handler;
58
60
};
59
61
60
62
static constexpr char kDefaultWindowTitle [] = " Flutter" ;
61
63
62
- // Callback forward declarations.
63
- static void GLFWKeyCallback (GLFWwindow *window, int key, int scancode,
64
- int action, int mods);
65
- static void GLFWCharCallback (GLFWwindow *window, unsigned int code_point);
66
- static void GLFWmouseButtonCallback (GLFWwindow *window, int key, int action,
67
- int mods);
68
-
64
+ // Retrieves state bag for the window in question from the GLFWWindow.
69
65
static FlutterEmbedderState *GetSavedEmbedderState (GLFWwindow *window) {
70
66
return reinterpret_cast <FlutterEmbedderState *>(
71
67
glfwGetWindowUserPointer (window));
72
68
}
73
69
74
- // Flushes event queue and then assigns default window callbacks.
75
- static void GLFWAssignEventCallbacks (GLFWwindow *window) {
76
- glfwPollEvents ();
77
- glfwSetKeyCallback (window, GLFWKeyCallback);
78
- glfwSetCharCallback (window, GLFWCharCallback);
79
- glfwSetMouseButtonCallback (window, GLFWmouseButtonCallback);
80
- }
81
-
82
- // Clears default window events.
83
- static void GLFWClearEventCallbacks (GLFWwindow *window) {
84
- glfwSetKeyCallback (window, nullptr );
85
- glfwSetCharCallback (window, nullptr );
86
- glfwSetMouseButtonCallback (window, nullptr );
87
- }
88
-
89
- static void GLFWwindowSizeCallback (GLFWwindow *window, int width, int height) {
90
- FlutterWindowMetricsEvent event = {};
91
- event.struct_size = sizeof (event);
92
- event.width = width;
93
- event.height = height;
94
- event.pixel_ratio = 1.0 ;
95
- auto state = GetSavedEmbedderState (window);
96
- FlutterEngineSendWindowMetricsEvent (state->engine , &event);
97
- }
98
-
99
- static void GLFWOnFlutterPlatformMessage (const FlutterPlatformMessage *message,
100
- void *user_data) {
101
- if (message->struct_size != sizeof (FlutterPlatformMessage)) {
102
- std::cerr << " Invalid message size received. Expected: "
103
- << sizeof (FlutterPlatformMessage) << " but received "
104
- << message->struct_size << std::endl;
105
- return ;
106
- }
107
-
108
- GLFWwindow *window = reinterpret_cast <GLFWwindow *>(user_data);
109
- auto state = GetSavedEmbedderState (window);
110
- state->plugin_handler ->HandleMethodCallMessage (
111
- message, [window] { GLFWClearEventCallbacks (window); },
112
- [window] { GLFWAssignEventCallbacks (window); });
113
- }
114
-
70
+ // When GLFW calls back to the window with a cursor position move, forwards to
71
+ // FlutterEngine as a pointer event with appropriate phase.
115
72
static void GLFWcursorPositionCallbackAtPhase (GLFWwindow *window,
116
73
FlutterPointerPhase phase,
117
74
double x, double y) {
@@ -124,14 +81,16 @@ static void GLFWcursorPositionCallbackAtPhase(GLFWwindow *window,
124
81
std::chrono::duration_cast<std::chrono::microseconds>(
125
82
std::chrono::high_resolution_clock::now ().time_since_epoch ())
126
83
.count ();
127
- auto state = GetSavedEmbedderState (window);
128
- FlutterEngineSendPointerEvent (state-> engine , &event, 1 );
84
+ FlutterEngineSendPointerEvent ( GetSavedEmbedderState (window)-> engine , &event,
85
+ 1 );
129
86
}
130
87
88
+ // Reports cursor move to the Flutter engine.
131
89
static void GLFWcursorPositionCallback (GLFWwindow *window, double x, double y) {
132
90
GLFWcursorPositionCallbackAtPhase (window, FlutterPointerPhase::kMove , x, y);
133
91
}
134
92
93
+ // Reports mouse button press to the Flutter engine.
135
94
static void GLFWmouseButtonCallback (GLFWwindow *window, int key, int action,
136
95
int mods) {
137
96
double x, y;
@@ -147,13 +106,15 @@ static void GLFWmouseButtonCallback(GLFWwindow *window, int key, int action,
147
106
}
148
107
}
149
108
109
+ // Passes character input events to registered handlers.
150
110
static void GLFWCharCallback (GLFWwindow *window, unsigned int code_point) {
151
111
for (flutter_desktop_embedding::KeyboardHookHandler *handler :
152
112
GetSavedEmbedderState (window)->keyboard_hook_handlers ) {
153
113
handler->CharHook (window, code_point);
154
114
}
155
115
}
156
116
117
+ // Passes raw key events to registered handlers.
157
118
static void GLFWKeyCallback (GLFWwindow *window, int key, int scancode,
158
119
int action, int mods) {
159
120
for (flutter_desktop_embedding::KeyboardHookHandler *handler :
@@ -162,6 +123,51 @@ static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode,
162
123
}
163
124
}
164
125
126
+ // Reports window size changes to the Flutter engine.
127
+ static void GLFWwindowSizeCallback (GLFWwindow *window, int width, int height) {
128
+ FlutterWindowMetricsEvent event = {};
129
+ event.struct_size = sizeof (event);
130
+ event.width = width;
131
+ event.height = height;
132
+ // TODO: Handle pixel ratio for different DPI monitors.
133
+ event.pixel_ratio = 1.0 ;
134
+ FlutterEngineSendWindowMetricsEvent (GetSavedEmbedderState (window)->engine ,
135
+ &event);
136
+ }
137
+
138
+ // Flushes event queue and then assigns default window callbacks.
139
+ static void GLFWAssignEventCallbacks (GLFWwindow *window) {
140
+ glfwPollEvents ();
141
+ glfwSetKeyCallback (window, GLFWKeyCallback);
142
+ glfwSetCharCallback (window, GLFWCharCallback);
143
+ glfwSetMouseButtonCallback (window, GLFWmouseButtonCallback);
144
+ }
145
+
146
+ // Clears default window events.
147
+ static void GLFWClearEventCallbacks (GLFWwindow *window) {
148
+ glfwSetKeyCallback (window, nullptr );
149
+ glfwSetCharCallback (window, nullptr );
150
+ glfwSetMouseButtonCallback (window, nullptr );
151
+ }
152
+
153
+ // The Flutter Engine calls out to this function when new platform messages are
154
+ // available
155
+ static void GLFWOnFlutterPlatformMessage (const FlutterPlatformMessage *message,
156
+ void *user_data) {
157
+ if (message->struct_size != sizeof (FlutterPlatformMessage)) {
158
+ std::cerr << " Invalid message size received. Expected: "
159
+ << sizeof (FlutterPlatformMessage) << " but received "
160
+ << message->struct_size << std::endl;
161
+ return ;
162
+ }
163
+
164
+ GLFWwindow *window = reinterpret_cast <GLFWwindow *>(user_data);
165
+ auto state = GetSavedEmbedderState (window);
166
+ state->plugin_handler ->HandleMethodCallMessage (
167
+ message, [window] { GLFWClearEventCallbacks (window); },
168
+ [window] { GLFWAssignEventCallbacks (window); });
169
+ }
170
+
165
171
static bool GLFWMakeContextCurrent (void *user_data) {
166
172
GLFWwindow *window = reinterpret_cast <GLFWwindow *>(user_data);
167
173
glfwMakeContextCurrent (window);
@@ -192,7 +198,7 @@ static uint32_t GLFWGetActiveFbo(void *user_data) { return 0; }
192
198
static void GLFWClearCanvas (GLFWwindow *window) {
193
199
glfwMakeContextCurrent (window);
194
200
// This color is Material Blue Grey.
195
- glClearColor (0.92549 , 0.93725 , 0.9451 , 0 );
201
+ glClearColor (236.0 / 255.0 , 239.0 / 255.0 , 241.0 / 255.0 , 0 );
196
202
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
197
203
glFlush ();
198
204
glfwSwapBuffers (window);
@@ -242,6 +248,13 @@ static FlutterEngine RunFlutterEngine(
242
248
243
249
namespace flutter_desktop_embedding {
244
250
251
+ // Initialize glfw
252
+ bool FlutterInit () { return glfwInit (); }
253
+
254
+ // Tear down glfw
255
+ void FlutterTerminate () { glfwTerminate (); }
256
+
257
+ // set up embedder state and add the plugin to the plugin_handler
245
258
bool AddPlugin (GLFWwindow *flutter_window, std::unique_ptr<Plugin> plugin) {
246
259
auto state = GetSavedEmbedderState (flutter_window);
247
260
return state->plugin_handler ->AddPlugin (std::move (plugin));
@@ -261,7 +274,9 @@ GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height,
261
274
const std::string &packages_path,
262
275
const std::string &icu_data_path,
263
276
const std::vector<std::string> &arguments) {
277
+ #ifdef __linux__
264
278
gtk_init (0 , nullptr );
279
+ #endif
265
280
auto window = glfwCreateWindow (initial_width, initial_height,
266
281
kDefaultWindowTitle , NULL , NULL );
267
282
if (window == nullptr ) {
@@ -274,6 +289,7 @@ GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height,
274
289
glfwDestroyWindow (window);
275
290
return nullptr ;
276
291
}
292
+
277
293
FlutterEmbedderState *state = new FlutterEmbedderState ();
278
294
state->plugin_handler = std::make_unique<PluginHandler>(engine);
279
295
state->engine = engine;
@@ -297,13 +313,19 @@ GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height,
297
313
}
298
314
299
315
void FlutterWindowLoop (GLFWwindow *flutter_window) {
316
+ #ifdef __linux__
300
317
// Necessary for GTK thread safety.
301
318
XInitThreads ();
319
+ #endif
302
320
while (!glfwWindowShouldClose (flutter_window)) {
321
+ #ifdef __linux__
303
322
glfwPollEvents ();
304
323
if (gtk_events_pending ()) {
305
324
gtk_main_iteration ();
306
325
}
326
+ #else
327
+ glfwWaitEvents ();
328
+ #endif
307
329
// TODO(awdavies): This will be deprecated soon.
308
330
__FlutterEngineFlushPendingTasksNow ();
309
331
}
0 commit comments