[PATCH v3 xserver 1/2] xwayland: Add optional xdg-output support

Olivier Fourdan ofourdan at redhat.com
Mon Dec 18 07:52:42 UTC 2017


Hi,

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?

Because of the difference between compositors, we cannot all patches at
once, that would break either weston or mutter/gnome-shell.

So we need to proceed as follow:

 1. Land xdg-output support in mutter ← we're here
     https://bugzilla.gnome.org/attachment.cgi?id=365582
 2. Land xdg-output support in wayland
     https://patchwork.freedesktop.org/patch/175575/

Then, once we have a release of both Xwayland and mutter supporting
xdg-output:

 3. Land the patc hto send the correct output size and position in mutter
     https://bugzilla.gnome.org/attachment.cgi?id=365575
 4. Land the second patch of this series, to apply output scale to monitor
resolution
     https://patchwork.freedesktop.org/patch/175578/

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.

Cheers,
Olivier


On Thu, Sep 7, 2017 at 5:43 PM, Olivier Fourdan <ofourdan at redhat.com> wrote:

> The xdg-output protocol aims at describing outputs in way which is
> more in line with the concept of an output on desktop oriented systems.
>
> For now it just features the position and logical size which describe
> the output position and size in the global compositor space.
>
> This is however much useful for Xwayland to advertise the output size
> and position to X11 clients which need this to configure their surfaces
> in the global compositor space as the compositor may apply a different
> scale from what is advertised by the output scaling property (to achieve
> fractional scaling, for example).
>
> This was added in wayland-protocols 1.10.
>
> Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
> ---
>  configure.ac                  |   2 +-
>  hw/xwayland/Makefile.am       |   9 +++-
>  hw/xwayland/meson.build       |   2 +
>  hw/xwayland/xwayland-output.c | 119 ++++++++++++++++++++++++++++++
> ++++++++----
>  hw/xwayland/xwayland.c        |   5 ++
>  hw/xwayland/xwayland.h        |   8 +++
>  meson.build                   |   2 +-
>  7 files changed, 134 insertions(+), 13 deletions(-)
>
> diff --git a/configure.ac b/configure.ac
> index eee1257a9..3f4206727 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -2350,7 +2350,7 @@ AM_CONDITIONAL(XEPHYR, [test "x$KDRIVE" = xyes &&
> test "x$XEPHYR" = xyes])
>
>  dnl Xwayland DDX
>
> -XWAYLANDMODULES="wayland-client >= 1.3.0 wayland-protocols >= 1.9
> $LIBDRM epoxy"
> +XWAYLANDMODULES="wayland-client >= 1.3.0 wayland-protocols >= 1.10
> $LIBDRM epoxy"
>  if test "x$XF86VIDMODE" = xyes; then
>         XWAYLANDMODULES="$XWAYLANDMODULES $VIDMODEPROTO"
>  fi
> diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
> index eda49799e..7204591e3 100644
> --- a/hw/xwayland/Makefile.am
> +++ b/hw/xwayland/Makefile.am
> @@ -59,7 +59,10 @@ Xwayland_built_sources +=
>       \
>         tablet-unstable-v2-client-protocol.h                    \
>         tablet-unstable-v2-protocol.c                           \
>         xwayland-keyboard-grab-unstable-v1-protocol.c           \
> -       xwayland-keyboard-grab-unstable-v1-client-protocol.h
> +       xwayland-keyboard-grab-unstable-v1-client-protocol.h    \
> +       xdg-output-unstable-v1-protocol.c                       \
> +       xdg-output-unstable-v1-client-protocol.h
> +
>
>  nodist_Xwayland_SOURCES = $(Xwayland_built_sources)
>  CLEANFILES = $(Xwayland_built_sources)
> @@ -91,6 +94,10 @@ xwayland-keyboard-grab-unstable-v1-protocol.c :
> $(WAYLAND_PROTOCOLS_DATADIR)/uns
>         $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
>  xwayland-keyboard-grab-unstable-v1-client-protocol.h :
> $(WAYLAND_PROTOCOLS_DATADIR)/unstable/xwayland-keyboard-
> grab/xwayland-keyboard-grab-unstable-v1.xml
>         $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
> +xdg-output-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/
> unstable/xdg-output/xdg-output-unstable-v1.xml
> +       $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
> +xdg-output-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/
> unstable/xdg-output/xdg-output-unstable-v1.xml
> +       $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
>
>  %-protocol.c : %.xml
>         $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
> diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build
> index b619a66a7..658483aca 100644
> --- a/hw/xwayland/meson.build
> +++ b/hw/xwayland/meson.build
> @@ -19,6 +19,7 @@ pointer_xml = join_paths(protodir, 'unstable',
> 'pointer-constraints', 'pointer-c
>  relative_xml = join_paths(protodir, 'unstable', 'relative-pointer',
> 'relative-pointer-unstable-v1.xml')
>  tablet_xml = join_paths(protodir, 'unstable', 'tablet',
> 'tablet-unstable-v2.xml')
>  kbgrab_xml = join_paths(protodir, 'unstable', 'xwayland-keyboard-grab',
> 'xwayland-keyboard-grab-unstable-v1.xml')
> +xdg_output_xml = join_paths(protodir, 'unstable', 'xdg-output',
> 'xdg-output-unstable-v1.xml')
>
>  client_header = generator(scanner,
>      output : '@BASENAME at -client-protocol.h',
> @@ -36,6 +37,7 @@ srcs += code.process(relative_xml)
>  srcs += code.process(pointer_xml)
>  srcs += code.process(tablet_xml)
>  srcs += code.process(kbgrab_xml)
> +srcs += code.process(xdg_output_xml)
>
>  xwayland_glamor = []
>  if gbm_dep.found()
> diff --git a/hw/xwayland/xwayland-output.c b/hw/xwayland/xwayland-output.c
> index 460caaf56..a504d2595 100644
> --- a/hw/xwayland/xwayland-output.c
> +++ b/hw/xwayland/xwayland-output.c
> @@ -93,9 +93,12 @@ output_handle_geometry(void *data, struct wl_output
> *wl_output, int x, int y,
>                              physical_width, physical_height);
>      RROutputSetSubpixelOrder(xwl_output->randr_output,
>                               wl_subpixel_to_xrandr(subpixel));
> -    xwl_output->x = x;
> -    xwl_output->y = y;
>
> +    /* Apply the change from wl_output only if xdg-output is not
> supported */
> +    if (!xwl_output->xdg_output) {
> +        xwl_output->x = x;
> +        xwl_output->y = y;
> +    }
>      xwl_output->rotation = wl_transform_to_xrandr(transform);
>  }
>
> @@ -108,18 +111,22 @@ output_handle_mode(void *data, struct wl_output
> *wl_output, uint32_t flags,
>      if (!(flags & WL_OUTPUT_MODE_CURRENT))
>          return;
>
> -    xwl_output->width = width;
> -    xwl_output->height = height;
> +    /* Apply the change from wl_output only if xdg-output is not
> supported */
> +    if (!xwl_output->xdg_output) {
> +        xwl_output->width = width;
> +        xwl_output->height = height;
> +    }
>      xwl_output->refresh = refresh;
>  }
>
>  static inline void
>  output_get_new_size(struct xwl_output *xwl_output,
> +                    Bool need_rotate,
>                      int *height, int *width)
>  {
>      int output_width, output_height;
>
> -    if (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) {
> +    if (need_rotate && (xwl_output->rotation & (RR_Rotate_0 |
> RR_Rotate_180))) {
>          output_width = xwl_output->width;
>          output_height = xwl_output->height;
>      } else {
> @@ -200,12 +207,20 @@ update_screen_size(struct xwl_output *xwl_output,
> int width, int height)
>  }
>
>  static void
> -output_handle_done(void *data, struct wl_output *wl_output)
> +apply_output_change(struct xwl_output *xwl_output)
>  {
> -    struct xwl_output *it, *xwl_output = data;
>      struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
> +    struct xwl_output *it;
>      int width = 0, height = 0, has_this_output = 0;
>      RRModePtr randr_mode;
> +    Bool need_rotate;
> +
> +    /* Clear out the "done" received flags */
> +    xwl_output->wl_output_done = FALSE;
> +    xwl_output->xdg_output_done = FALSE;
> +
> +    /* xdg-output sends output size in compositor space. so alredy
> rotated */
> +    need_rotate = (xwl_output->xdg_output != NULL);
>
>      randr_mode = xwayland_cvt(xwl_output->width, xwl_output->height,
>                                xwl_output->refresh / 1000.0, 0, 0);
> @@ -222,14 +237,14 @@ output_handle_done(void *data, struct wl_output
> *wl_output)
>          if (it == xwl_output)
>              has_this_output = 1;
>
> -        output_get_new_size(it, &height, &width);
> +        output_get_new_size(it, need_rotate, &height, &width);
>      }
>
>      if (!has_this_output) {
>          xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
>
>          /* we did not check this output for new screen size, do it now */
> -        output_get_new_size(xwl_output, &height, &width);
> +        output_get_new_size(xwl_output, need_rotate, &height, &width);
>
>         --xwl_screen->expecting_event;
>      }
> @@ -238,6 +253,19 @@ output_handle_done(void *data, struct wl_output
> *wl_output)
>  }
>
>  static void
> +output_handle_done(void *data, struct wl_output *wl_output)
> +{
> +    struct xwl_output *xwl_output = data;
> +
> +    xwl_output->wl_output_done = TRUE;
> +    /* Apply the changes from wl_output only if both "done" events are
> reveived,
> +     * or if xdg-output is not supported.
> +     */
> +    if (xwl_output->xdg_output_done || !xwl_output->xdg_output)
> +        apply_output_change(xwl_output);
> +}
> +
> +static void
>  output_handle_scale(void *data, struct wl_output *wl_output, int32_t
> factor)
>  {
>  }
> @@ -249,6 +277,42 @@ static const struct wl_output_listener
> output_listener = {
>      output_handle_scale
>  };
>
> +static void
> +xdg_output_handle_logical_position(void *data, struct zxdg_output_v1
> *xdg_output,
> +                                   int32_t x, int32_t y)
> +{
> +    struct xwl_output *xwl_output = data;
> +
> +    xwl_output->x = x;
> +    xwl_output->y = y;
> +}
> +
> +static void
> +xdg_output_handle_logical_size(void *data, struct zxdg_output_v1
> *xdg_output,
> +                               int32_t width, int32_t height)
> +{
> +    struct xwl_output *xwl_output = data;
> +
> +    xwl_output->width = width;
> +    xwl_output->height = height;
> +}
> +
> +static void
> +xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
> +{
> +    struct xwl_output *xwl_output = data;
> +
> +    xwl_output->xdg_output_done = TRUE;
> +    if (xwl_output->wl_output_done)
> +        apply_output_change(xwl_output);
> +}
> +
> +static const struct zxdg_output_v1_listener xdg_output_listener = {
> +    xdg_output_handle_logical_position,
> +    xdg_output_handle_logical_size,
> +    xdg_output_handle_done,
> +};
> +
>  struct xwl_output *
>  xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
>  {
> @@ -293,6 +357,15 @@ xwl_output_create(struct xwl_screen *xwl_screen,
> uint32_t id)
>      RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc,
> 1);
>      RROutputSetConnection(xwl_output->randr_output, RR_Connected);
>
> +    /* We want the output to be in the list as soon as created so we can
> +     * use it when binding to the xdg-output protocol...
> +     */
> +    xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
> +    --xwl_screen->expecting_event;
> +
> +    if (xwl_screen->xdg_output_manager)
> +        xwl_output_get_xdg_output(xwl_output);
> +
>      return xwl_output;
>
>  err:
> @@ -317,13 +390,14 @@ xwl_output_remove(struct xwl_output *xwl_output)
>      struct xwl_output *it;
>      struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
>      int width = 0, height = 0;
> +    Bool need_rotate = (xwl_output->xdg_output != NULL);
>
>      RRCrtcDestroy(xwl_output->randr_crtc);
>      RROutputDestroy(xwl_output->randr_output);
>      xorg_list_del(&xwl_output->link);
>
>      xorg_list_for_each_entry(it, &xwl_screen->output_list, link)
> -        output_get_new_size(it, &height, &width);
> +        output_get_new_size(it, need_rotate, &height, &width);
>      update_screen_size(xwl_output, width, height);
>
>      xwl_output_destroy(xwl_output);
> @@ -360,3 +434,28 @@ xwl_screen_init_output(struct xwl_screen *xwl_screen)
>
>      return TRUE;
>  }
> +
> +void
> +xwl_output_get_xdg_output(struct xwl_output *xwl_output)
> +{
> +    struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
> +
> +    xwl_output->xdg_output =
> +        zxdg_output_manager_v1_get_xdg_output (xwl_screen->xdg_output_
> manager,
> +                                               xwl_output->output);
> +
> +    zxdg_output_v1_add_listener(xwl_output->xdg_output,
> +                                &xdg_output_listener,
> +                                xwl_output);
> +}
> +
> +void
> +xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen)
> +{
> +    struct xwl_output *it;
> +
> +    assert(xwl_screen->xdg_output_manager);
> +
> +    xorg_list_for_each_entry(it, &xwl_screen->output_list, link)
> +        xwl_output_get_xdg_output(it);
> +}
> diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
> index cb929cad5..3b6abde64 100644
> --- a/hw/xwayland/xwayland.c
> +++ b/hw/xwayland/xwayland.c
> @@ -675,6 +675,11 @@ registry_global(void *data, struct wl_registry
> *registry, uint32_t id,
>          if (xwl_output_create(xwl_screen, id))
>              xwl_screen->expecting_event++;
>      }
> +    else if (strcmp(interface, "zxdg_output_manager_v1") == 0) {
> +        xwl_screen->xdg_output_manager =
> +            wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface,
> 1);
> +        xwl_screen_init_xdg_output(xwl_screen);
> +    }
>  #ifdef GLAMOR_HAS_GBM
>      else if (xwl_screen->glamor &&
>               strcmp(interface, "wl_drm") == 0 && version >= 2) {
> diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
> index 6d3edf33b..510d65e3c 100644
> --- a/hw/xwayland/xwayland.h
> +++ b/hw/xwayland/xwayland.h
> @@ -46,6 +46,7 @@
>  #include "pointer-constraints-unstable-v1-client-protocol.h"
>  #include "tablet-unstable-v2-client-protocol.h"
>  #include "xwayland-keyboard-grab-unstable-v1-client-protocol.h"
> +#include "xdg-output-unstable-v1-client-protocol.h"
>
>  struct xwl_screen {
>      int width;
> @@ -82,6 +83,7 @@ struct xwl_screen {
>      struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
>      struct zwp_pointer_constraints_v1 *pointer_constraints;
>      struct zwp_xwayland_keyboard_grab_manager_v1 *wp_grab;
> +    struct zxdg_output_manager_v1 *xdg_output_manager;
>      uint32_t serial;
>
>  #define XWL_FORMAT_ARGB8888 (1 << 0)
> @@ -258,12 +260,15 @@ struct xwl_tablet_pad {
>  struct xwl_output {
>      struct xorg_list link;
>      struct wl_output *output;
> +    struct zxdg_output_v1 *xdg_output;
>      uint32_t server_output_id;
>      struct xwl_screen *xwl_screen;
>      RROutputPtr randr_output;
>      RRCrtcPtr randr_crtc;
>      int32_t x, y, width, height, refresh;
>      Rotation rotation;
> +    Bool wl_output_done;
> +    Bool xdg_output_done;
>  };
>
>  struct xwl_pixmap;
> @@ -326,6 +331,9 @@ struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr
> pixmap);
>
>  void xwl_screen_release_tablet_manager(struct xwl_screen *xwl_screen);
>
> +void xwl_output_get_xdg_output(struct xwl_output *xwl_output);
> +void xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen);
> +
>  #ifdef XV
>  /* glamor Xv Adaptor */
>  Bool xwl_glamor_xv_init(ScreenPtr pScreen);
> diff --git a/meson.build b/meson.build
> index 3efec0def..88fbdae0a 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -98,7 +98,7 @@ if (host_machine.system() != 'darwin' and
>
>          xwayland_dep = [
>              dependency('wayland-client', version: '>= 1.3.0', required:
> xwayland_required),
> -            dependency('wayland-protocols', version: '>= 1.9', required:
> xwayland_required),
> +            dependency('wayland-protocols', version: '>= 1.10',
> required: xwayland_required),
>              dependency('libdrm', version: '>= 2.3.1', required:
> xwayland_required),
>              dependency('epoxy', required: xwayland_required),
>          ]
> --
> 2.13.5
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.x.org/archives/xorg-devel/attachments/20171218/a848bf8e/attachment-0001.html>


More information about the xorg-devel mailing list