34#include <wayland-client-protocol-extra.hpp>
35#include <wayland-egl.hpp>
37#include <linux/input.h>
38#include <wayland-cursor.hpp>
40using namespace wayland;
43template <
typename R,
typename T,
typename... Args>
44std::function<R(Args...)> bind_mem_fn(R(T::* func)(Args...), T *t)
46 return [func, t] (Args... args)
48 return (t->*func)(args...);
73 cursor_image_t cursor_image;
79 EGLDisplay egldisplay =
nullptr;
80 EGLSurface eglsurface =
nullptr;
81 EGLContext eglcontext =
nullptr;
89 egldisplay = eglGetDisplay(display);
90 if(egldisplay == EGL_NO_DISPLAY)
91 throw std::runtime_error(
"eglGetDisplay");
95 if(eglInitialize(egldisplay, &major, &minor) == EGL_FALSE)
96 throw std::runtime_error(
"eglInitialize");
97 if(!((major == 1 && minor >= 4) || major >= 2))
98 throw std::runtime_error(
"EGL version too old");
100 if(eglBindAPI(EGL_OPENGL_API) == EGL_FALSE)
101 throw std::runtime_error(
"eglBindAPI");
103 std::array<EGLint, 13> config_attribs = {{
104 EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
109 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
113 EGLConfig config =
nullptr;
115 if(eglChooseConfig(egldisplay, config_attribs.data(), &config, 1, &num) == EGL_FALSE || num == 0)
116 throw std::runtime_error(
"eglChooseConfig");
118 std::array<EGLint, 3> context_attribs = {{
119 EGL_CONTEXT_CLIENT_VERSION, 2,
123 eglcontext = eglCreateContext(egldisplay, config, EGL_NO_CONTEXT, context_attribs.data());
124 if(eglcontext == EGL_NO_CONTEXT)
125 throw std::runtime_error(
"eglCreateContext");
127 eglsurface = eglCreateWindowSurface(egldisplay, config, egl_window,
nullptr);
128 if(eglsurface == EGL_NO_SURFACE)
129 throw std::runtime_error(
"eglCreateWindowSurface");
131 if(eglMakeCurrent(egldisplay, eglsurface, eglsurface, eglcontext) == EGL_FALSE)
132 throw std::runtime_error(
"eglMakeCurrent");
135 void draw(uint32_t serial = 0)
137 float h =
static_cast<float>((serial >> 4) & 0xFF)/255.0F;
141 int hi =
static_cast<int>(h*6);
142 float f = h*6 -
static_cast<float>(hi);
145 float t = v*(1-s*(1-f));
173 glClearColor(r, g, b, 0.5F);
174 glClear(GL_COLOR_BUFFER_BIT);
177 frame_cb = surface.
frame();
178 frame_cb.
on_done() = bind_mem_fn(&example::draw,
this);
181 if(eglSwapBuffers(egldisplay, eglsurface) == EGL_FALSE)
182 throw std::runtime_error(
"eglSwapBuffers");
186 example(
const example&) =
delete;
187 example(example&&) noexcept = delete;
188 example& operator=(const example&) = delete;
189 example& operator=(example&&) noexcept = delete;
195 registry.
on_global() = [&] (uint32_t name,
const std::string& interface, uint32_t version)
197 if(interface == compositor_t::interface_name)
198 registry.
bind(name, compositor, version);
199 else if(interface == shell_t::interface_name)
200 registry.
bind(name, shell, version);
201 else if(interface == xdg_wm_base_t::interface_name)
202 registry.
bind(name, xdg_wm_base, version);
203 else if(interface == seat_t::interface_name)
204 registry.
bind(name, seat, version);
205 else if(interface == shm_t::interface_name)
206 registry.
bind(name, shm, version);
222 xdg_wm_base.
on_ping() = [&] (uint32_t serial) { xdg_wm_base.
pong(serial); };
227 xdg_toplevel.
on_close() = [&] () { running =
false; };
232 shell_surface.
on_ping() = [&] (uint32_t serial) { shell_surface.
pong(serial); };
242 throw std::runtime_error(
"No keyboard found.");
244 throw std::runtime_error(
"No pointer found.");
250 cursor_theme_t cursor_theme = cursor_theme_t(
"default", 16, shm);
251 cursor_t cursor = cursor_theme.get_cursor(
"cross");
252 cursor_image = cursor.image(0);
253 cursor_buffer = cursor_image.get_buffer();
259 pointer.
on_enter() = [&] (uint32_t serial,
const surface_t& , int32_t , int32_t )
261 cursor_surface.
attach(cursor_buffer, 0, 0);
262 cursor_surface.
damage(0, 0, cursor_image.width(), cursor_image.height());
264 pointer.
set_cursor(serial, cursor_surface, 0, 0);
268 pointer.
on_button() = [&] (uint32_t serial, uint32_t , uint32_t button, pointer_button_state state)
270 if(button == BTN_LEFT && state == pointer_button_state::pressed)
273 xdg_toplevel.
move(seat, serial);
275 shell_surface.
move(seat, serial);
280 keyboard.
on_key() = [&] (uint32_t , uint32_t , uint32_t key, keyboard_key_state state)
282 if(key == KEY_Q && state == keyboard_key_state::pressed)
297 if(eglDestroyContext(egldisplay, eglcontext) == EGL_FALSE)
298 std::cerr <<
"eglDestroyContext failed.";
299 if(eglTerminate(egldisplay) == EGL_FALSE)
300 std::cerr <<
"eglTerminate failed.";
std::function< void(uint32_t)> & on_done()
done event
surface_t create_surface()
create new surface
Represents a connection to the compositor and acts as a proxy to the display singleton object.
int dispatch() const
Process incoming events.
registry_t get_registry()
get global registry object
int roundtrip() const
Block until all pending request are processed by the server.
std::function< void(uint32_t, uint32_t, uint32_t, keyboard_key_state)> & on_key()
key event
std::function< void(uint32_t, surface_t, double, double)> & on_enter()
enter event
std::function< void(uint32_t, uint32_t, uint32_t, pointer_button_state)> & on_button()
pointer button event
void set_cursor(uint32_t serial, surface_t const &surface, int32_t hotspot_x, int32_t hotspot_y)
set the pointer surface
std::function< void(uint32_t, std::string, uint32_t)> & on_global()
announce global object
proxy_t bind(uint32_t name, proxy_t &interface, uint32_t version)
bind an object to the display
keyboard_t get_keyboard()
return keyboard object
pointer_t get_pointer()
return pointer object
std::function< void(seat_capability)> & on_capabilities()
seat capabilities changed
desktop-style metadata interface
void move(seat_t const &seat, uint32_t serial)
start an interactive move
void set_toplevel()
make the surface a toplevel surface
std::function< void(uint32_t)> & on_ping()
ping client
void pong(uint32_t serial)
respond to a ping event
void set_title(std::string const &title)
set surface title
create desktop-style surfaces
shell_surface_t get_shell_surface(surface_t const &surface)
create a shell surface from a surface
void commit()
commit pending surface state
void attach(buffer_t const &buffer, int32_t x, int32_t y)
set the surface contents
callback_t frame()
request a frame throttling hint
void damage(int32_t x, int32_t y, int32_t width, int32_t height)
mark part of the surface damaged
desktop user interface surface base interface
std::function< void(uint32_t)> & on_configure()
suggest a surface change
xdg_toplevel_t get_toplevel()
assign the xdg_toplevel surface role
void ack_configure(uint32_t serial)
ack a configure event
void set_title(std::string const &title)
set surface title
std::function< void()> & on_close()
surface wants to be closed
void move(seat_t const &seat, uint32_t serial)
start an interactive move
create desktop-style surfaces
std::function< void(uint32_t)> & on_ping()
check if the client is alive
void pong(uint32_t serial)
respond to a ping event
xdg_surface_t get_xdg_surface(surface_t const &surface)
create a shell surface from a surface
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