Bug 1299083 - Implement libwayland-client wrapper, r?glandium draft
authorMartin Stransky <stransky@redhat.com>
Mon, 06 Mar 2017 13:14:33 +0100
changeset 494039 75f0c1c8561104a3add00996dcdca2719ea9949b
parent 480508 3a95aa4246653a7863914ffec032897d13359fb0
child 547983 95e2338bd06effa41e3b4a43f675857ff9ebc18e
push id47906
push userstransky@redhat.com
push dateMon, 06 Mar 2017 12:17:14 +0000
reviewersglandium
bugs1299083
milestone54.0a1
Bug 1299083 - Implement libwayland-client wrapper, r?glandium MozReview-Commit-ID: 4nvSYnKNazy
widget/gtk/WaylandLibWrapper.cpp
widget/gtk/WaylandLibWrapper.h
widget/gtk/moz.build
new file mode 100644
--- /dev/null
+++ b/widget/gtk/WaylandLibWrapper.cpp
@@ -0,0 +1,107 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "WaylandLibWrapper.h"
+#include "mozilla/PodOperations.h"
+#include "mozilla/Types.h"
+#include "prlink.h"
+#include  <gdk/gdk.h>
+
+struct WaylandLibWrapper MozWaylandWrapper;
+
+WaylandLibWrapper::WaylandLibWrapper()
+{
+#ifdef GDK_WINDOWING_WAYLAND
+    PRLibSpec lspec;
+    lspec.type = PR_LibSpec_Pathname;
+    lspec.value.pathname = "libwayland-client.so.0";
+    mWaylandLib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
+    if (!mWaylandLib) {
+        SetFallbackCalls();
+        return;
+    }
+
+#define WAY_FUNC(func)                                                       \
+    if (!(func = (decltype(func))PR_FindSymbol(mWaylandLib, "wl_"#func))) {  \
+        NS_WARNING("Couldn't load function " # func);                        \
+        PR_UnloadLibrary(mWaylandLib);                                       \
+        SetFallbackCalls();                                                  \
+        return;                                                              \
+    }                                                                        \
+
+    WAY_FUNC(registry_interface);
+    WAY_FUNC(surface_interface);
+    WAY_FUNC(subcompositor_interface);
+
+    WAY_FUNC(display_roundtrip_queue);
+    WAY_FUNC(display_roundtrip);
+    WAY_FUNC(proxy_add_listener);
+    WAY_FUNC(proxy_marshal);
+    WAY_FUNC(proxy_marshal_constructor);
+    WAY_FUNC(proxy_marshal_constructor_versioned);
+    WAY_FUNC(proxy_destroy);
+#undef WAY_FUNC
+#else // GDK_WINDOWING_WAYLAND
+    SetFallbackCalls();
+#endif
+}
+
+static int
+fallback_display_roundtrip_queue(struct wl_display *display,
+                                 struct wl_event_queue *queue)
+{
+    return -1;
+}
+static int
+fallback_display_roundtrip(struct wl_display *display)
+{
+    return -1;
+}
+static int
+fallback_proxy_add_listener(struct wl_proxy *proxy,
+                            void (**implementation)(void), void *data)
+{
+    return -1;
+}
+static void
+fallback_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...)
+{
+    return;
+}
+static struct wl_proxy *
+fallback_proxy_marshal_constructor(struct wl_proxy *proxy,
+                                   uint32_t opcode,
+                                   const struct wl_interface *interface, ...)
+{
+    return nullptr;
+}
+static struct wl_proxy *
+fallback_proxy_marshal_constructor_versioned(struct wl_proxy *proxy,
+    uint32_t opcode, const struct wl_interface *interface, uint32_t version, ...)
+{
+    return nullptr;
+}
+static void
+fallback_proxy_destroy(struct wl_proxy *proxy)
+{
+    return;
+}
+
+void
+WaylandLibWrapper::SetFallbackCalls()
+{
+#define WAY_FALLBACK(func)  \
+    func = fallback_##func;
+
+    // Set up fallback calls to avoid unexpected crashes
+    WAY_FALLBACK(display_roundtrip_queue);
+    WAY_FALLBACK(display_roundtrip);
+    WAY_FALLBACK(proxy_add_listener);
+    WAY_FALLBACK(proxy_marshal);
+    WAY_FALLBACK(proxy_marshal_constructor);
+    WAY_FALLBACK(proxy_marshal_constructor_versioned);
+    WAY_FALLBACK(proxy_destroy);
+#undef WAY_FALLBACK
+}
new file mode 100644
--- /dev/null
+++ b/widget/gtk/WaylandLibWrapper.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef __WaylandLibWrapper_h__
+#define __WaylandLibWrapper_h__
+
+#include "mozilla/Types.h"
+
+struct PRLibrary;
+
+struct WaylandLibWrapper
+{
+  WaylandLibWrapper();
+
+  // The libraries are not unloaded in the destructor,
+  // it would only run on shutdown anyway.
+  ~WaylandLibWrapper() = default;
+
+  struct wl_interface *registry_interface;
+  struct wl_interface *surface_interface;
+  struct wl_interface *subcompositor_interface;
+
+  int (*display_roundtrip_queue)(struct wl_display *display,
+      struct wl_event_queue *queue);
+  int (*display_roundtrip)(struct wl_display *display);
+  int (*proxy_add_listener)(struct wl_proxy *proxy,
+      void (**implementation)(void), void *data);
+  void (*proxy_marshal)(struct wl_proxy *p, uint32_t opcode, ...);
+  struct wl_proxy * (*proxy_marshal_constructor)(struct wl_proxy *proxy,
+      uint32_t opcode, const struct wl_interface *interface, ...);
+  struct wl_proxy * (*proxy_marshal_constructor_versioned)(struct wl_proxy *proxy,
+      uint32_t opcode, const struct wl_interface *interface, uint32_t version, ...);
+  void (*proxy_destroy)(struct wl_proxy *proxy);
+
+private:
+  void SetFallbackCalls();
+
+  PRLibrary* mWaylandLib;
+};
+
+extern struct WaylandLibWrapper MozWaylandWrapper;
+
+// Redefine our wrapped code
+#define wl_registry_interface       (MozWaylandWrapper.registry_interface)
+#define wl_surface_interface        (MozWaylandWrapper.surface_interface)
+#define wl_subcompositor_interface  (MozWaylandWrapper.subcompositor_interface)
+
+#define wl_display_roundtrip_queue  (MozWaylandWrapper.display_roundtrip_queue)
+#define wl_display_roundtrip        (MozWaylandWrapper.display_roundtrip)
+#define wl_proxy_add_listener       (MozWaylandWrapper.proxy_add_listener)
+#define wl_proxy_marshal            (MozWaylandWrapper.proxy_marshal)
+#define wl_proxy_marshal_constructor (MozWaylandWrapper.proxy_marshal_constructor)
+#define wl_proxy_marshal_constructor_versioned \
+                                    (MozWaylandWrapper.proxy_marshal_constructor_versioned)
+#define wl_proxy_destroy            (MozWaylandWrapper.proxy_destroy)
+
+#endif // WaylandLibWrapper
--- a/widget/gtk/moz.build
+++ b/widget/gtk/moz.build
@@ -90,16 +90,17 @@ if CONFIG['ACCESSIBILITY']:
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk2':
     UNIFIED_SOURCES += [
         'gtk2drawing.c',
     ]
 else:
     UNIFIED_SOURCES += [
         'gtk3drawing.cpp',
         'nsApplicationChooser.cpp',
+        'WaylandLibWrapper.cpp',
         'WidgetStyleCache.cpp',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [