|
|
|
|
@@ -5,6 +5,7 @@
|
|
|
|
|
#include <cstdlib>
|
|
|
|
|
#include <cstring>
|
|
|
|
|
#include <poll.h>
|
|
|
|
|
#include <print>
|
|
|
|
|
#include <pthread.h>
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#include <sys/mman.h>
|
|
|
|
|
@@ -13,6 +14,7 @@
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
|
|
#include <GLES3/gl3.h>
|
|
|
|
|
#include <fontconfig/fontconfig.h>
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
#include <raylib.h>
|
|
|
|
|
#include <rlgl.h>
|
|
|
|
|
@@ -25,8 +27,39 @@
|
|
|
|
|
#include "blur-client-protocol.h"
|
|
|
|
|
#include "ext-background-effect-v1-client-protocol.h"
|
|
|
|
|
|
|
|
|
|
auto TypingBuffer::push_utf8(const char *s) -> void {
|
|
|
|
|
for (const unsigned char *p = reinterpret_cast<const unsigned char *>(s); *p;) {
|
|
|
|
|
auto find_font_path(std::string_view path = "sans-serif:style=Regular")
|
|
|
|
|
-> std::optional<std::string>
|
|
|
|
|
{
|
|
|
|
|
if (!FcInit())
|
|
|
|
|
return std::nullopt;
|
|
|
|
|
|
|
|
|
|
std::string query(path);
|
|
|
|
|
FcPattern *pattern
|
|
|
|
|
= FcNameParse(reinterpret_cast<FcChar8 const *>(query.c_str()));
|
|
|
|
|
FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
|
|
|
|
|
FcDefaultSubstitute(pattern);
|
|
|
|
|
|
|
|
|
|
FcResult result;
|
|
|
|
|
FcPattern *font = FcFontMatch(nullptr, pattern, &result);
|
|
|
|
|
|
|
|
|
|
std::optional<std::string> final_path;
|
|
|
|
|
|
|
|
|
|
if (font) {
|
|
|
|
|
FcChar8 *file;
|
|
|
|
|
if (FcPatternGetString(font, FC_FILE, 0, &file) == FcResultMatch)
|
|
|
|
|
final_path = reinterpret_cast<char *>(file);
|
|
|
|
|
FcPatternDestroy(font);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FcPatternDestroy(pattern);
|
|
|
|
|
FcFini();
|
|
|
|
|
return final_path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto TypingBuffer::push_utf8(char const *s) -> void
|
|
|
|
|
{
|
|
|
|
|
for (unsigned char const *p = reinterpret_cast<unsigned char const *>(s);
|
|
|
|
|
*p;) {
|
|
|
|
|
u32 cp = 0;
|
|
|
|
|
int len = 0;
|
|
|
|
|
if (*p < 0x80) {
|
|
|
|
|
@@ -48,14 +81,21 @@ auto TypingBuffer::push_utf8(const char *s) -> void {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
App::App() {
|
|
|
|
|
App::App()
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
auto const path = find_font_path();
|
|
|
|
|
if (path)
|
|
|
|
|
std::println("font path = {}", *path);
|
|
|
|
|
}
|
|
|
|
|
init_wayland();
|
|
|
|
|
init_egl();
|
|
|
|
|
init_signal();
|
|
|
|
|
init_theme_portal();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
App::~App() {
|
|
|
|
|
App::~App()
|
|
|
|
|
{
|
|
|
|
|
if (m_sfd != -1)
|
|
|
|
|
close(m_sfd);
|
|
|
|
|
|
|
|
|
|
@@ -67,12 +107,12 @@ App::~App() {
|
|
|
|
|
eglTerminate(m_gl.edpy);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_kbd.xkb_state)
|
|
|
|
|
xkb_state_unref(m_kbd.xkb_state);
|
|
|
|
|
if (m_kbd.xkb_keymap)
|
|
|
|
|
xkb_keymap_unref(m_kbd.xkb_keymap);
|
|
|
|
|
if (m_kbd.xkb_ctx)
|
|
|
|
|
xkb_context_unref(m_kbd.xkb_ctx);
|
|
|
|
|
if (m_kbd.xkb_state_v)
|
|
|
|
|
xkb_state_unref(m_kbd.xkb_state_v);
|
|
|
|
|
if (m_kbd.xkb_keymap_v)
|
|
|
|
|
xkb_keymap_unref(m_kbd.xkb_keymap_v);
|
|
|
|
|
if (m_kbd.xkb_ctx_v)
|
|
|
|
|
xkb_context_unref(m_kbd.xkb_ctx_v);
|
|
|
|
|
if (m_wayland.kbd)
|
|
|
|
|
wl_keyboard_destroy(m_wayland.kbd);
|
|
|
|
|
if (m_wayland.seat)
|
|
|
|
|
@@ -90,16 +130,18 @@ App::~App() {
|
|
|
|
|
g_object_unref(m_xdp.portal);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto App::run() -> void {
|
|
|
|
|
auto App::run() -> void
|
|
|
|
|
{
|
|
|
|
|
SetWindowSize(m_win_w, m_win_h);
|
|
|
|
|
while (m_running) {
|
|
|
|
|
pump_events();
|
|
|
|
|
render_frame();
|
|
|
|
|
tick();
|
|
|
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(16));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto App::set_visible(bool visible) -> void {
|
|
|
|
|
auto App::set_visible(bool visible) -> void
|
|
|
|
|
{
|
|
|
|
|
if (visible == m_visible)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
@@ -114,14 +156,15 @@ auto App::set_visible(bool visible) -> void {
|
|
|
|
|
wl_display_flush(m_wayland.display);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto App::init_wayland() -> void {
|
|
|
|
|
auto App::init_wayland() -> void
|
|
|
|
|
{
|
|
|
|
|
m_wayland.display = wl_display_connect(nullptr);
|
|
|
|
|
if (!m_wayland.display) {
|
|
|
|
|
std::fprintf(stderr, "failed to connect to Wayland display\n");
|
|
|
|
|
std::exit(EXIT_FAILURE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static wl_keyboard_listener keyboard_listener{};
|
|
|
|
|
static wl_keyboard_listener keyboard_listener {};
|
|
|
|
|
{
|
|
|
|
|
auto kb_keymap = [](void *data, wl_keyboard *, u32 format, i32 fd,
|
|
|
|
|
u32 size) -> void {
|
|
|
|
|
@@ -135,31 +178,33 @@ auto App::init_wayland() -> void {
|
|
|
|
|
close(fd);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (app->m_kbd.xkb_keymap)
|
|
|
|
|
xkb_keymap_unref(app->m_kbd.xkb_keymap);
|
|
|
|
|
if (app->m_kbd.xkb_state) {
|
|
|
|
|
xkb_state_unref(app->m_kbd.xkb_state);
|
|
|
|
|
app->m_kbd.xkb_state = nullptr;
|
|
|
|
|
if (app->m_kbd.xkb_keymap_v)
|
|
|
|
|
xkb_keymap_unref(app->m_kbd.xkb_keymap_v);
|
|
|
|
|
if (app->m_kbd.xkb_state_v) {
|
|
|
|
|
xkb_state_unref(app->m_kbd.xkb_state_v);
|
|
|
|
|
app->m_kbd.xkb_state_v = nullptr;
|
|
|
|
|
}
|
|
|
|
|
app->m_kbd.xkb_keymap = xkb_keymap_new_from_string(
|
|
|
|
|
app->m_kbd.xkb_ctx, static_cast<const char *>(map),
|
|
|
|
|
app->m_kbd.xkb_keymap_v = xkb_keymap_new_from_string(
|
|
|
|
|
app->m_kbd.xkb_ctx_v, static_cast<char const *>(map),
|
|
|
|
|
XKB_KEYMAP_FORMAT_TEXT_V1, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
|
|
|
|
app->m_kbd.xkb_state = app->m_kbd.xkb_keymap
|
|
|
|
|
? xkb_state_new(app->m_kbd.xkb_keymap)
|
|
|
|
|
app->m_kbd.xkb_state_v = app->m_kbd.xkb_keymap_v
|
|
|
|
|
? xkb_state_new(app->m_kbd.xkb_keymap_v)
|
|
|
|
|
: nullptr;
|
|
|
|
|
munmap(map, size);
|
|
|
|
|
close(fd);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto kb_enter = [](void *, wl_keyboard *, u32, wl_surface *, wl_array *) -> void {};
|
|
|
|
|
auto kb_leave = [](void *data, wl_keyboard *, u32, wl_surface *) -> void {
|
|
|
|
|
auto kb_enter = [](void *, wl_keyboard *, u32, wl_surface *,
|
|
|
|
|
wl_array *) -> void { };
|
|
|
|
|
auto kb_leave
|
|
|
|
|
= [](void *data, wl_keyboard *, u32, wl_surface *) -> void {
|
|
|
|
|
static_cast<App *>(data)->m_kbd.held.clear();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto kb_key = [](void *data, wl_keyboard *, u32, u32, u32 key,
|
|
|
|
|
u32 state) -> void {
|
|
|
|
|
auto *app = static_cast<App *>(data);
|
|
|
|
|
if (!app->m_kbd.xkb_state)
|
|
|
|
|
if (!app->m_kbd.xkb_state_v)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
xkb_keycode_t kc = key + 8;
|
|
|
|
|
@@ -167,8 +212,9 @@ auto App::init_wayland() -> void {
|
|
|
|
|
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
|
|
|
|
app->m_kbd.held.insert(key);
|
|
|
|
|
|
|
|
|
|
xkb_state_update_key(app->m_kbd.xkb_state, kc, XKB_KEY_DOWN);
|
|
|
|
|
xkb_keysym_t sym = xkb_state_key_get_one_sym(app->m_kbd.xkb_state, kc);
|
|
|
|
|
xkb_state_update_key(app->m_kbd.xkb_state_v, kc, XKB_KEY_DOWN);
|
|
|
|
|
xkb_keysym_t sym
|
|
|
|
|
= xkb_state_key_get_one_sym(app->m_kbd.xkb_state_v, kc);
|
|
|
|
|
app->m_kbd.pressed_syms.insert(sym);
|
|
|
|
|
|
|
|
|
|
bool ctrl = app->m_kbd.mod_active("Control");
|
|
|
|
|
@@ -184,31 +230,33 @@ auto App::init_wayland() -> void {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
xkb_keysym_t sym = xkb_state_key_get_one_sym(app->m_kbd.xkb_state, kc);
|
|
|
|
|
xkb_keysym_t sym
|
|
|
|
|
= xkb_state_key_get_one_sym(app->m_kbd.xkb_state_v, kc);
|
|
|
|
|
app->m_kbd.released_syms.insert(sym);
|
|
|
|
|
|
|
|
|
|
app->m_kbd.held.erase(key);
|
|
|
|
|
xkb_state_update_key(app->m_kbd.xkb_state, kc, XKB_KEY_UP);
|
|
|
|
|
xkb_state_update_key(app->m_kbd.xkb_state_v, kc, XKB_KEY_UP);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto kb_mods = [](void *data, wl_keyboard *, u32, u32 depressed, u32 latched,
|
|
|
|
|
u32 locked, u32 group) -> void {
|
|
|
|
|
auto kb_mods = [](void *data, wl_keyboard *, u32, u32 depressed,
|
|
|
|
|
u32 latched, u32 locked, u32 group) -> void {
|
|
|
|
|
auto *app = static_cast<App *>(data);
|
|
|
|
|
if (!app->m_kbd.xkb_state)
|
|
|
|
|
if (!app->m_kbd.xkb_state_v)
|
|
|
|
|
return;
|
|
|
|
|
xkb_state_update_mask(app->m_kbd.xkb_state, depressed, latched, locked, 0,
|
|
|
|
|
0, group);
|
|
|
|
|
xkb_state_update_mask(app->m_kbd.xkb_state_v, depressed, latched,
|
|
|
|
|
locked, 0, 0, group);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto kb_repeat_info = [](void *, wl_keyboard *, i32, i32) -> void {};
|
|
|
|
|
auto kb_repeat_info = [](void *, wl_keyboard *, i32, i32) -> void { };
|
|
|
|
|
|
|
|
|
|
keyboard_listener = {kb_keymap, kb_enter, kb_leave,
|
|
|
|
|
kb_key, kb_mods, kb_repeat_info};
|
|
|
|
|
keyboard_listener = { kb_keymap, kb_enter, kb_leave, kb_key, kb_mods,
|
|
|
|
|
kb_repeat_info };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto handle_registry_global = [](void *data, wl_registry *registry, u32 name,
|
|
|
|
|
const char *interface, u32 version) -> void {
|
|
|
|
|
auto handle_registry_global
|
|
|
|
|
= [](void *data, wl_registry *registry, u32 name, char const *interface,
|
|
|
|
|
u32 version) -> void {
|
|
|
|
|
auto *app = static_cast<App *>(data);
|
|
|
|
|
if (std::strcmp(interface, wl_compositor_interface.name) == 0) {
|
|
|
|
|
app->m_wayland.compositor = static_cast<wl_compositor *>(
|
|
|
|
|
@@ -217,79 +265,75 @@ auto App::init_wayland() -> void {
|
|
|
|
|
app->m_wayland.seat = static_cast<wl_seat *>(
|
|
|
|
|
wl_registry_bind(registry, name, &wl_seat_interface, 9));
|
|
|
|
|
static struct wl_seat_listener const seat_listener = {
|
|
|
|
|
.capabilities = [](void *data, struct wl_seat *seat, u32 caps) {
|
|
|
|
|
.capabilities =
|
|
|
|
|
[](void *data, struct wl_seat *seat, u32 caps) {
|
|
|
|
|
auto *app = static_cast<App *>(data);
|
|
|
|
|
if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
|
|
|
|
|
app->m_wayland.kbd = wl_seat_get_keyboard(seat);
|
|
|
|
|
wl_keyboard_add_listener(app->m_wayland.kbd, &keyboard_listener,
|
|
|
|
|
data);
|
|
|
|
|
wl_keyboard_add_listener(
|
|
|
|
|
app->m_wayland.kbd, &keyboard_listener, data);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
.name = [](void *, struct wl_seat *, const char *) {},
|
|
|
|
|
.name = [](void *, struct wl_seat *, char const *) {},
|
|
|
|
|
};
|
|
|
|
|
wl_seat_add_listener(app->m_wayland.seat, &seat_listener, data);
|
|
|
|
|
} else if (std::strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) {
|
|
|
|
|
} else if (std::strcmp(interface, zwlr_layer_shell_v1_interface.name)
|
|
|
|
|
== 0) {
|
|
|
|
|
app->m_wayland.layer_shell = static_cast<zwlr_layer_shell_v1 *>(
|
|
|
|
|
wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface,
|
|
|
|
|
version >= 4 ? 4 : version));
|
|
|
|
|
} else if (std::strcmp(interface,
|
|
|
|
|
ext_background_effect_manager_v1_interface.name) == 0) {
|
|
|
|
|
app->m_wayland.mgr = static_cast<ext_background_effect_manager_v1 *>(
|
|
|
|
|
ext_background_effect_manager_v1_interface.name)
|
|
|
|
|
== 0) {
|
|
|
|
|
app->m_wayland.mgr
|
|
|
|
|
= static_cast<ext_background_effect_manager_v1 *>(
|
|
|
|
|
wl_registry_bind(registry, name,
|
|
|
|
|
&ext_background_effect_manager_v1_interface, 1));
|
|
|
|
|
} else if (std::strcmp(interface, "org_kde_kwin_blur_manager") == 0) {
|
|
|
|
|
app->m_wayland.kde_blur_mgr = static_cast<org_kde_kwin_blur_manager *>(
|
|
|
|
|
wl_registry_bind(registry, name, &org_kde_kwin_blur_manager_interface,
|
|
|
|
|
1));
|
|
|
|
|
app->m_wayland.kde_blur_mgr
|
|
|
|
|
= static_cast<org_kde_kwin_blur_manager *>(wl_registry_bind(
|
|
|
|
|
registry, name, &org_kde_kwin_blur_manager_interface, 1));
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static wl_registry_listener const registry_listener{
|
|
|
|
|
static wl_registry_listener const registry_listener {
|
|
|
|
|
.global = handle_registry_global,
|
|
|
|
|
.global_remove = [](void *, wl_registry *, u32) {},
|
|
|
|
|
.global_remove = [](void *, wl_registry *, u32) { },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
m_wayland.registry = wl_display_get_registry(m_wayland.display);
|
|
|
|
|
wl_registry_add_listener(m_wayland.registry, ®istry_listener, this);
|
|
|
|
|
|
|
|
|
|
m_kbd.xkb_ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
|
|
|
|
m_kbd.xkb_ctx_v = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
|
|
|
|
|
|
|
|
|
wl_display_roundtrip(m_wayland.display);
|
|
|
|
|
|
|
|
|
|
create_layer_surface();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto App::init_egl() -> void {
|
|
|
|
|
m_gl.edpy =
|
|
|
|
|
eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(m_wayland.display));
|
|
|
|
|
auto App::init_egl() -> void
|
|
|
|
|
{
|
|
|
|
|
m_gl.edpy = eglGetDisplay(
|
|
|
|
|
reinterpret_cast<EGLNativeDisplayType>(m_wayland.display));
|
|
|
|
|
eglInitialize(m_gl.edpy, nullptr, nullptr);
|
|
|
|
|
|
|
|
|
|
const EGLint cfgAttribs[]{EGL_SURFACE_TYPE,
|
|
|
|
|
EGL_WINDOW_BIT,
|
|
|
|
|
EGL_RENDERABLE_TYPE,
|
|
|
|
|
EGL_OPENGL_ES2_BIT,
|
|
|
|
|
EGL_RED_SIZE,
|
|
|
|
|
8,
|
|
|
|
|
EGL_GREEN_SIZE,
|
|
|
|
|
8,
|
|
|
|
|
EGL_BLUE_SIZE,
|
|
|
|
|
8,
|
|
|
|
|
EGL_ALPHA_SIZE,
|
|
|
|
|
8,
|
|
|
|
|
EGL_NONE};
|
|
|
|
|
EGLint const cfgAttribs[] { EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
|
|
|
|
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RED_SIZE, 8,
|
|
|
|
|
EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8, EGL_NONE };
|
|
|
|
|
EGLint n = 0;
|
|
|
|
|
eglChooseConfig(m_gl.edpy, cfgAttribs, &m_gl.ecfg, 1, &n);
|
|
|
|
|
|
|
|
|
|
const EGLint ctxAttribs[] = {EGL_CONTEXT_MAJOR_VERSION, 2, EGL_NONE};
|
|
|
|
|
m_gl.ectx =
|
|
|
|
|
eglCreateContext(m_gl.edpy, m_gl.ecfg, EGL_NO_CONTEXT, ctxAttribs);
|
|
|
|
|
EGLint const ctxAttribs[] = { EGL_CONTEXT_MAJOR_VERSION, 2, EGL_NONE };
|
|
|
|
|
m_gl.ectx
|
|
|
|
|
= eglCreateContext(m_gl.edpy, m_gl.ecfg, EGL_NO_CONTEXT, ctxAttribs);
|
|
|
|
|
|
|
|
|
|
ensure_egl_surface();
|
|
|
|
|
|
|
|
|
|
InitWindow(m_win_w, m_win_h, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto App::init_signal() -> void {
|
|
|
|
|
auto App::init_signal() -> void
|
|
|
|
|
{
|
|
|
|
|
sigset_t mask;
|
|
|
|
|
sigemptyset(&mask);
|
|
|
|
|
sigaddset(&mask, SIGUSR1);
|
|
|
|
|
@@ -306,15 +350,14 @@ auto App::init_signal() -> void {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void App::on_settings_changed(XdpSettings * /*self*/, const char *ns,
|
|
|
|
|
const char *key, GVariant * /*value*/,
|
|
|
|
|
gpointer data) {
|
|
|
|
|
void App::on_settings_changed(XdpSettings * /*self*/, char const *ns,
|
|
|
|
|
char const *key, GVariant * /*value*/, gpointer data)
|
|
|
|
|
{
|
|
|
|
|
auto *app = static_cast<App *>(data);
|
|
|
|
|
if (g_strcmp0(ns, "org.freedesktop.appearance") == 0 &&
|
|
|
|
|
g_strcmp0(key, "color-scheme") == 0) {
|
|
|
|
|
if (g_strcmp0(ns, "org.freedesktop.appearance") == 0
|
|
|
|
|
&& g_strcmp0(key, "color-scheme") == 0) {
|
|
|
|
|
guint v = xdp_settings_read_uint(app->m_xdp.settings,
|
|
|
|
|
"org.freedesktop.appearance",
|
|
|
|
|
"color-scheme", NULL, NULL);
|
|
|
|
|
"org.freedesktop.appearance", "color-scheme", NULL, NULL);
|
|
|
|
|
|
|
|
|
|
if (v == 1)
|
|
|
|
|
app->m_active_theme = Theme::Dark;
|
|
|
|
|
@@ -323,41 +366,43 @@ void App::on_settings_changed(XdpSettings * /*self*/, const char *ns,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto App::init_theme_portal() -> void {
|
|
|
|
|
auto App::init_theme_portal() -> void
|
|
|
|
|
{
|
|
|
|
|
m_xdp.portal = xdp_portal_new();
|
|
|
|
|
m_xdp.settings = xdp_portal_get_settings(m_xdp.portal);
|
|
|
|
|
|
|
|
|
|
guint v = xdp_settings_read_uint(m_xdp.settings, "org.freedesktop.appearance",
|
|
|
|
|
"color-scheme", NULL, NULL);
|
|
|
|
|
guint v = xdp_settings_read_uint(m_xdp.settings,
|
|
|
|
|
"org.freedesktop.appearance", "color-scheme", NULL, NULL);
|
|
|
|
|
if (v == 1)
|
|
|
|
|
m_active_theme = Theme::Dark;
|
|
|
|
|
else
|
|
|
|
|
m_active_theme = Theme::Light;
|
|
|
|
|
|
|
|
|
|
g_signal_connect(m_xdp.settings, "changed", G_CALLBACK(on_settings_changed),
|
|
|
|
|
this);
|
|
|
|
|
g_signal_connect(
|
|
|
|
|
m_xdp.settings, "changed", G_CALLBACK(on_settings_changed), this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto App::create_layer_surface() -> void {
|
|
|
|
|
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);
|
|
|
|
|
m_wayland.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);
|
|
|
|
|
m_wayland.mgr, m_wayland.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.kde_blur_mgr, m_wayland.surface);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_wayland.layer_surface = zwlr_layer_shell_v1_get_layer_surface(
|
|
|
|
|
m_wayland.layer_shell, m_wayland.wl_surface, nullptr,
|
|
|
|
|
m_wayland.layer_shell, m_wayland.surface, nullptr,
|
|
|
|
|
ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, "waylight-overlay");
|
|
|
|
|
|
|
|
|
|
if (!m_wayland.layer_surface) {
|
|
|
|
|
@@ -369,9 +414,9 @@ auto App::create_layer_surface() -> void {
|
|
|
|
|
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;
|
|
|
|
|
if (m_wayland.surface) {
|
|
|
|
|
wl_surface_destroy(m_wayland.surface);
|
|
|
|
|
m_wayland.surface = nullptr;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
@@ -400,7 +445,8 @@ auto App::create_layer_surface() -> void {
|
|
|
|
|
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);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
@@ -408,15 +454,15 @@ auto App::create_layer_surface() -> void {
|
|
|
|
|
|
|
|
|
|
app->update_blur_region();
|
|
|
|
|
|
|
|
|
|
if (app->m_wayland.wl_surface)
|
|
|
|
|
wl_surface_commit(app->m_wayland.wl_surface);
|
|
|
|
|
if (app->m_wayland.surface)
|
|
|
|
|
wl_surface_commit(app->m_wayland.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 = {
|
|
|
|
|
static zwlr_layer_surface_v1_listener const lsl = {
|
|
|
|
|
.configure = handle_layer_configure,
|
|
|
|
|
.closed = handle_layer_closed,
|
|
|
|
|
};
|
|
|
|
|
@@ -425,8 +471,8 @@ auto App::create_layer_surface() -> void {
|
|
|
|
|
|
|
|
|
|
update_blur_region();
|
|
|
|
|
|
|
|
|
|
if (m_wayland.wl_surface)
|
|
|
|
|
wl_surface_commit(m_wayland.wl_surface);
|
|
|
|
|
if (m_wayland.surface)
|
|
|
|
|
wl_surface_commit(m_wayland.surface);
|
|
|
|
|
|
|
|
|
|
if (m_wayland.display)
|
|
|
|
|
wl_display_roundtrip(m_wayland.display);
|
|
|
|
|
@@ -436,9 +482,11 @@ auto App::create_layer_surface() -> void {
|
|
|
|
|
m_visible = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto App::destroy_layer_surface() -> void {
|
|
|
|
|
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);
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
@@ -463,9 +511,9 @@ auto App::destroy_layer_surface() -> void {
|
|
|
|
|
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.surface) {
|
|
|
|
|
wl_surface_destroy(m_wayland.surface);
|
|
|
|
|
m_wayland.surface = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_wayland.display)
|
|
|
|
|
@@ -474,22 +522,22 @@ auto App::destroy_layer_surface() -> void {
|
|
|
|
|
m_visible = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto App::ensure_egl_surface() -> void {
|
|
|
|
|
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)
|
|
|
|
|
if (!m_wayland.surface)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!m_gl.wegl)
|
|
|
|
|
m_gl.wegl = wl_egl_window_create(m_wayland.wl_surface, m_win_w, m_win_h);
|
|
|
|
|
m_gl.wegl = wl_egl_window_create(m_wayland.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);
|
|
|
|
|
m_gl.esurf = eglCreateWindowSurface(m_gl.edpy, m_gl.ecfg,
|
|
|
|
|
reinterpret_cast<EGLNativeWindowType>(m_gl.wegl), nullptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_gl.esurf == EGL_NO_SURFACE)
|
|
|
|
|
@@ -499,7 +547,8 @@ auto App::ensure_egl_surface() -> void {
|
|
|
|
|
eglSwapInterval(m_gl.edpy, 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto App::update_blur_region() -> void {
|
|
|
|
|
auto App::update_blur_region() -> void
|
|
|
|
|
{
|
|
|
|
|
if (!m_wayland.compositor)
|
|
|
|
|
return;
|
|
|
|
|
if (!m_wayland.eff && !m_wayland.kde_blur)
|
|
|
|
|
@@ -519,15 +568,16 @@ auto App::update_blur_region() -> void {
|
|
|
|
|
wl_region_destroy(region);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto App::pump_events() -> void {
|
|
|
|
|
auto App::pump_events() -> void
|
|
|
|
|
{
|
|
|
|
|
while (g_main_context_iteration(nullptr, false))
|
|
|
|
|
;
|
|
|
|
|
|
|
|
|
|
wl_display_dispatch_pending(m_wayland.display);
|
|
|
|
|
wl_display_flush(m_wayland.display);
|
|
|
|
|
|
|
|
|
|
pollfd fds[2]{{wl_display_get_fd(m_wayland.display), POLLIN, 0},
|
|
|
|
|
{m_sfd, POLLIN, 0}};
|
|
|
|
|
pollfd fds[2] { { wl_display_get_fd(m_wayland.display), POLLIN, 0 },
|
|
|
|
|
{ m_sfd, POLLIN, 0 } };
|
|
|
|
|
|
|
|
|
|
auto prepared = (wl_display_prepare_read(m_wayland.display) == 0);
|
|
|
|
|
auto ret = poll(fds, 2, 0);
|
|
|
|
|
|