35#include <wayland-client-protocol-extra.hpp>
36#include <wayland-egl.hpp>
38#include <linux/input.h>
39#include <wayland-cursor.hpp>
41using namespace wayland;
44template <
typename R,
typename T,
typename... Args>
45std::function<R(Args...)> bind_mem_fn(R(T::* func)(Args...), T *t)
47 return [func, t] (Args... args)
49 return (t->*func)(args...);
60 compositor_t compositor;
62 xdg_wm_base_t xdg_wm_base;
68 shell_surface_t shell_surface;
69 xdg_surface_t xdg_surface;
70 xdg_toplevel_t xdg_toplevel;
74 cursor_image_t cursor_image;
75 buffer_t cursor_buffer;
76 surface_t cursor_surface;
79 egl_window_t egl_window;
80 EGLDisplay egldisplay =
nullptr;
81 EGLSurface eglsurface =
nullptr;
82 EGLContext eglcontext =
nullptr;
90 egldisplay = eglGetDisplay(display);
91 if(egldisplay == EGL_NO_DISPLAY)
92 throw std::runtime_error(
"eglGetDisplay");
96 if(eglInitialize(egldisplay, &major, &minor) == EGL_FALSE)
97 throw std::runtime_error(
"eglInitialize");
98 if(!((major == 1 && minor >= 4) || major >= 2))
99 throw std::runtime_error(
"EGL version too old");
101 if(eglBindAPI(EGL_OPENGL_API) == EGL_FALSE)
102 throw std::runtime_error(
"eglBindAPI");
104 std::array<EGLint, 13> config_attribs = {{
105 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
110 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
114 EGLConfig config =
nullptr;
116 if(eglChooseConfig(egldisplay, config_attribs.data(), &config, 1, &num) == EGL_FALSE || num == 0)
117 throw std::runtime_error(
"eglChooseConfig");
119 std::array<EGLint, 3> context_attribs = {{
120 EGL_CONTEXT_CLIENT_VERSION, 2,
124 eglcontext = eglCreateContext(egldisplay, config, EGL_NO_CONTEXT, context_attribs.data());
125 if(eglcontext == EGL_NO_CONTEXT)
126 throw std::runtime_error(
"eglCreateContext");
128 eglsurface = eglCreateWindowSurface(egldisplay, config, egl_window,
nullptr);
129 if(eglsurface == EGL_NO_SURFACE)
130 throw std::runtime_error(
"eglCreateWindowSurface");
132 if(eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglcontext) == EGL_FALSE)
133 throw std::runtime_error(
"eglMakeCurrent");
136 void draw(uint32_t serial = 0)
138 float h =
static_cast<float>((serial >> 4) & 0xFF)/255.0F;
142 int hi =
static_cast<int>(h*6);
143 float f = h*6 -
static_cast<float>(hi);
146 float t = v*(1-s*(1-f));
174 glClearColor(r, g, b, 0.5F);
175 glClear(GL_COLOR_BUFFER_BIT);
178 frame_cb = surface.frame();
179 frame_cb.on_done() = bind_mem_fn(&example::draw,
this);
182 if(eglSwapBuffers(egldisplay, eglsurface) == EGL_FALSE)
183 throw std::runtime_error(
"eglSwapBuffers");
187 example(
const example&) =
delete;
188 example(example&&) noexcept = delete;
189 example& operator=(const example&) = delete;
190 example& operator=(example&&) noexcept = delete;
195 registry = display.get_registry();
196 registry.on_global() = [&] (uint32_t name,
const std::string& interface, uint32_t version)
198 if(interface == compositor_t::interface_name)
199 registry.bind(name, compositor, version);
200 else if(interface == shell_t::interface_name)
201 registry.bind(name, shell, version);
202 else if(interface == xdg_wm_base_t::interface_name)
203 registry.bind(name, xdg_wm_base, version);
204 else if(interface == seat_t::interface_name)
205 registry.bind(name, seat, version);
206 else if(interface == shm_t::interface_name)
207 registry.bind(name, shm, version);
211 seat.on_capabilities() = [&] (
const seat_capability& capability)
218 surface = compositor.create_surface();
223 xdg_wm_base.on_ping() = [&] (uint32_t serial) { xdg_wm_base.pong(serial); };
224 xdg_surface = xdg_wm_base.get_xdg_surface(surface);
225 xdg_surface.on_configure() = [&] (uint32_t serial) { xdg_surface.ack_configure(serial); };
226 xdg_toplevel = xdg_surface.get_toplevel();
227 xdg_toplevel.set_title(
"Window");
228 xdg_toplevel.on_close() = [&] () { running =
false; };
232 shell_surface = shell.get_shell_surface(surface);
233 shell_surface.on_ping() = [&] (uint32_t serial) { shell_surface.pong(serial); };
234 shell_surface.set_title(
"Window");
235 shell_surface.set_toplevel();
243 throw std::runtime_error(
"No keyboard found.");
245 throw std::runtime_error(
"No pointer found.");
247 pointer = seat.get_pointer();
248 keyboard = seat.get_keyboard();
251 cursor_theme_t cursor_theme = cursor_theme_t(
"default", 16, shm);
252 cursor_t cursor = cursor_theme.get_cursor(
"cross");
253 cursor_image = cursor.image(0);
254 cursor_buffer = cursor_image.get_buffer();
257 cursor_surface = compositor.create_surface();
260 pointer.on_enter() = [&] (uint32_t serial,
const surface_t& , int32_t , int32_t )
262 cursor_surface.attach(cursor_buffer, 0, 0);
263 cursor_surface.damage(0, 0, cursor_image.width(), cursor_image.height());
264 cursor_surface.commit();
265 pointer.set_cursor(serial, cursor_surface, 0, 0);
269 pointer.on_button() = [&] (uint32_t serial, uint32_t , uint32_t button, pointer_button_state state)
271 if(button == BTN_LEFT && state == pointer_button_state::pressed)
274 xdg_toplevel.move(seat, serial);
276 shell_surface.move(seat, serial);
281 keyboard.on_key() = [&] (uint32_t , uint32_t , uint32_t key, keyboard_key_state state)
283 if(key == KEY_Q && state == keyboard_key_state::pressed)
288 egl_window = egl_window_t(surface, 320, 240);
298 if(eglDestroyContext(egldisplay, eglcontext) == EGL_FALSE)
299 std::cerr <<
"eglDestroyContext failed.";
300 if(eglTerminate(egldisplay) == EGL_FALSE)
301 std::cerr <<
"eglTerminate failed.";
static const wayland::detail::bitfield< 3, 12 > keyboard
the seat has one or more keyboards
static const wayland::detail::bitfield< 3, 12 > pointer
the seat has pointer devices