xwayland: Add optional xdg-output support

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.

Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
This commit is contained in:
Olivier Fourdan 2017-09-07 17:43:16 +02:00 committed by Adam Jackson
parent 75408f53d4
commit da8de2a7f6
7 changed files with 135 additions and 13 deletions

View File

@ -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

View File

@ -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 < $< > $@

View File

@ -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()

View File

@ -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);
}

View File

@ -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) {

View File

@ -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);

View File

@ -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),
]