未验证 提交 6dc4d6ca 编写于 作者: S stuartmorgan 提交者: GitHub

Add refresh callback to GLFW shell (#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 https://github.com/flutter/flutter/issues/30731
上级 2d2cfc08
...@@ -96,6 +96,10 @@ struct FlutterDesktopWindow { ...@@ -96,6 +96,10 @@ struct FlutterDesktopWindow {
// The ratio of pixels per screen coordinate for the window. // The ratio of pixels per screen coordinate for the window.
double pixels_per_screen_coordinate = 1.0; double pixels_per_screen_coordinate = 1.0;
// Resizing triggers a window refresh, but the resize already updates Flutter.
// To avoid double messages, the refresh after each resize is skipped.
bool skip_next_window_refresh = false;
}; };
// Struct for storing state of a Flutter engine instance. // Struct for storing state of a Flutter engine instance.
...@@ -166,31 +170,53 @@ static double GetScreenCoordinatesPerInch() { ...@@ -166,31 +170,53 @@ static double GetScreenCoordinatesPerInch() {
return primary_monitor_mode->width / (primary_monitor_width_mm / 25.4); return primary_monitor_mode->width / (primary_monitor_width_mm / 25.4);
} }
// Sends a window metrics update to the Flutter engine using the given
// framebuffer size and the current window information in |state|.
static void SendWindowMetrics(FlutterDesktopWindowControllerState* state,
int width,
int height) {
double dpi = state->window_wrapper->pixels_per_screen_coordinate *
state->monitor_screen_coordinates_per_inch;
FlutterWindowMetricsEvent event = {};
event.struct_size = sizeof(event);
event.width = width;
event.height = height;
// The Flutter pixel_ratio is defined as DPI/dp. Limit the ratio to a minimum
// of 1 to avoid rendering a smaller UI on standard resolution monitors.
event.pixel_ratio = std::max(dpi / kDpPerInch, 1.0);
FlutterEngineSendWindowMetricsEvent(state->engine, &event);
}
// When GLFW calls back to the window with a framebuffer size change, notify // When GLFW calls back to the window with a framebuffer size change, notify
// FlutterEngine about the new window metrics. // FlutterEngine about the new window metrics.
// The Flutter pixel_ratio is defined as DPI/dp.
static void GLFWFramebufferSizeCallback(GLFWwindow* window, static void GLFWFramebufferSizeCallback(GLFWwindow* window,
int width_px, int width_px,
int height_px) { int height_px) {
int width; int width;
glfwGetWindowSize(window, &width, nullptr); glfwGetWindowSize(window, &width, nullptr);
auto* state = GetSavedWindowState(window);
auto state = GetSavedWindowState(window);
state->window_wrapper->pixels_per_screen_coordinate = state->window_wrapper->pixels_per_screen_coordinate =
width > 0 ? width_px / width : 1; width > 0 ? width_px / width : 1;
double dpi = state->window_wrapper->pixels_per_screen_coordinate * SendWindowMetrics(state, width_px, height_px);
state->monitor_screen_coordinates_per_inch; state->window_wrapper->skip_next_window_refresh = true;
// Limit the ratio to 1 to avoid rendering a smaller UI in standard resolution }
// monitors.
double pixel_ratio = std::max(dpi / kDpPerInch, 1.0);
FlutterWindowMetricsEvent event = {}; // Indicates that the window needs to be redrawn.
event.struct_size = sizeof(event); void GLFWWindowRefreshCallback(GLFWwindow* window) {
event.width = width_px; auto* state = GetSavedWindowState(window);
event.height = height_px; if (state->window_wrapper->skip_next_window_refresh) {
event.pixel_ratio = pixel_ratio; state->window_wrapper->skip_next_window_refresh = false;
FlutterEngineSendWindowMetricsEvent(state->engine, &event); return;
}
// There's no engine API to request a redraw explicitly, so instead send a
// window metrics event with the current size to trigger it.
int width_px, height_px;
glfwGetFramebufferSize(window, &width_px, &height_px);
if (width_px > 0 && height_px > 0) {
SendWindowMetrics(state, width_px, height_px);
}
} }
// Sends a pointer event to the Flutter engine based on the given data. // Sends a pointer event to the Flutter engine based on the given data.
...@@ -589,6 +615,7 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow( ...@@ -589,6 +615,7 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow(
// Set up GLFW callbacks for the window. // Set up GLFW callbacks for the window.
glfwSetFramebufferSizeCallback(window, GLFWFramebufferSizeCallback); glfwSetFramebufferSizeCallback(window, GLFWFramebufferSizeCallback);
glfwSetWindowRefreshCallback(window, GLFWWindowRefreshCallback);
GLFWAssignEventCallbacks(window); GLFWAssignEventCallbacks(window);
return state.release(); return state.release();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册