Font search

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-10-05 05:42:05 +03:00
parent 1414a66e56
commit 59acba3264
6 changed files with 603 additions and 545 deletions

View File

@@ -13,6 +13,7 @@ pkg_check_modules(GLES2 REQUIRED IMPORTED_TARGET glesv2)
pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0)
pkg_check_modules(LIBPORTAL REQUIRED IMPORTED_TARGET libportal) pkg_check_modules(LIBPORTAL REQUIRED IMPORTED_TARGET libportal)
pkg_check_modules(XKBCOMMON REQUIRED IMPORTED_TARGET xkbcommon) pkg_check_modules(XKBCOMMON REQUIRED IMPORTED_TARGET xkbcommon)
pkg_check_modules(FONTCONFIG REQUIRED IMPORTED_TARGET fontconfig)
pkg_check_modules(WAYLAND_PROTOCOLS REQUIRED wayland-protocols) pkg_check_modules(WAYLAND_PROTOCOLS REQUIRED wayland-protocols)
pkg_check_modules(WLR_PROTOCOLS REQUIRED wlr-protocols) pkg_check_modules(WLR_PROTOCOLS REQUIRED wlr-protocols)
@@ -117,7 +118,7 @@ add_executable(waylight
${GEN_C_PRIVATES} ${GEN_C_PRIVATES}
${CMAKE_CURRENT_SOURCE_DIR}/src/App.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/App.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/Frame.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/Tick.cpp
${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp
) )
add_dependencies(waylight generate_protocols) add_dependencies(waylight generate_protocols)
@@ -134,6 +135,7 @@ target_link_libraries(waylight PRIVATE
PkgConfig::GLIB PkgConfig::GLIB
PkgConfig::LIBPORTAL PkgConfig::LIBPORTAL
PkgConfig::XKBCOMMON PkgConfig::XKBCOMMON
PkgConfig::FONTCONFIG
raylib raylib

View File

@@ -23,7 +23,9 @@
]; ];
in in
{ {
devShells.default = pkgs.mkShell.override { stdenv = pkgs.llvmPackages_21.libcxxStdenv; } { devShells.default =
pkgs.mkShell.override { stdenv = pkgs.stdenvAdapters.useMoldLinker pkgs.gcc15Stdenv; }
{
packages = packages =
with pkgs; with pkgs;
[ [
@@ -44,6 +46,7 @@
libportal libportal
glib glib
libxkbcommon libxkbcommon
fontconfig
] ]
++ buildInputs ++ buildInputs
++ nativeBuildInputs ++ nativeBuildInputs

View File

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

View File

@@ -41,7 +41,7 @@ private:
auto init_signal() -> void; auto init_signal() -> void;
auto init_theme_portal() -> void; auto init_theme_portal() -> void;
auto pump_events() -> void; auto pump_events() -> void;
auto render_frame() -> void; auto tick() -> void;
auto create_layer_surface() -> void; auto create_layer_surface() -> void;
auto destroy_layer_surface() -> void; auto destroy_layer_surface() -> void;
auto ensure_egl_surface() -> void; auto ensure_egl_surface() -> void;
@@ -60,7 +60,7 @@ private:
wl_compositor *compositor {}; wl_compositor *compositor {};
wl_seat *seat {}; wl_seat *seat {};
wl_keyboard *kbd {}; wl_keyboard *kbd {};
wl_surface *wl_surface {}; wl_surface *surface {};
zwlr_layer_shell_v1 *layer_shell {}; zwlr_layer_shell_v1 *layer_shell {};
zwlr_layer_surface_v1 *layer_surface {}; zwlr_layer_surface_v1 *layer_surface {};
ext_background_effect_manager_v1 *mgr {}; ext_background_effect_manager_v1 *mgr {};
@@ -85,9 +85,9 @@ private:
struct { struct {
TypingBuffer typing {}; TypingBuffer typing {};
xkb_context *xkb_ctx {}; xkb_context *xkb_ctx_v {};
xkb_keymap *xkb_keymap {}; xkb_keymap *xkb_keymap_v {};
xkb_state *xkb_state {}; xkb_state *xkb_state_v {};
std::unordered_set<u32> held; std::unordered_set<u32> held;
std::unordered_set<u32> pressed_syms; std::unordered_set<u32> pressed_syms;
@@ -100,11 +100,11 @@ private:
auto is_down_sym(xkb_keysym_t sym) const -> bool auto is_down_sym(xkb_keysym_t sym) const -> bool
{ {
if (!xkb_state) if (!xkb_state_v)
return false; return false;
for (auto k : held) { for (auto k : held) {
if (xkb_state_key_get_one_sym( if (xkb_state_key_get_one_sym(
xkb_state, static_cast<xkb_keycode_t>(k + 8)) xkb_state_v, static_cast<xkb_keycode_t>(k + 8))
== sym) == sym)
return true; return true;
} }
@@ -123,9 +123,9 @@ private:
auto mod_active(char const *name) const -> bool auto mod_active(char const *name) const -> bool
{ {
return xkb_state return xkb_state_v
&& xkb_state_mod_name_is_active( && xkb_state_mod_name_is_active(
xkb_state, name, XKB_STATE_MODS_EFFECTIVE) xkb_state_v, name, XKB_STATE_MODS_EFFECTIVE)
> 0; > 0;
} }

View File

@@ -1,39 +0,0 @@
#include "App.hpp"
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <print>
#include <raylib.h>
#include <rlgl.h>
#include <xkbcommon/xkbcommon.h>
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);
for (auto const cp : m_kbd.typing) {
std::println("Char typed: {} ({}) shift={} ctrl={}", rune_to_string(cp), cp,
m_kbd.shift() ? 'y' : 'n', m_kbd.ctrl() ? 'y' : 'n');
}
if (m_kbd.is_sym_pressed(XKB_KEY_Escape)) {
set_visible(!visible());
if (m_kbd.ctrl() && m_kbd.shift()) {
m_running = false;
}
}
BeginDrawing();
ClearBackground(BLANK);
DrawFPS(10, 10);
EndDrawing();
eglSwapBuffers(m_gl.edpy, m_gl.esurf);
m_kbd.typing.clear();
m_kbd.clear_transients();
}

42
src/Tick.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include "App.hpp"
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <print>
#include <raylib.h>
#include <rlgl.h>
#include <xkbcommon/xkbcommon.h>
auto App::tick() -> 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);
for (auto const cp : m_kbd.typing) {
std::println("Char typed: {} ({}) shift={} ctrl={}",
rune_to_string(cp), cp, m_kbd.shift() ? 'y' : 'n',
m_kbd.ctrl() ? 'y' : 'n');
}
if (m_kbd.is_sym_pressed(XKB_KEY_Escape)) {
set_visible(!visible());
if (m_kbd.ctrl() && m_kbd.shift()) {
m_running = false;
}
}
BeginDrawing();
ClearBackground(BLANK);
DrawFPS(10, 10);
EndDrawing();
eglSwapBuffers(m_gl.edpy, m_gl.esurf);
m_kbd.typing.clear();
m_kbd.clear_transients();
}