[mutter] wayland: add min/max size from xdg-shell v6
- From: Olivier Fourdan <ofourdan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] wayland: add min/max size from xdg-shell v6
- Date: Tue, 6 Sep 2016 06:55:32 +0000 (UTC)
commit 4f58a4621725ac657dcfa1e232af4e0d063b8f76
Author: Olivier Fourdan <ofourdan redhat com>
Date: Wed Apr 6 14:07:08 2016 +0200
wayland: add min/max size from xdg-shell v6
Implement min/max size request from xdg-shell-v6 and plug it into the
existing code so that windows with fixed size cannot be tiled/maximized
in Wayland just like in X11.
Bugzilla: https://bugzilla.gnome.org/show_bug.cgi?id=770226
src/wayland/meta-wayland-surface.c | 8 ++
src/wayland/meta-wayland-surface.h | 8 ++
src/wayland/meta-wayland-xdg-shell.c | 83 +++++++++++++++++-
src/wayland/meta-window-wayland.c | 163 +++++++++++++++++++++++++++++++++-
src/wayland/meta-window-wayland.h | 18 ++++
5 files changed, 275 insertions(+), 5 deletions(-)
---
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index ffa6e2e..bfddef7 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -479,6 +479,8 @@ pending_state_init (MetaWaylandPendingState *state)
wl_list_init (&state->frame_callback_list);
state->has_new_geometry = FALSE;
+ state->has_new_min_size = FALSE;
+ state->has_new_max_size = FALSE;
}
static void
@@ -523,6 +525,12 @@ move_pending_state (MetaWaylandPendingState *from,
to->opaque_region_set = from->opaque_region_set;
to->new_geometry = from->new_geometry;
to->has_new_geometry = from->has_new_geometry;
+ to->has_new_min_size = from->has_new_min_size;
+ to->new_min_width = from->new_min_width;
+ to->new_min_height = from->new_min_height;
+ to->has_new_max_size = from->has_new_max_size;
+ to->new_max_width = from->new_max_width;
+ to->new_max_height = from->new_max_height;
wl_list_init (&to->frame_callback_list);
wl_list_insert_list (&to->frame_callback_list, &from->frame_callback_list);
diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h
index 6c892de..1682fb6 100644
--- a/src/wayland/meta-wayland-surface.h
+++ b/src/wayland/meta-wayland-surface.h
@@ -142,6 +142,14 @@ struct _MetaWaylandPendingState
MetaRectangle new_geometry;
gboolean has_new_geometry;
+
+ /* pending min/max size in window geometry coordinates */
+ gboolean has_new_min_size;
+ int new_min_width;
+ int new_min_height;
+ gboolean has_new_max_size;
+ int new_max_width;
+ int new_max_height;
};
struct _MetaWaylandDragDestFuncs
diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c
index f2d8572..8831f8b 100644
--- a/src/wayland/meta-wayland-xdg-shell.c
+++ b/src/wayland/meta-wayland-xdg-shell.c
@@ -295,7 +295,20 @@ xdg_toplevel_set_max_size (struct wl_client *client,
int32_t width,
int32_t height)
{
- /* TODO */
+ MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
+
+ if (width < 0 || height < 0)
+ {
+ wl_resource_post_error (resource,
+ ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
+ "invalid negative max size requested %i x %i",
+ width, height);
+ return;
+ }
+
+ surface->pending->has_new_max_size = TRUE;
+ surface->pending->new_max_width = width;
+ surface->pending->new_max_height = height;
}
static void
@@ -304,7 +317,20 @@ xdg_toplevel_set_min_size (struct wl_client *client,
int32_t width,
int32_t height)
{
- /* TODO */
+ MetaWaylandSurface *surface = surface_from_xdg_toplevel_resource (resource);
+
+ if (width < 0 || height < 0)
+ {
+ wl_resource_post_error (resource,
+ ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
+ "invalid negative min size requested %i x %i",
+ width, height);
+ return;
+ }
+
+ surface->pending->has_new_min_size = TRUE;
+ surface->pending->new_min_width = width;
+ surface->pending->new_min_height = height;
}
static void
@@ -520,6 +546,37 @@ meta_wayland_xdg_toplevel_send_configure (MetaWaylandXdgToplevel *xdg_toplevel,
}
}
+static gboolean
+is_new_size_hints_valid (MetaWindow *window,
+ MetaWaylandPendingState *pending)
+{
+ int new_min_width, new_min_height;
+ int new_max_width, new_max_height;
+
+ if (pending->has_new_min_size)
+ {
+ new_min_width = pending->new_min_width;
+ new_min_height = pending->new_min_height;
+ }
+ else
+ {
+ meta_window_wayland_get_min_size (window, &new_min_width, &new_min_height);
+ }
+
+ if (pending->has_new_max_size)
+ {
+ new_max_width = pending->new_max_width;
+ new_max_height = pending->new_max_height;
+ }
+ else
+ {
+ meta_window_wayland_get_max_size (window, &new_max_width, &new_max_height);
+ }
+ /* Zero means unlimited */
+ return ((new_max_width == 0 || new_min_width <= new_max_width) &&
+ (new_max_height == 0 || new_min_height <= new_max_height));
+}
+
static void
xdg_toplevel_role_commit (MetaWaylandSurfaceRole *surface_role,
MetaWaylandPendingState *pending)
@@ -560,6 +617,28 @@ xdg_toplevel_role_commit (MetaWaylandSurfaceRole *surface_role,
return;
}
+ /* When we get to this point, we ought to have valid size hints */
+ if (pending->has_new_min_size || pending->has_new_max_size)
+ {
+ if (is_new_size_hints_valid (window, pending))
+ {
+ if (pending->has_new_min_size)
+ meta_window_wayland_set_min_size (window, pending->new_min_width, pending->new_min_height);
+
+ if (pending->has_new_max_size)
+ meta_window_wayland_set_max_size (window, pending->new_max_width, pending->new_max_height);
+
+ meta_window_recalc_features (window);
+ }
+ else
+ {
+ wl_resource_post_error (surface->resource,
+ ZXDG_SHELL_V6_ERROR_INVALID_SURFACE_STATE,
+ "Invalid min/max size");
+
+ }
+ }
+
window_geometry = meta_wayland_xdg_surface_get_window_geometry (xdg_surface);
meta_window_wayland_move_resize (window,
&xdg_surface_priv->acked_configure_serial,
diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c
index 85c4296..7dd6f42 100644
--- a/src/wayland/meta-window-wayland.c
+++ b/src/wayland/meta-window-wayland.c
@@ -325,10 +325,28 @@ meta_window_wayland_move_resize_internal (MetaWindow *window,
}
static void
-scale_rect_size (MetaRectangle *rect, float scale)
+scale_size (int *width,
+ int *height,
+ float scale)
{
- rect->width = (int)(rect->width * scale);
- rect->height = (int)(rect->height * scale);
+ if (*width < G_MAXINT)
+ {
+ float new_width = (*width * scale);
+ *width = (int) MIN (new_width, G_MAXINT);
+ }
+
+ if (*height < G_MAXINT)
+ {
+ float new_height = (*height * scale);
+ *height = (int) MIN (new_height, G_MAXINT);
+ }
+}
+
+static void
+scale_rect_size (MetaRectangle *rect,
+ float scale)
+{
+ scale_size (&rect->width, &rect->height, scale);
}
static void
@@ -399,6 +417,9 @@ meta_window_wayland_main_monitor_changed (MetaWindow *window,
scale_rect_size (&window->rect, scale_factor);
scale_rect_size (&window->unconstrained_rect, scale_factor);
scale_rect_size (&window->saved_rect, scale_factor);
+ scale_size (&window->size_hints.min_width, &window->size_hints.min_height, scale_factor);
+ scale_size (&window->size_hints.max_width, &window->size_hints.max_height, scale_factor);
+
/* Window geometry offset (XXX: Need a better place, see
* meta_window_wayland_move_resize). */
@@ -650,3 +671,139 @@ meta_window_place_with_placement_rule (MetaWindow *window,
window->unconstrained_rect.height = placement_rule->height;
meta_window_force_placement (window);
}
+
+void
+meta_window_wayland_set_min_size (MetaWindow *window,
+ int width,
+ int height)
+{
+ gint64 new_width, new_height;
+ float scale;
+
+ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets min size %d x %d\n",
+ window->desc, width, height);
+
+ if (width == 0 && height == 0)
+ {
+ window->size_hints.min_width = 0;
+ window->size_hints.min_height = 0;
+ window->size_hints.flags &= ~PMinSize;
+
+ return;
+ }
+
+ scale = (float) meta_window_wayland_get_main_monitor_scale (window);
+ scale_size (&width, &height, scale);
+
+ new_width = width + (window->custom_frame_extents.left +
+ window->custom_frame_extents.right);
+ new_height = height + (window->custom_frame_extents.top +
+ window->custom_frame_extents.bottom);
+
+ window->size_hints.min_width = (int) MIN (new_width, G_MAXINT);
+ window->size_hints.min_height = (int) MIN (new_height, G_MAXINT);
+ window->size_hints.flags |= PMinSize;
+}
+
+void
+meta_window_wayland_set_max_size (MetaWindow *window,
+ int width,
+ int height)
+
+{
+ gint64 new_width, new_height;
+ float scale;
+
+ meta_topic (META_DEBUG_GEOMETRY, "Window %s sets max size %d x %d\n",
+ window->desc, width, height);
+
+ if (width == 0 && height == 0)
+ {
+ window->size_hints.max_width = G_MAXINT;
+ window->size_hints.max_height = G_MAXINT;
+ window->size_hints.flags &= ~PMaxSize;
+
+ return;
+ }
+
+ scale = (float) meta_window_wayland_get_main_monitor_scale (window);
+ scale_size (&width, &height, scale);
+
+ new_width = width + (window->custom_frame_extents.left +
+ window->custom_frame_extents.right);
+ new_height = height + (window->custom_frame_extents.top +
+ window->custom_frame_extents.bottom);
+
+ window->size_hints.max_width = (int) ((new_width > 0 && new_width < G_MAXINT) ?
+ new_width : G_MAXINT);
+ window->size_hints.max_height = (int) ((new_height > 0 && new_height < G_MAXINT) ?
+ new_height : G_MAXINT);
+ window->size_hints.flags |= PMaxSize;
+}
+
+void
+meta_window_wayland_get_min_size (MetaWindow *window,
+ int *width,
+ int *height)
+{
+ gint64 current_width, current_height;
+ float scale;
+
+ if (!(window->size_hints.flags & PMinSize))
+ {
+ /* Zero means unlimited */
+ *width = 0;
+ *height = 0;
+
+ return;
+ }
+
+ current_width = window->size_hints.min_width -
+ (window->custom_frame_extents.left +
+ window->custom_frame_extents.right);
+ current_height = window->size_hints.min_height -
+ (window->custom_frame_extents.top +
+ window->custom_frame_extents.bottom);
+
+ *width = MAX (current_width, 0);
+ *height = MAX (current_height, 0);
+
+ scale = 1.0 / (float) meta_window_wayland_get_main_monitor_scale (window);
+ scale_size (width, height, scale);
+}
+
+void
+meta_window_wayland_get_max_size (MetaWindow *window,
+ int *width,
+ int *height)
+{
+ gint64 current_width = 0;
+ gint64 current_height = 0;
+ float scale;
+
+ if (!(window->size_hints.flags & PMaxSize))
+ {
+ /* Zero means unlimited */
+ *width = 0;
+ *height = 0;
+
+ return;
+ }
+
+ if (window->size_hints.max_width < G_MAXINT)
+ current_width = window->size_hints.max_width -
+ (window->custom_frame_extents.left +
+ window->custom_frame_extents.right);
+
+ if (window->size_hints.max_height < G_MAXINT)
+ current_height = window->size_hints.max_height -
+ (window->custom_frame_extents.top +
+ window->custom_frame_extents.bottom);
+
+ *width = CLAMP (current_width, 0, G_MAXINT);
+ *height = CLAMP (current_height, 0, G_MAXINT);
+
+ scale = 1.0 / (float) meta_window_wayland_get_main_monitor_scale (window);
+ scale_size (width, height, scale);
+}
+
diff --git a/src/wayland/meta-window-wayland.h b/src/wayland/meta-window-wayland.h
index 1847f70..b7d7b20 100644
--- a/src/wayland/meta-window-wayland.h
+++ b/src/wayland/meta-window-wayland.h
@@ -61,4 +61,22 @@ void meta_window_wayland_place_relative_to (MetaWindow *window,
void meta_window_place_with_placement_rule (MetaWindow *window,
MetaPlacementRule *placement_rule);
+void meta_window_wayland_set_min_size (MetaWindow *window,
+ int width,
+ int height);
+
+void meta_window_wayland_set_max_size (MetaWindow *window,
+ int width,
+ int height);
+
+void meta_window_wayland_get_min_size (MetaWindow *window,
+ int *width,
+ int *height);
+
+
+void meta_window_wayland_get_max_size (MetaWindow *window,
+ int *width,
+ int *height);
+
+
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]