wayland: Add 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.

https://bugzilla.gnome.org/show_bug.cgi?id=787363
This commit is contained in:
Olivier Fourdan 2017-09-05 18:53:41 +02:00
parent b505eb261e
commit db32047a5d
6 changed files with 204 additions and 7 deletions

2
.gitignore vendored
View File

@ -88,6 +88,8 @@ src/pointer-constraints-unstable-v*-protocol.c
src/pointer-constraints-unstable-v*-server-protocol.h
src/xdg-foreign-unstable-v*-protocol.c
src/xdg-foreign-unstable-v*-server-protocol.h
src/xdg-output-unstable-v1-protocol.c
src/xdg-output-unstable-v1-server-protocol.h
src/meta/meta-version.h
src/libmutter-*.pc
doc/reference/*.args

View File

@ -306,7 +306,7 @@ AS_IF([test "$have_wayland" = "yes"], [
AC_SUBST([WAYLAND_SCANNER])
AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.9],
PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.10],
[ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`])
AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir)
])

View File

@ -82,6 +82,8 @@ mutter_built_sources += \
linux-dmabuf-unstable-v1-server-protocol.h \
keyboard-shortcuts-inhibit-unstable-v1-protocol.c \
keyboard-shortcuts-inhibit-unstable-v1-server-protocol.h \
xdg-output-unstable-v1-protocol.c \
xdg-output-unstable-v1-server-protocol.h \
$(NULL)
endif
@ -742,3 +744,7 @@ keyboard-shortcuts-inhibit-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
keyboard-shortcuts-inhibit-unstable-v1-server-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) server-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-server-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/xdg-output/xdg-output-unstable-v1.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@

View File

@ -29,6 +29,7 @@
#include "meta-wayland-private.h"
#include "backends/meta-logical-monitor.h"
#include "meta-monitor-manager-private.h"
#include "xdg-output-unstable-v1-server-protocol.h"
#include <string.h>
@ -42,6 +43,13 @@ static guint signals[LAST_SIGNAL];
G_DEFINE_TYPE (MetaWaylandOutput, meta_wayland_output, G_TYPE_OBJECT)
static void
send_xdg_output_events (struct wl_resource *resource,
MetaWaylandOutput *wayland_output,
MetaLogicalMonitor *logical_monitor,
gboolean need_all_events,
gboolean *pending_done_event);
static void
output_resource_destroy (struct wl_resource *res)
{
@ -124,7 +132,8 @@ static void
send_output_events (struct wl_resource *resource,
MetaWaylandOutput *wayland_output,
MetaLogicalMonitor *logical_monitor,
gboolean need_all_events)
gboolean need_all_events,
gboolean *pending_done_event)
{
int version = wl_resource_get_version (resource);
MetaMonitor *monitor;
@ -221,10 +230,16 @@ send_output_events (struct wl_resource *resource,
wl_output_send_scale (resource, scale);
need_done = TRUE;
}
if (need_done)
wl_output_send_done (resource);
}
if (need_all_events && version >= WL_OUTPUT_DONE_SINCE_VERSION)
{
wl_output_send_done (resource);
need_done = FALSE;
}
if (pending_done_event && need_done)
*pending_done_event = TRUE;
}
static void
@ -253,7 +268,7 @@ bind_output (struct wl_client *client,
logical_monitor->rect.width, logical_monitor->rect.height,
wayland_output->refresh_rate);
send_output_events (resource, wayland_output, logical_monitor, TRUE);
send_output_events (resource, wayland_output, logical_monitor, TRUE, NULL);
}
static void
@ -291,13 +306,37 @@ wayland_output_update_for_output (MetaWaylandOutput *wayland_output,
MetaLogicalMonitor *logical_monitor)
{
GList *iter;
gboolean pending_done_event;
pending_done_event = FALSE;
for (iter = wayland_output->resources; iter; iter = iter->next)
{
struct wl_resource *resource = iter->data;
send_output_events (resource, wayland_output, logical_monitor, FALSE);
send_output_events (resource, wayland_output, logical_monitor, FALSE, &pending_done_event);
}
for (iter = wayland_output->xdg_output_resources; iter; iter = iter->next)
{
struct wl_resource *xdg_output = iter->data;
send_xdg_output_events (xdg_output, wayland_output, logical_monitor, FALSE, &pending_done_event);
}
/* Send the "done" events if needed */
if (pending_done_event)
{
for (iter = wayland_output->resources; iter; iter = iter->next)
{
struct wl_resource *resource = iter->data;
if (wl_resource_get_version (resource) >= WL_OUTPUT_DONE_SINCE_VERSION)
wl_output_send_done (resource);
}
for (iter = wayland_output->xdg_output_resources; iter; iter = iter->next)
{
struct wl_resource *xdg_output = iter->data;
zxdg_output_v1_send_done (xdg_output);
}
}
/* It's very important that we change the output pointer here, as
the old structure is about to be freed by MetaMonitorManager */
meta_wayland_output_set_logical_monitor (wayland_output, logical_monitor);
@ -398,6 +437,15 @@ meta_wayland_output_finalize (GObject *object)
g_list_free (wayland_output->resources);
for (l = wayland_output->xdg_output_resources; l; l = l->next)
{
struct wl_resource *xdg_output_resource = l->data;
wl_resource_set_user_data (xdg_output_resource, NULL);
}
g_list_free (wayland_output->xdg_output_resources);
G_OBJECT_CLASS (meta_wayland_output_parent_class)->finalize (object);
}
@ -416,6 +464,139 @@ meta_wayland_output_class_init (MetaWaylandOutputClass *klass)
G_TYPE_NONE, 0);
}
static void
meta_xdg_output_destructor (struct wl_resource *resource)
{
MetaWaylandOutput *wayland_output;
wayland_output = wl_resource_get_user_data (resource);
if (!wayland_output)
return;
wayland_output->xdg_output_resources =
g_list_remove (wayland_output->xdg_output_resources, resource);
}
static void
meta_xdg_output_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct zxdg_output_v1_interface
meta_xdg_output_interface = {
meta_xdg_output_destroy,
};
static void
send_xdg_output_events (struct wl_resource *resource,
MetaWaylandOutput *wayland_output,
MetaLogicalMonitor *logical_monitor,
gboolean need_all_events,
gboolean *pending_done_event)
{
MetaRectangle new_layout;
MetaRectangle old_layout;
MetaLogicalMonitor *old_logical_monitor;
gboolean need_done;
need_done = FALSE;
old_logical_monitor = wayland_output->logical_monitor;
old_layout = meta_logical_monitor_get_layout (old_logical_monitor);
new_layout = meta_logical_monitor_get_layout (logical_monitor);
if (need_all_events ||
old_layout.x != new_layout.x ||
old_layout.y != new_layout.y)
{
zxdg_output_v1_send_logical_position (resource,
new_layout.x,
new_layout.y);
need_done = TRUE;
}
if (need_all_events ||
old_layout.width != new_layout.width ||
old_layout.height != new_layout.height)
{
zxdg_output_v1_send_logical_position (resource,
new_layout.width,
new_layout.height);
need_done = TRUE;
}
if (need_all_events)
{
zxdg_output_v1_send_done (resource);
need_done = FALSE;
}
if (pending_done_event && need_done)
*pending_done_event = TRUE;
}
static void
meta_xdg_output_manager_get_xdg_output (struct wl_client *client,
struct wl_resource *resource,
uint32_t id,
struct wl_resource *output)
{
struct wl_resource *xdg_output_resource;
MetaWaylandOutput *wayland_output;
xdg_output_resource = wl_resource_create (client,
&zxdg_output_v1_interface,
wl_resource_get_version (resource),
id);
wl_resource_set_implementation (xdg_output_resource,
&meta_xdg_output_interface,
NULL, meta_xdg_output_destructor);
wayland_output = wl_resource_get_user_data (output);
if (!wayland_output)
return;
wayland_output->xdg_output_resources =
g_list_prepend (wayland_output->xdg_output_resources, xdg_output_resource);
send_xdg_output_events (xdg_output_resource,
wayland_output,
wayland_output->logical_monitor,
TRUE, NULL);
}
static void
meta_xdg_output_manager_destroy (struct wl_client *client,
struct wl_resource *resource)
{
wl_resource_destroy (resource);
}
static const struct zxdg_output_manager_v1_interface
meta_xdg_output_manager_interface = {
meta_xdg_output_manager_destroy,
meta_xdg_output_manager_get_xdg_output,
};
static void
bind_xdg_output_manager (struct wl_client *client,
void *data,
uint32_t version,
uint32_t id)
{
struct wl_resource *resource;
resource = wl_resource_create (client,
&zxdg_output_manager_v1_interface,
version, id);
wl_resource_set_implementation (resource,
&meta_xdg_output_manager_interface,
NULL, NULL);
}
void
meta_wayland_outputs_init (MetaWaylandCompositor *compositor)
{
@ -427,4 +608,10 @@ meta_wayland_outputs_init (MetaWaylandCompositor *compositor)
compositor->outputs = g_hash_table_new_full (NULL, NULL, NULL, wayland_output_destroy_notify);
compositor->outputs = meta_wayland_compositor_update_outputs (compositor, monitors);
wl_global_create (compositor->wayland_display,
&zxdg_output_manager_v1_interface,
META_ZXDG_OUTPUT_V1_VERSION,
NULL,
bind_xdg_output_manager);
}

View File

@ -43,6 +43,7 @@ struct _MetaWaylandOutput
gint scale;
GList *resources;
GList *xdg_output_resources;
};
void meta_wayland_outputs_init (MetaWaylandCompositor *compositor);

View File

@ -49,5 +49,6 @@
#define META_ZXDG_IMPORTER_V1_VERSION 1
#define META_ZWP_LINUX_DMABUF_V1_VERSION 3
#define META_ZWP_KEYBOARD_SHORTCUTS_INHIBIT_V1_VERSION 1
#define META_ZXDG_OUTPUT_V1_VERSION 1
#endif