44
44
45
45
static_assert (FLUTTER_ENGINE_VERSION == 1 , " " );
46
46
47
+ static constexpr double kDpPerInch = 160.0 ;
48
+
47
49
// Struct for storing state within an instance of the GLFW Window.
48
50
struct FlutterEmbedderState {
49
51
FlutterEngine engine;
@@ -57,6 +59,12 @@ struct FlutterEmbedderState {
57
59
// Handles raw key interactions from GLFW.
58
60
// TODO: Revisit ownership model once Issue #102 is resolved.
59
61
std::unique_ptr<flutter_desktop_embedding::KeyEventHandler> key_event_handler;
62
+
63
+ // The screen coordinates per inch on the primary monitor. Defaults to a sane
64
+ // value based on pixel_ratio 1.0.
65
+ double monitor_screen_coordinates_per_inch = kDpPerInch ;
66
+ // The ratio of pixels per screen coordinate for the window.
67
+ double window_pixels_per_screen_coordinate = 1.0 ;
60
68
};
61
69
62
70
static constexpr char kDefaultWindowTitle [] = " Flutter" ;
@@ -67,41 +75,78 @@ static FlutterEmbedderState *GetSavedEmbedderState(GLFWwindow *window) {
67
75
glfwGetWindowUserPointer (window));
68
76
}
69
77
78
+ // Returns the number of screen coordinates per inch for the main monitor.
79
+ // If the information is unavailable, returns a default value that assumes
80
+ // that a screen coordinate is one dp.
81
+ static double GetScreenCoordinatesPerInch () {
82
+ auto *primary_monitor = glfwGetPrimaryMonitor ();
83
+ auto *primary_monitor_mode = glfwGetVideoMode (primary_monitor);
84
+ int primary_monitor_width_mm;
85
+ glfwGetMonitorPhysicalSize (primary_monitor, &primary_monitor_width_mm,
86
+ nullptr );
87
+ if (primary_monitor_width_mm == 0 ) {
88
+ return kDpPerInch ;
89
+ }
90
+ return primary_monitor_mode->width / (primary_monitor_width_mm / 25.4 );
91
+ }
92
+
93
+ // When GLFW calls back to the window with a framebuffer size change, notify
94
+ // FlutterEngine about the new window metrics.
95
+ // The Flutter pixel_ratio is defined as DPI/dp.
96
+ static void GLFWFramebufferSizeCallback (GLFWwindow *window, int width_px,
97
+ int height_px) {
98
+ int width;
99
+ glfwGetWindowSize (window, &width, nullptr );
100
+
101
+ auto state = GetSavedEmbedderState (window);
102
+ state->window_pixels_per_screen_coordinate = width_px / width;
103
+
104
+ double dpi = state->window_pixels_per_screen_coordinate *
105
+ state->monitor_screen_coordinates_per_inch ;
106
+
107
+ FlutterWindowMetricsEvent event = {};
108
+ event.struct_size = sizeof (event);
109
+ event.width = width_px;
110
+ event.height = height_px;
111
+ event.pixel_ratio = dpi / kDpPerInch ;
112
+ FlutterEngineSendWindowMetricsEvent (state->engine , &event);
113
+ }
114
+
70
115
// When GLFW calls back to the window with a cursor position move, forwards to
71
116
// FlutterEngine as a pointer event with appropriate phase.
72
- static void GLFWcursorPositionCallbackAtPhase (GLFWwindow *window,
117
+ static void GLFWCursorPositionCallbackAtPhase (GLFWwindow *window,
73
118
FlutterPointerPhase phase,
74
119
double x, double y) {
120
+ auto state = GetSavedEmbedderState (window);
75
121
FlutterPointerEvent event = {};
76
122
event.struct_size = sizeof (event);
77
123
event.phase = phase;
78
- event.x = x;
79
- event.y = y;
124
+ event.x = x * state-> window_pixels_per_screen_coordinate ;
125
+ event.y = y * state-> window_pixels_per_screen_coordinate ;
80
126
event.timestamp =
81
127
std::chrono::duration_cast<std::chrono::microseconds>(
82
128
std::chrono::high_resolution_clock::now ().time_since_epoch ())
83
129
.count ();
84
- FlutterEngineSendPointerEvent (GetSavedEmbedderState (window)->engine , &event,
85
- 1 );
130
+ FlutterEngineSendPointerEvent (state->engine , &event, 1 );
86
131
}
87
132
88
133
// Reports cursor move to the Flutter engine.
89
- static void GLFWcursorPositionCallback (GLFWwindow *window, double x, double y) {
90
- GLFWcursorPositionCallbackAtPhase (window, FlutterPointerPhase::kMove , x, y);
134
+ static void GLFWCursorPositionCallback (GLFWwindow *window, double x, double y) {
135
+ GLFWCursorPositionCallbackAtPhase (window, FlutterPointerPhase::kMove , x, y);
91
136
}
92
137
93
138
// Reports mouse button press to the Flutter engine.
94
- static void GLFWmouseButtonCallback (GLFWwindow *window, int key, int action,
139
+ static void GLFWMouseButtonCallback (GLFWwindow *window, int key, int action,
95
140
int mods) {
96
141
double x, y;
97
142
if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_PRESS) {
98
143
glfwGetCursorPos (window, &x, &y);
99
- GLFWcursorPositionCallbackAtPhase (window, FlutterPointerPhase::kDown , x, y);
100
- glfwSetCursorPosCallback (window, GLFWcursorPositionCallback );
144
+ GLFWCursorPositionCallbackAtPhase (window, FlutterPointerPhase::kDown , x, y);
145
+ glfwSetCursorPosCallback (window, GLFWCursorPositionCallback );
101
146
}
102
147
if (key == GLFW_MOUSE_BUTTON_1 && action == GLFW_RELEASE) {
103
148
glfwGetCursorPos (window, &x, &y);
104
- GLFWcursorPositionCallbackAtPhase (window, FlutterPointerPhase::kUp , x, y);
149
+ GLFWCursorPositionCallbackAtPhase (window, FlutterPointerPhase::kUp , x, y);
105
150
glfwSetCursorPosCallback (window, nullptr );
106
151
}
107
152
}
@@ -123,24 +168,12 @@ static void GLFWKeyCallback(GLFWwindow *window, int key, int scancode,
123
168
}
124
169
}
125
170
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
171
// Flushes event queue and then assigns default window callbacks.
139
172
static void GLFWAssignEventCallbacks (GLFWwindow *window) {
140
173
glfwPollEvents ();
141
174
glfwSetKeyCallback (window, GLFWKeyCallback);
142
175
glfwSetCharCallback (window, GLFWCharCallback);
143
- glfwSetMouseButtonCallback (window, GLFWmouseButtonCallback );
176
+ glfwSetMouseButtonCallback (window, GLFWMouseButtonCallback );
144
177
}
145
178
146
179
// Clears default window events.
@@ -311,10 +344,12 @@ GLFWwindow *CreateFlutterWindow(size_t initial_width, size_t initial_height,
311
344
312
345
AddPlugin (window, std::move (input_plugin));
313
346
314
- int width, height;
315
- glfwGetWindowSize (window, &width, &height);
316
- GLFWwindowSizeCallback (window, width, height);
317
- glfwSetWindowSizeCallback (window, GLFWwindowSizeCallback);
347
+ state->monitor_screen_coordinates_per_inch = GetScreenCoordinatesPerInch ();
348
+ int width_px, height_px;
349
+ glfwGetFramebufferSize (window, &width_px, &height_px);
350
+ glfwSetFramebufferSizeCallback (window, GLFWFramebufferSizeCallback);
351
+ GLFWFramebufferSizeCallback (window, width_px, height_px);
352
+
318
353
GLFWAssignEventCallbacks (window);
319
354
return window;
320
355
}
0 commit comments