diff --git a/configure.ac b/configure.ac index 512bc9e9e..01fa26c87 100644 --- a/configure.ac +++ b/configure.ac @@ -2356,7 +2356,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..24203c63e 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@-client-protocol.h', @@ -32,10 +33,12 @@ srcs += client_header.process(relative_xml) srcs += client_header.process(pointer_xml) srcs += client_header.process(tablet_xml) srcs += client_header.process(kbgrab_xml) +srcs += client_header.process(xdg_output_xml) 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..c59389617 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 already 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; } @@ -237,6 +252,19 @@ output_handle_done(void *data, struct wl_output *wl_output) update_screen_size(xwl_output, width, height); } +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 received, + * 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 7809ad8d0..ab7cee545 100644 --- a/hw/xwayland/xwayland.c +++ b/hw/xwayland/xwayland.c @@ -709,6 +709,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 e6eb37bec..ffa0d7297 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) @@ -259,12 +261,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; @@ -327,6 +332,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 c028cc8aa..c9d9f27e1 100644 --- a/meson.build +++ b/meson.build @@ -147,7 +147,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), ]