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
This commit is contained in:
parent
3acd562a41
commit
4f58a46217
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user