Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / widget / gtk / nsWaylandDisplay.cpp
blob365a0a297362c33ec8f2652fe6656a760c5add00
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsWaylandDisplay.h"
9 #include <dlfcn.h>
11 #include "base/message_loop.h" // for MessageLoop
12 #include "base/task.h" // for NewRunnableMethod, etc
13 #include "mozilla/gfx/Logging.h" // for gfxCriticalNote
14 #include "mozilla/StaticMutex.h"
15 #include "mozilla/Array.h"
16 #include "mozilla/StaticPtr.h"
17 #include "mozilla/ThreadLocal.h"
18 #include "mozilla/StaticPrefs_widget.h"
19 #include "mozilla/Sprintf.h"
20 #include "WidgetUtilsGtk.h"
21 #include "nsGtkKeyUtils.h"
23 namespace mozilla::widget {
25 static nsWaylandDisplay* gWaylandDisplay;
27 void WaylandDisplayRelease() {
28 MOZ_RELEASE_ASSERT(NS_IsMainThread(),
29 "WaylandDisplay can be released in main thread only!");
30 if (!gWaylandDisplay) {
31 return;
33 delete gWaylandDisplay;
34 gWaylandDisplay = nullptr;
37 wl_display* WaylandDisplayGetWLDisplay() {
38 GdkDisplay* disp = gdk_display_get_default();
39 if (!GdkIsWaylandDisplay(disp)) {
40 return nullptr;
42 return gdk_wayland_display_get_wl_display(disp);
45 nsWaylandDisplay* WaylandDisplayGet() {
46 if (!gWaylandDisplay) {
47 MOZ_RELEASE_ASSERT(NS_IsMainThread(),
48 "WaylandDisplay can be created in main thread only!");
49 wl_display* waylandDisplay = WaylandDisplayGetWLDisplay();
50 if (!waylandDisplay) {
51 return nullptr;
53 gWaylandDisplay = new nsWaylandDisplay(waylandDisplay);
55 return gWaylandDisplay;
58 void nsWaylandDisplay::SetShm(wl_shm* aShm) { mShm = aShm; }
60 void nsWaylandDisplay::SetCompositor(wl_compositor* aCompositor) {
61 mCompositor = aCompositor;
64 void nsWaylandDisplay::SetSubcompositor(wl_subcompositor* aSubcompositor) {
65 mSubcompositor = aSubcompositor;
68 void nsWaylandDisplay::SetIdleInhibitManager(
69 zwp_idle_inhibit_manager_v1* aIdleInhibitManager) {
70 mIdleInhibitManager = aIdleInhibitManager;
73 void nsWaylandDisplay::SetViewporter(wp_viewporter* aViewporter) {
74 mViewporter = aViewporter;
77 void nsWaylandDisplay::SetRelativePointerManager(
78 zwp_relative_pointer_manager_v1* aRelativePointerManager) {
79 mRelativePointerManager = aRelativePointerManager;
82 void nsWaylandDisplay::SetPointerConstraints(
83 zwp_pointer_constraints_v1* aPointerConstraints) {
84 mPointerConstraints = aPointerConstraints;
87 void nsWaylandDisplay::SetDmabuf(zwp_linux_dmabuf_v1* aDmabuf) {
88 mDmabuf = aDmabuf;
91 void nsWaylandDisplay::SetXdgActivation(xdg_activation_v1* aXdgActivation) {
92 mXdgActivation = aXdgActivation;
95 void nsWaylandDisplay::SetXdgDbusAnnotationManager(
96 xdg_dbus_annotation_manager_v1* aXdgDbusAnnotationManager) {
97 mXdgDbusAnnotationManager = aXdgDbusAnnotationManager;
100 static void global_registry_handler(void* data, wl_registry* registry,
101 uint32_t id, const char* interface,
102 uint32_t version) {
103 auto* display = static_cast<nsWaylandDisplay*>(data);
104 if (!display) {
105 return;
108 nsDependentCString iface(interface);
109 if (iface.EqualsLiteral("wl_shm")) {
110 auto* shm = WaylandRegistryBind<wl_shm>(registry, id, &wl_shm_interface, 1);
111 display->SetShm(shm);
112 } else if (iface.EqualsLiteral("zwp_idle_inhibit_manager_v1")) {
113 auto* idle_inhibit_manager =
114 WaylandRegistryBind<zwp_idle_inhibit_manager_v1>(
115 registry, id, &zwp_idle_inhibit_manager_v1_interface, 1);
116 display->SetIdleInhibitManager(idle_inhibit_manager);
117 } else if (iface.EqualsLiteral("zwp_relative_pointer_manager_v1")) {
118 auto* relative_pointer_manager =
119 WaylandRegistryBind<zwp_relative_pointer_manager_v1>(
120 registry, id, &zwp_relative_pointer_manager_v1_interface, 1);
121 display->SetRelativePointerManager(relative_pointer_manager);
122 } else if (iface.EqualsLiteral("zwp_pointer_constraints_v1")) {
123 auto* pointer_constraints = WaylandRegistryBind<zwp_pointer_constraints_v1>(
124 registry, id, &zwp_pointer_constraints_v1_interface, 1);
125 display->SetPointerConstraints(pointer_constraints);
126 } else if (iface.EqualsLiteral("wl_compositor")) {
127 // Requested wl_compositor version 4 as we need wl_surface_damage_buffer().
128 auto* compositor = WaylandRegistryBind<wl_compositor>(
129 registry, id, &wl_compositor_interface, 4);
130 display->SetCompositor(compositor);
131 } else if (iface.EqualsLiteral("wl_subcompositor")) {
132 auto* subcompositor = WaylandRegistryBind<wl_subcompositor>(
133 registry, id, &wl_subcompositor_interface, 1);
134 display->SetSubcompositor(subcompositor);
135 } else if (iface.EqualsLiteral("wp_viewporter")) {
136 auto* viewporter = WaylandRegistryBind<wp_viewporter>(
137 registry, id, &wp_viewporter_interface, 1);
138 display->SetViewporter(viewporter);
139 } else if (iface.EqualsLiteral("zwp_linux_dmabuf_v1") && version > 2) {
140 auto* dmabuf = WaylandRegistryBind<zwp_linux_dmabuf_v1>(
141 registry, id, &zwp_linux_dmabuf_v1_interface, 3);
142 display->SetDmabuf(dmabuf);
143 } else if (iface.EqualsLiteral("xdg_activation_v1")) {
144 auto* activation = WaylandRegistryBind<xdg_activation_v1>(
145 registry, id, &xdg_activation_v1_interface, 1);
146 display->SetXdgActivation(activation);
147 } else if (iface.EqualsLiteral("xdg_dbus_annotation_manager_v1")) {
148 auto* annotationManager =
149 WaylandRegistryBind<xdg_dbus_annotation_manager_v1>(
150 registry, id, &xdg_dbus_annotation_manager_v1_interface, 1);
151 display->SetXdgDbusAnnotationManager(annotationManager);
152 } else if (iface.EqualsLiteral("wl_seat")) {
153 // Install keyboard handlers for main thread only
154 auto* seat =
155 WaylandRegistryBind<wl_seat>(registry, id, &wl_seat_interface, 1);
156 KeymapWrapper::SetSeat(seat, id);
157 } else if (iface.EqualsLiteral("wp_fractional_scale_manager_v1")) {
158 auto* manager = WaylandRegistryBind<wp_fractional_scale_manager_v1>(
159 registry, id, &wp_fractional_scale_manager_v1_interface, 1);
160 display->SetFractionalScaleManager(manager);
161 } else if (iface.EqualsLiteral("gtk_primary_selection_device_manager") ||
162 iface.EqualsLiteral("zwp_primary_selection_device_manager_v1")) {
163 display->EnablePrimarySelection();
167 static void global_registry_remover(void* data, wl_registry* registry,
168 uint32_t id) {
169 KeymapWrapper::ClearSeat(id);
172 static const struct wl_registry_listener registry_listener = {
173 global_registry_handler, global_registry_remover};
175 nsWaylandDisplay::~nsWaylandDisplay() {}
177 static void WlLogHandler(const char* format, va_list args) {
178 char error[1000];
179 VsprintfLiteral(error, format, args);
180 gfxCriticalNote << "Wayland protocol error: " << error;
182 // See Bug 1826583 and Bug 1844653 for reference.
183 // "warning: queue %p destroyed while proxies still attached" and variants
184 // like "zwp_linux_dmabuf_feedback_v1@%d still attached" are exceptions on
185 // Wayland and non-fatal. They are triggered in certain versions of Mesa or
186 // the proprietary Nvidia driver and we don't want to crash because of them.
187 if (strstr(error, "still attached")) {
188 return;
191 MOZ_CRASH_UNSAFE(error);
194 nsWaylandDisplay::nsWaylandDisplay(wl_display* aDisplay)
195 : mThreadId(PR_GetCurrentThread()), mDisplay(aDisplay) {
196 // GTK sets the log handler on display creation, thus we overwrite it here
197 // in a similar fashion
198 wl_log_set_handler_client(WlLogHandler);
200 mRegistry = wl_display_get_registry(mDisplay);
201 wl_registry_add_listener(mRegistry, &registry_listener, this);
202 wl_display_roundtrip(mDisplay);
203 wl_display_roundtrip(mDisplay);
205 // Check we have critical Wayland interfaces.
206 // Missing ones indicates a compositor bug and we can't continue.
207 MOZ_DIAGNOSTIC_ASSERT(GetShm(), "We're missing shm interface!");
208 MOZ_DIAGNOSTIC_ASSERT(GetCompositor(), "We're missing compositor interface!");
209 MOZ_DIAGNOSTIC_ASSERT(GetSubcompositor(),
210 "We're missing subcompositor interface!");
213 } // namespace mozilla::widget