chromium/ui/events/platform/wayland/wayland_event_watcher_fdwatch.cc

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ui/events/platform/wayland/wayland_event_watcher_fdwatch.h"

#include "base/notreached.h"
#include "base/task/current_thread.h"

namespace ui {

WaylandEventWatcherFdWatch::WaylandEventWatcherFdWatch(
    wl_display* display,
    wl_event_queue* event_queue,
    bool use_threaded_polling)
    : WaylandEventWatcher(display, event_queue, use_threaded_polling),
      controller_(FROM_HERE) {}

WaylandEventWatcherFdWatch::~WaylandEventWatcherFdWatch() {
  StopProcessingEvents();
}

bool WaylandEventWatcherFdWatch::StartWatchingFD(int fd) {
  DCHECK(base::CurrentUIThread::IsSet());
  WlDisplayPrepareToRead();
  return base::CurrentUIThread::Get()->WatchFileDescriptor(
      fd, true, base::MessagePumpForUI::WATCH_READ, &controller_, this);
}

void WaylandEventWatcherFdWatch::StopWatchingFD() {
  DCHECK(base::CurrentUIThread::IsSet());
  CHECK(controller_.StopWatchingFileDescriptor())
      << "Unable to stop watching the Wayland display fd.";
}

void WaylandEventWatcherFdWatch::OnFileCanReadWithoutBlocking(int fd) {
  // All the error checking and conditions to read are handled by the base
  // class. See https://bit.ly/3tCjobF to get an idea how it works.
  //
  // TODO(crbug.com/40816750): once libevent is updated to the newest version,
  // use watcher callbacks that notify clients about intention to sleep/poll or
  // about bytes available to be read so that we are able to correctly call all
  // these methods. At the moment, they are constantly called whenever there is
  // something to read, which is inefficient. See WaylandEventWatcherGlib for
  // example.
  WlDisplayReadEvents();
  WlDisplayDispatchPendingQueue();

  // If prepare failed, dispatch the events once again.
  if (!WlDisplayPrepareToRead()) {
    WlDisplayDispatchPendingQueue();
  }
}

void WaylandEventWatcherFdWatch::OnFileCanWriteWithoutBlocking(int fd) {
  NOTREACHED_IN_MIGRATION();
}

// static
std::unique_ptr<WaylandEventWatcher>
WaylandEventWatcher::CreateWaylandEventWatcher(wl_display* display,
                                               wl_event_queue* event_queue,
                                               bool use_threaded_polling) {
  return std::make_unique<WaylandEventWatcherFdWatch>(display, event_queue,
                                                      use_threaded_polling);
}

}  // namespace ui