diff --git a/clients/window.c b/clients/window.c
index 97cce1a4..91c1ea06 100644
--- a/clients/window.c
+++ b/clients/window.c
@@ -3937,6 +3937,27 @@ window_sync_transient_for(struct window *window)
xdg_surface_set_transient_for(window->xdg_surface, parent_surface);
}
+static void
+window_sync_margin(struct window *window)
+{
+ int margin;
+
+ if (!window->xdg_surface)
+ return;
+
+ if (!window->frame)
+ return;
+
+ margin = frame_get_shadow_margin(window->frame->frame);
+
+ /* Shadow size is the same on every side. */
+ xdg_surface_set_margin(window->xdg_surface,
+ margin,
+ margin,
+ margin,
+ margin);
+}
+
static void
window_flush(struct window *window)
{
@@ -3953,6 +3974,7 @@ window_flush(struct window *window)
&xdg_surface_listener, window);
window_sync_transient_for(window);
+ window_sync_margin(window);
}
}
diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
index b9b49cb5..a73e8e02 100644
--- a/desktop-shell/shell.c
+++ b/desktop-shell/shell.c
@@ -3171,6 +3171,18 @@ xdg_surface_pong(struct wl_client *client,
surface_pong(shsurf, serial);
}
+static void
+xdg_surface_set_margin(struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t left,
+ int32_t right,
+ int32_t top,
+ int32_t bottom)
+{
+ /* Do nothing, Weston doesn't try to constrain or place
+ * surfaces in any special manner... */
+}
+
static void
xdg_surface_set_app_id(struct wl_client *client,
struct wl_resource *resource,
@@ -3309,6 +3321,7 @@ xdg_surface_unset_maximized(struct wl_client *client,
static const struct xdg_surface_interface xdg_surface_implementation = {
xdg_surface_destroy,
xdg_surface_set_transient_for,
+ xdg_surface_set_margin,
xdg_surface_set_title,
xdg_surface_set_app_id,
xdg_surface_pong,
diff --git a/protocol/xdg-shell.xml b/protocol/xdg-shell.xml
index 5c21f4eb..f0d04aa3 100644
--- a/protocol/xdg-shell.xml
+++ b/protocol/xdg-shell.xml
@@ -124,6 +124,32 @@
+
+
+ This tells the compositor what the visible size of the window
+ should be, so it can use it to determine what borders to use for
+ constrainment and alignment.
+
+ CSD often has invisible areas for decoration purposes, like drop
+ shadows. These "shadow" drawings need to be subtracted out of the
+ normal boundaries of the window when computing where to place
+ windows (e.g. to set this window so it's centered on top of another,
+ or to put it to the left or right of the screen.)
+
+ This value should change as little as possible at runtime, to
+ prevent flicker.
+
+ This value is also ignored when the window is maximized or
+ fullscreen, and assumed to be 0.
+
+ If never called, this value is assumed to be 0.
+
+
+
+
+
+
+
Set a short title for the surface.
diff --git a/shared/cairo-util.h b/shared/cairo-util.h
index 7bcbc296..4493b0d9 100644
--- a/shared/cairo-util.h
+++ b/shared/cairo-util.h
@@ -165,6 +165,9 @@ void
frame_opaque_rect(struct frame *frame, int32_t *x, int32_t *y,
int32_t *width, int32_t *height);
+int
+frame_get_shadow_margin(struct frame *frame);
+
uint32_t
frame_status(struct frame *frame);
diff --git a/shared/frame.c b/shared/frame.c
index a039d157..35e6b65e 100644
--- a/shared/frame.c
+++ b/shared/frame.c
@@ -578,6 +578,14 @@ frame_opaque_rect(struct frame *frame, int32_t *x, int32_t *y,
*height = frame->height - frame->opaque_margin * 2;
}
+int
+frame_get_shadow_margin(struct frame *frame)
+{
+ frame_refresh_geometry(frame);
+
+ return frame->shadow_margin;
+}
+
uint32_t
frame_status(struct frame *frame)
{