blob: c9c1929fe6b0dbd9d2e973cd024c415d0b6c798f [file]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_EVENTS_PLATFORM_WAYLAND_WAYLAND_EVENT_WATCHER_H_
#define UI_EVENTS_PLATFORM_WAYLAND_WAYLAND_EVENT_WATCHER_H_
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_pump_for_ui.h"
#include "base/threading/thread_checker.h"
struct wl_display;
struct wl_event_queue;
namespace base {
class Thread;
class SingleThreadTaskRunner;
class WaitableEvent;
} // namespace base
namespace ui {
// WaylandEventWatcher is a base class that provides a read/prepare/dispatch
// functionality to derived WaylandEventWatcherFDWatch and
// WaylandEventWatcherGlib classes. These classes serve a single purpose - they
// use libevent or libglib (depends on the build configuration of Chromium) to
// watch a Wayland file descriptor and get notified when they can read events
// from an event queue. They also strictly follow a strict prepare/read/dispatch
// dance to ensure Wayland client event loop's integration into the previously
// mentioned event loop libraries is correct. The events that the instance of
// this class dispatches trigger input objects (e.g: WaylandPointer,
// WaylandKeyboard, and others) callbacks, indirectly leading to calls into
// WaylandEventSource, so feeding the platform events pipeline.
class WaylandEventWatcher {
public:
WaylandEventWatcher(const WaylandEventWatcher&) = delete;
WaylandEventWatcher& operator=(const WaylandEventWatcher&) = delete;
virtual ~WaylandEventWatcher();
static std::unique_ptr<WaylandEventWatcher> CreateWaylandEventWatcher(
wl_display* display,
wl_event_queue* event_queue,
bool use_threaded_polling = false);
// Sets a callback that that shutdowns the browser in case of
// unrecoverable error. Can only be set once.
void SetShutdownCb(base::OnceCallback<void()> shutdown_cb);
// Starts polling for events from the wayland connection file descriptor.
// This method assumes connection is already estabilished and input objects
// are already bound and properly initialized.
void StartProcessingEvents();
// Calls wl_display_roundtrip_queue. Might be required during initialization
// of some objects that should block until they are initialized.
void RoundTripQueue();
protected:
WaylandEventWatcher(wl_display* display,
wl_event_queue* event_queue,
bool use_threaded_polling);
// Stops polling for events from input devices.
void StopProcessingEvents();
// Starts watching the fd. Returns true on success
virtual bool StartWatchingFD(int fd) = 0;
// Stops watching the previously passed fd.
virtual void StopWatchingFD() = 0;
// Prepares to read events. Must be called before the event loop goes to
// sleep. Returns true if prepared and false if prepare to read failed, which
// means there are events to be dispatched.
bool WlDisplayPrepareToRead();
// Read the events. Should be only called after the event loop polled the fd
// and if WlDisplayPrepareToRead has been called before.
void WlDisplayReadEvents();
// Cancels prepare to read.
void WlDisplayCancelRead();
// Dispatches all incoming events for objects assigned to the event queue
// after the events have been read with the WlDisplayReadEvents call. Also,
// checks for errors by calling WlDisplayCheckForErrors if the Wayland API
// failed.
void WlDisplayDispatchPendingQueue();
private:
void StartProcessingEventsThread();
void StartProcessingEventsInternal();
void StopProcessingEventsInternal();
void WlDisplayDispatchPendingQueueInternal(base::WaitableEvent* event);
// Checks if |display_| has any error set. If so, |shutdown_cb_| is executed
// and false is returned.
void WlDisplayCheckForErrors();
const raw_ptr<wl_display> display_; // Owned by WaylandConnection.
const raw_ptr<wl_event_queue> event_queue_; // Owned by WaylandConnection.
bool watching_ = false;
bool prepared_ = false;
base::OnceCallback<void()> shutdown_cb_;
// Use threaded polling to support --in-process-gpu with EGL wayland backend.
bool use_threaded_polling_ = false;
// Used to verify watching the fd happens on a valid thread.
THREAD_CHECKER(thread_checker_);
// See the |use_threaded_polling_| and also the comment in the source
// file for this header.
std::unique_ptr<base::Thread> thread_;
// The original ui task runner where |this| has been created.
scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner_;
// The thread's task runner where the wl_display's fd is being watched.
scoped_refptr<base::SingleThreadTaskRunner> watching_thread_task_runner_;
base::WeakPtr<WaylandEventWatcher> weak_this_; // Bound to the main thread.
// This weak factory must only be accessed on the main thread.
base::WeakPtrFactory<WaylandEventWatcher> weak_factory_{this};
};
} // namespace ui
#endif // UI_EVENTS_PLATFORM_WAYLAND_WAYLAND_EVENT_WATCHER_H_