diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h index da85e5531..12bb84038 100644 --- a/src/backends/meta-monitor-manager-private.h +++ b/src/backends/meta-monitor-manager-private.h @@ -307,6 +307,7 @@ GList * meta_monitor_manager_get_logical_monitors (MetaMonitorManage MetaLogicalMonitor *meta_monitor_manager_get_logical_monitor_from_number (MetaMonitorManager *manager, int number); +META_EXPORT_TEST MetaLogicalMonitor *meta_monitor_manager_get_primary_logical_monitor (MetaMonitorManager *manager); MetaLogicalMonitor *meta_monitor_manager_get_logical_monitor_at (MetaMonitorManager *manager, diff --git a/src/tests/wayland-test-clients/meson.build b/src/tests/wayland-test-clients/meson.build index 2b3c83389..48fad9afb 100644 --- a/src/tests/wayland-test-clients/meson.build +++ b/src/tests/wayland-test-clients/meson.build @@ -53,6 +53,7 @@ wayland_test_clients = [ 'invalid-xdg-shell-actions', 'xdg-apply-limits', 'xdg-activation', + 'xdg-toplevel-bounds', ] foreach test : wayland_test_clients diff --git a/src/tests/wayland-test-clients/xdg-toplevel-bounds.c b/src/tests/wayland-test-clients/xdg-toplevel-bounds.c new file mode 100644 index 000000000..f0fc47058 --- /dev/null +++ b/src/tests/wayland-test-clients/xdg-toplevel-bounds.c @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2021 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "wayland-test-client-utils.h" + +#include "test-driver-client-protocol.h" +#include "xdg-shell-client-protocol.h" + +typedef enum _State +{ + STATE_INIT = 0, + STATE_WAIT_FOR_CONFIGURE_1, + STATE_WAIT_FOR_FRAME_1, +} State; + +static struct wl_display *display; +static struct wl_registry *registry; +static struct wl_compositor *compositor; +static struct xdg_wm_base *xdg_wm_base; +static struct wl_shm *shm; +static struct test_driver *test_driver; + +static struct wl_surface *surface; +static struct xdg_surface *xdg_surface; +static struct xdg_toplevel *xdg_toplevel; + +static struct wl_callback *frame_callback; + +static gboolean running; + +static State state; +static int32_t pending_bounds_width; +static int32_t pending_bounds_height; + +static void +init_surface (void) +{ + xdg_toplevel_set_title (xdg_toplevel, "toplevel-bounds-test"); + wl_surface_commit (surface); +} + +static void +handle_buffer_release (void *data, + struct wl_buffer *buffer) +{ + wl_buffer_destroy (buffer); +} + +static const struct wl_buffer_listener buffer_listener = { + handle_buffer_release +}; + +static gboolean +create_shm_buffer (int width, + int height, + struct wl_buffer **out_buffer, + void **out_data, + int *out_size) +{ + struct wl_shm_pool *pool; + static struct wl_buffer *buffer; + int fd, size, stride; + int bytes_per_pixel; + void *data; + + bytes_per_pixel = 4; + stride = width * bytes_per_pixel; + size = stride * height; + + fd = create_anonymous_file (size); + if (fd < 0) + { + fprintf (stderr, "Creating a buffer file for %d B failed: %m\n", + size); + return FALSE; + } + + data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) + { + fprintf (stderr, "mmap failed: %m\n"); + close (fd); + return FALSE; + } + + pool = wl_shm_create_pool (shm, fd, size); + buffer = wl_shm_pool_create_buffer (pool, 0, + width, height, + stride, + WL_SHM_FORMAT_ARGB8888); + wl_buffer_add_listener (buffer, &buffer_listener, buffer); + wl_shm_pool_destroy (pool); + close (fd); + + *out_buffer = buffer; + *out_data = data; + *out_size = size; + + return TRUE; +} + +static void +fill (void *buffer_data, + int width, + int height, + uint32_t color) +{ + uint32_t *pixels = buffer_data; + int x, y; + + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + pixels[y * width + x] = color; + } +} + +static void +draw (struct wl_surface *surface, + int width, + int height, + uint32_t color) +{ + struct wl_buffer *buffer; + void *buffer_data; + int size; + + if (!create_shm_buffer (width, height, + &buffer, &buffer_data, &size)) + g_error ("Failed to create shm buffer"); + + fill (buffer_data, width, height, color); + + wl_surface_attach (surface, buffer, 0, 0); +} + +static void +draw_main (int width, + int height) +{ + draw (surface, width, height, 0xff00ff00); +} + +static void +handle_xdg_toplevel_configure (void *data, + struct xdg_toplevel *xdg_toplevel, + int32_t width, + int32_t height, + struct wl_array *state) +{ +} + +static void +handle_xdg_toplevel_close(void *data, + struct xdg_toplevel *xdg_toplevel) +{ + g_assert_not_reached (); +} + +static void +handle_xdg_toplevel_configure_bounds (void *data, + struct xdg_toplevel *xdg_toplevel, + int32_t bounds_width, + int32_t bounds_height) +{ + pending_bounds_width = bounds_width; + pending_bounds_height = bounds_height; +} + +static const struct xdg_toplevel_listener xdg_toplevel_listener = { + handle_xdg_toplevel_configure, + handle_xdg_toplevel_close, + handle_xdg_toplevel_configure_bounds, +}; + +static void +handle_frame_callback (void *data, + struct wl_callback *callback, + uint32_t time) +{ + switch (state) + { + case STATE_WAIT_FOR_FRAME_1: + test_driver_sync_point (test_driver, 1, NULL); + break; + case STATE_INIT: + case STATE_WAIT_FOR_CONFIGURE_1: + g_assert_not_reached (); + } +} + +static const struct wl_callback_listener frame_listener = { + handle_frame_callback, +}; + +static void +handle_xdg_surface_configure (void *data, + struct xdg_surface *xdg_surface, + uint32_t serial) +{ + switch (state) + { + case STATE_INIT: + g_assert_not_reached (); + case STATE_WAIT_FOR_CONFIGURE_1: + g_assert (pending_bounds_width > 0); + g_assert (pending_bounds_height > 0); + + draw_main (pending_bounds_width - 10, + pending_bounds_height - 10); + state = STATE_WAIT_FOR_FRAME_1; + break; + case STATE_WAIT_FOR_FRAME_1: + break; + } + + xdg_surface_ack_configure (xdg_surface, serial); + frame_callback = wl_surface_frame (surface); + wl_callback_add_listener (frame_callback, &frame_listener, NULL); + wl_surface_commit (surface); + wl_display_flush (display); +} + +static const struct xdg_surface_listener xdg_surface_listener = { + handle_xdg_surface_configure, +}; + +static void +handle_xdg_wm_base_ping (void *data, + struct xdg_wm_base *xdg_wm_base, + uint32_t serial) +{ + xdg_wm_base_pong (xdg_wm_base, serial); +} + +static const struct xdg_wm_base_listener xdg_wm_base_listener = { + handle_xdg_wm_base_ping, +}; + +static void +test_driver_handle_sync_event (void *data, + struct test_driver *test_driver, + uint32_t serial) +{ + g_assert (serial == 0); + + exit (EXIT_SUCCESS); +} + +static const struct test_driver_listener test_driver_listener = { + test_driver_handle_sync_event, +}; + +static void +handle_registry_global (void *data, + struct wl_registry *registry, + uint32_t id, + const char *interface, + uint32_t version) +{ + if (strcmp (interface, "wl_compositor") == 0) + { + compositor = wl_registry_bind (registry, id, &wl_compositor_interface, 1); + } + else if (strcmp (interface, "xdg_wm_base") == 0) + { + xdg_wm_base = wl_registry_bind (registry, id, + &xdg_wm_base_interface, 4); + xdg_wm_base_add_listener (xdg_wm_base, &xdg_wm_base_listener, NULL); + } + else if (strcmp (interface, "wl_shm") == 0) + { + shm = wl_registry_bind (registry, + id, &wl_shm_interface, 1); + } + else if (strcmp (interface, "test_driver") == 0) + { + test_driver = wl_registry_bind (registry, id, &test_driver_interface, 1); + test_driver_add_listener (test_driver, &test_driver_listener, NULL); + } +} + +static void +handle_registry_global_remove (void *data, + struct wl_registry *registry, + uint32_t name) +{ +} + +static const struct wl_registry_listener registry_listener = { + handle_registry_global, + handle_registry_global_remove +}; + +int +main (int argc, + char **argv) +{ + display = wl_display_connect (NULL); + registry = wl_display_get_registry (display); + wl_registry_add_listener (registry, ®istry_listener, NULL); + wl_display_roundtrip (display); + + if (!shm) + { + fprintf (stderr, "No wl_shm global\n"); + return EXIT_FAILURE; + } + + if (!xdg_wm_base) + { + fprintf (stderr, "No xdg_wm_base global\n"); + return EXIT_FAILURE; + } + + wl_display_roundtrip (display); + + surface = wl_compositor_create_surface (compositor); + xdg_surface = xdg_wm_base_get_xdg_surface (xdg_wm_base, surface); + xdg_surface_add_listener (xdg_surface, &xdg_surface_listener, NULL); + xdg_toplevel = xdg_surface_get_toplevel (xdg_surface); + xdg_toplevel_add_listener (xdg_toplevel, &xdg_toplevel_listener, NULL); + + init_surface (); + state = STATE_WAIT_FOR_CONFIGURE_1; + + wl_surface_commit (surface); + + running = TRUE; + while (running) + { + if (wl_display_dispatch (display) == -1) + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/src/tests/wayland-unit-tests.c b/src/tests/wayland-unit-tests.c index 4e95ab4f5..9c42b1633 100644 --- a/src/tests/wayland-unit-tests.c +++ b/src/tests/wayland-unit-tests.c @@ -25,6 +25,8 @@ #include "core/window-private.h" #include "meta-test/meta-context-test.h" #include "tests/meta-test-utils.h" +#include "meta/meta-later.h" +#include "meta/meta-workspace-manager.h" #include "tests/meta-wayland-test-driver.h" #include "tests/meta-wayland-test-utils.h" #include "wayland/meta-wayland-surface.h" @@ -363,6 +365,276 @@ toplevel_activation (void) meta_wayland_test_client_finish (data.wayland_test_client); } +static void +on_sync_point (MetaWaylandTestDriver *test_driver, + unsigned int sequence, + struct wl_resource *surface_resource, + struct wl_client *wl_client, + unsigned int *latest_sequence) +{ + *latest_sequence = sequence; +} + +static void +wait_for_sync_point (unsigned int sync_point) +{ + gulong handler_id; + unsigned int latest_sequence = 0; + + handler_id = g_signal_connect (test_driver, "sync-point", + G_CALLBACK (on_sync_point), + &latest_sequence); + while (latest_sequence != sync_point) + g_main_context_iteration (NULL, TRUE); + g_signal_handler_disconnect (test_driver, handler_id); +} + +static gboolean +mark_later_as_done (gpointer user_data) +{ + gboolean *done = user_data; + + *done = TRUE; + + return G_SOURCE_REMOVE; +} + +static void +wait_until_after_paint (void) +{ + MetaDisplay *display = meta_context_get_display (test_context); + MetaCompositor *compositor = meta_display_get_compositor (display); + MetaLaters *laters = meta_compositor_get_laters (compositor); + gboolean done; + + done = FALSE; + meta_laters_add (laters, + META_LATER_BEFORE_REDRAW, + mark_later_as_done, + &done, + NULL); + while (!done) + g_main_context_iteration (NULL, FALSE); + + done = FALSE; + meta_laters_add (laters, + META_LATER_IDLE, + mark_later_as_done, + &done, + NULL); + while (!done) + g_main_context_iteration (NULL, FALSE); +} + +static void +set_struts (MetaRectangle rect, + MetaSide side) +{ + MetaDisplay *display = meta_context_get_display (test_context); + MetaWorkspaceManager *workspace_manager = + meta_display_get_workspace_manager (display); + GList *workspaces = + meta_workspace_manager_get_workspaces (workspace_manager); + MetaStrut strut; + g_autoptr (GSList) struts = NULL; + GList *l; + + strut = (MetaStrut) { .rect = rect, .side = side }; + struts = g_slist_append (NULL, &strut); + + for (l = workspaces; l; l = l->next) + { + MetaWorkspace *workspace = l->data; + + meta_workspace_set_builtin_struts (workspace, struts); + } +} + +static void +clear_struts (void) +{ + MetaDisplay *display = meta_context_get_display (test_context); + MetaWorkspaceManager *workspace_manager = + meta_display_get_workspace_manager (display); + GList *workspaces = + meta_workspace_manager_get_workspaces (workspace_manager); + GList *l; + + for (l = workspaces; l; l = l->next) + { + MetaWorkspace *workspace = l->data; + + meta_workspace_set_builtin_struts (workspace, NULL); + } +} + +static MetaRectangle +get_primary_logical_monitor_layout (void) +{ + MetaBackend *backend = meta_context_get_backend (test_context); + MetaMonitorManager *monitor_manager = + meta_backend_get_monitor_manager (backend); + MetaLogicalMonitor *logical_monitor; + + logical_monitor = + meta_monitor_manager_get_primary_logical_monitor (monitor_manager); + return meta_logical_monitor_get_layout (logical_monitor); +} + +static void +toplevel_bounds_struts (void) +{ + MetaWaylandTestClient *wayland_test_client; + MetaWindow *window; + MetaRectangle logical_monitor_layout; + MetaRectangle work_area; + + /* + * This test case makes sure that setting and changing struts result in the + * right bounds are sent. + */ + + logical_monitor_layout = get_primary_logical_monitor_layout (); + set_struts ((MetaRectangle) { + .x = 0, + .y = 0, + .width = logical_monitor_layout.width, + .height = 10, + }, + META_SIDE_TOP); + + wayland_test_client = meta_wayland_test_client_new ("xdg-toplevel-bounds"); + + wait_for_sync_point (1); + wait_until_after_paint (); + + window = find_client_window ("toplevel-bounds-test"); + + g_assert_nonnull (window->monitor); + meta_window_get_work_area_current_monitor (window, &work_area); + g_assert_cmpint (work_area.width, ==, logical_monitor_layout.width); + g_assert_cmpint (work_area.height, ==, logical_monitor_layout.height - 10); + + g_assert_cmpint (window->rect.width, ==, work_area.width - 10); + g_assert_cmpint (window->rect.height, ==, work_area.height - 10); + + meta_wayland_test_driver_emit_sync_event (test_driver, 0); + meta_wayland_test_client_finish (wayland_test_client); + + clear_struts (); + + wayland_test_client = meta_wayland_test_client_new ("xdg-toplevel-bounds"); + + wait_for_sync_point (1); + wait_until_after_paint (); + + window = find_client_window ("toplevel-bounds-test"); + g_assert_nonnull (window->monitor); + meta_window_get_work_area_current_monitor (window, &work_area); + g_assert_cmpint (work_area.width, ==, logical_monitor_layout.width); + g_assert_cmpint (work_area.height, ==, logical_monitor_layout.height); + + g_assert_cmpint (window->rect.width, ==, work_area.width - 10); + g_assert_cmpint (window->rect.height, ==, work_area.height - 10); + + meta_wayland_test_driver_emit_sync_event (test_driver, 0); + meta_wayland_test_client_finish (wayland_test_client); +} + +static void +wait_for_cursor_position (float x, + float y) +{ + MetaBackend *backend = meta_context_get_backend (test_context); + MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); + graphene_point_t point; + + while (TRUE) + { + meta_cursor_tracker_get_pointer (cursor_tracker, &point, NULL); + if (G_APPROX_VALUE (x, point.x, FLT_EPSILON) && + G_APPROX_VALUE (y, point.y, FLT_EPSILON)) + break; + + g_main_context_iteration (NULL, TRUE); + } +} + +static void +toplevel_bounds_monitors (void) +{ + MetaBackend *backend = meta_context_get_backend (test_context); + ClutterSeat *seat; + g_autoptr (MetaVirtualMonitor) second_virtual_monitor = NULL; + MetaWaylandTestClient *wayland_test_client; + MetaRectangle logical_monitor_layout; + MetaRectangle work_area; + MetaWindow *window; + + /* + * This test case creates two monitors, with different sizes, with a fake + * panel on top of the primary monitor. It then makes sure launching on both + * monitors results in the correct bounds. + */ + + seat = meta_backend_get_default_seat (backend); + virtual_pointer = clutter_seat_create_virtual_device (seat, + CLUTTER_POINTER_DEVICE); + + second_virtual_monitor = meta_create_test_monitor (test_context, + 300, 200, 60.0); + + logical_monitor_layout = get_primary_logical_monitor_layout (); + set_struts ((MetaRectangle) { + .x = 0, + .y = 0, + .width = logical_monitor_layout.width, + .height = 10, + }, + META_SIDE_TOP); + + wayland_test_client = meta_wayland_test_client_new ("xdg-toplevel-bounds"); + + wait_for_sync_point (1); + wait_until_after_paint (); + + window = find_client_window ("toplevel-bounds-test"); + + g_assert_nonnull (window->monitor); + meta_window_get_work_area_current_monitor (window, &work_area); + g_assert_cmpint (work_area.width, ==, logical_monitor_layout.width); + g_assert_cmpint (work_area.height, ==, logical_monitor_layout.height - 10); + + g_assert_cmpint (window->rect.width, ==, work_area.width - 10); + g_assert_cmpint (window->rect.height, ==, work_area.height - 10); + + meta_wayland_test_driver_emit_sync_event (test_driver, 0); + meta_wayland_test_client_finish (wayland_test_client); + + clutter_virtual_input_device_notify_absolute_motion (virtual_pointer, + CLUTTER_CURRENT_TIME, + 550.0, 100.0); + wait_for_cursor_position (550.0, 100.0); + + wayland_test_client = meta_wayland_test_client_new ("xdg-toplevel-bounds"); + + wait_for_sync_point (1); + wait_until_after_paint (); + + window = find_client_window ("toplevel-bounds-test"); + + g_assert_nonnull (window->monitor); + meta_window_get_work_area_current_monitor (window, &work_area); + g_assert_cmpint (work_area.width, ==, 300); + g_assert_cmpint (work_area.height, ==, 200); + + g_assert_cmpint (window->rect.width, ==, 300 - 10); + g_assert_cmpint (window->rect.height, ==, 200 - 10); + + meta_wayland_test_driver_emit_sync_event (test_driver, 0); + meta_wayland_test_client_finish (wayland_test_client); +} + static void on_before_tests (void) { @@ -398,6 +670,10 @@ init_tests (void) toplevel_apply_limits); g_test_add_func ("/wayland/toplevel/activation", toplevel_activation); + g_test_add_func ("/wayland/toplevel/bounds/struts", + toplevel_bounds_struts); + g_test_add_func ("/wayland/toplevel/bounds/monitors", + toplevel_bounds_monitors); } int diff --git a/src/wayland/meta-wayland-legacy-xdg-shell.c b/src/wayland/meta-wayland-legacy-xdg-shell.c index cf822bcb6..b34a836c5 100644 --- a/src/wayland/meta-wayland-legacy-xdg-shell.c +++ b/src/wayland/meta-wayland-legacy-xdg-shell.c @@ -685,7 +685,7 @@ meta_wayland_zxdg_toplevel_v6_apply_state (MetaWaylandSurfaceRole *surface_role { MetaWaylandWindowConfiguration *configuration; - configuration = meta_wayland_window_configuration_new_empty (); + configuration = meta_wayland_window_configuration_new_empty (0, 0); meta_wayland_zxdg_toplevel_v6_send_configure (xdg_toplevel, configuration); meta_wayland_window_configuration_free (configuration); diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h index 598bdd2e5..cd1a73ea6 100644 --- a/src/wayland/meta-wayland-versions.h +++ b/src/wayland/meta-wayland-versions.h @@ -37,7 +37,7 @@ /* Global/master objects (version exported by wl_registry and negotiated through bind) */ #define META_WL_COMPOSITOR_VERSION 4 #define META_WL_DATA_DEVICE_MANAGER_VERSION 3 -#define META_XDG_WM_BASE_VERSION 3 +#define META_XDG_WM_BASE_VERSION 4 #define META_ZXDG_SHELL_V6_VERSION 1 #define META_WL_SEAT_VERSION 5 #define META_WL_OUTPUT_VERSION 2 diff --git a/src/wayland/meta-wayland-window-configuration.c b/src/wayland/meta-wayland-window-configuration.c index c1712136f..702c95a62 100644 --- a/src/wayland/meta-wayland-window-configuration.c +++ b/src/wayland/meta-wayland-window-configuration.c @@ -43,6 +43,8 @@ is_window_size_fixed (MetaWindow *window) MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new (MetaWindow *window, MetaRectangle rect, + int bounds_width, + int bounds_height, int scale, MetaMoveResizeFlags flags, MetaGravity gravity) @@ -53,6 +55,9 @@ meta_wayland_window_configuration_new (MetaWindow *window, *configuration = (MetaWaylandWindowConfiguration) { .serial = ++global_serial_counter, + .bounds_width = bounds_width, + .bounds_height = bounds_height, + .scale = scale, .gravity = gravity, .flags = flags, @@ -108,7 +113,8 @@ meta_wayland_window_configuration_new_relative (int rel_x, } MetaWaylandWindowConfiguration * -meta_wayland_window_configuration_new_empty (void) +meta_wayland_window_configuration_new_empty (int bounds_width, + int bounds_height) { MetaWaylandWindowConfiguration *configuration; @@ -116,6 +122,8 @@ meta_wayland_window_configuration_new_empty (void) *configuration = (MetaWaylandWindowConfiguration) { .serial = ++global_serial_counter, .scale = 1, + .bounds_width = bounds_width, + .bounds_height = bounds_height, }; return configuration; diff --git a/src/wayland/meta-wayland-window-configuration.h b/src/wayland/meta-wayland-window-configuration.h index 7e91a778e..c4c0f2e55 100644 --- a/src/wayland/meta-wayland-window-configuration.h +++ b/src/wayland/meta-wayland-window-configuration.h @@ -46,10 +46,15 @@ struct _MetaWaylandWindowConfiguration int scale; MetaGravity gravity; MetaMoveResizeFlags flags; + + int bounds_width; + int bounds_height; }; MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new (MetaWindow *window, MetaRectangle rect, + int max_width, + int max_height, int scale, MetaMoveResizeFlags flags, MetaGravity gravity); @@ -60,7 +65,8 @@ MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_relative int height, int scale); -MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_empty (void); +MetaWaylandWindowConfiguration * meta_wayland_window_configuration_new_empty (int bounds_width, + int bounds_height); void meta_wayland_window_configuration_free (MetaWaylandWindowConfiguration *configuration); diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c index acd0913d1..59a0f443e 100644 --- a/src/wayland/meta-wayland-xdg-shell.c +++ b/src/wayland/meta-wayland-xdg-shell.c @@ -700,6 +700,18 @@ meta_wayland_xdg_toplevel_send_configure (MetaWaylandXdgToplevel *xdg_to wl_array_init (&states); fill_states (xdg_toplevel, &states); + if (wl_resource_get_version (xdg_toplevel->resource) >= + XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION && + configuration->bounds_width > 0 && + configuration->bounds_height > 0) + { + xdg_toplevel_send_configure_bounds (xdg_toplevel->resource, + (configuration->bounds_width / + configuration->scale), + (configuration->bounds_height / + configuration->scale)); + } + xdg_toplevel_send_configure (xdg_toplevel->resource, configuration->width / configuration->scale, configuration->height / configuration->scale, @@ -777,8 +789,18 @@ meta_wayland_xdg_toplevel_apply_state (MetaWaylandSurfaceRole *surface_role, if (!xdg_surface_priv->configure_sent) { MetaWaylandWindowConfiguration *configuration; + int bounds_width; + int bounds_height; - configuration = meta_wayland_window_configuration_new_empty (); + if (!meta_window_calculate_bounds (window, &bounds_width, &bounds_height)) + { + bounds_width = 0; + bounds_height = 0; + } + + configuration = + meta_wayland_window_configuration_new_empty (bounds_width, + bounds_height); meta_wayland_xdg_toplevel_send_configure (xdg_toplevel, configuration); meta_wayland_window_configuration_free (configuration); return; diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c index 2a923ef8f..d0fbde843 100644 --- a/src/wayland/meta-window-wayland.c +++ b/src/wayland/meta-window-wayland.c @@ -181,6 +181,8 @@ surface_state_changed (MetaWindow *window) { MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); MetaWaylandWindowConfiguration *configuration; + int bounds_width; + int bounds_height; /* don't send notify when the window is being unmanaged */ if (window->unmanaging) @@ -188,9 +190,16 @@ surface_state_changed (MetaWindow *window) g_return_if_fail (wl_window->has_last_sent_configuration); + if (!meta_window_calculate_bounds (window, &bounds_width, &bounds_height)) + { + bounds_width = 0; + bounds_height = 0; + } + configuration = meta_wayland_window_configuration_new (window, wl_window->last_sent_rect, + bounds_width, bounds_height, wl_window->last_sent_geometry_scale, META_MOVE_RESIZE_STATE_CHANGED, wl_window->last_sent_gravity); @@ -345,6 +354,8 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, flags & META_MOVE_RESIZE_STATE_CHANGED) { MetaWaylandWindowConfiguration *configuration; + int bounds_width; + int bounds_height; if (!meta_wayland_surface_get_buffer (window->surface) && !META_WINDOW_MAXIMIZED (window) && @@ -352,9 +363,18 @@ meta_window_wayland_move_resize_internal (MetaWindow *window, !meta_window_is_fullscreen (window)) return; + if (!meta_window_calculate_bounds (window, + &bounds_width, + &bounds_height)) + { + bounds_width = 0; + bounds_height = 0; + } + configuration = meta_wayland_window_configuration_new (window, configured_rect, + bounds_width, bounds_height, geometry_scale, flags, gravity);