311
src/main.cpp
311
src/main.cpp
@@ -3,6 +3,7 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <optional>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <sys/signalfd.h>
|
#include <sys/signalfd.h>
|
||||||
@@ -50,6 +51,8 @@ struct App {
|
|||||||
auto set_visible(bool visible) -> void;
|
auto set_visible(bool visible) -> void;
|
||||||
auto visible() const -> bool { return m_visible; }
|
auto visible() const -> bool { return m_visible; }
|
||||||
|
|
||||||
|
auto stop() -> void { m_running = false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
auto init_wayland() -> void;
|
auto init_wayland() -> void;
|
||||||
auto init_egl() -> void;
|
auto init_egl() -> void;
|
||||||
@@ -57,6 +60,10 @@ private:
|
|||||||
auto init_theme_portal() -> void;
|
auto init_theme_portal() -> void;
|
||||||
auto pump_events() -> void;
|
auto pump_events() -> void;
|
||||||
auto render_frame() -> 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]; }
|
auto theme() const -> ColorScheme const & { return m_themes[m_active_theme]; }
|
||||||
|
|
||||||
static void on_settings_changed(XdpSettings * /*self*/, const char *ns,
|
static void on_settings_changed(XdpSettings * /*self*/, const char *ns,
|
||||||
@@ -104,19 +111,14 @@ App::~App() {
|
|||||||
if (m_sfd != -1)
|
if (m_sfd != -1)
|
||||||
close(m_sfd);
|
close(m_sfd);
|
||||||
|
|
||||||
|
destroy_layer_surface();
|
||||||
|
|
||||||
if (m_gl.edpy != EGL_NO_DISPLAY) {
|
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)
|
if (m_gl.ectx != EGL_NO_CONTEXT)
|
||||||
eglDestroyContext(m_gl.edpy, m_gl.ectx);
|
eglDestroyContext(m_gl.edpy, m_gl.ectx);
|
||||||
eglTerminate(m_gl.edpy);
|
eglTerminate(m_gl.edpy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_wayland.wl_surface)
|
|
||||||
wl_surface_destroy(m_wayland.wl_surface);
|
|
||||||
if (m_wayland.compositor)
|
if (m_wayland.compositor)
|
||||||
wl_compositor_destroy(m_wayland.compositor);
|
wl_compositor_destroy(m_wayland.compositor);
|
||||||
if (m_wayland.registry)
|
if (m_wayland.registry)
|
||||||
@@ -169,99 +171,22 @@ auto App::init_wayland() -> void {
|
|||||||
|
|
||||||
wl_display_roundtrip(m_wayland.display);
|
wl_display_roundtrip(m_wayland.display);
|
||||||
|
|
||||||
m_wayland.wl_surface = wl_compositor_create_surface(m_wayland.compositor);
|
create_layer_surface();
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto App::set_visible(bool visible) -> void {
|
auto App::set_visible(bool visible) -> void {
|
||||||
if (!m_wayland.layer_surface)
|
if (visible == m_visible)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (visible) {
|
if (visible) {
|
||||||
zwlr_layer_surface_v1_set_size(m_wayland.layer_surface, m_win_w, m_win_h);
|
create_layer_surface();
|
||||||
wl_surface_commit(m_wayland.wl_surface);
|
ensure_egl_surface();
|
||||||
} else {
|
} else {
|
||||||
wl_surface_attach(m_wayland.wl_surface, nullptr, 0, 0);
|
destroy_layer_surface();
|
||||||
wl_surface_commit(m_wayland.wl_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 {
|
auto App::init_egl() -> void {
|
||||||
@@ -291,13 +216,7 @@ auto App::init_egl() -> void {
|
|||||||
m_gl.ectx =
|
m_gl.ectx =
|
||||||
eglCreateContext(m_gl.edpy, m_gl.ecfg, EGL_NO_CONTEXT, ctxAttribs);
|
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);
|
ensure_egl_surface();
|
||||||
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);
|
|
||||||
|
|
||||||
InitWindow(m_win_w, m_win_h, "");
|
InitWindow(m_win_w, m_win_h, "");
|
||||||
}
|
}
|
||||||
@@ -352,6 +271,9 @@ auto App::init_theme_portal() -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto App::render_frame() -> 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);
|
glViewport(0, 0, m_win_w, m_win_h);
|
||||||
|
|
||||||
BeginDrawing();
|
BeginDrawing();
|
||||||
@@ -365,6 +287,188 @@ auto App::render_frame() -> void {
|
|||||||
eglSwapBuffers(m_gl.edpy, m_gl.esurf);
|
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 {
|
auto App::pump_events() -> void {
|
||||||
while (g_main_context_iteration(nullptr, false))
|
while (g_main_context_iteration(nullptr, false))
|
||||||
;
|
;
|
||||||
@@ -422,11 +526,18 @@ bool check_or_signal_running() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<App> g_app{};
|
||||||
|
|
||||||
auto main() -> int {
|
auto main() -> int {
|
||||||
if (check_or_signal_running()) {
|
if (check_or_signal_running()) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
App app;
|
std::signal(SIGINT, [](int) {
|
||||||
app.run();
|
if (g_app)
|
||||||
|
g_app->stop();
|
||||||
|
});
|
||||||
|
|
||||||
|
g_app.emplace();
|
||||||
|
g_app->run();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user