From 8ce185a45ad60b591e56814a4fef67afc54f430c Mon Sep 17 00:00:00 2001 From: Lucy Qu Date: Fri, 5 Jan 2024 15:00:32 +1100 Subject: [PATCH] vm_tools: Use viewport to handle window resizing BUG=b:316990641 TEST=left4dead2 Change-Id: I6543c60b5e8dba9242cb4d0854c0d1d29190b642 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/5171466 Commit-Queue: Lucy Qu Reviewed-by: Chloe Pelling Tested-by: Lucy Qu --- compositor/sommelier-compositor.cc | 10 +- sommelier-ctx.cc | 1 + sommelier-ctx.h | 1 + sommelier-seat.cc | 3 +- sommelier-transform-test.cc | 42 +++++- sommelier-transform.cc | 20 ++- sommelier-transform.h | 6 + sommelier-window-test.cc | 215 +++++++++++++++++++++++++++++ sommelier-window.cc | 94 ++++++++++--- sommelier-window.h | 10 ++ sommelier.cc | 5 + sommelier.h | 4 + testing/x11-test-base.h | 5 +- 13 files changed, 383 insertions(+), 33 deletions(-) diff --git a/compositor/sommelier-compositor.cc b/compositor/sommelier-compositor.cc index 56fd5b2..4c41bde 100644 --- a/compositor/sommelier-compositor.cc +++ b/compositor/sommelier-compositor.cc @@ -9,7 +9,7 @@ #include "../sommelier-xshape.h" // NOLINT(build/include_directory) #include "sommelier-dmabuf-sync.h" // NOLINT(build/include_directory) #include "sommelier-formats.h" // NOLINT(build/include_directory) - +#include "viewporter-shim.h" // NOLINT(build/include_directory) #include #include #include @@ -600,8 +600,8 @@ static void copy_damaged_rect(sl_host_surface* host, } } -static void sl_host_surface_commit(struct wl_client* client, - struct wl_resource* resource) { +void sl_host_surface_commit(struct wl_client* client, + struct wl_resource* resource) { auto resource_id = try_wl_resource_get_id(resource); TRACE_EVENT( "surface", "sl_host_surface_commit", "resource_id", resource_id, @@ -741,12 +741,12 @@ static void sl_host_surface_commit(struct wl_client* client, int32_t vp_width = width; int32_t vp_height = height; - // Consult with the transform function to see if the // viewport destination set is necessary if (sl_transform_viewport_scale(host->ctx, host, host->contents_scale, &vp_width, &vp_height)) { - wp_viewport_set_destination(host->viewport, vp_width, vp_height); + wp_viewport_shim()->set_destination(host->viewport, vp_width, + vp_height); } } else { wl_surface_set_buffer_scale(host->proxy, scale); diff --git a/sommelier-ctx.cc b/sommelier-ctx.cc index cb9bf92..6a6bae1 100644 --- a/sommelier-ctx.cc +++ b/sommelier-ctx.cc @@ -197,6 +197,7 @@ void sl_context_init_default(struct sl_context* ctx) { ctx->stable_scaling = false; ctx->frame_stats = nullptr; ctx->stats_timer_delay = 60 * 1000; + ctx->viewport_resize = false; wl_list_init(&ctx->registries); wl_list_init(&ctx->globals); diff --git a/sommelier-ctx.h b/sommelier-ctx.h index 53f4895..334d30f 100644 --- a/sommelier-ctx.h +++ b/sommelier-ctx.h @@ -218,6 +218,7 @@ struct sl_context { bool use_explicit_fence; bool use_virtgpu_channel; bool use_direct_scale; + bool viewport_resize; // Experimental feature flags to be cleaned up. bool enable_x11_move_windows; // TODO(b/247452928): Clean this up. diff --git a/sommelier-seat.cc b/sommelier-seat.cc index 569186b..558e684 100644 --- a/sommelier-seat.cc +++ b/sommelier-seat.cc @@ -169,8 +169,7 @@ static void sl_pointer_motion(void* data, wl_fixed_t mx = x; wl_fixed_t my = y; - sl_transform_host_to_guest_fixed(host->seat->ctx, host->focus_surface, &mx, - &my); + sl_transform_pointer(host->seat->ctx, host->focus_surface, &mx, &my); wl_pointer_send_motion(host->resource, time, mx, my); } diff --git a/sommelier-transform-test.cc b/sommelier-transform-test.cc index aa4ca4c..3d8adbb 100644 --- a/sommelier-transform-test.cc +++ b/sommelier-transform-test.cc @@ -6,10 +6,13 @@ #include "sommelier-ctx.h" // NOLINT(build/include_directory) #include "sommelier-transform.h" // NOLINT(build/include_directory) +#include "testing/x11-test-base.h" namespace vm_tools { namespace sommelier { +using TransformDirectScaleTest = X11DirectScaleTest; + class TransformTest : public ::testing::Test { public: void SetUp() override { @@ -478,16 +481,43 @@ TEST_F(TransformTest, GuestToHostFixedCoord_UnscaledWithDirectScale) { EXPECT_EQ(wl_fixed_to_double(coord), 16.0); } -TEST_F(TransformTest, GuestToHostFixedCoord_ScaledWithDirectScale) { +TEST_F(TransformDirectScaleTest, Pointer_WithViewportOverride) { + ctx.viewport_resize = true; + sl_window* window = CreateToplevelWindow(); + window->viewport_override = true; + window->viewport_pointer_scale = 1.1; + sl_host_surface* surface = window->paired_surface; + surface->has_own_scale = true; + surface->xdg_scale_x = 0.9; + surface->xdg_scale_y = 1.6; + + wl_fixed_t x = wl_fixed_from_double(16.0); + wl_fixed_t y = wl_fixed_from_double(16.0); + + sl_transform_pointer(&ctx, surface, &x, &y); + + EXPECT_EQ(x, wl_fixed_from_double(0.9 * 16 * 1.1)); + EXPECT_EQ(y, wl_fixed_from_double(1.6 * 16 * 1.1)); +} + +TEST_F(TransformDirectScaleTest, Pointer_WithoutViewportOverride) { + ctx.viewport_resize = true; + sl_window* window = CreateToplevelWindow(); + window->viewport_override = false; + window->viewport_pointer_scale = 0.9; + sl_host_surface* surface = window->paired_surface; ctx.use_direct_scale = true; - fake_surface.has_own_scale = true; - fake_surface.xdg_scale_y = 1.6; + surface->has_own_scale = true; + surface->xdg_scale_x = 0.9; + surface->xdg_scale_y = 1.6; - wl_fixed_t coord = wl_fixed_from_double(26.0); + wl_fixed_t x = wl_fixed_from_double(16.0); + wl_fixed_t y = wl_fixed_from_double(16.0); - sl_transform_guest_to_host_fixed(&ctx, &fake_surface, &coord, 0u); + sl_transform_pointer(&ctx, surface, &x, &y); - EXPECT_EQ(coord, wl_fixed_from_double(26 / 1.6)); + EXPECT_EQ(x, wl_fixed_from_double(0.9 * 16)); + EXPECT_EQ(y, wl_fixed_from_double(1.6 * 16)); } } // namespace sommelier } // namespace vm_tools diff --git a/sommelier-transform.cc b/sommelier-transform.cc index 0a309ec..b52ff6b 100644 --- a/sommelier-transform.cc +++ b/sommelier-transform.cc @@ -200,7 +200,10 @@ bool sl_transform_viewport_scale(struct sl_context* ctx, // when the virtual and logical space match. bool do_viewport = true; - if (ctx->use_direct_scale) { + if (surface && surface->window && surface->window->viewport_override) { + *width = surface->window->viewport_width; + *height = surface->window->viewport_height; + } else if (ctx->use_direct_scale) { sl_transform_direct_to_host(ctx, surface, width, height); // For very small windows (in pixels), the resulting logical dimensions @@ -294,6 +297,21 @@ void sl_transform_host_to_guest_fixed(struct sl_context* ctx, } } +void sl_transform_pointer(struct sl_context* ctx, + struct sl_host_surface* surface, + wl_fixed_t* x, + wl_fixed_t* y) { + sl_transform_host_to_guest_fixed(ctx, surface, x, y); + if (surface && surface->window && surface->window->viewport_override) { + double dx = wl_fixed_to_double(*x); + double dy = wl_fixed_to_double(*y); + dx *= surface->window->viewport_pointer_scale; + dy *= surface->window->viewport_pointer_scale; + *x = wl_fixed_from_double(dx); + *y = wl_fixed_from_double(dy); + } +} + void sl_transform_host_to_guest_fixed(struct sl_context* ctx, struct sl_host_surface* surface, wl_fixed_t* coord, diff --git a/sommelier-transform.h b/sommelier-transform.h index 3011891..a6c6c2f 100644 --- a/sommelier-transform.h +++ b/sommelier-transform.h @@ -200,4 +200,10 @@ void sl_transform_output_dimensions(struct sl_context* ctx, int32_t* width, int32_t* height); +// Used to transform pointer coordinates from host to guest. +void sl_transform_pointer(struct sl_context* ctx, + struct sl_host_surface* surface, + wl_fixed_t* x, + wl_fixed_t* y); + #endif // VM_TOOLS_SOMMELIER_SOMMELIER_TRANSFORM_H_ diff --git a/sommelier-window-test.cc b/sommelier-window-test.cc index 5f647dc..4ecd22f 100644 --- a/sommelier-window-test.cc +++ b/sommelier-window-test.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "mock-viewporter-shim.h" // NOLINT(build/include_directory) #include "testing/x11-test-base.h" #include @@ -23,6 +24,220 @@ using ::testing::PrintToString; using X11Test = X11TestBase; +TEST_F(X11DirectScaleTest, ViewportOverrideStretchedVertically) { + // Arrange + ctx.viewport_resize = true; + AdvertiseOutputs(xwayland.get(), + {{.logical_width = 1536, .logical_height = 864}}); + sl_window* window = CreateToplevelWindow(); + const int pixel_width = 1920; + const int pixel_height = 1080; + window->managed = true; + window->max_width = pixel_width; + window->min_height = pixel_height; + window->min_width = pixel_width; + window->max_height = pixel_height; + window->width = pixel_width; + window->height = pixel_height; + window->paired_surface->contents_width = pixel_width; + window->paired_surface->contents_height = pixel_height; + wl_array states; + wl_array_init(&states); + + // Assert + EXPECT_CALL(mock_viewport_shim_, + set_destination(window->paired_surface->viewport, 1393, 784)) + .Times(1); + + // Act: Configure with height smaller than min_height. + HostEventHandler(window->xdg_toplevel) + ->configure(nullptr, window->xdg_toplevel, 1536 /*1920*/, 784 /*980*/, + &states); + HostEventHandler(window->xdg_surface) + ->configure(nullptr, window->xdg_surface, 123); + sl_host_surface_commit(nullptr, window->paired_surface->resource); + Pump(); + + // Assert: viewport size and pointer scale are set, width height are + // unchanged. + EXPECT_TRUE(window->viewport_override); + EXPECT_EQ(window->viewport_width, 1393); + EXPECT_EQ(window->viewport_height, 784); + EXPECT_FLOAT_EQ(window->viewport_pointer_scale, 1.1026561); + EXPECT_EQ(window->width, 1920); + EXPECT_EQ(window->height, 1080); + + // Assert + EXPECT_CALL(mock_viewport_shim_, + set_destination(window->paired_surface->viewport, -1, -1)) + // Act: Configure with the size that is within the window bounds. + .Times(1); + HostEventHandler(window->xdg_toplevel) + ->configure(nullptr, window->xdg_toplevel, 1536, 864, &states); + HostEventHandler(window->xdg_surface) + ->configure(nullptr, window->xdg_surface, 124); + + // Assert + EXPECT_CALL(mock_viewport_shim_, + set_destination(window->paired_surface->viewport, 1536, 864)) + .Times(1); + + // Act + sl_host_surface_commit(nullptr, window->paired_surface->resource); + Pump(); + + // Assert: viewport override is no longer used. + EXPECT_FALSE(window->viewport_override); + EXPECT_EQ(window->viewport_width, -1); + EXPECT_EQ(window->viewport_height, -1); + EXPECT_EQ(window->width, pixel_width); + EXPECT_EQ(window->height, pixel_height); +} + +TEST_F(X11DirectScaleTest, ViewportOverrideStretchedHorizontally) { + // Arrange + ctx.viewport_resize = true; + AdvertiseOutputs(xwayland.get(), + {{.logical_width = 1536, .logical_height = 864}}); + sl_window* window = CreateToplevelWindow(); + window->managed = true; + window->max_width = 1700; + window->max_height = 900; + window->min_width = 1600; + window->min_height = 800; + window->width = 1650; + window->height = 800; + window->paired_surface->contents_width = 1650; + window->paired_surface->contents_height = 800; + wl_array states; + wl_array_init(&states); + + // Assert + EXPECT_CALL(mock_viewport_shim_, + set_destination(window->paired_surface->viewport, 1200, 581)) + .Times(1); + + // Act: Height is set to equal to max height, width smaller than min + // width. + HostEventHandler(window->xdg_toplevel) + ->configure(nullptr, window->xdg_toplevel, 1200 /*1500*/, 720 /*900*/, + &states); + HostEventHandler(window->xdg_surface) + ->configure(nullptr, window->xdg_surface, 123); + sl_host_surface_commit(nullptr, window->paired_surface->resource); + Pump(); + + // Assert: viewport size and pointer scale are set, width height are + // unchanged. + EXPECT_TRUE(window->viewport_override); + EXPECT_EQ(window->viewport_width, 1200); + EXPECT_EQ(window->viewport_height, 581); + EXPECT_FLOAT_EQ(window->viewport_pointer_scale, 1.1); + EXPECT_EQ(window->width, 1650); + EXPECT_EQ(window->height, 800); + + // Assert + EXPECT_CALL(mock_viewport_shim_, + set_destination(window->paired_surface->viewport, -1, -1)) + .Times(1); + + // Act: Configure with the size that is within the window bounds. + HostEventHandler(window->xdg_toplevel) + ->configure(nullptr, window->xdg_toplevel, 1360 /*1700*/, 680 /*850*/, + &states); + HostEventHandler(window->xdg_surface) + ->configure(nullptr, window->xdg_surface, 124); + window->paired_surface->contents_width = 1700; + window->paired_surface->contents_height = 850; + + // Assert + EXPECT_CALL(mock_viewport_shim_, + set_destination(window->paired_surface->viewport, 1360, 680)) + .Times(1); + + // Act + sl_host_surface_commit(nullptr, window->paired_surface->resource); + Pump(); + + // Assert: viewport override is no longer used. + EXPECT_FALSE(window->viewport_override); + EXPECT_EQ(window->viewport_width, -1); + EXPECT_EQ(window->viewport_height, -1); + EXPECT_EQ(window->width, 1700); + EXPECT_EQ(window->height, 850); +} + +TEST_F(X11DirectScaleTest, ViewportOverrideSameAspectRatio) { + // Arrange + ctx.viewport_resize = true; + AdvertiseOutputs(xwayland.get(), + {{.logical_width = 1536, .logical_height = 864}}); + sl_window* window = CreateToplevelWindow(); + window->managed = true; + const int pixel_width = 1920; + const int pixel_height = 1080; + window->max_width = pixel_width; + window->min_height = pixel_height; + window->min_width = pixel_width; + window->max_height = pixel_height; + window->paired_surface->contents_width = pixel_width; + window->paired_surface->contents_height = pixel_height; + window->width = pixel_width; + window->height = pixel_height; + wl_array states; + wl_array_init(&states); + + // Assert + EXPECT_CALL(mock_viewport_shim_, + set_destination(window->paired_surface->viewport, 1280, 720)) + .Times(1); + + // Act: Height and width squished while maintaining aspect ratio. + HostEventHandler(window->xdg_toplevel) + ->configure(nullptr, window->xdg_toplevel, 1280 /*1600*/, 720 /*900*/, + &states); + HostEventHandler(window->xdg_surface) + ->configure(nullptr, window->xdg_surface, 123); + sl_host_surface_commit(nullptr, window->paired_surface->resource); + Pump(); + + // Assert: viewport size and pointer scale are set, width height are + // unchanged. + EXPECT_TRUE(window->viewport_override); + EXPECT_EQ(window->viewport_width, 1280); + EXPECT_EQ(window->viewport_height, 720); + EXPECT_FLOAT_EQ(window->viewport_pointer_scale, 1.2); + EXPECT_EQ(window->width, pixel_width); + EXPECT_EQ(window->height, pixel_height); + + // Assert + EXPECT_CALL(mock_viewport_shim_, + set_destination(window->paired_surface->viewport, -1, -1)) + .Times(1); + + // Act: Configure with the size that is within the window bounds. + HostEventHandler(window->xdg_toplevel) + ->configure(nullptr, window->xdg_toplevel, 1536, 864, &states); + HostEventHandler(window->xdg_surface) + ->configure(nullptr, window->xdg_surface, 123); + + // Assert + EXPECT_CALL(mock_viewport_shim_, + set_destination(window->paired_surface->viewport, 1536, 864)) + .Times(1); + + // Act + sl_host_surface_commit(nullptr, window->paired_surface->resource); + Pump(); + + // Assert: viewport override is no longer used. + EXPECT_FALSE(window->viewport_override); + EXPECT_EQ(window->viewport_width, -1); + EXPECT_EQ(window->viewport_height, -1); + EXPECT_EQ(window->width, 1920); + EXPECT_EQ(window->height, 1080); +} + TEST_F(X11Test, TogglesFullscreenOnWmStateFullscreen) { // Arrange: Create an xdg_toplevel surface. Initially it's not fullscreen. AdvertiseOutputs(xwayland.get(), {OutputConfig()}); diff --git a/sommelier-window.cc b/sommelier-window.cc index 39640b4..1dd0d5a 100644 --- a/sommelier-window.cc +++ b/sommelier-window.cc @@ -11,9 +11,11 @@ #include "sommelier.h" // NOLINT(build/include_directory) #include "sommelier-tracing.h" // NOLINT(build/include_directory) #include "sommelier-transform.h" // NOLINT(build/include_directory) +#include "viewporter-shim.h" // NOLINT(build/include_directory) #include "xcb/xcb-shim.h" #include "aura-shell-client-protocol.h" // NOLINT(build/include_directory) +#include "viewporter-client-protocol.h" // NOLINT(build/include_directory) #include "xdg-shell-client-protocol.h" // NOLINT(build/include_directory) #ifdef QUIRKS_SUPPORT @@ -160,8 +162,9 @@ int sl_process_pending_configure_acks(struct sl_window* window, uint32_t height = window->height + window->border_width * 2; // Early out if we expect contents to match window size at some point in // the future. - if (width != host_surface->contents_width || - height != host_surface->contents_height) { + if (!window->viewport_override && + (width != host_surface->contents_width || + height != host_surface->contents_height)) { return 0; } } @@ -247,16 +250,15 @@ static const int32_t kUnspecifiedCoord = INT32_MIN; // for toplevel objects that don't send positions. // width, height: Configured size in host logical space. // states: Array of XDG_TOPLEVEL_STATE_* enum values. -static void sl_internal_toplevel_configure(struct sl_window* window, - int32_t x, - int32_t y, - int32_t width, - int32_t height, - struct wl_array* states) { +void sl_internal_toplevel_configure(struct sl_window* window, + int32_t x, + int32_t y, + int32_t width, + int32_t height, + struct wl_array* states) { int activated = 0; uint32_t* state; int i = 0; - if (!window->managed) return; @@ -280,9 +282,58 @@ static void sl_internal_toplevel_configure(struct sl_window* window, window->width, window->height); } } - sl_transform_host_to_guest(window->ctx, window->paired_surface, &width_in_pixels, &height_in_pixels); + + // Workaround using viewport for when Exo sets sizes that are not + // within the bounds the client requested. + if (window->ctx->viewport_resize && + ((window->max_width != 0 && width_in_pixels > window->max_width) || + (window->min_width != 0 && width_in_pixels < window->min_width) || + (window->max_height != 0 && height_in_pixels > window->max_height) || + (window->min_height != 0 && height_in_pixels < window->min_height))) { + window->viewport_override = true; + float width_ratio = static_cast(window->width) / width_in_pixels; + float height_ratio = + static_cast(window->height) / height_in_pixels; + if (std::abs(width_ratio - height_ratio) < 0.01) { + window->viewport_override = true; + window->viewport_width = width; + window->viewport_height = height; + // If Exo sets a size that is of a different aspect ratio we shrink + // the window to maintain aspect ratio. We do this by always shrinking + // the side that is now proportionally larger as if we expand the + // smaller side it might result in the window becoming larger than the + // allowed bounds of the screen. + } else if (width_ratio < height_ratio) { + window->viewport_width = + (static_cast(window->width) * height) / window->height; + window->viewport_height = height; + + } else if (width_ratio > height_ratio) { + window->viewport_height = + (static_cast(window->height) * width) / window->width; + window->viewport_width = width; + } + + int32_t window_width = window->width; + int32_t window_height = window->height; + sl_transform_guest_to_host(window->ctx, window->paired_surface, + &window_width, &window_height); + window->viewport_pointer_scale = + static_cast(window_width) / window->viewport_width; + xdg_toplevel_set_min_size(window->xdg_toplevel, window->viewport_width, + window->viewport_height); + xdg_toplevel_set_max_size(window->xdg_toplevel, window->viewport_width, + window->viewport_height); + } else if (window->viewport_override) { + window->viewport_width = -1; + window->viewport_height = -1; + wp_viewport_shim()->set_destination(paired_surface->viewport, + window->viewport_width, + window->viewport_height); + window->viewport_override = false; + } window->next_config.mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT | XCB_CONFIG_WINDOW_BORDER_WIDTH; @@ -313,9 +364,15 @@ static void sl_internal_toplevel_configure(struct sl_window* window, window->ctx->screen->height_in_pixels / 2 - height_in_pixels / 2; } } - window->next_config.values[i++] = width_in_pixels; - window->next_config.values[i++] = height_in_pixels; - window->next_config.values[i++] = 0; + if (window->viewport_override) { + window->next_config.values[i++] = window->width; + window->next_config.values[i++] = window->height; + window->next_config.values[i++] = 0; + } else { + window->next_config.values[i++] = width_in_pixels; + window->next_config.values[i++] = height_in_pixels; + window->next_config.values[i++] = 0; + } } window->allow_resize = 1; @@ -554,6 +611,7 @@ void sl_window_update(struct sl_window* window) { wl_list_remove(&window->link); wl_list_insert(&ctx->unpaired_windows, &window->link); window->unpaired = 1; + window->paired_surface->window = nullptr; window->paired_surface = nullptr; } @@ -585,6 +643,7 @@ void sl_window_update(struct sl_window* window) { if (!window->unpaired) { window->paired_surface = host_surface; + host_surface->window = window; sl_transform_try_window_scale(ctx, host_surface, window->width, window->height); } @@ -669,11 +728,10 @@ void sl_window_update(struct sl_window* window) { } zaura_surface_set_frame(window->aura_surface, - window->decorated - ? ZAURA_SURFACE_FRAME_TYPE_NORMAL - : window->depth == 32 - ? ZAURA_SURFACE_FRAME_TYPE_NONE - : ZAURA_SURFACE_FRAME_TYPE_SHADOW); + window->decorated ? ZAURA_SURFACE_FRAME_TYPE_NORMAL + : window->depth == 32 + ? ZAURA_SURFACE_FRAME_TYPE_NONE + : ZAURA_SURFACE_FRAME_TYPE_SHADOW); frame_color = window->dark_frame ? ctx->dark_frame_color : ctx->frame_color; zaura_surface_set_frame_colors(window->aura_surface, frame_color, diff --git a/sommelier-window.h b/sommelier-window.h index 6966b95..418f09f 100644 --- a/sommelier-window.h +++ b/sommelier-window.h @@ -88,6 +88,10 @@ struct sl_window { int min_height = 0; int max_width = 0; int max_height = 0; + int viewport_width = -1; + int viewport_height = -1; + int viewport_override = false; + double viewport_pointer_scale = 0; #ifdef QUIRKS_SUPPORT // Quirk feature flags previously applied to this window, for which log @@ -225,6 +229,12 @@ void sl_toplevel_send_window_bounds_to_host(struct sl_window* window); void sl_update_application_id(struct sl_context* ctx, struct sl_window* window); void sl_configure_window(struct sl_window* window); void sl_send_configure_notify(struct sl_window* window); +void sl_internal_toplevel_configure(struct sl_window* window, + int32_t x, + int32_t y, + int32_t width, + int32_t height, + struct wl_array* states); int sl_process_pending_configure_acks(struct sl_window* window, struct sl_host_surface* host_surface); diff --git a/sommelier.cc b/sommelier.cc index acf8179..fa9cca8 100644 --- a/sommelier.cc +++ b/sommelier.cc @@ -12,6 +12,7 @@ #ifdef GAMEPAD_SUPPORT #include "libevdev/libevdev-shim.h" #endif +#include "viewporter-shim.h" // NOLINT(build/include_directory) #include "xcb/xcb-shim.h" #include @@ -3461,6 +3462,7 @@ static void sl_print_usage() { " --glamor\t\t\tUse glamor to accelerate X11 clients\n" " --timing-filename=PATH\tPath to timing output log\n" " --direct-scale\t\tEnable direct scaling mode\n" + " --viewport-resize\t\tUse viewport to resize unresizable windows." #ifdef PERFETTO_TRACING " --trace-filename=PATH\t\tPath to Perfetto trace filename\n" " --trace-system\t\tPerfetto trace to system daemon\n" @@ -3809,6 +3811,7 @@ void create_shims() { set_xdg_toplevel_shim(new XdgToplevelShim()); set_xdg_surface_shim(new XdgSurfaceShim()); set_xdg_wm_base_shim(new XdgWmBaseShim()); + set_wp_viewport_shim(new WpViewportShim()); #ifdef GAMEPAD_SUPPORT Libevdev::Set(new LibevdevShim()); @@ -3951,6 +3954,8 @@ int real_main(int argc, char** argv) { noop_driver = true; } else if (strstr(arg, "--stable-scaling") == arg) { ctx.stable_scaling = true; + } else if (strstr(arg, "--viewport-resize") == arg) { + ctx.viewport_resize = true; #ifdef PERFETTO_TRACING } else if (strstr(arg, "--trace-filename") == arg) { ctx.trace_filename = sl_arg_value(arg); diff --git a/sommelier.h b/sommelier.h index f3b282f..9297086 100644 --- a/sommelier.h +++ b/sommelier.h @@ -177,6 +177,7 @@ struct sl_host_surface { struct zwp_linux_surface_synchronization_v1* surface_sync; struct wl_list released_buffers; struct wl_list busy_buffers; + struct sl_window* window = nullptr; WeakResourcePtr output; }; MAP_STRUCTS(wl_surface, sl_host_surface); @@ -631,6 +632,9 @@ void sl_handle_client_message(struct sl_context* ctx, xcb_client_message_event_t* event); void sl_handle_focus_in(struct sl_context* ctx, xcb_focus_in_event_t* event); +void sl_host_surface_commit(struct wl_client* client, + struct wl_resource* resource); + #ifdef GAMEPAD_SUPPORT void sl_gaming_seat_add_listener(struct sl_context* ctx); #endif diff --git a/testing/x11-test-base.h b/testing/x11-test-base.h index f6e8273..168714d 100644 --- a/testing/x11-test-base.h +++ b/testing/x11-test-base.h @@ -10,7 +10,8 @@ #include #include "../xcb/mock-xcb-shim.h" -#include "wayland-test-base.h" // NOLINT(build/include_directory) +#include "mock-viewporter-shim.h" // NOLINT(build/include_directory) +#include "wayland-test-base.h" // NOLINT(build/include_directory) namespace vm_tools { namespace sommelier { @@ -50,6 +51,7 @@ class X11TestBase : public WaylandTestBase { void Connect() override { set_xcb_shim(&xcb); + set_wp_viewport_shim(&mock_viewport_shim_); WaylandTestBase::Connect(); // Pretend Xwayland has connected to Sommelier as a Wayland client. @@ -116,6 +118,7 @@ class X11TestBase : public WaylandTestBase { protected: NiceMock xcb; std::unique_ptr xwayland; + NiceMock mock_viewport_shim_; }; // Fixture for unit tests which use direct scale.