Skip to content

Commit

Permalink
Add refresh callback to GLFW shell (flutter#9280)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
stuartmorgan committed Jun 11, 2019
1 parent 2d2cfc0 commit 6dc4d6c
Showing 1 changed file with 41 additions and 14 deletions.
55 changes: 41 additions & 14 deletions shell/platform/glfw/flutter_glfw.cc
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ struct FlutterDesktopWindow {

// The ratio of pixels per screen coordinate for the window.
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.
Expand Down Expand Up @@ -166,31 +170,53 @@ static double GetScreenCoordinatesPerInch() {
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
// FlutterEngine about the new window metrics.
// The Flutter pixel_ratio is defined as DPI/dp.
static void GLFWFramebufferSizeCallback(GLFWwindow* window,
int width_px,
int height_px) {
int width;
glfwGetWindowSize(window, &width, nullptr);

auto state = GetSavedWindowState(window);
auto* state = GetSavedWindowState(window);
state->window_wrapper->pixels_per_screen_coordinate =
width > 0 ? width_px / width : 1;

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

FlutterWindowMetricsEvent event = {};
event.struct_size = sizeof(event);
event.width = width_px;
event.height = height_px;
event.pixel_ratio = pixel_ratio;
FlutterEngineSendWindowMetricsEvent(state->engine, &event);
// Indicates that the window needs to be redrawn.
void GLFWWindowRefreshCallback(GLFWwindow* window) {
auto* state = GetSavedWindowState(window);
if (state->window_wrapper->skip_next_window_refresh) {
state->window_wrapper->skip_next_window_refresh = false;
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.
Expand Down Expand Up @@ -589,6 +615,7 @@ FlutterDesktopWindowControllerRef FlutterDesktopCreateWindow(

// Set up GLFW callbacks for the window.
glfwSetFramebufferSizeCallback(window, GLFWFramebufferSizeCallback);
glfwSetWindowRefreshCallback(window, GLFWWindowRefreshCallback);
GLFWAssignEventCallbacks(window);

return state.release();
Expand Down

0 comments on commit 6dc4d6c

Please sign in to comment.