diff options
Diffstat (limited to 'src/canvas/wayland/window')
| -rw-r--r-- | src/canvas/wayland/window/shm.cpp | 75 | ||||
| -rw-r--r-- | src/canvas/wayland/window/shm.hpp | 47 | ||||
| -rw-r--r-- | src/canvas/wayland/window/waylandegl.cpp | 235 | ||||
| -rw-r--r-- | src/canvas/wayland/window/waylandegl.hpp | 88 | ||||
| -rw-r--r-- | src/canvas/wayland/window/waylandshm.cpp | 186 | ||||
| -rw-r--r-- | src/canvas/wayland/window/waylandshm.hpp | 77 | ||||
| -rw-r--r-- | src/canvas/wayland/window/waylandwindow.hpp | 46 |
7 files changed, 754 insertions, 0 deletions
diff --git a/src/canvas/wayland/window/shm.cpp b/src/canvas/wayland/window/shm.cpp new file mode 100644 index 0000000..461267d --- /dev/null +++ b/src/canvas/wayland/window/shm.cpp @@ -0,0 +1,75 @@ +// Display images inside a terminal +// Copyright (C) 2023 JustKidding +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +#include "shm.hpp" +#include "util.hpp" +#include "util/ptr.hpp" + +#include <fcntl.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <fmt/format.h> + +#include <cerrno> +#include <system_error> + +WaylandShm::WaylandShm(int width, int height, int scale_factor, struct wl_shm *shm) + : shm(shm), + width(width), + height(height), + stride(width * 4), + pool_size(height * stride * scale_factor) +{ + const int path_size = 32; + shm_path = fmt::format("/{}", util::generate_random_string(path_size)); + create_shm_file(); + allocate_pool_buffers(); +} + +void WaylandShm::create_shm_file() +{ + fd = memfd_create("ueberzugpp-shm", 0); + if (fd == -1) { + throw std::system_error(errno, std::system_category()); + } + int res = ftruncate(fd, pool_size); + if (res == -1) { + throw std::system_error(errno, std::system_category()); + } + auto *pool_ptr = mmap(nullptr, pool_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (pool_ptr == MAP_FAILED) { + throw std::system_error(errno, std::system_category()); + } + pool_data = static_cast<uint8_t *>(pool_ptr); +} + +void WaylandShm::allocate_pool_buffers() +{ + const auto pool = c_unique_ptr<struct wl_shm_pool, wl_shm_pool_destroy>{wl_shm_create_pool(shm, fd, pool_size)}; + buffer = wl_shm_pool_create_buffer(pool.get(), 0, width, height, stride, WL_SHM_FORMAT_ARGB8888); +} + +WaylandShm::~WaylandShm() +{ + shm_unlink(shm_path.c_str()); + close(fd); + munmap(pool_data, pool_size); + if (buffer != nullptr) { + wl_buffer_destroy(buffer); + } +} diff --git a/src/canvas/wayland/window/shm.hpp b/src/canvas/wayland/window/shm.hpp new file mode 100644 index 0000000..fca1f88 --- /dev/null +++ b/src/canvas/wayland/window/shm.hpp @@ -0,0 +1,47 @@ +// Display images inside a terminal +// Copyright (C) 2023 JustKidding +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +#ifndef WAYLAND_SHM_H +#define WAYLAND_SHM_H + +#include <string> +#include <wayland-client.h> + +class WaylandShm +{ + public: + WaylandShm(int width, int height, int scale_factor, struct wl_shm *shm); + ~WaylandShm(); + + struct wl_buffer *buffer = nullptr; + uint8_t *pool_data; + + private: + void create_shm_file(); + void allocate_pool_buffers(); + + struct wl_shm *shm = nullptr; + + int fd = 0; + std::string shm_path; + + int width = 0; + int height = 0; + int stride = 0; + int pool_size = 0; +}; + +#endif diff --git a/src/canvas/wayland/window/waylandegl.cpp b/src/canvas/wayland/window/waylandegl.cpp new file mode 100644 index 0000000..3545d20 --- /dev/null +++ b/src/canvas/wayland/window/waylandegl.cpp @@ -0,0 +1,235 @@ +// Display images inside a terminal +// Copyright (C) 2023 JustKidding +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +#include "waylandegl.hpp" +#include "dimensions.hpp" +#include "util.hpp" + +#include <fmt/format.h> +#include <thread> + +constexpr int id_len = 10; + +constexpr struct xdg_surface_listener xdg_surface_listener_egl = { + .configure = WaylandEglWindow::xdg_surface_configure, +}; + +constexpr struct wl_callback_listener frame_listener_egl = {.done = WaylandEglWindow::wl_surface_frame_done}; + +WaylandEglWindow::WaylandEglWindow(struct wl_compositor *compositor, struct xdg_wm_base *xdg_base, + const EGLUtil<struct wl_display, struct wl_egl_window> *egl, + std::unique_ptr<Image> new_image, WaylandConfig *new_config, + struct XdgStructAgg *xdg_agg) + : compositor(compositor), + xdg_base(xdg_base), + surface(wl_compositor_create_surface(compositor)), + xdg_surface(xdg_wm_base_get_xdg_surface(xdg_base, surface)), + xdg_toplevel(xdg_surface_get_toplevel(xdg_surface)), + image(std::move(new_image)), + config(new_config), + egl_window(wl_egl_window_create(surface, image->width(), image->height())), + egl(egl), + appid(fmt::format("ueberzugpp_{}", util::generate_random_string(id_len))), + xdg_agg(xdg_agg) +{ + config->initial_setup(appid); + opengl_setup(); + xdg_setup(); +} + +WaylandEglWindow::~WaylandEglWindow() +{ + opengl_cleanup(); + delete_xdg_structs(); + delete_wayland_structs(); +} + +void WaylandEglWindow::opengl_cleanup() +{ + egl->run_contained(egl_context, egl_surface, [this] { + glDeleteTextures(1, &texture); + glDeleteFramebuffers(1, &fbo); + }); + eglDestroySurface(egl->display, egl_surface); + eglDestroyContext(egl->display, egl_context); +} + +void WaylandEglWindow::finish_init() +{ + auto xdg = std::make_unique<XdgStruct>(); + xdg->ptr = weak_from_this(); + this_ptr = xdg.get(); + xdg_agg->ptrs.push_back(std::move(xdg)); + setup_listeners(); + visible = true; +} + +void WaylandEglWindow::opengl_setup() +{ + egl_surface = egl->create_surface(egl_window); + if (egl_surface == EGL_NO_SURFACE) { + throw std::runtime_error(""); + } + + egl_context = egl->create_context(egl_surface); + if (egl_context == EGL_NO_CONTEXT) { + throw std::runtime_error(""); + } + + egl->run_contained(egl_surface, egl_context, [this] { + eglSwapInterval(egl->display, 0); + glGenFramebuffers(1, &fbo); + glGenTextures(1, &texture); + }); +} + +void WaylandEglWindow::setup_listeners() +{ + xdg_surface_add_listener(xdg_surface, &xdg_surface_listener_egl, this_ptr); + wl_surface_commit(surface); + + if (image->is_animated()) { + callback = wl_surface_frame(surface); + wl_callback_add_listener(callback, &frame_listener_egl, this_ptr); + } +} + +void WaylandEglWindow::xdg_setup() +{ + xdg_toplevel_set_app_id(xdg_toplevel, appid.c_str()); + xdg_toplevel_set_title(xdg_toplevel, appid.c_str()); +} + +void WaylandEglWindow::delete_xdg_structs() +{ + if (xdg_toplevel != nullptr) { + xdg_toplevel_destroy(xdg_toplevel); + xdg_toplevel = nullptr; + } + if (xdg_surface != nullptr) { + xdg_surface_destroy(xdg_surface); + xdg_surface = nullptr; + } +} + +void WaylandEglWindow::delete_wayland_structs() +{ + if (egl_window != nullptr) { + wl_egl_window_destroy(egl_window); + egl_window = nullptr; + } + if (surface != nullptr) { + wl_surface_destroy(surface); + surface = nullptr; + } +} + +void WaylandEglWindow::draw() +{ + load_framebuffer(); + + wl_surface_commit(surface); + move_window(); +} + +void WaylandEglWindow::load_framebuffer() +{ + std::scoped_lock lock{egl_mutex}; + egl->run_contained(egl_surface, egl_context, [this] { + egl->get_texture_from_image(*image, texture); + glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); + glBlitFramebuffer(0, 0, image->width(), image->height(), 0, 0, image->width(), image->height(), + GL_COLOR_BUFFER_BIT, GL_NEAREST); + + eglSwapBuffers(egl->display, egl_surface); + }); +} + +void WaylandEglWindow::move_window() +{ + const auto dims = image->dimensions(); + const auto cur_window = config->get_window_info(); + const int wayland_x = dims.xpixels() + dims.padding_horizontal; + const int wayland_y = dims.ypixels() + dims.padding_vertical; + const int xcoord = cur_window.x + wayland_x; + const int ycoord = cur_window.y + wayland_y; + config->move_window(appid, xcoord, ycoord); +} + +void WaylandEglWindow::generate_frame() +{ + std::this_thread::sleep_for(std::chrono::milliseconds(image->frame_delay())); + callback = wl_surface_frame(surface); + wl_callback_add_listener(callback, &frame_listener_egl, this_ptr); + + image->next_frame(); + load_framebuffer(); + + wl_surface_commit(surface); +} + +void WaylandEglWindow::show() +{ + if (visible) { + return; + } + visible = true; + xdg_surface = xdg_wm_base_get_xdg_surface(xdg_base, surface); + xdg_toplevel = xdg_surface_get_toplevel(xdg_surface); + xdg_setup(); + setup_listeners(); +} + +void WaylandEglWindow::hide() +{ + if (!visible) { + return; + } + visible = false; + const std::scoped_lock lock{draw_mutex}; + delete_xdg_structs(); + wl_surface_attach(surface, nullptr, 0, 0); + wl_surface_commit(surface); +} + +void WaylandEglWindow::xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) +{ + xdg_surface_ack_configure(xdg_surface, serial); + const auto *tmp = static_cast<struct XdgStruct *>(data); + const auto window = tmp->ptr.lock(); + if (!window) { + return; + } + auto *egl_window = dynamic_cast<WaylandEglWindow *>(window.get()); + egl_window->draw(); +} + +void WaylandEglWindow::wl_surface_frame_done(void *data, struct wl_callback *callback, [[maybe_unused]] uint32_t time) +{ + wl_callback_destroy(callback); + const auto *tmp = static_cast<struct XdgStruct *>(data); + const auto window = tmp->ptr.lock(); + if (!window) { + return; + } + auto *egl_window = dynamic_cast<WaylandEglWindow *>(window.get()); + const std::scoped_lock lock{egl_window->draw_mutex}; + if (!egl_window->visible) { + return; + } + egl_window->generate_frame(); +} diff --git a/src/canvas/wayland/window/waylandegl.hpp b/src/canvas/wayland/window/waylandegl.hpp new file mode 100644 index 0000000..768e57f --- /dev/null +++ b/src/canvas/wayland/window/waylandegl.hpp @@ -0,0 +1,88 @@ +// Display images inside a terminal +// Copyright (C) 2023 JustKidding +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +#ifndef WAYLAND_EGL_WINDOW_H +#define WAYLAND_EGL_WINDOW_H + +#include "../config.hpp" +#include "image.hpp" +#include "util/egl.hpp" +#include "wayland-xdg-shell-client-protocol.h" +#include "waylandwindow.hpp" + +#include <wayland-client.h> +#include <wayland-egl.h> + +#include <memory> +#include <mutex> + +class WaylandEglWindow : public WaylandWindow +{ + public: + WaylandEglWindow(struct wl_compositor *compositor, struct xdg_wm_base *xdg_base, + const EGLUtil<struct wl_display, struct wl_egl_window> *egl, std::unique_ptr<Image> new_image, + WaylandConfig *new_config, struct XdgStructAgg *xdg_agg); + ~WaylandEglWindow() override; + static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial); + static void wl_surface_frame_done(void *data, struct wl_callback *callback, uint32_t time); + + void draw() override; + void generate_frame() override; + void show() override; + void hide() override; + + void finish_init() override; + + private: + struct wl_compositor *compositor; + struct xdg_wm_base *xdg_base; + + struct wl_surface *surface = nullptr; + struct xdg_surface *xdg_surface = nullptr; + struct xdg_toplevel *xdg_toplevel = nullptr; + struct wl_callback *callback; + + std::unique_ptr<Image> image; + WaylandConfig *config; + + EGLSurface egl_surface; + EGLContext egl_context; + + struct wl_egl_window *egl_window = nullptr; + const EGLUtil<struct wl_display, struct wl_egl_window> *egl; + + GLuint texture; + GLuint fbo; + + std::mutex draw_mutex; + std::mutex egl_mutex; + + std::string appid; + void *this_ptr; + struct XdgStructAgg *xdg_agg; + bool visible = false; + + void move_window(); + void delete_wayland_structs(); + void delete_xdg_structs(); + + void opengl_cleanup(); + void xdg_setup(); + void setup_listeners(); + void opengl_setup(); + void load_framebuffer(); +}; +#endif diff --git a/src/canvas/wayland/window/waylandshm.cpp b/src/canvas/wayland/window/waylandshm.cpp new file mode 100644 index 0000000..1ee5994 --- /dev/null +++ b/src/canvas/wayland/window/waylandshm.cpp @@ -0,0 +1,186 @@ +// Display images inside a terminal +// Copyright (C) 2023 JustKidding +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +#include "waylandshm.hpp" +#include "dimensions.hpp" +#include "shm.hpp" +#include "util.hpp" + +#include <fmt/format.h> + +constexpr int id_len = 10; + +constexpr struct xdg_surface_listener xdg_surface_listener = { + .configure = WaylandShmWindow::xdg_surface_configure, +}; + +constexpr struct wl_callback_listener frame_listener = {.done = WaylandShmWindow::wl_surface_frame_done}; + +void WaylandShmWindow::xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) +{ + xdg_surface_ack_configure(xdg_surface, serial); + const auto *tmp = static_cast<struct XdgStruct *>(data); + const auto window = tmp->ptr.lock(); + if (!window) { + return; + } + auto *shm_window = dynamic_cast<WaylandShmWindow *>(window.get()); + shm_window->wl_draw(shm_window->output_scale); +} + +void WaylandShmWindow::wl_surface_frame_done(void *data, struct wl_callback *callback, [[maybe_unused]] uint32_t time) +{ + wl_callback_destroy(callback); + const auto *tmp = static_cast<struct XdgStruct *>(data); + const auto window = tmp->ptr.lock(); + if (!window) { + return; + } + auto *shm_window = dynamic_cast<WaylandShmWindow *>(window.get()); + const std::scoped_lock lock{shm_window->draw_mutex}; + if (!shm_window->visible) { + return; + } + shm_window->generate_frame(); +} + +WaylandShmWindow::WaylandShmWindow(WaylandCanvas *canvas, std::unique_ptr<Image> new_image, + struct XdgStructAgg *xdg_agg, WaylandConfig *config) + : config(config), + xdg_base(canvas->xdg_base), + surface(wl_compositor_create_surface(canvas->compositor)), + xdg_surface(xdg_wm_base_get_xdg_surface(xdg_base, surface)), + xdg_toplevel(xdg_surface_get_toplevel(xdg_surface)), + image(std::move(new_image)), + appid(fmt::format("ueberzugpp_{}", util::generate_random_string(id_len))), + xdg_agg(xdg_agg) +{ + config->initial_setup(appid); + xdg_setup(); + output_scale = canvas->output_info.at(config->get_focused_output_name()); + shm = std::make_unique<WaylandShm>(image->width(), image->height(), output_scale, canvas->wl_shm); +} + +void WaylandShmWindow::finish_init() +{ + auto xdg = std::make_unique<XdgStruct>(); + xdg->ptr = weak_from_this(); + this_ptr = xdg.get(); + xdg_agg->ptrs.push_back(std::move(xdg)); + + setup_listeners(); + visible = true; +} + +void WaylandShmWindow::setup_listeners() +{ + xdg_surface_add_listener(xdg_surface, &xdg_surface_listener, this_ptr); + wl_surface_commit(surface); + + if (image->is_animated()) { + callback = wl_surface_frame(surface); + wl_callback_add_listener(callback, &frame_listener, this_ptr); + } +} + +void WaylandShmWindow::xdg_setup() +{ + xdg_toplevel_set_app_id(xdg_toplevel, appid.c_str()); + xdg_toplevel_set_title(xdg_toplevel, appid.c_str()); +} + +WaylandShmWindow::~WaylandShmWindow() +{ + delete_xdg_structs(); + delete_wayland_structs(); +} + +void WaylandShmWindow::wl_draw(int32_t scale_factor) +{ + std::memcpy(shm->pool_data, image->data(), image->size()); + wl_surface_attach(surface, shm->buffer, 0, 0); + wl_surface_set_buffer_scale(surface, scale_factor); + wl_surface_commit(surface); + move_window(); +} + +void WaylandShmWindow::show() +{ + if (visible) { + return; + } + visible = true; + xdg_surface = xdg_wm_base_get_xdg_surface(xdg_base, surface); + xdg_toplevel = xdg_surface_get_toplevel(xdg_surface); + xdg_setup(); + setup_listeners(); +} + +void WaylandShmWindow::hide() +{ + if (!visible) { + return; + } + visible = false; + const std::scoped_lock lock{draw_mutex}; + delete_xdg_structs(); + wl_surface_attach(surface, nullptr, 0, 0); + wl_surface_commit(surface); +} + +void WaylandShmWindow::delete_xdg_structs() +{ + if (xdg_toplevel != nullptr) { + xdg_toplevel_destroy(xdg_toplevel); + xdg_toplevel = nullptr; + } + if (xdg_surface != nullptr) { + xdg_surface_destroy(xdg_surface); + xdg_surface = nullptr; + } +} + +void WaylandShmWindow::delete_wayland_structs() +{ + if (surface != nullptr) { + wl_surface_destroy(surface); + surface = nullptr; + } +} + +void WaylandShmWindow::move_window() +{ + const auto dims = image->dimensions(); + const auto cur_window = config->get_window_info(); + const int wayland_x = dims.xpixels() + dims.padding_horizontal; + const int wayland_y = dims.ypixels() + dims.padding_vertical; + const int xcoord = cur_window.x + wayland_x; + const int ycoord = cur_window.y + wayland_y; + config->move_window(appid, xcoord, ycoord); +} + +void WaylandShmWindow::generate_frame() +{ + std::this_thread::sleep_for(std::chrono::milliseconds(image->frame_delay())); + callback = wl_surface_frame(surface); + wl_callback_add_listener(callback, &frame_listener, this_ptr); + + image->next_frame(); + std::memcpy(shm->pool_data, image->data(), image->size()); + wl_surface_attach(surface, shm->buffer, 0, 0); + wl_surface_damage_buffer(surface, 0, 0, image->width(), image->height()); + wl_surface_commit(surface); +} diff --git a/src/canvas/wayland/window/waylandshm.hpp b/src/canvas/wayland/window/waylandshm.hpp new file mode 100644 index 0000000..f275c4c --- /dev/null +++ b/src/canvas/wayland/window/waylandshm.hpp @@ -0,0 +1,77 @@ +// Display images inside a terminal +// Copyright (C) 2023 JustKidding +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +#ifndef WAYLAND_SHM_WINDOW_H +#define WAYLAND_SHM_WINDOW_H + +#include "../wayland.hpp" +#include "image.hpp" +#include "shm.hpp" +#include "wayland-xdg-shell-client-protocol.h" +#include "waylandwindow.hpp" + +#include <atomic> +#include <memory> +#include <mutex> +#include <string> +#include <wayland-client.h> + +class WaylandShmWindow : public WaylandWindow +{ + public: + WaylandShmWindow(WaylandCanvas *canvas, std::unique_ptr<Image> new_image, struct XdgStructAgg *xdg_agg, + WaylandConfig *config); + ~WaylandShmWindow() override; + static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial); + static void wl_surface_frame_done(void *data, struct wl_callback *callback, uint32_t time); + + void draw() override {} + void wl_draw(int32_t scale_factor) override; + void generate_frame() override; + void show() override; + void hide() override; + + void finish_init() override; + + std::mutex draw_mutex; + std::atomic<bool> visible{false}; + std::unique_ptr<WaylandShm> shm; + int32_t output_scale; + + private: + WaylandConfig *config; + + struct xdg_wm_base *xdg_base = nullptr; + struct wl_surface *surface = nullptr; + struct xdg_surface *xdg_surface = nullptr; + struct xdg_toplevel *xdg_toplevel = nullptr; + struct wl_callback *callback; + + std::unique_ptr<Image> image; + std::string appid; + + struct XdgStructAgg *xdg_agg; + void *this_ptr; + + void move_window(); + void xdg_setup(); + + void setup_listeners(); + void delete_wayland_structs(); + void delete_xdg_structs(); +}; + +#endif diff --git a/src/canvas/wayland/window/waylandwindow.hpp b/src/canvas/wayland/window/waylandwindow.hpp new file mode 100644 index 0000000..0a1a1e8 --- /dev/null +++ b/src/canvas/wayland/window/waylandwindow.hpp @@ -0,0 +1,46 @@ +// Display images inside a terminal +// Copyright (C) 2023 JustKidding +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +#ifndef WAYLAND_WINDOW_H +#define WAYLAND_WINDOW_H + +#include "window.hpp" + +#include <memory> +#include <vector> + +class WaylandWindow: + public Window, + public std::enable_shared_from_this<WaylandWindow> +{ +public: + ~WaylandWindow() override = default; + + virtual void wl_draw([[maybe_unused]] int32_t scale_factor) {}; + virtual void finish_init() = 0; +}; + +struct XdgStruct +{ + std::weak_ptr<WaylandWindow> ptr; +}; + +struct XdgStructAgg +{ + std::vector<std::unique_ptr<XdgStruct>> ptrs; +}; + +#endif |
