1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/ozone/platform/wayland/test/test_wayland_server_thread.h"
6
7 #include <stdlib.h>
8 #include <sys/socket.h>
9 #include <wayland-server.h>
10 #include <memory>
11
12 #include "base/bind.h"
13 #include "base/files/file_util.h"
14 #include "base/files/scoped_file.h"
15 #include "base/run_loop.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/task_runner_util.h"
18
19 namespace wl {
20
operator ()(wl_display * display)21 void DisplayDeleter::operator()(wl_display* display) {
22 wl_display_destroy(display);
23 }
24
TestWaylandServerThread()25 TestWaylandServerThread::TestWaylandServerThread()
26 : Thread("test_wayland_server"),
27 pause_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
28 base::WaitableEvent::InitialState::NOT_SIGNALED),
29 resume_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
30 base::WaitableEvent::InitialState::NOT_SIGNALED),
31 controller_(FROM_HERE) {}
32
~TestWaylandServerThread()33 TestWaylandServerThread::~TestWaylandServerThread() {
34 if (client_)
35 wl_client_destroy(client_);
36
37 Resume();
38 Stop();
39 }
40
Start(uint32_t shell_version)41 bool TestWaylandServerThread::Start(uint32_t shell_version) {
42 display_.reset(wl_display_create());
43 if (!display_)
44 return false;
45 event_loop_ = wl_display_get_event_loop(display_.get());
46
47 int fd[2];
48 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, fd) < 0)
49 return false;
50 base::ScopedFD server_fd(fd[0]);
51 base::ScopedFD client_fd(fd[1]);
52
53 // If client has not specified rect before, user standard ones.
54 if (output_.GetRect().IsEmpty())
55 output_.SetRect(gfx::Rect(0, 0, 800, 600));
56
57 if (wl_display_init_shm(display_.get()) < 0)
58 return false;
59 if (!compositor_.Initialize(display_.get()))
60 return false;
61 if (!sub_compositor_.Initialize(display_.get()))
62 return false;
63 if (!output_.Initialize(display_.get()))
64 return false;
65 if (!data_device_manager_.Initialize(display_.get()))
66 return false;
67 if (!seat_.Initialize(display_.get()))
68 return false;
69 if (shell_version == 6) {
70 if (!zxdg_shell_v6_.Initialize(display_.get()))
71 return false;
72 } else if (shell_version == 7) {
73 if (!xdg_shell_.Initialize(display_.get()))
74 return false;
75 } else {
76 NOTREACHED() << "Unsupported shell version: " << shell_version;
77 }
78 if (!zwp_text_input_manager_v1_.Initialize(display_.get()))
79 return false;
80 if (!zwp_linux_dmabuf_v1_.Initialize(display_.get()))
81 return false;
82
83 client_ = wl_client_create(display_.get(), server_fd.release());
84 if (!client_)
85 return false;
86
87 base::Thread::Options options;
88 options.message_pump_factory = base::BindRepeating(
89 &TestWaylandServerThread::CreateMessagePump, base::Unretained(this));
90 if (!base::Thread::StartWithOptions(options))
91 return false;
92
93 setenv("WAYLAND_SOCKET", base::NumberToString(client_fd.release()).c_str(),
94 1);
95
96 return true;
97 }
98
Pause()99 void TestWaylandServerThread::Pause() {
100 task_runner()->PostTask(FROM_HERE,
101 base::BindOnce(&TestWaylandServerThread::DoPause,
102 base::Unretained(this)));
103 pause_event_.Wait();
104 }
105
Resume()106 void TestWaylandServerThread::Resume() {
107 if (display_)
108 wl_display_flush_clients(display_.get());
109 resume_event_.Signal();
110 }
111
EnsureWpPresentation()112 MockWpPresentation* TestWaylandServerThread::EnsureWpPresentation() {
113 if (wp_presentation_.Initialize(display_.get()))
114 return &wp_presentation_;
115 return nullptr;
116 }
117
DoPause()118 void TestWaylandServerThread::DoPause() {
119 base::RunLoop().RunUntilIdle();
120 pause_event_.Signal();
121 resume_event_.Wait();
122 }
123
124 std::unique_ptr<base::MessagePump>
CreateMessagePump()125 TestWaylandServerThread::CreateMessagePump() {
126 auto pump = std::make_unique<base::MessagePumpLibevent>();
127 pump->WatchFileDescriptor(wl_event_loop_get_fd(event_loop_), true,
128 base::MessagePumpLibevent::WATCH_READ, &controller_,
129 this);
130 return std::move(pump);
131 }
132
OnFileCanReadWithoutBlocking(int fd)133 void TestWaylandServerThread::OnFileCanReadWithoutBlocking(int fd) {
134 wl_event_loop_dispatch(event_loop_, 0);
135 wl_display_flush_clients(display_.get());
136 }
137
OnFileCanWriteWithoutBlocking(int fd)138 void TestWaylandServerThread::OnFileCanWriteWithoutBlocking(int fd) {}
139
140 } // namespace wl
141