1 //
2 // Copyright 2022 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // WaylandWindow.cpp: Implementation of OSWindow for Wayland
8
9 #include "util/linux/wayland/WaylandWindow.h"
10 #include <cerrno>
11 #include <cstring>
12
WaylandWindow()13 WaylandWindow::WaylandWindow()
14 : mDisplay{nullptr}, mCompositor{nullptr}, mSurface{nullptr}, mWindow{nullptr}
15 {}
16
~WaylandWindow()17 WaylandWindow::~WaylandWindow()
18 {
19 destroy();
20 }
21
RegistryHandleGlobal(void * data,struct wl_registry * registry,uint32_t name,const char * interface,uint32_t version)22 void WaylandWindow::RegistryHandleGlobal(void *data,
23 struct wl_registry *registry,
24 uint32_t name,
25 const char *interface,
26 uint32_t version)
27 {
28 WaylandWindow *vc = reinterpret_cast<WaylandWindow *>(data);
29
30 if (strcmp(interface, "wl_compositor") == 0)
31 {
32 void *compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 1);
33 vc->mCompositor = reinterpret_cast<wl_compositor *>(compositor);
34 }
35 }
36
RegistryHandleGlobalRemove(void * data,struct wl_registry * registry,uint32_t name)37 void WaylandWindow::RegistryHandleGlobalRemove(void *data,
38 struct wl_registry *registry,
39 uint32_t name)
40 {}
41
42 const struct wl_registry_listener WaylandWindow::registryListener = {
43 WaylandWindow::RegistryHandleGlobal, WaylandWindow::RegistryHandleGlobalRemove};
44
initializeImpl(const std::string & name,int width,int height)45 bool WaylandWindow::initializeImpl(const std::string &name, int width, int height)
46 {
47 destroy();
48
49 if (!mDisplay)
50 {
51 mDisplay = wl_display_connect(nullptr);
52 if (!mDisplay)
53 {
54 return false;
55 }
56 }
57
58 // Not get a window
59 struct wl_registry *registry = wl_display_get_registry(mDisplay);
60 wl_registry_add_listener(registry, ®istryListener, this);
61
62 // Round-trip to get globals
63 wl_display_roundtrip(mDisplay);
64 if (!mCompositor)
65 {
66 return false;
67 }
68
69 // We don't need this anymore
70 wl_registry_destroy(registry);
71
72 mSurface = wl_compositor_create_surface(mCompositor);
73 if (!mSurface)
74 {
75 return false;
76 }
77
78 mWindow = wl_egl_window_create(mSurface, width, height);
79 if (!mWindow)
80 {
81 return false;
82 }
83
84 fds[0] = {wl_display_get_fd(mDisplay), POLLIN, 0};
85
86 mY = 0;
87 mX = 0;
88 mWidth = width;
89 mHeight = height;
90
91 return true;
92 }
93
disableErrorMessageDialog()94 void WaylandWindow::disableErrorMessageDialog() {}
95
destroy()96 void WaylandWindow::destroy()
97 {
98 if (mWindow)
99 {
100 wl_egl_window_destroy(mWindow);
101 mWindow = nullptr;
102 }
103
104 if (mSurface)
105 {
106 wl_surface_destroy(mSurface);
107 mSurface = nullptr;
108 }
109
110 if (mCompositor)
111 {
112 wl_compositor_destroy(mCompositor);
113 mCompositor = nullptr;
114 }
115 }
116
resetNativeWindow()117 void WaylandWindow::resetNativeWindow() {}
118
setNativeDisplay(EGLNativeDisplayType display)119 void WaylandWindow::setNativeDisplay(EGLNativeDisplayType display)
120 {
121 mDisplay = reinterpret_cast<wl_display *>(display);
122 }
123
getNativeWindow() const124 EGLNativeWindowType WaylandWindow::getNativeWindow() const
125 {
126 return reinterpret_cast<EGLNativeWindowType>(mWindow);
127 }
128
getNativeDisplay() const129 EGLNativeDisplayType WaylandWindow::getNativeDisplay() const
130 {
131 return reinterpret_cast<EGLNativeDisplayType>(mDisplay);
132 }
133
messageLoop()134 void WaylandWindow::messageLoop()
135 {
136 while (wl_display_prepare_read(mDisplay) != 0)
137 wl_display_dispatch_pending(mDisplay);
138 if (wl_display_flush(mDisplay) < 0 && errno != EAGAIN)
139 {
140 wl_display_cancel_read(mDisplay);
141 return;
142 }
143 if (poll(fds, 1, 0) > 0)
144 {
145 wl_display_read_events(mDisplay);
146 wl_display_dispatch_pending(mDisplay);
147 }
148 else
149 {
150 wl_display_cancel_read(mDisplay);
151 }
152 }
153
setMousePosition(int x,int y)154 void WaylandWindow::setMousePosition(int x, int y) {}
155
setOrientation(int width,int height)156 bool WaylandWindow::setOrientation(int width, int height)
157 {
158 return true;
159 }
160
setPosition(int x,int y)161 bool WaylandWindow::setPosition(int x, int y)
162 {
163 return true;
164 }
165
resize(int width,int height)166 bool WaylandWindow::resize(int width, int height)
167 {
168 wl_egl_window_resize(mWindow, width, height, 0, 0);
169
170 mWidth = width;
171 mHeight = height;
172
173 return true;
174 }
175
setVisible(bool isVisible)176 void WaylandWindow::setVisible(bool isVisible) {}
177
signalTestEvent()178 void WaylandWindow::signalTestEvent() {}
179
IsWaylandWindowAvailable()180 bool IsWaylandWindowAvailable()
181 {
182 wl_display *display = wl_display_connect(nullptr);
183 if (!display)
184 {
185 return false;
186 }
187 wl_display_disconnect(display);
188 return true;
189 }
190