<div dir="ltr"><div><div><div><div><div><div><div><div>Hi,<br><br></div>xdg-support has now been added to mutter (in git master), can we consider this patch (only this one for now) which adds xdg-output support to Xwayland?<br><br></div>Because of the difference between compositors, we cannot all patches at once, that would break either weston or mutter/gnome-shell.<br><br></div>So we need to proceed as follow:<br><br></div> 1. Land xdg-output support in mutter ← we're here</div><div>     <a href="https://bugzilla.gnome.org/attachment.cgi?id=365582">https://bugzilla.gnome.org/attachment.cgi?id=365582</a><br></div> 2. Land xdg-output support in wayland</div><div>     <a href="https://patchwork.freedesktop.org/patch/175575/">https://patchwork.freedesktop.org/patch/175575/</a><br><br></div>Then, once we have a release of both Xwayland and mutter supporting xdg-output:<br><br></div> 3. Land the patc hto send the correct output size and position in mutter<br>     <a href="https://bugzilla.gnome.org/attachment.cgi?id=365575">https://bugzilla.gnome.org/attachment.cgi?id=365575</a><br></div> 4. Land the second patch of this series, to apply output scale to monitor resolution<br>     <a href="https://patchwork.freedesktop.org/patch/175578/">https://patchwork.freedesktop.org/patch/175578/</a><br>      <br><div><div><div><div><div><div>This way, in both weston and mutter/gnome-shell, a mode X×Y at scale 2 will still show up as X×Y in xrandr.</div><div><br></div><div>Cheers,</div><div>Olivier</div><div><br></div></div></div></div></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Sep 7, 2017 at 5:43 PM, Olivier Fourdan <span dir="ltr"><<a href="mailto:ofourdan@redhat.com" target="_blank">ofourdan@redhat.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The xdg-output protocol aims at describing outputs in way which is<br>
more in line with the concept of an output on desktop oriented systems.<br>
<br>
For now it just features the position and logical size which describe<br>
the output position and size in the global compositor space.<br>
<br>
This is however much useful for Xwayland to advertise the output size<br>
and position to X11 clients which need this to configure their surfaces<br>
in the global compositor space as the compositor may apply a different<br>
scale from what is advertised by the output scaling property (to achieve<br>
fractional scaling, for example).<br>
<br>
This was added in wayland-protocols 1.10.<br>
<br>
Signed-off-by: Olivier Fourdan <<a href="mailto:ofourdan@redhat.com">ofourdan@redhat.com</a>><br>
---<br>
 <a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a>                  |   2 +-<br>
 hw/xwayland/Makefile.am       |   9 +++-<br>
 hw/xwayland/meson.build       |   2 +<br>
 hw/xwayland/xwayland-output.c | 119 ++++++++++++++++++++++++++++++<wbr>++++++++----<br>
 hw/xwayland/xwayland.c        |   5 ++<br>
 hw/xwayland/xwayland.h        |   8 +++<br>
 meson.build                   |   2 +-<br>
 7 files changed, 134 insertions(+), 13 deletions(-)<br>
<br>
diff --git a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a> b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
index eee1257a9..3f4206727 100644<br>
--- a/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
+++ b/<a href="http://configure.ac" rel="noreferrer" target="_blank">configure.ac</a><br>
@@ -2350,7 +2350,7 @@ AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes && test "x$XEPHYR" = xyes])<br>
<br>
 dnl Xwayland DDX<br>
<br>
-XWAYLANDMODULES="wayland-<wbr>client >= 1.3.0 wayland-protocols >= 1.9 $LIBDRM epoxy"<br>
+XWAYLANDMODULES="wayland-<wbr>client >= 1.3.0 wayland-protocols >= 1.10 $LIBDRM epoxy"<br>
 if test "x$XF86VIDMODE" = xyes; then<br>
        XWAYLANDMODULES="$<wbr>XWAYLANDMODULES $VIDMODEPROTO"<br>
 fi<br>
diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am<br>
index eda49799e..7204591e3 100644<br>
--- a/hw/xwayland/Makefile.am<br>
+++ b/hw/xwayland/Makefile.am<br>
@@ -59,7 +59,10 @@ Xwayland_built_sources +=                                    \<br>
        tablet-unstable-v2-client-<wbr>protocol.h                    \<br>
        tablet-unstable-v2-protocol.c                           \<br>
        xwayland-keyboard-grab-<wbr>unstable-v1-protocol.c           \<br>
-       xwayland-keyboard-grab-<wbr>unstable-v1-client-protocol.h<br>
+       xwayland-keyboard-grab-<wbr>unstable-v1-client-protocol.h    \<br>
+       xdg-output-unstable-v1-<wbr>protocol.c                       \<br>
+       xdg-output-unstable-v1-client-<wbr>protocol.h<br>
+<br>
<br>
 nodist_Xwayland_SOURCES = $(Xwayland_built_sources)<br>
 CLEANFILES = $(Xwayland_built_sources)<br>
@@ -91,6 +94,10 @@ xwayland-keyboard-grab-<wbr>unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/<wbr>uns<br>
        $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@<br>
 xwayland-keyboard-grab-<wbr>unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/<wbr>unstable/xwayland-keyboard-<wbr>grab/xwayland-keyboard-grab-<wbr>unstable-v1.xml<br>
        $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@<br>
+xdg-output-unstable-v1-<wbr>protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/<wbr>unstable/xdg-output/xdg-<wbr>output-unstable-v1.xml<br>
+       $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@<br>
+xdg-output-unstable-v1-<wbr>client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/<wbr>unstable/xdg-output/xdg-<wbr>output-unstable-v1.xml<br>
+       $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@<br>
<br>
 %-protocol.c : %.xml<br>
        $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@<br>
diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build<br>
index b619a66a7..658483aca 100644<br>
--- a/hw/xwayland/meson.build<br>
+++ b/hw/xwayland/meson.build<br>
@@ -19,6 +19,7 @@ pointer_xml = join_paths(protodir, 'unstable', 'pointer-constraints', 'pointer-c<br>
 relative_xml = join_paths(protodir, 'unstable', 'relative-pointer', 'relative-pointer-unstable-v1.<wbr>xml')<br>
 tablet_xml = join_paths(protodir, 'unstable', 'tablet', 'tablet-unstable-v2.xml')<br>
 kbgrab_xml = join_paths(protodir, 'unstable', 'xwayland-keyboard-grab', 'xwayland-keyboard-grab-<wbr>unstable-v1.xml')<br>
+xdg_output_xml = join_paths(protodir, 'unstable', 'xdg-output', 'xdg-output-unstable-v1.xml')<br>
<br>
 client_header = generator(scanner,<br>
     output : '@BASENAME@-client-protocol.h'<wbr>,<br>
@@ -36,6 +37,7 @@ srcs += code.process(relative_xml)<br>
 srcs += code.process(pointer_xml)<br>
 srcs += code.process(tablet_xml)<br>
 srcs += code.process(kbgrab_xml)<br>
+srcs += code.process(xdg_output_xml)<br>
<br>
 xwayland_glamor = []<br>
 if gbm_dep.found()<br>
diff --git a/hw/xwayland/xwayland-output.<wbr>c b/hw/xwayland/xwayland-output.<wbr>c<br>
index 460caaf56..a504d2595 100644<br>
--- a/hw/xwayland/xwayland-output.<wbr>c<br>
+++ b/hw/xwayland/xwayland-output.<wbr>c<br>
@@ -93,9 +93,12 @@ output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,<br>
                             physical_width, physical_height);<br>
     RROutputSetSubpixelOrder(xwl_<wbr>output->randr_output,<br>
                              wl_subpixel_to_xrandr(<wbr>subpixel));<br>
-    xwl_output->x = x;<br>
-    xwl_output->y = y;<br>
<br>
+    /* Apply the change from wl_output only if xdg-output is not supported */<br>
+    if (!xwl_output->xdg_output) {<br>
+        xwl_output->x = x;<br>
+        xwl_output->y = y;<br>
+    }<br>
     xwl_output->rotation = wl_transform_to_xrandr(<wbr>transform);<br>
 }<br>
<br>
@@ -108,18 +111,22 @@ output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,<br>
     if (!(flags & WL_OUTPUT_MODE_CURRENT))<br>
         return;<br>
<br>
-    xwl_output->width = width;<br>
-    xwl_output->height = height;<br>
+    /* Apply the change from wl_output only if xdg-output is not supported */<br>
+    if (!xwl_output->xdg_output) {<br>
+        xwl_output->width = width;<br>
+        xwl_output->height = height;<br>
+    }<br>
     xwl_output->refresh = refresh;<br>
 }<br>
<br>
 static inline void<br>
 output_get_new_size(struct xwl_output *xwl_output,<br>
+                    Bool need_rotate,<br>
                     int *height, int *width)<br>
 {<br>
     int output_width, output_height;<br>
<br>
-    if (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) {<br>
+    if (need_rotate && (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180))) {<br>
         output_width = xwl_output->width;<br>
         output_height = xwl_output->height;<br>
     } else {<br>
@@ -200,12 +207,20 @@ update_screen_size(struct xwl_output *xwl_output, int width, int height)<br>
 }<br>
<br>
 static void<br>
-output_handle_done(void *data, struct wl_output *wl_output)<br>
+apply_output_change(struct xwl_output *xwl_output)<br>
 {<br>
-    struct xwl_output *it, *xwl_output = data;<br>
     struct xwl_screen *xwl_screen = xwl_output->xwl_screen;<br>
+    struct xwl_output *it;<br>
     int width = 0, height = 0, has_this_output = 0;<br>
     RRModePtr randr_mode;<br>
+    Bool need_rotate;<br>
+<br>
+    /* Clear out the "done" received flags */<br>
+    xwl_output->wl_output_done = FALSE;<br>
+    xwl_output->xdg_output_done = FALSE;<br>
+<br>
+    /* xdg-output sends output size in compositor space. so alredy rotated */<br>
+    need_rotate = (xwl_output->xdg_output != NULL);<br>
<br>
     randr_mode = xwayland_cvt(xwl_output-><wbr>width, xwl_output->height,<br>
                               xwl_output->refresh / 1000.0, 0, 0);<br>
@@ -222,14 +237,14 @@ output_handle_done(void *data, struct wl_output *wl_output)<br>
         if (it == xwl_output)<br>
             has_this_output = 1;<br>
<br>
-        output_get_new_size(it, &height, &width);<br>
+        output_get_new_size(it, need_rotate, &height, &width);<br>
     }<br>
<br>
     if (!has_this_output) {<br>
         xorg_list_append(&xwl_output-><wbr>link, &xwl_screen->output_list);<br>
<br>
         /* we did not check this output for new screen size, do it now */<br>
-        output_get_new_size(xwl_<wbr>output, &height, &width);<br>
+        output_get_new_size(xwl_<wbr>output, need_rotate, &height, &width);<br>
<br>
        --xwl_screen->expecting_event;<br>
     }<br>
@@ -238,6 +253,19 @@ output_handle_done(void *data, struct wl_output *wl_output)<br>
 }<br>
<br>
 static void<br>
+output_handle_done(void *data, struct wl_output *wl_output)<br>
+{<br>
+    struct xwl_output *xwl_output = data;<br>
+<br>
+    xwl_output->wl_output_done = TRUE;<br>
+    /* Apply the changes from wl_output only if both "done" events are reveived,<br>
+     * or if xdg-output is not supported.<br>
+     */<br>
+    if (xwl_output->xdg_output_done || !xwl_output->xdg_output)<br>
+        apply_output_change(xwl_<wbr>output);<br>
+}<br>
+<br>
+static void<br>
 output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor)<br>
 {<br>
 }<br>
@@ -249,6 +277,42 @@ static const struct wl_output_listener output_listener = {<br>
     output_handle_scale<br>
 };<br>
<br>
+static void<br>
+xdg_output_handle_logical_<wbr>position(void *data, struct zxdg_output_v1 *xdg_output,<br>
+                                   int32_t x, int32_t y)<br>
+{<br>
+    struct xwl_output *xwl_output = data;<br>
+<br>
+    xwl_output->x = x;<br>
+    xwl_output->y = y;<br>
+}<br>
+<br>
+static void<br>
+xdg_output_handle_logical_<wbr>size(void *data, struct zxdg_output_v1 *xdg_output,<br>
+                               int32_t width, int32_t height)<br>
+{<br>
+    struct xwl_output *xwl_output = data;<br>
+<br>
+    xwl_output->width = width;<br>
+    xwl_output->height = height;<br>
+}<br>
+<br>
+static void<br>
+xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)<br>
+{<br>
+    struct xwl_output *xwl_output = data;<br>
+<br>
+    xwl_output->xdg_output_done = TRUE;<br>
+    if (xwl_output->wl_output_done)<br>
+        apply_output_change(xwl_<wbr>output);<br>
+}<br>
+<br>
+static const struct zxdg_output_v1_listener xdg_output_listener = {<br>
+    xdg_output_handle_logical_<wbr>position,<br>
+    xdg_output_handle_logical_<wbr>size,<br>
+    xdg_output_handle_done,<br>
+};<br>
+<br>
 struct xwl_output *<br>
 xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)<br>
 {<br>
@@ -293,6 +357,15 @@ xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)<br>
     RROutputSetCrtcs(xwl_output-><wbr>randr_output, &xwl_output->randr_crtc, 1);<br>
     RROutputSetConnection(xwl_<wbr>output->randr_output, RR_Connected);<br>
<br>
+    /* We want the output to be in the list as soon as created so we can<br>
+     * use it when binding to the xdg-output protocol...<br>
+     */<br>
+    xorg_list_append(&xwl_output-><wbr>link, &xwl_screen->output_list);<br>
+    --xwl_screen->expecting_event;<br>
+<br>
+    if (xwl_screen->xdg_output_<wbr>manager)<br>
+        xwl_output_get_xdg_output(xwl_<wbr>output);<br>
+<br>
     return xwl_output;<br>
<br>
 err:<br>
@@ -317,13 +390,14 @@ xwl_output_remove(struct xwl_output *xwl_output)<br>
     struct xwl_output *it;<br>
     struct xwl_screen *xwl_screen = xwl_output->xwl_screen;<br>
     int width = 0, height = 0;<br>
+    Bool need_rotate = (xwl_output->xdg_output != NULL);<br>
<br>
     RRCrtcDestroy(xwl_output-><wbr>randr_crtc);<br>
     RROutputDestroy(xwl_output-><wbr>randr_output);<br>
     xorg_list_del(&xwl_output-><wbr>link);<br>
<br>
     xorg_list_for_each_entry(it, &xwl_screen->output_list, link)<br>
-        output_get_new_size(it, &height, &width);<br>
+        output_get_new_size(it, need_rotate, &height, &width);<br>
     update_screen_size(xwl_output, width, height);<br>
<br>
     xwl_output_destroy(xwl_output)<wbr>;<br>
@@ -360,3 +434,28 @@ xwl_screen_init_output(struct xwl_screen *xwl_screen)<br>
<br>
     return TRUE;<br>
 }<br>
+<br>
+void<br>
+xwl_output_get_xdg_output(<wbr>struct xwl_output *xwl_output)<br>
+{<br>
+    struct xwl_screen *xwl_screen = xwl_output->xwl_screen;<br>
+<br>
+    xwl_output->xdg_output =<br>
+        zxdg_output_manager_v1_get_<wbr>xdg_output (xwl_screen->xdg_output_<wbr>manager,<br>
+                                               xwl_output->output);<br>
+<br>
+    zxdg_output_v1_add_listener(<wbr>xwl_output->xdg_output,<br>
+                                &xdg_output_listener,<br>
+                                xwl_output);<br>
+}<br>
+<br>
+void<br>
+xwl_screen_init_xdg_output(<wbr>struct xwl_screen *xwl_screen)<br>
+{<br>
+    struct xwl_output *it;<br>
+<br>
+    assert(xwl_screen->xdg_output_<wbr>manager);<br>
+<br>
+    xorg_list_for_each_entry(it, &xwl_screen->output_list, link)<br>
+        xwl_output_get_xdg_output(it);<br>
+}<br>
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c<br>
index cb929cad5..3b6abde64 100644<br>
--- a/hw/xwayland/xwayland.c<br>
+++ b/hw/xwayland/xwayland.c<br>
@@ -675,6 +675,11 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,<br>
         if (xwl_output_create(xwl_screen, id))<br>
             xwl_screen->expecting_event++;<br>
     }<br>
+    else if (strcmp(interface, "zxdg_output_manager_v1") == 0) {<br>
+        xwl_screen->xdg_output_manager =<br>
+            wl_registry_bind(registry, id, &zxdg_output_manager_v1_<wbr>interface, 1);<br>
+        xwl_screen_init_xdg_output(<wbr>xwl_screen);<br>
+    }<br>
 #ifdef GLAMOR_HAS_GBM<br>
     else if (xwl_screen->glamor &&<br>
              strcmp(interface, "wl_drm") == 0 && version >= 2) {<br>
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h<br>
index 6d3edf33b..510d65e3c 100644<br>
--- a/hw/xwayland/xwayland.h<br>
+++ b/hw/xwayland/xwayland.h<br>
@@ -46,6 +46,7 @@<br>
 #include "pointer-constraints-unstable-<wbr>v1-client-protocol.h"<br>
 #include "tablet-unstable-v2-client-<wbr>protocol.h"<br>
 #include "xwayland-keyboard-grab-<wbr>unstable-v1-client-protocol.h"<br>
+#include "xdg-output-unstable-v1-<wbr>client-protocol.h"<br>
<br>
 struct xwl_screen {<br>
     int width;<br>
@@ -82,6 +83,7 @@ struct xwl_screen {<br>
     struct zwp_relative_pointer_manager_<wbr>v1 *relative_pointer_manager;<br>
     struct zwp_pointer_constraints_v1 *pointer_constraints;<br>
     struct zwp_xwayland_keyboard_grab_<wbr>manager_v1 *wp_grab;<br>
+    struct zxdg_output_manager_v1 *xdg_output_manager;<br>
     uint32_t serial;<br>
<br>
 #define XWL_FORMAT_ARGB8888 (1 << 0)<br>
@@ -258,12 +260,15 @@ struct xwl_tablet_pad {<br>
 struct xwl_output {<br>
     struct xorg_list link;<br>
     struct wl_output *output;<br>
+    struct zxdg_output_v1 *xdg_output;<br>
     uint32_t server_output_id;<br>
     struct xwl_screen *xwl_screen;<br>
     RROutputPtr randr_output;<br>
     RRCrtcPtr randr_crtc;<br>
     int32_t x, y, width, height, refresh;<br>
     Rotation rotation;<br>
+    Bool wl_output_done;<br>
+    Bool xdg_output_done;<br>
 };<br>
<br>
 struct xwl_pixmap;<br>
@@ -326,6 +331,9 @@ struct wl_buffer *xwl_glamor_pixmap_get_wl_<wbr>buffer(PixmapPtr pixmap);<br>
<br>
 void xwl_screen_release_tablet_<wbr>manager(struct xwl_screen *xwl_screen);<br>
<br>
+void xwl_output_get_xdg_output(<wbr>struct xwl_output *xwl_output);<br>
+void xwl_screen_init_xdg_output(<wbr>struct xwl_screen *xwl_screen);<br>
+<br>
 #ifdef XV<br>
 /* glamor Xv Adaptor */<br>
 Bool xwl_glamor_xv_init(ScreenPtr pScreen);<br>
diff --git a/meson.build b/meson.build<br>
index 3efec0def..88fbdae0a 100644<br>
--- a/meson.build<br>
+++ b/meson.build<br>
@@ -98,7 +98,7 @@ if (host_machine.system() != 'darwin' and<br>
<br>
         xwayland_dep = [<br>
             dependency('wayland-client', version: '>= 1.3.0', required: xwayland_required),<br>
-            dependency('wayland-protocols'<wbr>, version: '>= 1.9', required: xwayland_required),<br>
+            dependency('wayland-protocols'<wbr>, version: '>= 1.10', required: xwayland_required),<br>
             dependency('libdrm', version: '>= 2.3.1', required: xwayland_required),<br>
             dependency('epoxy', required: xwayland_required),<br>
         ]<br>
<span class="HOEnZb"><font color="#888888">--<br>
2.13.5<br>
<br>
</font></span></blockquote></div><br></div>