blob: 27ea61f84b3bf4992a45070288aac58df25fcbf0 [file] [log] [blame]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/exo/wayland/test/test_wayland_client_thread.h"
#include <utility>
#include <wayland-client-core.h>
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/run_loop.h"
#include "base/task/current_thread.h"
namespace exo::wayland::test {
TestWaylandClientThread::TestWaylandClientThread(const std::string& name)
: Thread(name), controller_(FROM_HERE) {}
TestWaylandClientThread::~TestWaylandClientThread() {
// Stop watching the descriptor here to guarantee that no new events will come
// during or after the destruction of the display.
controller_.StopWatchingFileDescriptor();
task_runner()->PostTask(FROM_HERE,
base::BindOnce(&TestWaylandClientThread::DoCleanUp,
base::Unretained(this)));
// Ensure the task above is run.
FlushForTesting();
}
bool TestWaylandClientThread::Start(
base::OnceCallback<std::unique_ptr<TestClient>()> init_callback) {
base::Thread::Options options;
options.message_pump_type = base::MessagePumpType::IO;
CHECK(base::Thread::StartWithOptions(std::move(options)));
RunAndWait(base::BindOnce(&TestWaylandClientThread::DoInit,
base::Unretained(this), std::move(init_callback)));
return !!client_;
}
void TestWaylandClientThread::RunAndWait(
base::OnceCallback<void(TestClient*)> callback) {
base::OnceClosure closure =
base::BindOnce(std::move(callback), base::Unretained(client_.get()));
RunAndWait(std::move(closure));
}
void TestWaylandClientThread::RunAndWait(base::OnceClosure closure) {
base::RunLoop run_loop;
task_runner()->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&TestWaylandClientThread::DoRun, base::Unretained(this),
std::move(closure)),
run_loop.QuitClosure());
run_loop.Run();
}
void TestWaylandClientThread::OnFileCanReadWithoutBlocking(int fd) {
while (wl_display_prepare_read(client_->display()) != 0)
wl_display_dispatch_pending(client_->display());
wl_display_read_events(client_->display());
wl_display_dispatch_pending(client_->display());
}
void TestWaylandClientThread::OnFileCanWriteWithoutBlocking(int fd) {}
void TestWaylandClientThread::DoInit(
TestWaylandClientThread::InitCallback init_callback) {
client_ = std::move(init_callback).Run();
if (!client_)
return;
const bool result = base::CurrentIOThread::Get().WatchFileDescriptor(
wl_display_get_fd(client_->display()), /*persistent=*/true,
base::MessagePumpLibevent::WATCH_READ, &controller_, this);
if (!result)
client_.reset();
}
void TestWaylandClientThread::DoRun(base::OnceClosure closure) {
std::move(closure).Run();
wl_display_roundtrip(client_->display());
}
void TestWaylandClientThread::DoCleanUp() {
client_.reset();
}
} // namespace exo::wayland::test