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 745655 - wayland: Fix subsurface positioning on HiDPI
wayland: Fix subsurface positioning on HiDPI
Status: RESOLVED FIXED
Product: mutter
Classification: Core
Component: wayland
unspecified
Other All
: Normal normal
: ---
Assigned To: mutter-maint
mutter-maint
Depends on: 743617
Blocks:
 
 
Reported: 2015-03-05 08:17 UTC by Jonas Ådahl
Modified: 2015-07-16 03:48 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
wayland: Fix subsurface positioning on HiDPI (6.16 KB, patch)
2015-03-05 08:17 UTC, Jonas Ådahl
none Details | Review
wayland: Fix subsurface place_above/below type cast error (1.64 KB, patch)
2015-03-05 08:17 UTC, Jonas Ådahl
none Details | Review
wayland: Fix subsurface place_above/below type cast error (1.88 KB, patch)
2015-03-19 03:46 UTC, Jonas Ådahl
committed Details | Review
wayland: Factor out some parts of meta_surface_actor_wayland_get_scale (5.07 KB, patch)
2015-03-25 10:06 UTC, Jonas Ådahl
committed Details | Review
wayland: Fix subsurface positioning on HiDPI (7.45 KB, patch)
2015-03-25 10:06 UTC, Jonas Ådahl
none Details | Review
wayland: Fix subsurface positioning on HiDPI (7.45 KB, patch)
2015-03-27 09:48 UTC, Jonas Ådahl
committed Details | Review

Description Jonas Ådahl 2015-03-05 08:17:06 UTC
Positioning of subsurfaces was broken on the Wayland backend when on a high DPI monitor. The first patch fixes that, and the other fixes an unrelated invalid type cast.

These patches depends on the patches in https://bugzilla.gnome.org/show_bug.cgi?id=743617 and https://bugzilla.gnome.org/show_bug.cgi?id=744453 .
Comment 1 Jonas Ådahl 2015-03-05 08:17:13 UTC
Created attachment 298604 [details] [review]
wayland: Fix subsurface positioning on HiDPI

Keep the active position state in its original coordinate space, and
synchronize the surface actor with it when it changes and when
synchronizing the rest of the surface state, in case the surface scale
had changed.
Comment 2 Jonas Ådahl 2015-03-05 08:17:18 UTC
Created attachment 298605 [details] [review]
wayland: Fix subsurface place_above/below type cast error

A MetaWaylandSurface was casted into a ClutterActor, but it should have
been the MetaSurfaceActor.
Comment 3 Owen Taylor 2015-03-18 14:35:22 UTC
Review of attachment 298604 [details] [review]:

::: src/compositor/meta-surface-actor-wayland.c
@@ +140,3 @@
+
+  texture_scale = meta_surface_actor_wayland_get_scale (self);
+  scale = (int)(surface->scale * texture_scale);

This is propagating a bug that we have in the current code. surface->scale is the scale factor specified by the application and says what the scale factor is between pixels and that buffer and logical pixels. But an app is perfectly free to provide a buffer with a scale factor of 2 on a non-hidpi screen. The scale factor between logical pixels and device pixels for a window is up to the compositor - for right now, it should be the scale factor of the "main monitor" for the window.
Comment 4 Owen Taylor 2015-03-18 14:41:36 UTC
Review of attachment 298605 [details] [review]:

Patch looks correct. I think stylistically it would be better to pull surface_actor actor out of the loop as well if you are pulling parent_actor out, since having parent_actor separate from surface_actor implies that surface_actor is like sibling_actor and varies per-op.
Comment 5 Jonas Ådahl 2015-03-18 15:07:06 UTC
Review of attachment 298604 [details] [review]:

::: src/compositor/meta-surface-actor-wayland.c
@@ +140,3 @@
+
+  texture_scale = meta_surface_actor_wayland_get_scale (self);
+  scale = (int)(surface->scale * texture_scale);

If a client provides a surface with a scale 2 buffer and its drawn on a scale 1 output, we should scale the buffer with output->scale / surface->scale = 1 / 2 = 0.5. That is what meta_surface_actor_wayland_get_scale does. Meaning:

 texture_scale = output->scale / surface->scale (where output = "main monitor" output)
 scale = surface->scale * texture_scale =
       = surface->scale * (output->scale / surface->scale) =
       = output->scale

except that meta_surface_actor_wayland_get_scale doesn't return "output->scale / surface->scale" for surfaces which top level parent is an Xwayland window since they are never scaled. So we don't actually hit that bug, but would still work for the hypothetical case where Xwayland starts using subsurfaces. That might never happen though so might be unnecessary confusion.
Comment 6 Owen Taylor 2015-03-18 19:29:06 UTC
(In reply to Jonas Ådahl from comment #5)
> Review of attachment 298604 [details] [review] [review]:
> 
> ::: src/compositor/meta-surface-actor-wayland.c
> @@ +140,3 @@
> +
> +  texture_scale = meta_surface_actor_wayland_get_scale (self);
> +  scale = (int)(surface->scale * texture_scale);
> 
> If a client provides a surface with a scale 2 buffer and its drawn on a
> scale 1 output, we should scale the buffer with output->scale /
> surface->scale = 1 / 2 = 0.5. That is what
> meta_surface_actor_wayland_get_scale does. Meaning:
> 
>  texture_scale = output->scale / surface->scale (where output = "main
> monitor" output)
>  scale = surface->scale * texture_scale =
>        = surface->scale * (output->scale / surface->scale) =
>        = output->scale

OK - true - sorry for not reading the code closely enough. 

But - but - the logical-to-device scale for a surface is something that's a fundamental property, not a derived property, so getting it by multiplying and dividing by surface->scale is really roundabout. There likely should be a MetaWaylandSurface getter for this - which can do the walking up the parent hierarchy. Then when the output scale is needed it can be computed from that. 

(surface->scale and meta_surface_actor_wayland_get_scale are both bad names, because there's no unique thing that is a "scale")
Comment 7 Jonas Ådahl 2015-03-19 03:44:14 UTC
(In reply to Owen Taylor from comment #6)
> (In reply to Jonas Ådahl from comment #5)
> > Review of attachment 298604 [details] [review] [review] [review]:
> > 
> > ::: src/compositor/meta-surface-actor-wayland.c
> > @@ +140,3 @@
> > +
> > +  texture_scale = meta_surface_actor_wayland_get_scale (self);
> > +  scale = (int)(surface->scale * texture_scale);
> > 
> > If a client provides a surface with a scale 2 buffer and its drawn on a
> > scale 1 output, we should scale the buffer with output->scale /
> > surface->scale = 1 / 2 = 0.5. That is what
> > meta_surface_actor_wayland_get_scale does. Meaning:
> > 
> >  texture_scale = output->scale / surface->scale (where output = "main
> > monitor" output)
> >  scale = surface->scale * texture_scale =
> >        = surface->scale * (output->scale / surface->scale) =
> >        = output->scale
> 
> OK - true - sorry for not reading the code closely enough. 
> 
> But - but - the logical-to-device scale for a surface is something that's a
> fundamental property, not a derived property, so getting it by multiplying
> and dividing by surface->scale is really roundabout. There likely should be
> a MetaWaylandSurface getter for this - which can do the walking up the
> parent hierarchy. Then when the output scale is needed it can be computed
> from that.

Except that "output" here really is state of the window, not the Wayland surface. A Wayland surface doesn't and shouldn't have a single "output" parameter, as thats something that is purely a rendering and window management detail.

If we want to avoid the surface->scale * texture_scale thing, we should rather not allow subsurfaces on Xwayland windows and then just use the output->scale in that case, but I don't think it should be a MetaWaylandSurface getter.

> 
> (surface->scale and meta_surface_actor_wayland_get_scale are both bad names,
> because there's no unique thing that is a "scale")

Yes, It should rather be something like surface->buffer_scale and meta_surface_actor_calculate_texture_scale ().
Comment 8 Jonas Ådahl 2015-03-19 03:46:12 UTC
Created attachment 299779 [details] [review]
wayland: Fix subsurface place_above/below type cast error

A MetaWaylandSurface was casted into a ClutterActor, but it should have
been the MetaSurfaceActor.

Move out parent_actor and surface_actor out of the loop while at it
since they won't change when iterating.
Comment 9 Jasper St. Pierre (not reading bugmail) 2015-03-19 03:47:06 UTC
For now, a Wayland surface's output is the same as its parent's window, and a toplevel surface's output is its window's output.
Comment 10 Jasper St. Pierre (not reading bugmail) 2015-03-19 03:47:25 UTC
Review of attachment 299779 [details] [review]:

OK.
Comment 11 Jonas Ådahl 2015-03-25 10:06:24 UTC
Created attachment 300261 [details] [review]
wayland: Factor out some parts of meta_surface_actor_wayland_get_scale

Put a toplevel window getter in meta-wayland-surface.h and a main
monitor scale getter in window-wayland.h.
Comment 12 Jonas Ådahl 2015-03-25 10:06:30 UTC
Created attachment 300262 [details] [review]
wayland: Fix subsurface positioning on HiDPI

Keep the active position state in its original coordinate space, and
synchronize the surface actor with it when it changes and when
synchronizing the rest of the surface state, in case the surface scale
had changed.
Comment 13 Jonas Ådahl 2015-03-27 09:48:18 UTC
Created attachment 300424 [details] [review]
wayland: Fix subsurface positioning on HiDPI

Keep the active position state in its original coordinate space, and
synchronize the surface actor with it when it changes and when
synchronizing the rest of the surface state, in case the surface scale
had changed.

----

Changes since previous version:

 - Fixed incorrect g_warn_if_fail conditions
Comment 14 Owen Taylor 2015-04-10 15:13:58 UTC
Review of attachment 300261 [details] [review]:

Looks fine. With https://bug744934.bugzilla-attachments.gnome.org/attachment.cgi?id=301180 does meta_window_wayland_get_main_monitor_scale() just become window->monitor->scale ?
Comment 15 Owen Taylor 2015-04-10 15:33:56 UTC
Review of attachment 300424 [details] [review]:

Looks good to me.

::: src/compositor/meta-surface-actor-wayland.c
@@ +131,3 @@
+       * to happen. */
+      g_warn_if_fail (clutter_actor_get_x (CLUTTER_ACTOR (self)) == 0);
+      g_warn_if_fail (clutter_actor_get_y (CLUTTER_ACTOR (self)) == 0);

Are you worried that an application embedding Mutter will move the surface around within the window actor? If so, it seems like it should get what it deserves - there are all sorts of other things that *could* be done to the scene graph (like doing the same thing to a wayland window...) and this one isn't particularly worth a warning.
Comment 16 Jonas Ådahl 2015-04-10 15:47:13 UTC
Review of attachment 300424 [details] [review]:

::: src/compositor/meta-surface-actor-wayland.c
@@ +131,3 @@
+       * to happen. */
+      g_warn_if_fail (clutter_actor_get_x (CLUTTER_ACTOR (self)) == 0);
+      g_warn_if_fail (clutter_actor_get_y (CLUTTER_ACTOR (self)) == 0);

These warnings were because normally the relative position should be (0,0) because Xwayland is not expected to deal with subsurfaces (which positions the surface actor relative to its parent actor), and if Xwayland changed that we'd get a warning. I suppose an application can move around surface actors, but that application should be aware that doing that will more or less break subsurfaces and other things.
Comment 17 Owen Taylor 2015-04-10 16:12:27 UTC
(In reply to Jonas Ådahl from comment #16)
> Review of attachment 300424 [details] [review] [review]:
> 
> ::: src/compositor/meta-surface-actor-wayland.c
> @@ +131,3 @@
> +       * to happen. */
> +      g_warn_if_fail (clutter_actor_get_x (CLUTTER_ACTOR (self)) == 0);
> +      g_warn_if_fail (clutter_actor_get_y (CLUTTER_ACTOR (self)) == 0);
> 
> These warnings were because normally the relative position should be (0,0)
> because Xwayland is not expected to deal with subsurfaces (which positions
> the surface actor relative to its parent actor), and if Xwayland changed
> that we'd get a warning. I suppose an application can move around surface
> actors, but that application should be aware that doing that will more or
> less break subsurfaces and other things.

If you are worried about Xwayland setting offsets or using subsurfaces, shouldn't the assertions be on x/y rather than on the current position of the actor? If we return out at this point, we'll never change the actor's position and never hit the warnings. Right?
Comment 18 Jonas Ådahl 2015-04-10 17:12:46 UTC
(In reply to Owen Taylor from comment #17)
> (In reply to Jonas Ådahl from comment #16)
> > Review of attachment 300424 [details] [review] [review] [review]:
> > 
> > ::: src/compositor/meta-surface-actor-wayland.c
> > @@ +131,3 @@
> > +       * to happen. */
> > +      g_warn_if_fail (clutter_actor_get_x (CLUTTER_ACTOR (self)) == 0);
> > +      g_warn_if_fail (clutter_actor_get_y (CLUTTER_ACTOR (self)) == 0);
> > 
> > These warnings were because normally the relative position should be (0,0)
> > because Xwayland is not expected to deal with subsurfaces (which positions
> > the surface actor relative to its parent actor), and if Xwayland changed
> > that we'd get a warning. I suppose an application can move around surface
> > actors, but that application should be aware that doing that will more or
> > less break subsurfaces and other things.
> 
> If you are worried about Xwayland setting offsets or using subsurfaces,
> shouldn't the assertions be on x/y rather than on the current position of
> the actor? If we return out at this point, we'll never change the actor's
> position and never hit the warnings. Right?

Eh, that is true.
Comment 19 Jonas Ådahl 2015-07-16 03:47:46 UTC
Attachment 299779 [details] pushed as 208da23 - wayland: Fix subsurface place_above/below type cast error
Attachment 300261 [details] pushed as 117f57f - wayland: Factor out some parts of meta_surface_actor_wayland_get_scale
Attachment 300424 [details] pushed as 3b99313 - wayland: Fix subsurface positioning on HiDPI