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