[mutter] wayland: Add xdg-output support



commit db32047a5dd631812a94be72568504ba64a06b43
Author: Olivier Fourdan <ofourdan redhat com>
Date:   Tue Sep 5 18:53:41 2017 +0200

    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

 .gitignore                          |    2 +
 configure.ac                        |    2 +-
 src/Makefile.am                     |    6 +
 src/wayland/meta-wayland-outputs.c  |  197 ++++++++++++++++++++++++++++++++++-
 src/wayland/meta-wayland-outputs.h  |    1 +
 src/wayland/meta-wayland-versions.h |    1 +
 6 files changed, 203 insertions(+), 6 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index eb123d4..07c5157 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 d8fe6d6..6954867 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 4f96a11..59dc248 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 51f62f9..88460cb 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 <string.h>
 
@@ -43,6 +44,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)
 {
   MetaWaylandOutput *wayland_output;
@@ -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 f9f096a..e6b60d5 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 42bab7d..76da02f 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]