41#include <wayland-client-protocol-extra.hpp>
42#include <linux/input.h>
43#include <wayland-cursor.hpp>
50using namespace wayland;
53template <
typename R,
typename T,
typename... Args>
54std::function<R(Args...)> bind_mem_fn(R(T::* func)(Args...), T *t)
56 return [func, t] (Args... args)
58 return (t->*func)(args...);
72 shared_mem_t() =
default;
73 shared_mem_t(
const shared_mem_t&) =
delete;
74 shared_mem_t(shared_mem_t&&) noexcept = delete;
75 shared_mem_t& operator=(const shared_mem_t&) = delete;
76 shared_mem_t& operator=(shared_mem_t&&) noexcept = delete;
78 shared_mem_t(
size_t size)
83 std::random_device device;
84 std::default_random_engine engine(device());
85 std::uniform_int_distribution<unsigned int> distribution(0, std::numeric_limits<unsigned int>::max());
86 ss << distribution(engine);
90 fd = memfd_create(name.c_str(), 0);
92 throw std::runtime_error(
"shm_open failed.");
95 if(ftruncate(fd, size) < 0)
96 throw std::runtime_error(
"ftruncate failed.");
99 mem = mmap(
nullptr, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
100 if(mem == MAP_FAILED)
101 throw std::runtime_error(
"mmap failed.");
104 ~shared_mem_t() noexcept
108 if(munmap(mem, len) < 0)
109 std::cerr <<
"munmap failed.";
111 std::cerr <<
"close failed.";
112 if(shm_unlink(name.c_str()) < 0)
113 std::cerr <<
"shm_unlink failed";
135 compositor_t compositor;
137 xdg_wm_base_t xdg_wm_base;
143 shell_surface_t shell_surface;
144 xdg_surface_t xdg_surface;
145 xdg_toplevel_t xdg_toplevel;
149 cursor_image_t cursor_image;
150 buffer_t cursor_buffer;
151 surface_t cursor_surface;
153 std::shared_ptr<shared_mem_t> shared_mem;
154 std::array<buffer_t, 2> buffer;
161 void draw(uint32_t serial = 0)
163 float h =
static_cast<float>((serial >> 4) & 0xFF)/255.0F;
167 int hi =
static_cast<int>(h*6);
168 float f = h*6 -
static_cast<float>(hi);
171 float t = v*(1-s*(1-f));
199 uint32_t pixel = (0x80 << 24)
200 | (
static_cast<uint32_t
>(r * 255.0) << 16)
201 | (
static_cast<uint32_t
>(g * 255.0) << 8)
202 |
static_cast<uint32_t
>(b * 255.0);
204 std::fill_n(
static_cast<uint32_t*
>(shared_mem->get_mem())+cur_buf*320*240, 320*240, pixel);
205 surface.attach(buffer.at(cur_buf), 0, 0);
206 surface.damage(0, 0, 320, 240);
213 frame_cb = surface.frame();
214 frame_cb.on_done() = bind_mem_fn(&example::draw,
this);
219 example(
const example&) =
delete;
220 example(example&&) noexcept = delete;
221 ~example() noexcept = default;
222 example& operator=(const example&) = delete;
223 example& operator=(example&&) noexcept = delete;
228 registry = display.get_registry();
229 registry.on_global() = [&] (uint32_t name,
const std::string& interface, uint32_t version)
231 if(interface == compositor_t::interface_name)
232 registry.bind(name, compositor, version);
233 else if(interface == shell_t::interface_name)
234 registry.bind(name, shell, version);
235 else if(interface == xdg_wm_base_t::interface_name)
236 registry.bind(name, xdg_wm_base, version);
237 else if(interface == seat_t::interface_name)
238 registry.bind(name, seat, version);
239 else if(interface == shm_t::interface_name)
240 registry.bind(name, shm, version);
244 seat.on_capabilities() = [&] (
const seat_capability& capability)
251 surface = compositor.create_surface();
256 xdg_wm_base.on_ping() = [&] (uint32_t serial) { xdg_wm_base.pong(serial); };
257 xdg_surface = xdg_wm_base.get_xdg_surface(surface);
258 xdg_surface.on_configure() = [&] (uint32_t serial) { xdg_surface.ack_configure(serial); };
259 xdg_toplevel = xdg_surface.get_toplevel();
260 xdg_toplevel.set_title(
"Window");
261 xdg_toplevel.on_close() = [&] () { running =
false; };
265 shell_surface = shell.get_shell_surface(surface);
266 shell_surface.on_ping() = [&] (uint32_t serial) { shell_surface.pong(serial); };
267 shell_surface.set_title(
"Window");
268 shell_surface.set_toplevel();
276 throw std::runtime_error(
"No keyboard found.");
278 throw std::runtime_error(
"No pointer found.");
280 pointer = seat.get_pointer();
281 keyboard = seat.get_keyboard();
284 shared_mem = std::make_shared<shared_mem_t>(2*320*240*4);
285 auto pool = shm.create_pool(shared_mem->get_fd(), 2*320*240*4);
286 for(
unsigned int c = 0; c < 2; c++)
287 buffer.at(c) = pool.create_buffer(c*320*240*4, 320, 240, 320*4, shm_format::argb8888);
291 cursor_theme_t cursor_theme = cursor_theme_t(
"default", 16, shm);
292 cursor_t cursor = cursor_theme.get_cursor(
"cross");
293 cursor_image = cursor.image(0);
294 cursor_buffer = cursor_image.get_buffer();
297 cursor_surface = compositor.create_surface();
300 pointer.on_enter() = [&] (uint32_t serial,
const surface_t& , int32_t , int32_t )
302 cursor_surface.attach(cursor_buffer, 0, 0);
303 cursor_surface.damage(0, 0, cursor_image.width(), cursor_image.height());
304 cursor_surface.commit();
305 pointer.set_cursor(serial, cursor_surface, 0, 0);
309 pointer.on_button() = [&] (uint32_t serial, uint32_t , uint32_t button, pointer_button_state state)
311 if(button == BTN_LEFT && state == pointer_button_state::pressed)
314 xdg_toplevel.move(seat, serial);
316 shell_surface.move(seat, serial);
321 keyboard.on_key() = [&] (uint32_t , uint32_t , uint32_t key, keyboard_key_state state)
323 if(key == KEY_Q && state == keyboard_key_state::pressed)
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