From 48057c7735edd6d906075625aeefae6806c4f890 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Thu, 2 May 2019 23:37:21 -0400 Subject: [PATCH] Add resize functions to GLFW shell Adds methods to get and set the window size, as well as to query the window's scale factor. This is useful both for custom clients, and for building a window resize plugin to prototype what will eventually likely be a system channel. --- .../include/flutter/flutter_window.h | 32 +++++++++ .../testing/stub_flutter_glfw_api.cc | 28 ++++++++ .../testing/stub_flutter_glfw_api.h | 11 +++ shell/platform/glfw/flutter_glfw.cc | 68 ++++++++++++++++--- shell/platform/glfw/public/flutter_glfw.h | 21 ++++++ 5 files changed, 150 insertions(+), 10 deletions(-) diff --git a/shell/platform/glfw/client_wrapper/include/flutter/flutter_window.h b/shell/platform/glfw/client_wrapper/include/flutter/flutter_window.h index 4b6b646a08974..a788bc72e69a4 100644 --- a/shell/platform/glfw/client_wrapper/include/flutter/flutter_window.h +++ b/shell/platform/glfw/client_wrapper/include/flutter/flutter_window.h @@ -14,6 +14,14 @@ namespace flutter { +// A data type for window position and size. +struct WindowFrame { + int left; + int top; + int width; + int height; +}; + // A window displaying Flutter content. class FlutterWindow { public: @@ -48,6 +56,30 @@ class FlutterWindow { FlutterDesktopWindowSetIcon(window_, pixel_data, width, height); } + // Returns the frame of the window, including any decoration (e.g., title + // bar), in screen coordinates. + WindowFrame GetFrame() { + WindowFrame frame = {}; + FlutterDesktopWindowGetFrame(window_, &frame.left, &frame.top, &frame.width, + &frame.height); + return frame; + } + + // Set the frame of the window, including any decoration (e.g., title + // bar), in screen coordinates. + void SetFrame(const WindowFrame& frame) { + FlutterDesktopWindowSetFrame(window_, frame.left, frame.top, frame.width, + frame.height); + } + + // Returns the number of pixels per screen coordinate for the window. + // + // Flutter uses pixel coordinates, so this is the ratio of positions and sizes + // seen by Flutter as compared to the screen. + double GetScaleFactor() { + return FlutterDesktopWindowGetScaleFactor(window_); + } + private: // Handle for interacting with the C API's window. // diff --git a/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc b/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc index 6965739ee9d7c..a3390ad07ff01 100644 --- a/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc +++ b/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.cc @@ -93,6 +93,34 @@ void FlutterDesktopWindowSetIcon(FlutterDesktopWindowRef flutter_window, } } +void FlutterDesktopWindowGetFrame(FlutterDesktopWindowRef flutter_window, + int* x, + int* y, + int* width, + int* height) { + if (s_stub_implementation) { + s_stub_implementation->GetWindowFrame(x, y, width, height); + } +} + +void FlutterDesktopWindowSetFrame(FlutterDesktopWindowRef flutter_window, + int x, + int y, + int width, + int height) { + if (s_stub_implementation) { + s_stub_implementation->SetWindowFrame(x, y, width, height); + } +} + +double FlutterDesktopWindowGetScaleFactor( + FlutterDesktopWindowRef flutter_window) { + if (s_stub_implementation) { + return s_stub_implementation->GetWindowScaleFactor(); + } + return 1.0; +} + void FlutterDesktopRunWindowLoop(FlutterDesktopWindowControllerRef controller) { if (s_stub_implementation) { s_stub_implementation->RunWindowLoop(); diff --git a/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h b/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h index 0b2ee455fb8dc..d974584dfae3c 100644 --- a/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h +++ b/shell/platform/glfw/client_wrapper/testing/stub_flutter_glfw_api.h @@ -59,6 +59,17 @@ class StubFlutterGlfwApi { // Called for FlutterDesktopWindowSetIcon. virtual void SetWindowIcon(uint8_t* pixel_data, int width, int height) {} + // Called for FlutterDesktopWindowGetFrame. + virtual void GetWindowFrame(int* x, int* y, int* width, int* height) { + x = y = width = height = 0; + } + + // Called for FlutterDesktopWindowGetFrame. + virtual void SetWindowFrame(int x, int y, int width, int height) {} + + // Called for FlutterDesktopWindowGetScaleFactor. + virtual double GetWindowScaleFactor() { return 1.0; } + // Called for FlutterDesktopRunWindowLoop. virtual void RunWindowLoop() {} diff --git a/shell/platform/glfw/flutter_glfw.cc b/shell/platform/glfw/flutter_glfw.cc index 7b124cc35357e..92796c50d4860 100644 --- a/shell/platform/glfw/flutter_glfw.cc +++ b/shell/platform/glfw/flutter_glfw.cc @@ -69,8 +69,6 @@ struct FlutterDesktopWindowControllerState { // The screen coordinates per inch on the primary monitor. Defaults to a sane // value based on pixel_ratio 1.0. double monitor_screen_coordinates_per_inch = kDpPerInch; - // The ratio of pixels per screen coordinate for the window. - double window_pixels_per_screen_coordinate = 1.0; }; // Opaque reference for the GLFW window itself. This is separate from the @@ -82,6 +80,9 @@ struct FlutterDesktopWindow { // Whether or not to track mouse movements to send kHover events. bool hover_tracking_enabled = false; + + // The ratio of pixels per screen coordinate for the window. + double pixels_per_screen_coordinate = 1.0; }; // Struct for storing state of a Flutter engine instance. @@ -152,9 +153,9 @@ static void GLFWFramebufferSizeCallback(GLFWwindow* window, glfwGetWindowSize(window, &width, nullptr); auto state = GetSavedWindowState(window); - state->window_pixels_per_screen_coordinate = width_px / width; + state->window_wrapper->pixels_per_screen_coordinate = width_px / width; - double dpi = state->window_pixels_per_screen_coordinate * + 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. @@ -200,10 +201,12 @@ static void SendPointerEventWithData(GLFWwindow* window, std::chrono::high_resolution_clock::now().time_since_epoch()) .count(); // Convert all screen coordinates to pixel coordinates. - event.x *= state->window_pixels_per_screen_coordinate; - event.y *= state->window_pixels_per_screen_coordinate; - event.scroll_delta_x *= state->window_pixels_per_screen_coordinate; - event.scroll_delta_y *= state->window_pixels_per_screen_coordinate; + double pixels_per_coordinate = + state->window_wrapper->pixels_per_screen_coordinate; + event.x *= pixels_per_coordinate; + event.y *= pixels_per_coordinate; + event.scroll_delta_x *= pixels_per_coordinate; + event.scroll_delta_y *= pixels_per_coordinate; FlutterEngineSendPointerEvent(state->engine, &event, 1); @@ -579,9 +582,54 @@ void FlutterDesktopWindowSetIcon(FlutterDesktopWindowRef flutter_window, uint8_t* pixel_data, int width, int height) { - GLFWwindow* window = flutter_window->window; GLFWimage image = {width, height, static_cast(pixel_data)}; - glfwSetWindowIcon(window, pixel_data ? 1 : 0, &image); + glfwSetWindowIcon(flutter_window->window, pixel_data ? 1 : 0, &image); +} + +void FlutterDesktopWindowGetFrame(FlutterDesktopWindowRef flutter_window, + int* x, + int* y, + int* width, + int* height) { + glfwGetWindowPos(flutter_window->window, x, y); + glfwGetWindowSize(flutter_window->window, width, height); + // The above gives content area size and position; adjust for the window + // decoration to give actual window frame. + int frame_left, frame_top, frame_right, frame_bottom; + glfwGetWindowFrameSize(flutter_window->window, &frame_left, &frame_top, + &frame_right, &frame_bottom); + if (x) { + *x -= frame_left; + } + if (y) { + *y -= frame_top; + } + if (width) { + *width += frame_left + frame_right; + } + if (height) { + *height += frame_top + frame_bottom; + } +} + +void FlutterDesktopWindowSetFrame(FlutterDesktopWindowRef flutter_window, + int x, + int y, + int width, + int height) { + // Get the window decoration sizes to adjust, since the GLFW setters take + // content position and size. + int frame_left, frame_top, frame_right, frame_bottom; + glfwGetWindowFrameSize(flutter_window->window, &frame_left, &frame_top, + &frame_right, &frame_bottom); + glfwSetWindowPos(flutter_window->window, x + frame_left, y + frame_top); + glfwSetWindowSize(flutter_window->window, width - frame_left - frame_right, + height - frame_top - frame_bottom); +} + +double FlutterDesktopWindowGetScaleFactor( + FlutterDesktopWindowRef flutter_window) { + return flutter_window->pixels_per_screen_coordinate; } void FlutterDesktopRunWindowLoop(FlutterDesktopWindowControllerRef controller) { diff --git a/shell/platform/glfw/public/flutter_glfw.h b/shell/platform/glfw/public/flutter_glfw.h index bffc769a3cffa..573c821346a51 100644 --- a/shell/platform/glfw/public/flutter_glfw.h +++ b/shell/platform/glfw/public/flutter_glfw.h @@ -119,6 +119,27 @@ FLUTTER_EXPORT void FlutterDesktopWindowSetIcon( int width, int height); +// Gets the position and size of |flutter_window| in screen coordinates. +FLUTTER_EXPORT void FlutterDesktopWindowGetFrame( + FlutterDesktopWindowRef flutter_window, + int* x, + int* y, + int* width, + int* height); + +// Sets the position and size of |flutter_window| in screen coordinates. +FLUTTER_EXPORT void FlutterDesktopWindowSetFrame( + FlutterDesktopWindowRef flutter_window, + int x, + int y, + int width, + int height); + +// Returns the scale factor--the number of pixels per screen coordinate--for +// |flutter_window|. +FLUTTER_EXPORT double FlutterDesktopWindowGetScaleFactor( + FlutterDesktopWindowRef flutter_window); + // Runs an instance of a headless Flutter engine. // // The |assets_path| is the path to the flutter_assets folder for the Flutter