Bug 1931425 - Limit how often moz-label's #setStyles runs r=reusable-components-revie...
[gecko.git] / widget / gtk / nsWaylandDisplay.cpp
blob8cfcdce3086a429b3775169195144942e698d8af
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"
8 #include "DMABufFormats.h"
10 #include "base/message_loop.h" // for MessageLoop
11 #include "base/task.h" // for NewRunnableMethod, etc
12 #include "mozilla/gfx/Logging.h" // for gfxCriticalNote
13 #include "mozilla/StaticMutex.h"
14 #include "mozilla/Array.h"
15 #include "mozilla/StaticPtr.h"
16 #include "mozilla/ThreadLocal.h"
17 #include "mozilla/StaticPrefs_widget.h"
18 #include "mozilla/StaticPrefs_general.h"
19 #include "mozilla/Sprintf.h"
20 #include "WidgetUtilsGtk.h"
21 #include "nsGtkKeyUtils.h"
22 #include "nsWindow.h"
23 #include "wayland-proxy.h"
25 namespace mozilla::widget {
27 static nsWaylandDisplay* gWaylandDisplay;
29 void WaylandDisplayRelease() {
30 MOZ_RELEASE_ASSERT(NS_IsMainThread(),
31 "WaylandDisplay can be released in main thread only!");
32 if (!gWaylandDisplay) {
33 return;
35 delete gWaylandDisplay;
36 gWaylandDisplay = nullptr;
39 wl_display* WaylandDisplayGetWLDisplay() {
40 GdkDisplay* disp = gdk_display_get_default();
41 if (!GdkIsWaylandDisplay(disp)) {
42 return nullptr;
44 return gdk_wayland_display_get_wl_display(disp);
47 nsWaylandDisplay* WaylandDisplayGet() {
48 if (!gWaylandDisplay) {
49 MOZ_RELEASE_ASSERT(NS_IsMainThread(),
50 "WaylandDisplay can be created in main thread only!");
51 wl_display* waylandDisplay = WaylandDisplayGetWLDisplay();
52 if (!waylandDisplay) {
53 return nullptr;
55 // We're setting Wayland client buffer size here (i.e. our write buffer).
56 // Server buffer size is set by compositor and we may use the same buffer
57 // sizes on both sides. Mutter uses 1024 * 1024 (1M) so let's use the same
58 // value.
59 wl_display_set_max_buffer_size(waylandDisplay, 1024 * 1024);
60 gWaylandDisplay = new nsWaylandDisplay(waylandDisplay);
62 return gWaylandDisplay;
65 void nsWaylandDisplay::SetShm(wl_shm* aShm) { mShm = aShm; }
67 class WaylandPointerEvent {
68 public:
69 RefPtr<nsWindow> TakeWindow(wl_surface* aSurface) {
70 if (!aSurface) {
71 mWindow = nullptr;
72 } else {
73 GdkWindow* window =
74 static_cast<GdkWindow*>(wl_surface_get_user_data(aSurface));
75 mWindow = window ? static_cast<nsWindow*>(
76 g_object_get_data(G_OBJECT(window), "nsWindow"))
77 : nullptr;
79 return mWindow;
81 already_AddRefed<nsWindow> GetAndClearWindow() { return mWindow.forget(); }
82 RefPtr<nsWindow> GetWindow() { return mWindow; }
84 void SetSource(int32_t aSource) { mSource = aSource; }
86 void SetDelta120(uint32_t aAxis, int32_t aDelta) {
87 switch (aAxis) {
88 case WL_POINTER_AXIS_VERTICAL_SCROLL:
89 mDeltaY = aDelta / 120.0f;
90 break;
91 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
92 mDeltaX = aDelta / 120.0f;
93 break;
94 default:
95 NS_WARNING("WaylandPointerEvent::SetDelta120(): wrong axis!");
96 break;
100 void SetTime(uint32_t aTime) { mTime = aTime; }
102 void SendScrollEvent() {
103 if (!mWindow || !StaticPrefs::general_smoothScroll()) {
104 return;
107 // nsWindow::OnSmoothScrollEvent() may spin event loop so
108 // mWindow/mSource/delta may be replaced.
109 int32_t source = mSource;
110 float deltaX = mDeltaX;
111 float deltaY = mDeltaY;
113 mSource = -1;
114 mDeltaX = mDeltaY = 0.0f;
116 // We process wheel events only now.
117 if (source != WL_POINTER_AXIS_SOURCE_WHEEL) {
118 return;
121 RefPtr<nsWindow> win = mWindow;
122 uint32_t eventTime = mTime;
123 win->OnSmoothScrollEvent(eventTime, deltaX, deltaY);
126 void Clear() { mWindow = nullptr; }
128 WaylandPointerEvent() { Clear(); }
130 private:
131 StaticRefPtr<nsWindow> mWindow;
132 uint32_t mTime = 0;
133 int32_t mSource = 0;
134 float mDeltaX = 0;
135 float mDeltaY = 0;
138 MOZ_RUNINIT static WaylandPointerEvent sHoldGesture;
140 static void gesture_hold_begin(void* data,
141 struct zwp_pointer_gesture_hold_v1* hold,
142 uint32_t serial, uint32_t time,
143 struct wl_surface* surface, uint32_t fingers) {
144 RefPtr<nsWindow> window = sHoldGesture.TakeWindow(surface);
145 if (!window) {
146 return;
148 window->OnTouchpadHoldEvent(GDK_TOUCHPAD_GESTURE_PHASE_BEGIN, time, fingers);
151 static void gesture_hold_end(void* data,
152 struct zwp_pointer_gesture_hold_v1* hold,
153 uint32_t serial, uint32_t time,
154 int32_t cancelled) {
155 RefPtr<nsWindow> window = sHoldGesture.GetAndClearWindow();
156 if (!window) {
157 return;
159 window->OnTouchpadHoldEvent(cancelled ? GDK_TOUCHPAD_GESTURE_PHASE_CANCEL
160 : GDK_TOUCHPAD_GESTURE_PHASE_END,
161 time, 0);
164 static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_listener =
165 {gesture_hold_begin, gesture_hold_end};
167 MOZ_RUNINIT static WaylandPointerEvent sScrollEvent;
169 static void pointer_handle_enter(void* data, struct wl_pointer* pointer,
170 uint32_t serial, struct wl_surface* surface,
171 wl_fixed_t sx, wl_fixed_t sy) {
172 sScrollEvent.TakeWindow(surface);
175 static void pointer_handle_leave(void* data, struct wl_pointer* pointer,
176 uint32_t serial, struct wl_surface* surface) {
177 sScrollEvent.Clear();
180 static void pointer_handle_motion(void* data, struct wl_pointer* pointer,
181 uint32_t time, wl_fixed_t sx, wl_fixed_t sy) {
184 static void pointer_handle_button(void* data, struct wl_pointer* pointer,
185 uint32_t serial, uint32_t time,
186 uint32_t button, uint32_t state) {}
188 static void pointer_handle_axis(void* data, struct wl_pointer* pointer,
189 uint32_t time, uint32_t axis,
190 wl_fixed_t value) {
191 sScrollEvent.SetTime(time);
194 static void pointer_handle_frame(void* data, struct wl_pointer* pointer) {
195 sScrollEvent.SendScrollEvent();
198 static void pointer_handle_axis_source(
199 void* data, struct wl_pointer* pointer,
200 /*enum wl_pointer_axis_source */ uint32_t source) {
201 sScrollEvent.SetSource(source);
204 static void pointer_handle_axis_stop(void* data, struct wl_pointer* pointer,
205 uint32_t time, uint32_t axis) {}
207 static void pointer_handle_axis_discrete(void* data, struct wl_pointer* pointer,
208 uint32_t axis, int32_t value) {}
210 static void pointer_handle_axis_value120(void* data, struct wl_pointer* pointer,
211 uint32_t axis, int32_t value) {
212 sScrollEvent.SetDelta120(axis, value);
216 * Example of scroll events we get for various devices. Note that
217 * even three different devices has the same wl_pointer.
219 * Standard mouse wheel:
221 * pointer_handle_axis_source pointer 0x7fd14fd4bac0 source 0
222 * pointer_handle_axis_value120 pointer 0x7fd14fd4bac0 value 120
223 * pointer_handle_axis pointer 0x7fd14fd4bac0 time 9470441 value 10.000000
224 * pointer_handle_frame
226 * Hi-res mouse wheel:
228 * pointer_handle_axis_source pointer 0x7fd14fd4bac0 source 0
229 * pointer_handle_axis_value120 pointer 0x7fd14fd4bac0 value -24
230 * pointer_handle_axis pointer 0x7fd14fd4bac0 time 9593205 value -1.992188
231 * pointer_handle_frame
233 * Touchpad:
235 * pointer_handle_axis_source pointer 0x7fd14fd4bac0 source 1
236 * pointer_handle_axis pointer 0x7fd14fd4bac0 time 9431830 value 0.312500
237 * pointer_handle_axis pointer 0x7fd14fd4bac0 time 9431830 value -1.015625
238 * pointer_handle_frame
241 static const struct moz_wl_pointer_listener pointer_listener = {
242 pointer_handle_enter, pointer_handle_leave,
243 pointer_handle_motion, pointer_handle_button,
244 pointer_handle_axis, pointer_handle_frame,
245 pointer_handle_axis_source, pointer_handle_axis_stop,
246 pointer_handle_axis_discrete, pointer_handle_axis_value120,
249 void nsWaylandDisplay::SetPointer(wl_pointer* aPointer) {
250 // Don't even try on such old interface
251 if (wl_proxy_get_version((struct wl_proxy*)aPointer) <
252 WL_POINTER_RELEASE_SINCE_VERSION) {
253 return;
256 MOZ_DIAGNOSTIC_ASSERT(!mPointer);
257 mPointer = aPointer;
259 // We're interested in pointer_handle_axis_value120() only for now.
260 if (wl_proxy_get_version((struct wl_proxy*)aPointer) >=
261 WL_POINTER_AXIS_VALUE120_SINCE_VERSION) {
262 wl_pointer_add_listener(
263 mPointer, (const wl_pointer_listener*)&pointer_listener, this);
266 // mPointerGestures is set by zwp_pointer_gestures_v1 if we have it.
267 if (mPointerGestures) {
268 mPointerGestureHold =
269 zwp_pointer_gestures_v1_get_hold_gesture(mPointerGestures, mPointer);
270 zwp_pointer_gesture_hold_v1_set_user_data(mPointerGestureHold, this);
271 zwp_pointer_gesture_hold_v1_add_listener(mPointerGestureHold,
272 &gesture_hold_listener, this);
276 void nsWaylandDisplay::RemovePointer() {
277 wl_pointer_release(mPointer);
278 mPointer = nullptr;
281 static void seat_handle_capabilities(void* data, struct wl_seat* seat,
282 unsigned int caps) {
283 auto* display = static_cast<nsWaylandDisplay*>(data);
284 if (!display) {
285 return;
288 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !display->GetPointer()) {
289 display->SetPointer(wl_seat_get_pointer(seat));
290 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && display->GetPointer()) {
291 display->RemovePointer();
294 wl_keyboard* keyboard = display->GetKeyboard();
295 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !keyboard) {
296 display->SetKeyboard(wl_seat_get_keyboard(seat));
297 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && keyboard) {
298 display->ClearKeyboard();
302 static void seat_handle_name(void* data, struct wl_seat* seat,
303 const char* name) {
304 /* We don't care about the name. */
307 static const struct wl_seat_listener seat_listener = {
308 seat_handle_capabilities,
309 seat_handle_name,
312 void nsWaylandDisplay::SetSeat(wl_seat* aSeat, int aSeatId) {
313 mSeat = aSeat;
314 mSeatId = aSeatId;
315 wl_seat_add_listener(aSeat, &seat_listener, this);
318 void nsWaylandDisplay::RemoveSeat(int aSeatId) {
319 if (mSeatId == aSeatId) {
320 mSeat = nullptr;
321 mSeatId = -1;
325 /* This keymap routine is derived from weston-2.0.0/clients/simple-im.c
327 static void keyboard_handle_keymap(void* data, struct wl_keyboard* wl_keyboard,
328 uint32_t format, int fd, uint32_t size) {
329 KeymapWrapper::HandleKeymap(format, fd, size);
332 static void keyboard_handle_enter(void* data, struct wl_keyboard* keyboard,
333 uint32_t serial, struct wl_surface* surface,
334 struct wl_array* keys) {
335 KeymapWrapper::SetFocusIn(surface, serial);
338 static void keyboard_handle_leave(void* data, struct wl_keyboard* keyboard,
339 uint32_t serial, struct wl_surface* surface) {
340 KeymapWrapper::SetFocusOut(surface);
343 static void keyboard_handle_key(void* data, struct wl_keyboard* keyboard,
344 uint32_t serial, uint32_t time, uint32_t key,
345 uint32_t state) {}
346 static void keyboard_handle_modifiers(void* data, struct wl_keyboard* keyboard,
347 uint32_t serial, uint32_t mods_depressed,
348 uint32_t mods_latched,
349 uint32_t mods_locked, uint32_t group) {}
350 static void keyboard_handle_repeat_info(void* data,
351 struct wl_keyboard* keyboard,
352 int32_t rate, int32_t delay) {}
354 static const struct wl_keyboard_listener keyboard_listener = {
355 keyboard_handle_keymap, keyboard_handle_enter,
356 keyboard_handle_leave, keyboard_handle_key,
357 keyboard_handle_modifiers, keyboard_handle_repeat_info};
359 void nsWaylandDisplay::SetKeyboard(wl_keyboard* aKeyboard) {
360 MOZ_ASSERT(aKeyboard);
361 MOZ_DIAGNOSTIC_ASSERT(!mKeyboard);
362 mKeyboard = aKeyboard;
363 wl_keyboard_add_listener(mKeyboard, &keyboard_listener, nullptr);
366 void nsWaylandDisplay::ClearKeyboard() {
367 if (mKeyboard) {
368 wl_keyboard_destroy(mKeyboard);
369 mKeyboard = nullptr;
373 void nsWaylandDisplay::SetCompositor(wl_compositor* aCompositor) {
374 mCompositor = aCompositor;
377 void nsWaylandDisplay::SetSubcompositor(wl_subcompositor* aSubcompositor) {
378 mSubcompositor = aSubcompositor;
381 void nsWaylandDisplay::SetIdleInhibitManager(
382 zwp_idle_inhibit_manager_v1* aIdleInhibitManager) {
383 mIdleInhibitManager = aIdleInhibitManager;
386 void nsWaylandDisplay::SetViewporter(wp_viewporter* aViewporter) {
387 mViewporter = aViewporter;
390 void nsWaylandDisplay::SetRelativePointerManager(
391 zwp_relative_pointer_manager_v1* aRelativePointerManager) {
392 mRelativePointerManager = aRelativePointerManager;
395 void nsWaylandDisplay::SetPointerConstraints(
396 zwp_pointer_constraints_v1* aPointerConstraints) {
397 mPointerConstraints = aPointerConstraints;
400 void nsWaylandDisplay::SetPointerGestures(
401 zwp_pointer_gestures_v1* aPointerGestures) {
402 mPointerGestures = aPointerGestures;
405 void nsWaylandDisplay::SetDmabuf(zwp_linux_dmabuf_v1* aDmabuf, int aVersion) {
406 if (!aDmabuf || aVersion < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
407 return;
409 mDmabuf = aDmabuf;
410 mFormats = new DMABufFormats();
411 mDmabufIsFeedback =
412 (aVersion >= ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION);
413 if (mDmabufIsFeedback) {
414 mFormats->InitFeedback(mDmabuf, nullptr);
415 } else {
416 mFormats->InitV3(mDmabuf);
420 void nsWaylandDisplay::SetXdgActivation(xdg_activation_v1* aXdgActivation) {
421 mXdgActivation = aXdgActivation;
424 void nsWaylandDisplay::SetXdgDbusAnnotationManager(
425 xdg_dbus_annotation_manager_v1* aXdgDbusAnnotationManager) {
426 mXdgDbusAnnotationManager = aXdgDbusAnnotationManager;
429 void nsWaylandDisplay::SetCMSupportedFeature(uint32_t aFeature) {
430 switch (aFeature) {
431 case XX_COLOR_MANAGER_V4_FEATURE_ICC_V2_V4:
432 mColorManagerSupportedFeature.mICC = true;
433 break;
434 case XX_COLOR_MANAGER_V4_FEATURE_PARAMETRIC:
435 mColorManagerSupportedFeature.mParametric = true;
436 break;
437 case XX_COLOR_MANAGER_V4_FEATURE_SET_PRIMARIES:
438 mColorManagerSupportedFeature.mPrimaries = true;
439 break;
440 case XX_COLOR_MANAGER_V4_FEATURE_SET_TF_POWER:
441 mColorManagerSupportedFeature.mFTPower = true;
442 break;
443 case XX_COLOR_MANAGER_V4_FEATURE_SET_LUMINANCES:
444 mColorManagerSupportedFeature.mLuminances = true;
445 break;
446 case XX_COLOR_MANAGER_V4_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES:
447 mColorManagerSupportedFeature.mDisplayPrimaries = true;
448 break;
452 void nsWaylandDisplay::SetCMSupportedTFNamed(uint32_t aTF) {
453 if (aTF < sColorTransfersNum) {
454 mSupportedTransfer[aTF] = aTF;
455 } else {
456 NS_WARNING("Unknow color transfer function!");
460 void nsWaylandDisplay::SetCMSupportedPrimariesNamed(uint32_t aPrimaries) {
461 if (aPrimaries < sColorPrimariesNum) {
462 mSupportedPrimaries[aPrimaries] = aPrimaries;
463 } else {
464 NS_WARNING("Unknown color primaries!");
468 static void supported_intent(void* data,
469 struct xx_color_manager_v4* color_manager,
470 uint32_t render_intent) {}
472 static void supported_feature(void* data,
473 struct xx_color_manager_v4* color_manager,
474 uint32_t feature) {
475 auto* display = static_cast<nsWaylandDisplay*>(data);
476 display->SetCMSupportedFeature(feature);
479 static void supported_tf_named(void* data,
480 struct xx_color_manager_v4* color_manager,
481 uint32_t tf) {
482 auto* display = static_cast<nsWaylandDisplay*>(data);
483 display->SetCMSupportedTFNamed(tf);
486 static void supported_primaries_named(void* data,
487 struct xx_color_manager_v4* color_manager,
488 uint32_t primaries) {
489 auto* display = static_cast<nsWaylandDisplay*>(data);
490 display->SetCMSupportedPrimariesNamed(primaries);
493 static const struct xx_color_manager_v4_listener color_manager_listener = {
494 supported_intent,
495 supported_feature,
496 supported_tf_named,
497 supported_primaries_named,
500 void nsWaylandDisplay::SetColorManager(xx_color_manager_v4* aColorManager) {
501 mColorManager = aColorManager;
502 if (mColorManager) {
503 xx_color_manager_v4_add_listener(mColorManager, &color_manager_listener,
504 this);
508 static void global_registry_handler(void* data, wl_registry* registry,
509 uint32_t id, const char* interface,
510 uint32_t version) {
511 auto* display = static_cast<nsWaylandDisplay*>(data);
512 if (!display) {
513 return;
516 nsDependentCString iface(interface);
517 if (iface.EqualsLiteral("wl_shm")) {
518 auto* shm = WaylandRegistryBind<wl_shm>(registry, id, &wl_shm_interface, 1);
519 display->SetShm(shm);
520 } else if (iface.EqualsLiteral("zwp_idle_inhibit_manager_v1")) {
521 auto* idle_inhibit_manager =
522 WaylandRegistryBind<zwp_idle_inhibit_manager_v1>(
523 registry, id, &zwp_idle_inhibit_manager_v1_interface, 1);
524 display->SetIdleInhibitManager(idle_inhibit_manager);
525 } else if (iface.EqualsLiteral("zwp_relative_pointer_manager_v1")) {
526 auto* relative_pointer_manager =
527 WaylandRegistryBind<zwp_relative_pointer_manager_v1>(
528 registry, id, &zwp_relative_pointer_manager_v1_interface, 1);
529 display->SetRelativePointerManager(relative_pointer_manager);
530 } else if (iface.EqualsLiteral("zwp_pointer_constraints_v1")) {
531 auto* pointer_constraints = WaylandRegistryBind<zwp_pointer_constraints_v1>(
532 registry, id, &zwp_pointer_constraints_v1_interface, 1);
533 display->SetPointerConstraints(pointer_constraints);
534 } else if (iface.EqualsLiteral("wl_compositor") &&
535 version >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) {
536 auto* compositor = WaylandRegistryBind<wl_compositor>(
537 registry, id, &wl_compositor_interface,
538 WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION);
539 display->SetCompositor(compositor);
540 } else if (iface.EqualsLiteral("wl_subcompositor")) {
541 auto* subcompositor = WaylandRegistryBind<wl_subcompositor>(
542 registry, id, &wl_subcompositor_interface, 1);
543 display->SetSubcompositor(subcompositor);
544 } else if (iface.EqualsLiteral("wp_viewporter")) {
545 auto* viewporter = WaylandRegistryBind<wp_viewporter>(
546 registry, id, &wp_viewporter_interface, 1);
547 display->SetViewporter(viewporter);
548 } else if (iface.EqualsLiteral("zwp_linux_dmabuf_v1")) {
549 if (version < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
550 return;
552 int vers =
553 MIN(version, ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION);
554 auto* dmabuf = WaylandRegistryBind<zwp_linux_dmabuf_v1>(
555 registry, id, &zwp_linux_dmabuf_v1_interface, vers);
556 display->SetDmabuf(dmabuf, vers);
557 } else if (iface.EqualsLiteral("xdg_activation_v1")) {
558 auto* activation = WaylandRegistryBind<xdg_activation_v1>(
559 registry, id, &xdg_activation_v1_interface, 1);
560 display->SetXdgActivation(activation);
561 } else if (iface.EqualsLiteral("xdg_dbus_annotation_manager_v1")) {
562 auto* annotationManager =
563 WaylandRegistryBind<xdg_dbus_annotation_manager_v1>(
564 registry, id, &xdg_dbus_annotation_manager_v1_interface, 1);
565 display->SetXdgDbusAnnotationManager(annotationManager);
566 } else if (iface.EqualsLiteral("wl_seat") &&
567 version >= WL_POINTER_RELEASE_SINCE_VERSION) {
568 auto* seat = WaylandRegistryBind<wl_seat>(
569 registry, id, &wl_seat_interface,
570 MIN(version, WL_POINTER_AXIS_VALUE120_SINCE_VERSION));
571 display->SetSeat(seat, id);
572 } else if (iface.EqualsLiteral("wp_fractional_scale_manager_v1")) {
573 auto* manager = WaylandRegistryBind<wp_fractional_scale_manager_v1>(
574 registry, id, &wp_fractional_scale_manager_v1_interface, 1);
575 display->SetFractionalScaleManager(manager);
576 } else if (iface.EqualsLiteral("gtk_primary_selection_device_manager") ||
577 iface.EqualsLiteral("zwp_primary_selection_device_manager_v1")) {
578 display->EnablePrimarySelection();
579 } else if (iface.EqualsLiteral("zwp_pointer_gestures_v1") &&
580 version >=
581 ZWP_POINTER_GESTURES_V1_GET_HOLD_GESTURE_SINCE_VERSION) {
582 auto* gestures = WaylandRegistryBind<zwp_pointer_gestures_v1>(
583 registry, id, &zwp_pointer_gestures_v1_interface,
584 ZWP_POINTER_GESTURES_V1_GET_HOLD_GESTURE_SINCE_VERSION);
585 display->SetPointerGestures(gestures);
586 } else if (iface.EqualsLiteral("xx_color_manager_v4")) {
587 // initialize_color_maps(wl);
588 auto* colorManager = WaylandRegistryBind<xx_color_manager_v4>(
589 registry, id, &xx_color_manager_v4_interface, version);
590 display->SetColorManager(colorManager);
594 static void global_registry_remover(void* data, wl_registry* registry,
595 uint32_t id) {
596 auto* display = static_cast<nsWaylandDisplay*>(data);
597 if (!display) {
598 return;
600 display->RemoveSeat(id);
603 static const struct wl_registry_listener registry_listener = {
604 global_registry_handler, global_registry_remover};
606 nsWaylandDisplay::~nsWaylandDisplay() = default;
608 static void WlLogHandler(const char* format, va_list args) {
609 char error[1000];
610 VsprintfLiteral(error, format, args);
611 gfxCriticalNote << "(" << GetDesktopEnvironmentIdentifier().get()
612 << ") Wayland protocol error: " << error;
614 // See Bug 1826583 and Bug 1844653 for reference.
615 // "warning: queue %p destroyed while proxies still attached" and variants
616 // like "zwp_linux_dmabuf_feedback_v1@%d still attached" are exceptions on
617 // Wayland and non-fatal. They are triggered in certain versions of Mesa or
618 // the proprietary Nvidia driver and we don't want to crash because of them.
619 if (strstr(error, "still attached")) {
620 return;
623 MOZ_CRASH_UNSAFE_PRINTF("(%s) %s Proxy: %s",
624 GetDesktopEnvironmentIdentifier().get(), error,
625 WaylandProxy::GetState());
628 void WlCompositorCrashHandler() {
629 gfxCriticalNote << "Wayland protocol error: Compositor ("
630 << GetDesktopEnvironmentIdentifier().get()
631 << ") crashed, proxy: " << WaylandProxy::GetState();
632 MOZ_CRASH_UNSAFE_PRINTF("Compositor crashed (%s) proxy: %s",
633 GetDesktopEnvironmentIdentifier().get(),
634 WaylandProxy::GetState());
637 nsWaylandDisplay::nsWaylandDisplay(wl_display* aDisplay)
638 : mThreadId(PR_GetCurrentThread()), mDisplay(aDisplay) {
639 // GTK sets the log handler on display creation, thus we overwrite it here
640 // in a similar fashion
641 wl_log_set_handler_client(WlLogHandler);
643 mRegistry = wl_display_get_registry(mDisplay);
644 wl_registry_add_listener(mRegistry, &registry_listener, this);
645 wl_display_roundtrip(mDisplay);
646 wl_display_roundtrip(mDisplay);
647 if (mDmabuf && !mDmabufIsFeedback) {
648 mFormats->InitV3Done();
651 for (auto& e : mSupportedTransfer) {
652 e = -1;
654 for (auto& e : mSupportedPrimaries) {
655 e = -1;
658 // Check we have critical Wayland interfaces.
659 // Missing ones indicates a compositor bug and we can't continue.
660 MOZ_RELEASE_ASSERT(GetShm(), "We're missing shm interface!");
661 MOZ_RELEASE_ASSERT(GetCompositor(), "We're missing compositor interface!");
662 MOZ_RELEASE_ASSERT(GetSubcompositor(),
663 "We're missing subcompositor interface!");
666 } // namespace mozilla::widget