311
src/main.cpp
311
src/main.cpp
@@ -3,6 +3,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <optional>
|
||||
#include <poll.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/signalfd.h>
|
||||
@@ -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<App *>(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<App *>(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<EGLNativeWindowType>(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<App *>(data);
|
||||
if (w)
|
||||
app->m_win_w = static_cast<int>(w);
|
||||
if (h)
|
||||
app->m_win_h = static_cast<int>(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<App *>(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<EGLNativeWindowType>(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<App> 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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user