Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/widget/gtk/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 23 kB image not shown  

Quelle  nsWaylandDisplay.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* 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 "nsWaylandDisplay.h"
#include "DMABufFormats.h"

#include "base/message_loop.h"    // for MessageLoop
#include "base/task.h"            // for NewRunnableMethod, etc
#include "mozilla/gfx/Logging.h"  // for gfxCriticalNote
#include "mozilla/StaticMutex.h"
#include "mozilla/Array.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/ThreadLocal.h"
#include "mozilla/StaticPrefs_widget.h"
#include "mozilla/StaticPrefs_general.h"
#include "mozilla/Sprintf.h"
#include "WidgetUtilsGtk.h"
#include "nsGtkKeyUtils.h"
#include "nsWindow.h"
#include "wayland-proxy.h"

namespace mozilla::widget {

static nsWaylandDisplay* gWaylandDisplay;

void WaylandDisplayRelease() {
  MOZ_RELEASE_ASSERT(NS_IsMainThread(),
                     "WaylandDisplay can be released in main thread only!");
  if (!gWaylandDisplay) {
    return;
  }
  delete gWaylandDisplay;
  gWaylandDisplay = nullptr;
}

wl_display* WaylandDisplayGetWLDisplay() {
  GdkDisplay* disp = gdk_display_get_default();
  if (!GdkIsWaylandDisplay(disp)) {
    return nullptr;
  }
  return gdk_wayland_display_get_wl_display(disp);
}

nsWaylandDisplay* WaylandDisplayGet() {
  if (!gWaylandDisplay) {
    MOZ_RELEASE_ASSERT(NS_IsMainThread(),
                       "WaylandDisplay can be created in main thread only!");
    wl_display* waylandDisplay = WaylandDisplayGetWLDisplay();
    if (!waylandDisplay) {
      return nullptr;
    }
    // We're setting Wayland client buffer size here (i.e. our write buffer).
    // Server buffer size is set by compositor and we may use the same buffer
    // sizes on both sides. Mutter uses 1024 * 1024 (1M) so let's use the same
    // value.
    wl_display_set_max_buffer_size(waylandDisplay, 1024 * 1024);
    gWaylandDisplay = new nsWaylandDisplay(waylandDisplay);
  }
  return gWaylandDisplay;
}

void nsWaylandDisplay::SetShm(wl_shm* aShm) { mShm = aShm; }

class WaylandPointerEvent {
 public:
  RefPtr<nsWindow> TakeWindow(wl_surface* aSurface) {
    if (!aSurface) {
      mWindow = nullptr;
    } else {
      GdkWindow* window =
          static_cast<GdkWindow*>(wl_surface_get_user_data(aSurface));
      mWindow = window ? static_cast<nsWindow*>(
                             g_object_get_data(G_OBJECT(window), "nsWindow"))
                       : nullptr;
    }
    return mWindow;
  }
  already_AddRefed<nsWindow> GetAndClearWindow() { return mWindow.forget(); }
  RefPtr<nsWindow> GetWindow() { return mWindow; }

  void SetSource(int32_t aSource) { mSource = aSource; }

  void SetDelta120(uint32_t aAxis, int32_t aDelta) {
    switch (aAxis) {
      case WL_POINTER_AXIS_VERTICAL_SCROLL:
        mDeltaY = aDelta / 120.0f;
        break;
      case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
        mDeltaX = aDelta / 120.0f;
        break;
      default:
        NS_WARNING("WaylandPointerEvent::SetDelta120(): wrong axis!");
        break;
    }
  }

  void SetTime(uint32_t aTime) { mTime = aTime; }

  void SendScrollEvent() {
    if (!mWindow || !StaticPrefs::general_smoothScroll()) {
      return;
    }

    // nsWindow::OnSmoothScrollEvent() may spin event loop so
    // mWindow/mSource/delta may be replaced.
    int32_t source = mSource;
    float deltaX = mDeltaX;
    float deltaY = mDeltaY;

    mSource = -1;
    mDeltaX = mDeltaY = 0.0f;

    // We process wheel events only now.
    if (source != WL_POINTER_AXIS_SOURCE_WHEEL) {
      return;
    }

    RefPtr<nsWindow> win = mWindow;
    uint32_t eventTime = mTime;
    win->OnSmoothScrollEvent(eventTime, deltaX, deltaY);
  }

  void Clear() { mWindow = nullptr; }

  WaylandPointerEvent() { Clear(); }

 private:
  StaticRefPtr<nsWindow> mWindow;
  uint32_t mTime = 0;
  int32_t mSource = 0;
  float mDeltaX = 0;
  float mDeltaY = 0;
};

MOZ_RUNINIT static WaylandPointerEvent sHoldGesture;

static void gesture_hold_begin(void* data,
                               struct zwp_pointer_gesture_hold_v1* hold,
                               uint32_t serial, uint32_t time,
                               struct wl_surface* surface, uint32_t fingers) {
  RefPtr<nsWindow> window = sHoldGesture.TakeWindow(surface);
  if (!window) {
    return;
  }
  window->OnTouchpadHoldEvent(GDK_TOUCHPAD_GESTURE_PHASE_BEGIN, time, fingers);
}

static void gesture_hold_end(void* data,
                             struct zwp_pointer_gesture_hold_v1* hold,
                             uint32_t serial, uint32_t time,
                             int32_t cancelled) {
  RefPtr<nsWindow> window = sHoldGesture.GetAndClearWindow();
  if (!window) {
    return;
  }
  window->OnTouchpadHoldEvent(cancelled ? GDK_TOUCHPAD_GESTURE_PHASE_CANCEL
                                        : GDK_TOUCHPAD_GESTURE_PHASE_END,
                              time, 0);
}

static const struct zwp_pointer_gesture_hold_v1_listener gesture_hold_listener =
    {gesture_hold_begin, gesture_hold_end};

MOZ_RUNINIT static WaylandPointerEvent sScrollEvent;

static void pointer_handle_enter(void* data, struct wl_pointer* pointer,
                                 uint32_t serial, struct wl_surface* surface,
                                 wl_fixed_t sx, wl_fixed_t sy) {
  sScrollEvent.TakeWindow(surface);
}

static void pointer_handle_leave(void* data, struct wl_pointer* pointer,
                                 uint32_t serial, struct wl_surface* surface) {
  sScrollEvent.Clear();
}

static void pointer_handle_motion(void* data, struct wl_pointer* pointer,
                                  uint32_t time, wl_fixed_t sx, wl_fixed_t sy) {
}

static void pointer_handle_button(void* data, struct wl_pointer* pointer,
                                  uint32_t serial, uint32_t time,
                                  uint32_t button, uint32_t state) {}

static void pointer_handle_axis(void* data, struct wl_pointer* pointer,
                                uint32_t time, uint32_t axis,
                                wl_fixed_t value) {
  sScrollEvent.SetTime(time);
}

static void pointer_handle_frame(void* data, struct wl_pointer* pointer) {
  sScrollEvent.SendScrollEvent();
}

static void pointer_handle_axis_source(
    void* data, struct wl_pointer* pointer,
    /*enum wl_pointer_axis_source */ uint32_t source) {
  sScrollEvent.SetSource(source);
}

static void pointer_handle_axis_stop(void* data, struct wl_pointer* pointer,
                                     uint32_t time, uint32_t axis) {}

static void pointer_handle_axis_discrete(void* data, struct wl_pointer* pointer,
                                         uint32_t axis, int32_t value) {}

static void pointer_handle_axis_value120(void* data, struct wl_pointer* pointer,
                                         uint32_t axis, int32_t value) {
  sScrollEvent.SetDelta120(axis, value);
}

/*
 * Example of scroll events we get for various devices. Note that
 * even three different devices has the same wl_pointer.
 *
 * Standard mouse wheel:
 *
 *  pointer_handle_axis_source pointer 0x7fd14fd4bac0 source 0
 *  pointer_handle_axis_value120 pointer 0x7fd14fd4bac0 value 120
 *  pointer_handle_axis pointer 0x7fd14fd4bac0 time 9470441 value 10.000000
 *  pointer_handle_frame
 *
 * Hi-res mouse wheel:
 *
 * pointer_handle_axis_source pointer 0x7fd14fd4bac0 source 0
 * pointer_handle_axis_value120 pointer 0x7fd14fd4bac0 value -24
 * pointer_handle_axis pointer 0x7fd14fd4bac0 time 9593205 value -1.992188
 * pointer_handle_frame
 *
 * Touchpad:
 *
 * pointer_handle_axis_source pointer 0x7fd14fd4bac0 source 1
 * pointer_handle_axis pointer 0x7fd14fd4bac0 time 9431830 value 0.312500
 * pointer_handle_axis pointer 0x7fd14fd4bac0 time 9431830 value -1.015625
 * pointer_handle_frame
 */


static const struct moz_wl_pointer_listener pointer_listener = {
    pointer_handle_enter,         pointer_handle_leave,
    pointer_handle_motion,        pointer_handle_button,
    pointer_handle_axis,          pointer_handle_frame,
    pointer_handle_axis_source,   pointer_handle_axis_stop,
    pointer_handle_axis_discrete, pointer_handle_axis_value120,
};

void nsWaylandDisplay::SetPointer(wl_pointer* aPointer) {
  // Don't even try on such old interface
  if (wl_proxy_get_version((struct wl_proxy*)aPointer) <
      WL_POINTER_RELEASE_SINCE_VERSION) {
    return;
  }

  MOZ_DIAGNOSTIC_ASSERT(!mPointer);
  mPointer = aPointer;

  // We're interested in pointer_handle_axis_value120() only for now.
  if (wl_proxy_get_version((struct wl_proxy*)aPointer) >=
      WL_POINTER_AXIS_VALUE120_SINCE_VERSION) {
    wl_pointer_add_listener(
        mPointer, (const wl_pointer_listener*)&pointer_listener, this);
  }

  // mPointerGestures is set by zwp_pointer_gestures_v1 if we have it.
  if (mPointerGestures) {
    mPointerGestureHold =
        zwp_pointer_gestures_v1_get_hold_gesture(mPointerGestures, mPointer);
    zwp_pointer_gesture_hold_v1_set_user_data(mPointerGestureHold, this);
    zwp_pointer_gesture_hold_v1_add_listener(mPointerGestureHold,
                                             &gesture_hold_listener, this);
  }
}

void nsWaylandDisplay::RemovePointer() {
  wl_pointer_release(mPointer);
  mPointer = nullptr;
}

static void seat_handle_capabilities(void* data, struct wl_seat* seat,
                                     unsigned int caps) {
  auto* display = static_cast<nsWaylandDisplay*>(data);
  if (!display) {
    return;
  }

  if ((caps & WL_SEAT_CAPABILITY_POINTER) && !display->GetPointer()) {
    display->SetPointer(wl_seat_get_pointer(seat));
  } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && display->GetPointer()) {
    display->RemovePointer();
  }

  wl_keyboard* keyboard = display->GetKeyboard();
  if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !keyboard) {
    display->SetKeyboard(wl_seat_get_keyboard(seat));
  } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && keyboard) {
    display->ClearKeyboard();
  }
}

static void seat_handle_name(void* data, struct wl_seat* seat,
                             const char* name) {
  /* We don't care about the name. */
}

static const struct wl_seat_listener seat_listener = {
    seat_handle_capabilities,
    seat_handle_name,
};

void nsWaylandDisplay::SetSeat(wl_seat* aSeat, int aSeatId) {
  mSeat = aSeat;
  mSeatId = aSeatId;
  wl_seat_add_listener(aSeat, &seat_listener, this);
}

void nsWaylandDisplay::RemoveSeat(int aSeatId) {
  if (mSeatId == aSeatId) {
    mSeat = nullptr;
    mSeatId = -1;
  }
}

/* This keymap routine is derived from weston-2.0.0/clients/simple-im.c
 */

static void keyboard_handle_keymap(void* data, struct wl_keyboard* wl_keyboard,
                                   uint32_t format, int fd, uint32_t size) {
  KeymapWrapper::HandleKeymap(format, fd, size);
}

static void keyboard_handle_enter(void* data, struct wl_keyboard* keyboard,
                                  uint32_t serial, struct wl_surface* surface,
                                  struct wl_array* keys) {
  KeymapWrapper::SetFocusIn(surface, serial);
}

static void keyboard_handle_leave(void* data, struct wl_keyboard* keyboard,
                                  uint32_t serial, struct wl_surface* surface) {
  KeymapWrapper::SetFocusOut(surface);
}

static void keyboard_handle_key(void* data, struct wl_keyboard* keyboard,
                                uint32_t serial, uint32_t time, uint32_t key,
                                uint32_t state) {}
static void keyboard_handle_modifiers(void* data, struct wl_keyboard* keyboard,
                                      uint32_t serial, uint32_t mods_depressed,
                                      uint32_t mods_latched,
                                      uint32_t mods_locked, uint32_t group) {}
static void keyboard_handle_repeat_info(void* data,
                                        struct wl_keyboard* keyboard,
                                        int32_t rate, int32_t delay) {}

static const struct wl_keyboard_listener keyboard_listener = {
    keyboard_handle_keymap,    keyboard_handle_enter,
    keyboard_handle_leave,     keyboard_handle_key,
    keyboard_handle_modifiers, keyboard_handle_repeat_info};

void nsWaylandDisplay::SetKeyboard(wl_keyboard* aKeyboard) {
  MOZ_ASSERT(aKeyboard);
  MOZ_DIAGNOSTIC_ASSERT(!mKeyboard);
  mKeyboard = aKeyboard;
  wl_keyboard_add_listener(mKeyboard, &keyboard_listener, nullptr);
}

void nsWaylandDisplay::ClearKeyboard() {
  if (mKeyboard) {
    wl_keyboard_destroy(mKeyboard);
    mKeyboard = nullptr;
  }
}

void nsWaylandDisplay::SetCompositor(wl_compositor* aCompositor) {
  mCompositor = aCompositor;
}

void nsWaylandDisplay::SetSubcompositor(wl_subcompositor* aSubcompositor) {
  mSubcompositor = aSubcompositor;
}

void nsWaylandDisplay::SetIdleInhibitManager(
    zwp_idle_inhibit_manager_v1* aIdleInhibitManager) {
  mIdleInhibitManager = aIdleInhibitManager;
}

void nsWaylandDisplay::SetViewporter(wp_viewporter* aViewporter) {
  mViewporter = aViewporter;
}

void nsWaylandDisplay::SetRelativePointerManager(
    zwp_relative_pointer_manager_v1* aRelativePointerManager) {
  mRelativePointerManager = aRelativePointerManager;
}

void nsWaylandDisplay::SetPointerConstraints(
    zwp_pointer_constraints_v1* aPointerConstraints) {
  mPointerConstraints = aPointerConstraints;
}

void nsWaylandDisplay::SetPointerGestures(
    zwp_pointer_gestures_v1* aPointerGestures) {
  mPointerGestures = aPointerGestures;
}

void nsWaylandDisplay::SetDmabuf(zwp_linux_dmabuf_v1* aDmabuf, int aVersion) {
  if (!aDmabuf || aVersion < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
    return;
  }
  mDmabuf = aDmabuf;
  mFormats = new DMABufFormats();
  mDmabufIsFeedback =
      (aVersion >= ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION);
  if (mDmabufIsFeedback) {
    mFormats->InitFeedback(mDmabuf, nullptr);
  } else {
    mFormats->InitV3(mDmabuf);
  }
}

void nsWaylandDisplay::SetXdgActivation(xdg_activation_v1* aXdgActivation) {
  mXdgActivation = aXdgActivation;
}

void nsWaylandDisplay::SetXdgDbusAnnotationManager(
    xdg_dbus_annotation_manager_v1* aXdgDbusAnnotationManager) {
  mXdgDbusAnnotationManager = aXdgDbusAnnotationManager;
}

void nsWaylandDisplay::SetCMSupportedFeature(uint32_t aFeature) {
  switch (aFeature) {
    case XX_COLOR_MANAGER_V4_FEATURE_ICC_V2_V4:
      mColorManagerSupportedFeature.mICC = true;
      break;
    case XX_COLOR_MANAGER_V4_FEATURE_PARAMETRIC:
      mColorManagerSupportedFeature.mParametric = true;
      break;
    case XX_COLOR_MANAGER_V4_FEATURE_SET_PRIMARIES:
      mColorManagerSupportedFeature.mPrimaries = true;
      break;
    case XX_COLOR_MANAGER_V4_FEATURE_SET_TF_POWER:
      mColorManagerSupportedFeature.mFTPower = true;
      break;
    case XX_COLOR_MANAGER_V4_FEATURE_SET_LUMINANCES:
      mColorManagerSupportedFeature.mLuminances = true;
      break;
    case XX_COLOR_MANAGER_V4_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES:
      mColorManagerSupportedFeature.mDisplayPrimaries = true;
      break;
  }
}

void nsWaylandDisplay::SetCMSupportedTFNamed(uint32_t aTF) {
  if (aTF < sColorTransfersNum) {
    mSupportedTransfer[aTF] = aTF;
  } else {
    NS_WARNING("Unknow color transfer function!");
  }
}

void nsWaylandDisplay::SetCMSupportedPrimariesNamed(uint32_t aPrimaries) {
  if (aPrimaries < sColorPrimariesNum) {
    mSupportedPrimaries[aPrimaries] = aPrimaries;
  } else {
    NS_WARNING("Unknown color primaries!");
  }
}

static void supported_intent(void* data,
                             struct xx_color_manager_v4* color_manager,
                             uint32_t render_intent) {}

static void supported_feature(void* data,
                              struct xx_color_manager_v4* color_manager,
                              uint32_t feature) {
  auto* display = static_cast<nsWaylandDisplay*>(data);
  display->SetCMSupportedFeature(feature);
}

static void supported_tf_named(void* data,
                               struct xx_color_manager_v4* color_manager,
                               uint32_t tf) {
  auto* display = static_cast<nsWaylandDisplay*>(data);
  display->SetCMSupportedTFNamed(tf);
}

static void supported_primaries_named(void* data,
                                      struct xx_color_manager_v4* color_manager,
                                      uint32_t primaries) {
  auto* display = static_cast<nsWaylandDisplay*>(data);
  display->SetCMSupportedPrimariesNamed(primaries);
}

static const struct xx_color_manager_v4_listener color_manager_listener = {
    supported_intent,
    supported_feature,
    supported_tf_named,
    supported_primaries_named,
};

void nsWaylandDisplay::SetColorManager(xx_color_manager_v4* aColorManager) {
  mColorManager = aColorManager;
  if (mColorManager) {
    xx_color_manager_v4_add_listener(mColorManager, &color_manager_listener,
                                     this);
  }
}

static void global_registry_handler(void* data, wl_registry* registry,
                                    uint32_t id, const char* interface,
                                    uint32_t version) {
  auto* display = static_cast<nsWaylandDisplay*>(data);
  if (!display) {
    return;
  }

  nsDependentCString iface(interface);
  if (iface.EqualsLiteral("wl_shm")) {
    auto* shm = WaylandRegistryBind<wl_shm>(registry, id, &wl_shm_interface, 1);
    display->SetShm(shm);
  } else if (iface.EqualsLiteral("zwp_idle_inhibit_manager_v1")) {
    auto* idle_inhibit_manager =
        WaylandRegistryBind<zwp_idle_inhibit_manager_v1>(
            registry, id, &zwp_idle_inhibit_manager_v1_interface, 1);
    display->SetIdleInhibitManager(idle_inhibit_manager);
  } else if (iface.EqualsLiteral("zwp_relative_pointer_manager_v1")) {
    auto* relative_pointer_manager =
        WaylandRegistryBind<zwp_relative_pointer_manager_v1>(
            registry, id, &zwp_relative_pointer_manager_v1_interface, 1);
    display->SetRelativePointerManager(relative_pointer_manager);
  } else if (iface.EqualsLiteral("zwp_pointer_constraints_v1")) {
    auto* pointer_constraints = WaylandRegistryBind<zwp_pointer_constraints_v1>(
        registry, id, &zwp_pointer_constraints_v1_interface, 1);
    display->SetPointerConstraints(pointer_constraints);
  } else if (iface.EqualsLiteral("wl_compositor") &&
             version >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION) {
    auto* compositor = WaylandRegistryBind<wl_compositor>(
        registry, id, &wl_compositor_interface,
        WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION);
    display->SetCompositor(compositor);
  } else if (iface.EqualsLiteral("wl_subcompositor")) {
    auto* subcompositor = WaylandRegistryBind<wl_subcompositor>(
        registry, id, &wl_subcompositor_interface, 1);
    display->SetSubcompositor(subcompositor);
  } else if (iface.EqualsLiteral("wp_viewporter")) {
    auto* viewporter = WaylandRegistryBind<wp_viewporter>(
        registry, id, &wp_viewporter_interface, 1);
    display->SetViewporter(viewporter);
  } else if (iface.EqualsLiteral("zwp_linux_dmabuf_v1")) {
    if (version < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
      return;
    }
    int vers =
        MIN(version, ZWP_LINUX_DMABUF_V1_GET_DEFAULT_FEEDBACK_SINCE_VERSION);
    auto* dmabuf = WaylandRegistryBind<zwp_linux_dmabuf_v1>(
        registry, id, &zwp_linux_dmabuf_v1_interface, vers);
    display->SetDmabuf(dmabuf, vers);
  } else if (iface.EqualsLiteral("xdg_activation_v1")) {
    auto* activation = WaylandRegistryBind<xdg_activation_v1>(
        registry, id, &xdg_activation_v1_interface, 1);
    display->SetXdgActivation(activation);
  } else if (iface.EqualsLiteral("xdg_dbus_annotation_manager_v1")) {
    auto* annotationManager =
        WaylandRegistryBind<xdg_dbus_annotation_manager_v1>(
            registry, id, &xdg_dbus_annotation_manager_v1_interface, 1);
    display->SetXdgDbusAnnotationManager(annotationManager);
  } else if (iface.EqualsLiteral("wl_seat") &&
             version >= WL_POINTER_RELEASE_SINCE_VERSION) {
    auto* seat = WaylandRegistryBind<wl_seat>(
        registry, id, &wl_seat_interface,
        MIN(version, WL_POINTER_AXIS_VALUE120_SINCE_VERSION));
    display->SetSeat(seat, id);
  } else if (iface.EqualsLiteral("wp_fractional_scale_manager_v1")) {
    auto* manager = WaylandRegistryBind<wp_fractional_scale_manager_v1>(
        registry, id, &wp_fractional_scale_manager_v1_interface, 1);
    display->SetFractionalScaleManager(manager);
  } else if (iface.EqualsLiteral("gtk_primary_selection_device_manager") ||
             iface.EqualsLiteral("zwp_primary_selection_device_manager_v1")) {
    display->EnablePrimarySelection();
  } else if (iface.EqualsLiteral("zwp_pointer_gestures_v1") &&
             version >=
                 ZWP_POINTER_GESTURES_V1_GET_HOLD_GESTURE_SINCE_VERSION) {
    auto* gestures = WaylandRegistryBind<zwp_pointer_gestures_v1>(
        registry, id, &zwp_pointer_gestures_v1_interface,
        ZWP_POINTER_GESTURES_V1_GET_HOLD_GESTURE_SINCE_VERSION);
    display->SetPointerGestures(gestures);
  } else if (iface.EqualsLiteral("xx_color_manager_v4")) {
    // initialize_color_maps(wl);
    auto* colorManager = WaylandRegistryBind<xx_color_manager_v4>(
        registry, id, &xx_color_manager_v4_interface, version);
    display->SetColorManager(colorManager);
  }
}

static void global_registry_remover(void* data, wl_registry* registry,
                                    uint32_t id) {
  auto* display = static_cast<nsWaylandDisplay*>(data);
  if (!display) {
    return;
  }
  display->RemoveSeat(id);
}

static const struct wl_registry_listener registry_listener = {
    global_registry_handler, global_registry_remover};

nsWaylandDisplay::~nsWaylandDisplay() = default;

static void WlLogHandler(const char* format, va_list args) {
  char error[1000];
  VsprintfLiteral(error, format, args);
  gfxCriticalNote << "(" << GetDesktopEnvironmentIdentifier().get()
                  << ") Wayland protocol error: " << error;

  // See Bug 1826583 and Bug 1844653 for reference.
  // "warning: queue %p destroyed while proxies still attached" and variants
  // like "zwp_linux_dmabuf_feedback_v1@%d still attached" are exceptions on
  // Wayland and non-fatal. They are triggered in certain versions of Mesa or
  // the proprietary Nvidia driver and we don't want to crash because of them.
  if (strstr(error, "still attached")) {
    return;
  }

  MOZ_CRASH_UNSAFE_PRINTF("(%s) %s Proxy: %s",
                          GetDesktopEnvironmentIdentifier().get(), error,
                          WaylandProxy::GetState());
}

void WlCompositorCrashHandler() {
  gfxCriticalNote << "Wayland protocol error: Compositor ("
                  << GetDesktopEnvironmentIdentifier().get()
                  << ") crashed, proxy: " << WaylandProxy::GetState();
  MOZ_CRASH_UNSAFE_PRINTF("Compositor crashed (%s) proxy: %s",
                          GetDesktopEnvironmentIdentifier().get(),
                          WaylandProxy::GetState());
}

nsWaylandDisplay::nsWaylandDisplay(wl_display* aDisplay)
    : mThreadId(PR_GetCurrentThread()), mDisplay(aDisplay) {
  // GTK sets the log handler on display creation, thus we overwrite it here
  // in a similar fashion
  wl_log_set_handler_client(WlLogHandler);

  mRegistry = wl_display_get_registry(mDisplay);
  wl_registry_add_listener(mRegistry, ®istry_listener, this);
  wl_display_roundtrip(mDisplay);
  wl_display_roundtrip(mDisplay);
  if (mDmabuf && !mDmabufIsFeedback) {
    mFormats->InitV3Done();
  }

  for (auto& e : mSupportedTransfer) {
    e = -1;
  };
  for (auto& e : mSupportedPrimaries) {
    e = -1;
  };

  // Check we have critical Wayland interfaces.
  // Missing ones indicates a compositor bug and we can't continue.
  MOZ_RELEASE_ASSERT(GetShm(), "We're missing shm interface!");
  MOZ_RELEASE_ASSERT(GetCompositor(), "We're missing compositor interface!");
  MOZ_RELEASE_ASSERT(GetSubcompositor(),
                     "We're missing subcompositor interface!");
}

}  // namespace mozilla::widget

Messung V0.5
C=92 H=98 G=94

¤ Dauer der Verarbeitung: 0.7 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.