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"
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
) {
35 delete gWaylandDisplay
;
36 gWaylandDisplay
= nullptr;
39 wl_display
* WaylandDisplayGetWLDisplay() {
40 GdkDisplay
* disp
= gdk_display_get_default();
41 if (!GdkIsWaylandDisplay(disp
)) {
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
) {
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
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
{
69 RefPtr
<nsWindow
> TakeWindow(wl_surface
* aSurface
) {
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"))
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
) {
88 case WL_POINTER_AXIS_VERTICAL_SCROLL
:
89 mDeltaY
= aDelta
/ 120.0f
;
91 case WL_POINTER_AXIS_HORIZONTAL_SCROLL
:
92 mDeltaX
= aDelta
/ 120.0f
;
95 NS_WARNING("WaylandPointerEvent::SetDelta120(): wrong axis!");
100 void SetTime(uint32_t aTime
) { mTime
= aTime
; }
102 void SendScrollEvent() {
103 if (!mWindow
|| !StaticPrefs::general_smoothScroll()) {
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
;
114 mDeltaX
= mDeltaY
= 0.0f
;
116 // We process wheel events only now.
117 if (source
!= WL_POINTER_AXIS_SOURCE_WHEEL
) {
121 RefPtr
<nsWindow
> win
= mWindow
;
122 uint32_t eventTime
= mTime
;
123 win
->OnSmoothScrollEvent(eventTime
, deltaX
, deltaY
);
126 void Clear() { mWindow
= nullptr; }
128 WaylandPointerEvent() { Clear(); }
131 StaticRefPtr
<nsWindow
> mWindow
;
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
);
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
,
155 RefPtr
<nsWindow
> window
= sHoldGesture
.GetAndClearWindow();
159 window
->OnTouchpadHoldEvent(cancelled
? GDK_TOUCHPAD_GESTURE_PHASE_CANCEL
160 : GDK_TOUCHPAD_GESTURE_PHASE_END
,
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
,
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
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
) {
256 MOZ_DIAGNOSTIC_ASSERT(!mPointer
);
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
);
281 static void seat_handle_capabilities(void* data
, struct wl_seat
* seat
,
283 auto* display
= static_cast<nsWaylandDisplay
*>(data
);
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
,
304 /* We don't care about the name. */
307 static const struct wl_seat_listener seat_listener
= {
308 seat_handle_capabilities
,
312 void nsWaylandDisplay::SetSeat(wl_seat
* aSeat
, int aSeatId
) {
315 wl_seat_add_listener(aSeat
, &seat_listener
, this);
318 void nsWaylandDisplay::RemoveSeat(int aSeatId
) {
319 if (mSeatId
== aSeatId
) {
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
,
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() {
368 wl_keyboard_destroy(mKeyboard
);
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
) {
410 mFormats
= new DMABufFormats();
412 (aVersion
>= ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION
);
413 if (mDmabufIsFeedback
) {
414 mFormats
->InitFeedback(mDmabuf
, nullptr);
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
) {
431 case XX_COLOR_MANAGER_V4_FEATURE_ICC_V2_V4
:
432 mColorManagerSupportedFeature
.mICC
= true;
434 case XX_COLOR_MANAGER_V4_FEATURE_PARAMETRIC
:
435 mColorManagerSupportedFeature
.mParametric
= true;
437 case XX_COLOR_MANAGER_V4_FEATURE_SET_PRIMARIES
:
438 mColorManagerSupportedFeature
.mPrimaries
= true;
440 case XX_COLOR_MANAGER_V4_FEATURE_SET_TF_POWER
:
441 mColorManagerSupportedFeature
.mFTPower
= true;
443 case XX_COLOR_MANAGER_V4_FEATURE_SET_LUMINANCES
:
444 mColorManagerSupportedFeature
.mLuminances
= true;
446 case XX_COLOR_MANAGER_V4_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES
:
447 mColorManagerSupportedFeature
.mDisplayPrimaries
= true;
452 void nsWaylandDisplay::SetCMSupportedTFNamed(uint32_t aTF
) {
453 if (aTF
< sColorTransfersNum
) {
454 mSupportedTransfer
[aTF
] = aTF
;
456 NS_WARNING("Unknow color transfer function!");
460 void nsWaylandDisplay::SetCMSupportedPrimariesNamed(uint32_t aPrimaries
) {
461 if (aPrimaries
< sColorPrimariesNum
) {
462 mSupportedPrimaries
[aPrimaries
] = aPrimaries
;
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
,
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
,
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
= {
497 supported_primaries_named
,
500 void nsWaylandDisplay::SetColorManager(xx_color_manager_v4
* aColorManager
) {
501 mColorManager
= aColorManager
;
503 xx_color_manager_v4_add_listener(mColorManager
, &color_manager_listener
,
508 static void global_registry_handler(void* data
, wl_registry
* registry
,
509 uint32_t id
, const char* interface
,
511 auto* display
= static_cast<nsWaylandDisplay
*>(data
);
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
) {
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") &&
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
,
596 auto* display
= static_cast<nsWaylandDisplay
*>(data
);
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
) {
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")) {
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
, ®istry_listener
, this);
645 wl_display_roundtrip(mDisplay
);
646 wl_display_roundtrip(mDisplay
);
647 if (mDmabuf
&& !mDmabufIsFeedback
) {
648 mFormats
->InitV3Done();
651 for (auto& e
: mSupportedTransfer
) {
654 for (auto& e
: mSupportedPrimaries
) {
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