From 7397917c6149699811d6c1ef74bfff5749d349c4 Mon Sep 17 00:00:00 2001 From: Slendi Date: Sun, 5 Oct 2025 01:25:05 +0300 Subject: [PATCH] Toggleable window Signed-off-by: Slendi --- src/main.cpp | 311 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 211 insertions(+), 100 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 4d5b736..d1c4cba 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,8 @@ struct App { auto set_visible(bool visible) -> void; auto visible() const -> bool { return m_visible; } + auto stop() -> void { m_running = false; } + private: auto init_wayland() -> void; auto init_egl() -> void; @@ -57,6 +60,10 @@ private: auto init_theme_portal() -> void; auto pump_events() -> void; auto render_frame() -> void; + auto create_layer_surface() -> void; + auto destroy_layer_surface() -> void; + auto ensure_egl_surface() -> void; + auto update_blur_region() -> void; auto theme() const -> ColorScheme const & { return m_themes[m_active_theme]; } static void on_settings_changed(XdpSettings * /*self*/, const char *ns, @@ -104,19 +111,14 @@ App::~App() { if (m_sfd != -1) close(m_sfd); + destroy_layer_surface(); + if (m_gl.edpy != EGL_NO_DISPLAY) { - eglMakeCurrent(m_gl.edpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (m_gl.esurf != EGL_NO_SURFACE) - eglDestroySurface(m_gl.edpy, m_gl.esurf); - if (m_gl.wegl) - wl_egl_window_destroy(m_gl.wegl); if (m_gl.ectx != EGL_NO_CONTEXT) eglDestroyContext(m_gl.edpy, m_gl.ectx); eglTerminate(m_gl.edpy); } - if (m_wayland.wl_surface) - wl_surface_destroy(m_wayland.wl_surface); if (m_wayland.compositor) wl_compositor_destroy(m_wayland.compositor); if (m_wayland.registry) @@ -169,99 +171,22 @@ auto App::init_wayland() -> void { wl_display_roundtrip(m_wayland.display); - m_wayland.wl_surface = wl_compositor_create_surface(m_wayland.compositor); - if (m_wayland.mgr && !m_wayland.eff) { - m_wayland.eff = ext_background_effect_manager_v1_get_background_effect( - m_wayland.mgr, m_wayland.wl_surface); - } - if (m_wayland.kde_blur_mgr && !m_wayland.kde_blur) { - m_wayland.kde_blur = org_kde_kwin_blur_manager_create( - m_wayland.kde_blur_mgr, m_wayland.wl_surface); - } - - auto apply_blur_full_surface = [&] { - wl_region *r = wl_compositor_create_region(m_wayland.compositor); - wl_region_add(r, 0, 0, m_win_w, m_win_h); - if (m_wayland.eff) { - ext_background_effect_surface_v1_set_blur_region(m_wayland.eff, r); - } - if (m_wayland.kde_blur) { - org_kde_kwin_blur_set_region(m_wayland.kde_blur, r); - } - wl_region_destroy(r); - }; - - m_wayland.layer_surface = zwlr_layer_shell_v1_get_layer_surface( - m_wayland.layer_shell, m_wayland.wl_surface, /*output*/ nullptr, - ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "waylight-overlay"); - - zwlr_layer_surface_v1_set_anchor(m_wayland.layer_surface, 0); - - zwlr_layer_surface_v1_set_size(m_wayland.layer_surface, m_win_w, m_win_h); - - zwlr_layer_surface_v1_set_exclusive_zone(m_wayland.layer_surface, 0); - - if (zwlr_layer_shell_v1_get_version(m_wayland.layer_shell) >= 3) - zwlr_layer_surface_v1_set_keyboard_interactivity( - m_wayland.layer_surface, - ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND); - - auto handle_layer_configure = [](void *data, zwlr_layer_surface_v1 *ls, - uint32_t serial, uint32_t w, - uint32_t h) -> void { - auto *app = static_cast(data); - app->m_win_w = (int)(w ? w : app->m_win_w); - app->m_win_h = (int)(h ? h : app->m_win_h); - - zwlr_layer_surface_v1_ack_configure(ls, serial); - - if (!app->m_gl.wegl) { - app->m_gl.wegl = wl_egl_window_create(app->m_wayland.wl_surface, - app->m_win_w, app->m_win_h); - app->m_gl.esurf = - eglCreateWindowSurface(app->m_gl.edpy, app->m_gl.ecfg, - (EGLNativeWindowType)app->m_gl.wegl, nullptr); - eglMakeCurrent(app->m_gl.edpy, app->m_gl.esurf, app->m_gl.esurf, - app->m_gl.ectx); - eglSwapInterval(app->m_gl.edpy, 1); - } else { - wl_egl_window_resize(app->m_gl.wegl, app->m_win_w, app->m_win_h, 0, 0); - } - - if (app->m_wayland.wl_surface) - wl_surface_commit(app->m_wayland.wl_surface); - }; - - auto handle_layer_closed = [](void *data, zwlr_layer_surface_v1 *) -> void { - static_cast(data)->m_running = false; - }; - - static const zwlr_layer_surface_v1_listener lsl = { - .configure = handle_layer_configure, - .closed = handle_layer_closed, - }; - zwlr_layer_surface_v1_add_listener(m_wayland.layer_surface, &lsl, this); - - apply_blur_full_surface(); - - wl_surface_commit(m_wayland.wl_surface); - wl_display_roundtrip(m_wayland.display); + create_layer_surface(); } auto App::set_visible(bool visible) -> void { - if (!m_wayland.layer_surface) + if (visible == m_visible) return; if (visible) { - zwlr_layer_surface_v1_set_size(m_wayland.layer_surface, m_win_w, m_win_h); - wl_surface_commit(m_wayland.wl_surface); + create_layer_surface(); + ensure_egl_surface(); } else { - wl_surface_attach(m_wayland.wl_surface, nullptr, 0, 0); - wl_surface_commit(m_wayland.wl_surface); + destroy_layer_surface(); } - wl_display_flush(m_wayland.display); - m_visible = visible; + if (m_wayland.display) + wl_display_flush(m_wayland.display); } auto App::init_egl() -> void { @@ -291,13 +216,7 @@ auto App::init_egl() -> void { m_gl.ectx = eglCreateContext(m_gl.edpy, m_gl.ecfg, EGL_NO_CONTEXT, ctxAttribs); - m_gl.wegl = wl_egl_window_create(m_wayland.wl_surface, m_win_w, m_win_h); - m_gl.esurf = eglCreateWindowSurface( - m_gl.edpy, m_gl.ecfg, reinterpret_cast(m_gl.wegl), - nullptr); - - eglMakeCurrent(m_gl.edpy, m_gl.esurf, m_gl.esurf, m_gl.ectx); - eglSwapInterval(m_gl.edpy, 1); + ensure_egl_surface(); InitWindow(m_win_w, m_win_h, ""); } @@ -352,6 +271,9 @@ auto App::init_theme_portal() -> void { } auto App::render_frame() -> void { + if (!m_visible || m_gl.edpy == EGL_NO_DISPLAY || m_gl.esurf == EGL_NO_SURFACE) + return; + glViewport(0, 0, m_win_w, m_win_h); BeginDrawing(); @@ -365,6 +287,188 @@ auto App::render_frame() -> void { eglSwapBuffers(m_gl.edpy, m_gl.esurf); } +auto App::create_layer_surface() -> void { + if (m_wayland.layer_surface) + return; + + if (!m_wayland.compositor || !m_wayland.layer_shell) + return; + + m_wayland.wl_surface = wl_compositor_create_surface(m_wayland.compositor); + + if (m_wayland.mgr) { + m_wayland.eff = ext_background_effect_manager_v1_get_background_effect( + m_wayland.mgr, m_wayland.wl_surface); + } + if (m_wayland.kde_blur_mgr) { + m_wayland.kde_blur = org_kde_kwin_blur_manager_create( + m_wayland.kde_blur_mgr, m_wayland.wl_surface); + } + + m_wayland.layer_surface = zwlr_layer_shell_v1_get_layer_surface( + m_wayland.layer_shell, m_wayland.wl_surface, nullptr, + ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "waylight-overlay"); + + if (!m_wayland.layer_surface) { + if (m_wayland.eff) { + ext_background_effect_surface_v1_destroy(m_wayland.eff); + m_wayland.eff = nullptr; + } + if (m_wayland.kde_blur) { + org_kde_kwin_blur_destroy(m_wayland.kde_blur); + m_wayland.kde_blur = nullptr; + } + if (m_wayland.wl_surface) { + wl_surface_destroy(m_wayland.wl_surface); + m_wayland.wl_surface = nullptr; + } + return; + } + + zwlr_layer_surface_v1_set_anchor(m_wayland.layer_surface, 0); + zwlr_layer_surface_v1_set_size(m_wayland.layer_surface, m_win_w, m_win_h); + zwlr_layer_surface_v1_set_exclusive_zone(m_wayland.layer_surface, 0); + + if (zwlr_layer_shell_v1_get_version(m_wayland.layer_shell) >= 3) { + zwlr_layer_surface_v1_set_keyboard_interactivity( + m_wayland.layer_surface, + ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_ON_DEMAND); + } + + auto handle_layer_configure = [](void *data, zwlr_layer_surface_v1 *ls, + uint32_t serial, uint32_t w, + uint32_t h) -> void { + auto *app = static_cast(data); + if (w) + app->m_win_w = static_cast(w); + if (h) + app->m_win_h = static_cast(h); + + zwlr_layer_surface_v1_ack_configure(ls, serial); + + if (app->m_gl.edpy != EGL_NO_DISPLAY) { + if (!app->m_gl.wegl || app->m_gl.esurf == EGL_NO_SURFACE) { + app->ensure_egl_surface(); + } else { + wl_egl_window_resize(app->m_gl.wegl, app->m_win_w, app->m_win_h, 0, 0); + eglMakeCurrent(app->m_gl.edpy, app->m_gl.esurf, app->m_gl.esurf, + app->m_gl.ectx); + } + } + + app->update_blur_region(); + + if (app->m_wayland.wl_surface) + wl_surface_commit(app->m_wayland.wl_surface); + }; + + auto handle_layer_closed = [](void *data, zwlr_layer_surface_v1 *) -> void { + static_cast(data)->m_running = false; + }; + + static const zwlr_layer_surface_v1_listener lsl = { + .configure = handle_layer_configure, + .closed = handle_layer_closed, + }; + + zwlr_layer_surface_v1_add_listener(m_wayland.layer_surface, &lsl, this); + + update_blur_region(); + + if (m_wayland.wl_surface) + wl_surface_commit(m_wayland.wl_surface); + + if (m_wayland.display) + wl_display_roundtrip(m_wayland.display); + + ensure_egl_surface(); + + m_visible = true; +} + +auto App::destroy_layer_surface() -> void { + if (m_gl.edpy != EGL_NO_DISPLAY && m_gl.esurf != EGL_NO_SURFACE) { + eglMakeCurrent(m_gl.edpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroySurface(m_gl.edpy, m_gl.esurf); + m_gl.esurf = EGL_NO_SURFACE; + } + + if (m_gl.wegl) { + wl_egl_window_destroy(m_gl.wegl); + m_gl.wegl = nullptr; + } + + if (m_wayland.eff) { + ext_background_effect_surface_v1_destroy(m_wayland.eff); + m_wayland.eff = nullptr; + } + + if (m_wayland.kde_blur) { + org_kde_kwin_blur_destroy(m_wayland.kde_blur); + m_wayland.kde_blur = nullptr; + } + + if (m_wayland.layer_surface) { + zwlr_layer_surface_v1_destroy(m_wayland.layer_surface); + m_wayland.layer_surface = nullptr; + } + + if (m_wayland.wl_surface) { + wl_surface_destroy(m_wayland.wl_surface); + m_wayland.wl_surface = nullptr; + } + + if (m_wayland.display) + wl_display_flush(m_wayland.display); + + m_visible = false; +} + +auto App::ensure_egl_surface() -> void { + if (m_gl.edpy == EGL_NO_DISPLAY || m_gl.ectx == EGL_NO_CONTEXT) + return; + if (!m_wayland.wl_surface) + return; + + if (!m_gl.wegl) + m_gl.wegl = wl_egl_window_create(m_wayland.wl_surface, m_win_w, m_win_h); + + if (!m_gl.wegl) + return; + + if (m_gl.esurf == EGL_NO_SURFACE) { + m_gl.esurf = eglCreateWindowSurface( + m_gl.edpy, m_gl.ecfg, reinterpret_cast(m_gl.wegl), + nullptr); + } + + if (m_gl.esurf == EGL_NO_SURFACE) + return; + + eglMakeCurrent(m_gl.edpy, m_gl.esurf, m_gl.esurf, m_gl.ectx); + eglSwapInterval(m_gl.edpy, 1); +} + +auto App::update_blur_region() -> void { + if (!m_wayland.compositor) + return; + if (!m_wayland.eff && !m_wayland.kde_blur) + return; + + wl_region *region = wl_compositor_create_region(m_wayland.compositor); + if (!region) + return; + + wl_region_add(region, 0, 0, m_win_w, m_win_h); + + if (m_wayland.eff) + ext_background_effect_surface_v1_set_blur_region(m_wayland.eff, region); + if (m_wayland.kde_blur) + org_kde_kwin_blur_set_region(m_wayland.kde_blur, region); + + wl_region_destroy(region); +} + auto App::pump_events() -> void { while (g_main_context_iteration(nullptr, false)) ; @@ -422,11 +526,18 @@ bool check_or_signal_running() { return false; } +std::optional g_app{}; + auto main() -> int { if (check_or_signal_running()) { return 0; } - App app; - app.run(); + std::signal(SIGINT, [](int) { + if (g_app) + g_app->stop(); + }); + + g_app.emplace(); + g_app->run(); }