diff --git a/.gitignore b/.gitignore index eb123d49a..07c51573d 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/configure.ac b/configure.ac index d8fe6d697..69548673d 100644 --- a/configure.ac +++ b/configure.ac @@ -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) ]) diff --git a/src/Makefile.am b/src/Makefile.am index 4f96a1113..59dc248e8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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 < $< > $@ diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c index 51f62f98f..88460cb8f 100644 --- a/src/wayland/meta-wayland-outputs.c +++ b/src/wayland/meta-wayland-outputs.c @@ -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 @@ -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); } diff --git a/src/wayland/meta-wayland-outputs.h b/src/wayland/meta-wayland-outputs.h index f9f096aba..e6b60d5fa 100644 --- a/src/wayland/meta-wayland-outputs.h +++ b/src/wayland/meta-wayland-outputs.h @@ -43,6 +43,7 @@ struct _MetaWaylandOutput gint scale; GList *resources; + GList *xdg_output_resources; }; void meta_wayland_outputs_init (MetaWaylandCompositor *compositor); diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h index 42bab7db1..76da02f84 100644 --- a/src/wayland/meta-wayland-versions.h +++ b/src/wayland/meta-wayland-versions.h @@ -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