After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 770226 - wayland: add min/max size from xdg-shell v6
wayland: add min/max size from xdg-shell v6
Status: RESOLVED FIXED
Product: mutter
Classification: Core
Component: wayland
git master
Other Linux
: Normal normal
: ---
Assigned To: mutter-maint
mutter-maint
Depends on:
Blocks:
 
 
Reported: 2016-08-22 09:35 UTC by Olivier Fourdan
Modified: 2016-09-06 06:56 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
[PATCH] wayland: add min/max size from xdg-shell v6 (12.01 KB, patch)
2016-08-22 09:36 UTC, Olivier Fourdan
none Details | Review
[PATCH] wayland: add min/max size from xdg-shell v6 (16.60 KB, patch)
2016-09-02 17:28 UTC, Olivier Fourdan
none Details | Review
[PATCH] wayland: add min/max size from xdg-shell v6 (16.58 KB, patch)
2016-09-02 17:29 UTC, Olivier Fourdan
none Details | Review
[PATCH] wayland: add min/max size from xdg-shell v6 (13.28 KB, patch)
2016-09-05 12:17 UTC, Olivier Fourdan
committed Details | Review

Description Olivier Fourdan 2016-08-22 09:35:59 UTC
Spin off bug 764413 for the mutter part.
Comment 1 Olivier Fourdan 2016-08-22 09:36:51 UTC
Created attachment 333875 [details] [review]
[PATCH] wayland: add min/max size from xdg-shell v6
Comment 2 Olivier Fourdan 2016-08-22 09:38:28 UTC
Patch has been rebased on top of https://github.com/jadahl/mutter.git :wip/xdg-shell-v6
Comment 3 Olivier Fourdan 2016-09-02 07:10:06 UTC
Anyone to review this patch?
Comment 4 Jonas Ådahl 2016-09-02 07:33:31 UTC
Review of attachment 333875 [details] [review]:

::: src/wayland/meta-wayland-surface.h
@@ +148,3 @@
+  gboolean has_new_min_geometry;
+  MetaRectangle max_geometry;
+  gboolean has_new_max_geometry;

I'd rather see we use a more correct data type even if it means having two 'int'. It's also not a "min/max" geometry, its a min/max size. The geometry includes an position offset.

::: src/wayland/meta-wayland-xdg-shell.c
@@ +634,3 @@
+       check_valid_size_hints (window);
+       meta_window_wayland_update_size_hints (window);
+    }

I'd rather see this as something like

static gboolean
is_new_size_hints_valid (MetaWindow              *window,
                         MetaWaylandPendingState *pending)
{
  ...
}

if (is_new_size_hints_valid (window, pending))
  {
    actually_set_new_size_hints (window, pending);
  }
else
  {
    wl_resource_post_error (...);
  }

So that we don't actually set things it in a function called "check".

::: src/wayland/meta-window-wayland.c
@@ +54,3 @@
+  /* min/max size in window geometry coordinates */
+  MetaRectangle min_size;
+  MetaRectangle max_size;

Do we really need these? Whats wrong with the window->size_hints (except being an X11 data type)?

@@ +499,3 @@
   MetaScreen *scr = display->screen;
   MetaWindow *window;
+  MetaRectangle none = {0, 0, 0, 0};

nit: can be { 0 };

@@ +730,3 @@
+                        window->custom_frame_extents.bottom);
+      else
+        size.height = G_MAXINT;

Won't this potentially overflow if we scale up?

::: src/wayland/meta-window-wayland.h
@@ +65,3 @@
+
+void meta_window_wayland_set_min_size (MetaWindow    *window,
+                                       MetaRectangle *size);

Why is size a rectangle? Makes more sense to have it just 'int *with, int *height' if we don't have a data type that represents that.
Comment 5 Olivier Fourdan 2016-09-02 08:22:41 UTC
(In reply to Jonas Ådahl from comment #4)
> Review of attachment 333875 [details] [review] [review]:
> [...]
> ::: src/wayland/meta-window-wayland.c
> @@ +54,3 @@
> +  /* min/max size in window geometry coordinates */
> +  MetaRectangle min_size;
> +  MetaRectangle max_size;
> 
> Do we really need these? Whats wrong with the window->size_hints (except
> being an X11 data type)?

Yes, I think we do, because min/max size here are in window geometry coordinates and need to be adjusted depending in the output scale.

So we need to keep those around when the window is move to another output with a different scaling factor, so that we can then adjust the window->size_hints which is in pixels.
Comment 6 Jonas Ådahl 2016-09-02 08:28:35 UTC
(In reply to Olivier Fourdan from comment #5)
> (In reply to Jonas Ådahl from comment #4)
> > Review of attachment 333875 [details] [review] [review] [review]:
> > [...]
> > ::: src/wayland/meta-window-wayland.c
> > @@ +54,3 @@
> > +  /* min/max size in window geometry coordinates */
> > +  MetaRectangle min_size;
> > +  MetaRectangle max_size;
> > 
> > Do we really need these? Whats wrong with the window->size_hints (except
> > being an X11 data type)?
> 
> Yes, I think we do, because min/max size here are in window geometry
> coordinates and need to be adjusted depending in the output scale.
> 
> So we need to keep those around when the window is move to another output
> with a different scaling factor, so that we can then adjust the
> window->size_hints which is in pixels.

Can't those be scaled properly still? I mean we know the scale they were in, and we know the scale they are to be converted to, so we know how to scale them, without using the non-scaled dimensions. See how scale_rect_size() is used on window->rect, window->unconstrained_rect and window->saved_rect.
Comment 7 Olivier Fourdan 2016-09-02 08:32:54 UTC
(In reply to Jonas Ådahl from comment #6)
> Can't those be scaled properly still? I mean we know the scale they were in,
> and we know the scale they are to be converted to, so we know how to scale
> them, without using the non-scaled dimensions. See how scale_rect_size() is
> used on window->rect, window->unconstrained_rect and window->saved_rect.

Yes, that's how I did it initially, but I found this adds needless complexity to a rather simple code otherwise. But I can change that if needed.
Comment 8 Jonas Ådahl 2016-09-02 08:36:54 UTC
(In reply to Olivier Fourdan from comment #7)
> (In reply to Jonas Ådahl from comment #6)
> > Can't those be scaled properly still? I mean we know the scale they were in,
> > and we know the scale they are to be converted to, so we know how to scale
> > them, without using the non-scaled dimensions. See how scale_rect_size() is
> > used on window->rect, window->unconstrained_rect and window->saved_rect.
> 
> Yes, that's how I did it initially, but I found this adds needless
> complexity to a rather simple code otherwise. But I can change that if
> needed.

As it'd be just another scale_rect_size (window->..., scale_factor); next to all the others I'd say it'd be less complex doing it that way.
Comment 9 Olivier Fourdan 2016-09-02 08:57:26 UTC
No, it's all that simple because mutter uses G_MAXINT when the max size is not set, so we need to test for those special cases and not scale them, which is ugly.

See meta_set_normal_hints()

   https://git.gnome.org/browse/mutter/tree/src/x11/window-props.c#n1223

Apparently, this way, it doesn;t have to check for the actual value of the size flags once this is done...
Comment 10 Jonas Ådahl 2016-09-02 09:01:37 UTC
(In reply to Olivier Fourdan from comment #9)
> No, it's all that simple because mutter uses G_MAXINT when the max size is
> not set, so we need to test for those special cases and not scale them,
> which is ugly.
> 
> See meta_set_normal_hints()
> 
>    https://git.gnome.org/browse/mutter/tree/src/x11/window-props.c#n1223
> 
> Apparently, this way, it doesn;t have to check for the actual value of the
> size flags once this is done...

Ah, I see. Can't scale_rect_size be fixed to handle widtdh/height == INT_MAX as a special case?
Comment 11 Olivier Fourdan 2016-09-02 09:04:31 UTC
(In reply to Jonas Ådahl from comment #10)
> Ah, I see. Can't scale_rect_size be fixed to handle widtdh/height == INT_MAX
> as a special case?

Yes, that would be the least ugly :) I'll try that instead (reason I initially ruled this out was to avoid changing code shared elsewhere)
Comment 12 Olivier Fourdan 2016-09-02 17:28:59 UTC
Created attachment 334664 [details] [review]
[PATCH] wayland: add min/max size from xdg-shell v6

Updated patch - This ended up being a lot more work that anticipated actually, but that seems to work.
Comment 13 Olivier Fourdan 2016-09-02 17:29:55 UTC
Created attachment 334665 [details] [review]
[PATCH] wayland: add min/max size from xdg-shell v6
Comment 14 Olivier Fourdan 2016-09-02 17:34:01 UTC
Note: I tested only in mutter as I have some difficulties building/running gnome-shell from git master at the moment...
Comment 15 Jonas Ådahl 2016-09-03 03:07:06 UTC
Review of attachment 334665 [details] [review]:

::: src/wayland/meta-wayland-xdg-shell.c
@@ +630,3 @@
+
+      return TRUE;
+    }

Couldn't this function be simplified to

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_min_size (window, &new_max_width, &new_max_height);
  }

return new_min_width <= new_max_width && new_min_height <= new_max_height;


?

@@ +687,3 @@
+
+          meta_window_recalc_features (window);
+        }

I think a "is_...()" function should still be side-effect less, i.e. post error here. I don't think we need any more error message than "size limit invalid".

::: src/wayland/meta-window-wayland.c
@@ +334,1 @@
 }

nit: Actually think it'd be nicer to have

static void
scale_size (int  *width
            int  *height,
            float scale)
{
  if (width < INT_MAX)
    *width = (int)(width * scale);
  if (height < INT_MAX)
    *height = (int)(height * scale);
}

static void
scale_rect_size (MetaRectangle *rect,
                 float          scale)
{
  scale_size (&rect->width, &rect->height, scale);
}

so that you don't have to create all those dummy rects.

@@ +704,3 @@
+    rect.width = MIN (G_MAXINT,
+                      rect.width + (window->custom_frame_extents.left +
+                                    window->custom_frame_extents.right));

Hmm. MIN (INT_MAX, ...) feels like ... will always be less (than the highest number possible). Or did you mean to make the right hand expression a (uint64_t) so that it can actually be greater?
Comment 16 Olivier Fourdan 2016-09-03 06:08:38 UTC
(In reply to Jonas Ådahl from comment #15)
> Review of attachment 334665 [details] [review] [review]:
> 
> ::: src/wayland/meta-wayland-xdg-shell.c
> @@ +630,3 @@
> +
> +      return TRUE;
> +    }
> 
> Couldn't this function be simplified to
> 
> 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_min_size (window, &new_max_width,
> &new_max_height);
>   }
> 
> return new_min_width <= new_max_width && new_min_height <= new_max_height;

Tempting, but we still need to check for 0, as a value size of 0 in a new request means it's unlimited, so a client may request a new max size with one dimension set and the other not.

That doesn't matter for min size, but it does for max size. Another possibility is to set a max size of 0 in get_max_size for unlimited values so that we remain consistent in sizes semantics and the test would work in all cases.
 
> @@ +687,3 @@
> +
> +          meta_window_recalc_features (window);
> +        }
> 
> I think a "is_...()" function should still be side-effect less, i.e. post
> error here. I don't think we need any more error message than "size limit
> invalid".

That's very useful for debugging clients, the compositor tells exactly why the size is invalid - Making it a generic invalid size limit will makes debugging harder.
 
> ::: src/wayland/meta-window-wayland.c
> @@ +334,1 @@
>  }
> 
> nit: Actually think it'd be nicer to have
> 
> static void
> scale_size (int  *width
>             int  *height,
>             float scale)
> {
>   if (width < INT_MAX)
>     *width = (int)(width * scale);
>   if (height < INT_MAX)
>     *height = (int)(height * scale);
> }
> 
> static void
> scale_rect_size (MetaRectangle *rect,
>                  float          scale)
> {
>   scale_size (&rect->width, &rect->height, scale);
> }
> 
> so that you don't have to create all those dummy rects.

Good idea!
 
> @@ +704,3 @@
> +    rect.width = MIN (G_MAXINT,
> +                      rect.width + (window->custom_frame_extents.left +
> +                                    window->custom_frame_extents.right));
> 
> Hmm. MIN (INT_MAX, ...) feels like ... will always be less (than the highest
> number possible). Or did you mean to make the right hand expression a
> (uint64_t) so that it can actually be greater?

Yeah, it's probably overkill and useless, although I don't know exactly how the compiler deals with such intermediate cases internally.
Comment 17 Jonas Ådahl 2016-09-03 07:25:33 UTC
(In reply to Olivier Fourdan from comment #16)
> (In reply to Jonas Ådahl from comment #15)
> > Review of attachment 334665 [details] [review] [review] [review]:
> > 
> > ::: src/wayland/meta-wayland-xdg-shell.c
> > @@ +630,3 @@
> > +
> > +      return TRUE;
> > +    }
> > 
> > Couldn't this function be simplified to
> > 
> > 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_min_size (window, &new_max_width,
> > &new_max_height);
> >   }
> > 
> > return new_min_width <= new_max_width && new_min_height <= new_max_height;
> 
> Tempting, but we still need to check for 0, as a value size of 0 in a new
> request means it's unlimited, so a client may request a new max size with
> one dimension set and the other not.

The main simplification was the "what-if" new_min/max_width/height.

> 
> That doesn't matter for min size, but it does for max size. Another
> possibility is to set a max size of 0 in get_max_size for unlimited values
> so that we remain consistent in sizes semantics and the test would work in
> all cases.
>  
> > @@ +687,3 @@
> > +
> > +          meta_window_recalc_features (window);
> > +        }
> > 
> > I think a "is_...()" function should still be side-effect less, i.e. post
> > error here. I don't think we need any more error message than "size limit
> > invalid".
> 
> That's very useful for debugging clients, the compositor tells exactly why
> the size is invalid - Making it a generic invalid size limit will makes
> debugging harder.

Personally I don't think complicating things is worth the better error messages for this particular case; its just size comparation. If you insist, then should reflect the side-effect-ness in the naming, (my is_...() suggestion was only if it was just checking, not disconnecting clients).

>  
> > ::: src/wayland/meta-window-wayland.c
> > @@ +334,1 @@
> >  }
> > 
> > nit: Actually think it'd be nicer to have
> > 
> > static void
> > scale_size (int  *width
> >             int  *height,
> >             float scale)
> > {
> >   if (width < INT_MAX)
> >     *width = (int)(width * scale);
> >   if (height < INT_MAX)
> >     *height = (int)(height * scale);
> > }
> > 
> > static void
> > scale_rect_size (MetaRectangle *rect,
> >                  float          scale)
> > {
> >   scale_size (&rect->width, &rect->height, scale);
> > }
> > 
> > so that you don't have to create all those dummy rects.
> 
> Good idea!
>  
> > @@ +704,3 @@
> > +    rect.width = MIN (G_MAXINT,
> > +                      rect.width + (window->custom_frame_extents.left +
> > +                                    window->custom_frame_extents.right));
> > 
> > Hmm. MIN (INT_MAX, ...) feels like ... will always be less (than the highest
> > number possible). Or did you mean to make the right hand expression a
> > (uint64_t) so that it can actually be greater?
> 
> Yeah, it's probably overkill and useless, although I don't know exactly how
> the compiler deals with such intermediate cases internally.

We could do it properly by using INT32_MAX and casting something to (int64_t) in the right-hand-side expression. A broken client can still pass a less than INT_MAX large value that will still cause issues, and for that it'd be good to clamp properly.
Comment 18 Olivier Fourdan 2016-09-05 12:17:43 UTC
Created attachment 334801 [details] [review]
[PATCH] wayland: add min/max size from xdg-shell v6

Updated patch
Comment 19 Jonas Ådahl 2016-09-06 02:55:15 UTC
Review of attachment 334801 [details] [review]:

Looks good to me.
Comment 20 Olivier Fourdan 2016-09-06 06:56:14 UTC
Comment on attachment 334801 [details] [review]
[PATCH] wayland: add min/max size from xdg-shell v6

attachment 334801 [details] [review] pushed to git master as commit 4f58a46 - wayland: add min/max size from xdg-shell v6