34 #include <wayland-client-protocol-extra.hpp> 35 #include <wayland-egl.hpp> 37 #include <linux/input.h> 38 #include <wayland-cursor.hpp> 43 template <
typename R,
typename T,
typename... Args>
44 std::function<R(Args...)> bind_mem_fn(R(T::* func)(Args...), T *t)
46 return [func, t] (Args... args)
48 return (t->*func)(args...);
59 compositor_t compositor;
61 xdg_wm_base_t xdg_wm_base;
67 shell_surface_t shell_surface;
68 xdg_surface_t xdg_surface;
69 xdg_toplevel_t xdg_toplevel;
73 cursor_image_t cursor_image;
74 buffer_t cursor_buffer;
75 surface_t cursor_surface;
79 EGLDisplay egldisplay;
80 EGLSurface eglsurface;
81 EGLContext eglcontext;
89 egldisplay = eglGetDisplay(display);
90 if(egldisplay == EGL_NO_DISPLAY)
91 throw std::runtime_error(
"eglGetDisplay");
94 if(eglInitialize(egldisplay, &major, &minor) == EGL_FALSE)
95 throw std::runtime_error(
"eglInitialize");
96 if(!((major == 1 && minor >= 4) || major >= 2))
97 throw std::runtime_error(
"EGL version too old");
99 if(eglBindAPI(EGL_OPENGL_API) == EGL_FALSE)
100 throw std::runtime_error(
"eglBindAPI");
102 std::array<EGLint, 13> config_attribs = {{
103 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
108 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
114 if(eglChooseConfig(egldisplay, config_attribs.data(), &config, 1, &num) == EGL_FALSE || num == 0)
115 throw std::runtime_error(
"eglChooseConfig");
117 std::array<EGLint, 3> context_attribs = {{
118 EGL_CONTEXT_CLIENT_VERSION, 2,
122 eglcontext = eglCreateContext(egldisplay, config, EGL_NO_CONTEXT, context_attribs.data());
123 if(eglcontext == EGL_NO_CONTEXT)
124 throw std::runtime_error(
"eglCreateContext");
126 eglsurface = eglCreateWindowSurface(egldisplay, config, egl_window, NULL);
127 if(eglsurface == EGL_NO_SURFACE)
128 throw std::runtime_error(
"eglCreateWindowSurface");
130 if(eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglcontext) == EGL_FALSE)
131 throw std::runtime_error(
"eglMakeCurrent");
134 void draw(uint32_t serial = 0)
136 float h = ((serial >> 4) & 0xFF)/255.0;
143 float t = v*(1-s*(1-f));
169 glClearColor(r, g, b, 0.5f);
170 glClear(GL_COLOR_BUFFER_BIT);
173 frame_cb = surface.frame();
174 frame_cb.on_done() = bind_mem_fn(&example::draw,
this);
177 if(eglSwapBuffers(egldisplay, eglsurface) == EGL_FALSE)
178 throw std::runtime_error(
"eglSwapBuffers");
186 registry.on_global() = [&] (uint32_t name, std::string interface, uint32_t version)
188 if(interface == compositor_t::interface_name)
189 registry.bind(name, compositor, version);
190 else if(interface == shell_t::interface_name)
191 registry.bind(name, shell, version);
192 else if(interface == xdg_wm_base_t::interface_name)
193 registry.bind(name, xdg_wm_base, version);
194 else if(interface == seat_t::interface_name)
195 registry.bind(name, seat, version);
196 else if(interface == shm_t::interface_name)
197 registry.bind(name, shm, version);
201 seat.on_capabilities() = [&] (seat_capability capability)
203 has_keyboard = capability & seat_capability::keyboard;
204 has_pointer = capability & seat_capability::pointer;
209 throw std::runtime_error(
"No keyboard found.");
211 throw std::runtime_error(
"No pointer found.");
214 surface = compositor.create_surface();
219 xdg_wm_base.on_ping() = [&] (uint32_t serial) { xdg_wm_base.pong(serial); };
220 xdg_surface = xdg_wm_base.get_xdg_surface(surface);
221 xdg_toplevel = xdg_surface.get_toplevel();
222 xdg_toplevel.set_title(
"Window");
223 xdg_toplevel.on_close() = [&] () { running =
false; };
227 shell_surface = shell.get_shell_surface(surface);
228 shell_surface.on_ping() = [&] (uint32_t serial) { shell_surface.pong(serial); };
229 shell_surface.set_title(
"Window");
230 shell_surface.set_toplevel();
234 pointer = seat.get_pointer();
235 keyboard = seat.get_keyboard();
238 cursor_theme_t cursor_theme = cursor_theme_t(
"default", 16, shm);
239 cursor_t cursor = cursor_theme.get_cursor(
"cross");
240 cursor_image = cursor.image(0);
241 cursor_buffer = cursor_image.get_buffer();
244 cursor_surface = compositor.create_surface();
247 pointer.on_enter() = [&] (uint32_t serial, surface_t, int32_t, int32_t)
249 cursor_surface.attach(cursor_buffer, 0, 0);
250 cursor_surface.damage(0, 0, cursor_image.width(), cursor_image.height());
251 cursor_surface.commit();
252 pointer.set_cursor(serial, cursor_surface, 0, 0);
256 pointer.on_button() = [&] (uint32_t serial, uint32_t time, uint32_t button, pointer_button_state state)
258 if(button == BTN_LEFT && state == pointer_button_state::pressed)
261 xdg_toplevel.move(seat, serial);
263 shell_surface.move(seat, serial);
268 keyboard.on_key() = [&] (uint32_t, uint32_t, uint32_t key, keyboard_key_state state)
270 if(key == KEY_Q && state == keyboard_key_state::pressed)
282 ~example() noexcept(false)
285 if(eglDestroyContext(egldisplay, eglcontext) == EGL_FALSE)
286 throw std::runtime_error(
"eglDestroyContext");
287 if(eglTerminate(egldisplay) == EGL_FALSE)
288 throw std::runtime_error(
"eglTerminate");
registry_t get_registry()
get global registry object
Represents a connection to the compositor and acts as a proxy to the display singleton object...
int dispatch()
Process incoming events.
int roundtrip()
Block until all pending request are processed by the server.