@@ -155,57 +155,86 @@ static void GLFWFramebufferSizeCallback(GLFWwindow* window,
155
155
FlutterEngineSendWindowMetricsEvent (state->engine , &event);
156
156
}
157
157
158
- // Sends a pointer event to the Flutter engine with the given phase.
159
- static void SendPointerEventWithPhase (GLFWwindow* window,
160
- FlutterPointerPhase phase,
161
- double x,
162
- double y) {
163
- auto state = GetSavedWindowState (window);
158
+ // Sends a pointer event to the Flutter engine based on the given data.
159
+ //
160
+ // Any coordinate/distance values in |event_data| should be in screen
161
+ // coordinates; they will be adjusted to pixel values before being sent.
162
+ static void SendPointerEventWithData (GLFWwindow* window,
163
+ const FlutterPointerEvent& event_data) {
164
+ auto * state = GetSavedWindowState (window);
164
165
// If sending anything other than an add, and the pointer isn't already added,
165
166
// synthesize an add to satisfy Flutter's expectations about events.
166
- if (!state->pointer_currently_added && phase != FlutterPointerPhase::kAdd ) {
167
- SendPointerEventWithPhase (window, FlutterPointerPhase::kAdd , x, y);
167
+ if (!state->pointer_currently_added &&
168
+ event_data.phase != FlutterPointerPhase::kAdd ) {
169
+ FlutterPointerEvent event = {};
170
+ event.phase = FlutterPointerPhase::kAdd ;
171
+ event.x = event_data.x ;
172
+ event.y = event_data.y ;
173
+ SendPointerEventWithData (window, event);
168
174
}
169
175
// Don't double-add (e.g., if events are delivered out of order, so an add has
170
176
// already been synthesized).
171
- if (state->pointer_currently_added && phase == FlutterPointerPhase::kAdd ) {
177
+ if (state->pointer_currently_added &&
178
+ event_data.phase == FlutterPointerPhase::kAdd ) {
172
179
return ;
173
180
}
174
181
175
- FlutterPointerEvent event = {};
182
+ FlutterPointerEvent event = event_data;
183
+ // Set metadata that's always the same regardless of the event.
176
184
event.struct_size = sizeof (event);
177
- event.phase = phase;
178
- event.x = x * state->window_pixels_per_screen_coordinate ;
179
- event.y = y * state->window_pixels_per_screen_coordinate ;
180
185
event.timestamp =
181
186
std::chrono::duration_cast<std::chrono::microseconds>(
182
187
std::chrono::high_resolution_clock::now ().time_since_epoch ())
183
188
.count ();
189
+ // Convert all screen coordinates to pixel coordinates.
190
+ event.x *= state->window_pixels_per_screen_coordinate ;
191
+ event.y *= state->window_pixels_per_screen_coordinate ;
192
+ event.scroll_delta_x *= state->window_pixels_per_screen_coordinate ;
193
+ event.scroll_delta_y *= state->window_pixels_per_screen_coordinate ;
194
+
184
195
FlutterEngineSendPointerEvent (state->engine , &event, 1 );
185
196
186
- if (phase == FlutterPointerPhase::kAdd ) {
197
+ if (event_data. phase == FlutterPointerPhase::kAdd ) {
187
198
state->pointer_currently_added = true ;
188
- } else if (phase == FlutterPointerPhase::kRemove ) {
199
+ } else if (event_data. phase == FlutterPointerPhase::kRemove ) {
189
200
state->pointer_currently_added = false ;
190
201
}
191
202
}
192
203
204
+ // Updates |event_data| with the current location of the mouse cursor.
205
+ static void SetEventLocationFromCursorPosition (
206
+ GLFWwindow* window,
207
+ FlutterPointerEvent* event_data) {
208
+ glfwGetCursorPos (window, &event_data->x , &event_data->y );
209
+ }
210
+
211
+ // Set's |event_data|'s phase to either kMove or kHover depending on the current
212
+ // primary mouse button state.
213
+ static void SetEventPhaseFromCursorButtonState (
214
+ GLFWwindow* window,
215
+ FlutterPointerEvent* event_data) {
216
+ event_data->phase =
217
+ glfwGetMouseButton (window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS
218
+ ? FlutterPointerPhase::kMove
219
+ : FlutterPointerPhase::kHover ;
220
+ }
221
+
193
222
// Reports the mouse entering or leaving the Flutter view.
194
223
static void GLFWCursorEnterCallback (GLFWwindow* window, int entered) {
195
- double x, y;
196
- glfwGetCursorPos (window, &x, &y);
197
- FlutterPointerPhase phase =
224
+ FlutterPointerEvent event = {};
225
+ event.phase =
198
226
entered ? FlutterPointerPhase::kAdd : FlutterPointerPhase::kRemove ;
199
- SendPointerEventWithPhase (window, phase, x, y);
227
+ SetEventLocationFromCursorPosition (window, &event);
228
+ SendPointerEventWithData (window, event);
200
229
}
201
230
202
231
// Reports mouse movement to the Flutter engine.
203
232
static void GLFWCursorPositionCallback (GLFWwindow* window, double x, double y) {
204
- bool button_down =
205
- glfwGetMouseButton (window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS ;
206
- FlutterPointerPhase phase =
207
- button_down ? FlutterPointerPhase:: kMove : FlutterPointerPhase:: kHover ;
208
- SendPointerEventWithPhase (window, phase, x, y );
233
+ FlutterPointerEvent event = {};
234
+ event. x = x ;
235
+ event. y = y;
236
+ SetEventPhaseFromCursorButtonState (window, &event) ;
237
+ SendPointerEventWithData (window, event );
209
238
}
210
239
211
240
// Reports mouse button press to the Flutter engine.
@@ -219,12 +248,11 @@ static void GLFWMouseButtonCallback(GLFWwindow* window,
219
248
return ;
220
249
}
221
250
222
- double x, y;
223
- glfwGetCursorPos (window, &x, &y);
224
- FlutterPointerPhase phase = (action == GLFW_PRESS)
225
- ? FlutterPointerPhase::kDown
226
- : FlutterPointerPhase::kUp ;
227
- SendPointerEventWithPhase (window, phase, x, y);
251
+ FlutterPointerEvent event = {};
252
+ event.phase = (action == GLFW_PRESS) ? FlutterPointerPhase::kDown
253
+ : FlutterPointerPhase::kUp ;
254
+ SetEventLocationFromCursorPosition (window, &event);
255
+ SendPointerEventWithData (window, event);
228
256
229
257
// If mouse tracking isn't already enabled, turn it on for the duration of
230
258
// the drag to generate kMove events.
@@ -242,6 +270,22 @@ static void GLFWMouseButtonCallback(GLFWwindow* window,
242
270
}
243
271
}
244
272
273
+ // Reports scroll wheel events to the Flutter engine.
274
+ static void GLFWScrollCallback (GLFWwindow* window,
275
+ double delta_x,
276
+ double delta_y) {
277
+ FlutterPointerEvent event = {};
278
+ SetEventLocationFromCursorPosition (window, &event);
279
+ SetEventPhaseFromCursorButtonState (window, &event);
280
+ event.signal_kind = FlutterPointerSignalKind::kFlutterPointerSignalKindScroll ;
281
+ // TODO: See if this can be queried from the OS; this value is chosen
282
+ // arbitrarily to get something that feels reasonable.
283
+ const int kScrollOffsetMultiplier = 20 ;
284
+ event.scroll_delta_x = delta_x * kScrollOffsetMultiplier ;
285
+ event.scroll_delta_y = -delta_y * kScrollOffsetMultiplier ;
286
+ SendPointerEventWithData (window, event);
287
+ }
288
+
245
289
// Passes character input events to registered handlers.
246
290
static void GLFWCharCallback (GLFWwindow* window, unsigned int code_point) {
247
291
for (const auto & handler :
@@ -276,6 +320,7 @@ static void GLFWAssignEventCallbacks(GLFWwindow* window) {
276
320
glfwSetKeyCallback (window, GLFWKeyCallback);
277
321
glfwSetCharCallback (window, GLFWCharCallback);
278
322
glfwSetMouseButtonCallback (window, GLFWMouseButtonCallback);
323
+ glfwSetScrollCallback (window, GLFWScrollCallback);
279
324
if (GetSavedWindowState (window)->hover_tracking_enabled ) {
280
325
SetHoverCallbacksEnabled (window, true );
281
326
}
@@ -286,6 +331,7 @@ static void GLFWClearEventCallbacks(GLFWwindow* window) {
286
331
glfwSetKeyCallback (window, nullptr );
287
332
glfwSetCharCallback (window, nullptr );
288
333
glfwSetMouseButtonCallback (window, nullptr );
334
+ glfwSetScrollCallback (window, nullptr );
289
335
SetHoverCallbacksEnabled (window, false );
290
336
}
291
337
0 commit comments