Skip to content

Commit 6dc4d6c

Browse files
Add refresh callback to GLFW shell (flutter#9280)
In some cases, the window needs to be redrawn without a resize. This adds a callback for that case to trigger a repaint. Since there's no embedding API for repainting, trigger it with a window metrics event using the current window size. Fixes flutter#30731
1 parent 2d2cfc0 commit 6dc4d6c

File tree

1 file changed

+41
-14
lines changed

1 file changed

+41
-14
lines changed

shell/platform/glfw/flutter_glfw.cc

Lines changed: 41 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ struct FlutterDesktopWindow {
9696

9797
// The ratio of pixels per screen coordinate for the window.
9898
double pixels_per_screen_coordinate = 1.0;
99+
100+
// Resizing triggers a window refresh, but the resize already updates Flutter.
101+
// To avoid double messages, the refresh after each resize is skipped.
102+
bool skip_next_window_refresh = false;
99103
};
100104

101105
// Struct for storing state of a Flutter engine instance.
@@ -166,31 +170,53 @@ static double GetScreenCoordinatesPerInch() {
166170
return primary_monitor_mode->width / (primary_monitor_width_mm / 25.4);
167171
}
168172

173+
// Sends a window metrics update to the Flutter engine using the given
174+
// framebuffer size and the current window information in |state|.
175+
static void SendWindowMetrics(FlutterDesktopWindowControllerState* state,
176+
int width,
177+
int height) {
178+
double dpi = state->window_wrapper->pixels_per_screen_coordinate *
179+
state->monitor_screen_coordinates_per_inch;
180+
181+
FlutterWindowMetricsEvent event = {};
182+
event.struct_size = sizeof(event);
183+
event.width = width;
184+
event.height = height;
185+
// The Flutter pixel_ratio is defined as DPI/dp. Limit the ratio to a minimum
186+
// of 1 to avoid rendering a smaller UI on standard resolution monitors.
187+
event.pixel_ratio = std::max(dpi / kDpPerInch, 1.0);
188+
FlutterEngineSendWindowMetricsEvent(state->engine, &event);
189+
}
190+
169191
// When GLFW calls back to the window with a framebuffer size change, notify
170192
// FlutterEngine about the new window metrics.
171-
// The Flutter pixel_ratio is defined as DPI/dp.
172193
static void GLFWFramebufferSizeCallback(GLFWwindow* window,
173194
int width_px,
174195
int height_px) {
175196
int width;
176197
glfwGetWindowSize(window, &width, nullptr);
177-
178-
auto state = GetSavedWindowState(window);
198+
auto* state = GetSavedWindowState(window);
179199
state->window_wrapper->pixels_per_screen_coordinate =
180200
width > 0 ? width_px / width : 1;
181201

182-
double dpi = state->window_wrapper->pixels_per_screen_coordinate *
183-
state->monitor_screen_coordinates_per_inch;
184-
// Limit the ratio to 1 to avoid rendering a smaller UI in standard resolution
185-
// monitors.
186-
double pixel_ratio = std::max(dpi / kDpPerInch, 1.0);
202+
SendWindowMetrics(state, width_px, height_px);
203+
state->window_wrapper->skip_next_window_refresh = true;
204+
}
187205

188-
FlutterWindowMetricsEvent event = {};
189-
event.struct_size = sizeof(event);
190-
event.width = width_px;
191-
event.height = height_px;
192-
event.pixel_ratio = pixel_ratio;
193-
FlutterEngineSendWindowMetricsEvent(state->engine, &event);
206+
// Indicates that the window needs to be redrawn.
207+
void GLFWWindowRefreshCallback(GLFWwindow* window) {
208+
auto* state = GetSavedWindowState(window);
209+
if (state->window_wrapper->skip_next_window_refresh) {
210+
state->window_wrapper->skip_next_window_refresh = false;
211+
return;
212+
}
213+
// There's no engine API to request a redraw explicitly, so instead send a
214+
// window metrics event with the current size to trigger it.
215+
int width_px, height_px;
216+
glfwGetFramebufferSize(window, &width_px, &height_px);
217+
if (width_px > 0 && height_px > 0) {
218+
SendWindowMetrics(state, width_px, height_px);
219+
}
194220
}
195221

196222
// Sends a pointer event to the Flutter engine based on the given data.
@@ -589,6 +615,7 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow(
589615

590616
// Set up GLFW callbacks for the window.
591617
glfwSetFramebufferSizeCallback(window, GLFWFramebufferSizeCallback);
618+
glfwSetWindowRefreshCallback(window, GLFWWindowRefreshCallback);
592619
GLFWAssignEventCallbacks(window);
593620

594621
return state.release();

0 commit comments

Comments
 (0)