232 lines
5.6 KiB
C++
232 lines
5.6 KiB
C++
#pragma once
|
|
|
|
#include <cassert>
|
|
#include <filesystem>
|
|
#include <string>
|
|
#include <unordered_set>
|
|
#include <vector>
|
|
|
|
#include <EGL/egl.h>
|
|
#include <libportal/portal.h>
|
|
#include <wayland-client-protocol.h>
|
|
extern "C" {
|
|
#include "blur-client-protocol.h"
|
|
#define namespace namespace_
|
|
#include "ext-background-effect-v1-client-protocol.h"
|
|
#include "text-input-unstable-v3-client-protocol.h"
|
|
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
|
#include <libportal/settings.h>
|
|
#undef namespace
|
|
}
|
|
#include <wayland-client.h>
|
|
#include <wayland-egl.h>
|
|
#include <xkbcommon/xkbcommon.h>
|
|
|
|
#include "IconRegistry.hpp"
|
|
#include "ImGui.hpp"
|
|
#include "TextRenderer.hpp"
|
|
#include "Theme.hpp"
|
|
#include "common.hpp"
|
|
|
|
struct TypingBuffer : std::pmr::vector<u32> {
|
|
void push_utf8(char const *s);
|
|
};
|
|
|
|
struct App {
|
|
App();
|
|
~App();
|
|
|
|
auto run() -> void;
|
|
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;
|
|
auto init_signal() -> void;
|
|
auto init_theme_portal() -> void;
|
|
auto pump_events() -> void;
|
|
auto tick() -> void;
|
|
auto create_layer_surface() -> void;
|
|
auto destroy_layer_surface() -> void;
|
|
auto ensure_egl_surface() -> void;
|
|
auto update_blur_region() -> void;
|
|
auto process_pending_text_input() -> void;
|
|
auto update_text_input_state(
|
|
std::pmr::string const &text, usize id, Rectangle field_rect) -> void;
|
|
auto theme() const -> ColorScheme const &
|
|
{
|
|
return m_themes[m_active_theme];
|
|
}
|
|
|
|
auto clipboard() const -> std::pmr::string const &
|
|
{
|
|
return m_clipboard_cache;
|
|
}
|
|
auto clipboard(std::string_view const &str) -> void;
|
|
|
|
static void on_settings_changed(XdpSettings * /*self*/, char const *ns,
|
|
char const *key, GVariant * /*value*/, gpointer data);
|
|
|
|
struct {
|
|
wl_display *display {};
|
|
wl_registry *registry {};
|
|
wl_compositor *compositor {};
|
|
wl_seat *seat {};
|
|
wl_keyboard *kbd {};
|
|
wl_surface *surface {};
|
|
zwlr_layer_shell_v1 *layer_shell {};
|
|
zwlr_layer_surface_v1 *layer_surface {};
|
|
ext_background_effect_manager_v1 *mgr {};
|
|
ext_background_effect_surface_v1 *eff {};
|
|
org_kde_kwin_blur_manager *kde_blur_mgr {};
|
|
org_kde_kwin_blur *kde_blur {};
|
|
zwp_text_input_manager_v3 *text_input_mgr {};
|
|
zwp_text_input_v3 *text_input {};
|
|
wl_data_device_manager *ddm {};
|
|
wl_data_device *ddev {};
|
|
wl_data_offer *curr_offer {};
|
|
wl_data_source *curr_source {};
|
|
} m_wayland;
|
|
std::pmr::string m_clipboard_cache;
|
|
u32 m_last_serial { 0 };
|
|
|
|
struct {
|
|
EGLDisplay edpy { EGL_NO_DISPLAY };
|
|
EGLConfig ecfg {};
|
|
EGLContext ectx { EGL_NO_CONTEXT };
|
|
EGLSurface esurf { EGL_NO_SURFACE };
|
|
wl_egl_window *wegl {};
|
|
} m_gl;
|
|
|
|
struct {
|
|
XdpPortal *portal {};
|
|
XdpSettings *settings {};
|
|
} m_xdp;
|
|
|
|
struct {
|
|
TypingBuffer typing {};
|
|
|
|
xkb_context *xkb_ctx_v {};
|
|
xkb_keymap *xkb_keymap_v {};
|
|
xkb_state *xkb_state_v {};
|
|
|
|
std::unordered_set<u32> held;
|
|
std::unordered_set<u32> pressed_syms;
|
|
std::unordered_set<u32> released_syms;
|
|
|
|
auto is_down_evdev(u32 evdev) const -> bool
|
|
{
|
|
return held.find(evdev) != held.end();
|
|
}
|
|
|
|
auto is_down_sym(xkb_keysym_t sym) const -> bool
|
|
{
|
|
if (!xkb_state_v)
|
|
return false;
|
|
for (auto k : held) {
|
|
if (xkb_state_key_get_one_sym(
|
|
xkb_state_v, static_cast<xkb_keycode_t>(k + 8))
|
|
== sym)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
auto is_sym_pressed(xkb_keysym_t sym) const -> bool
|
|
{
|
|
return pressed_syms.find(sym) != pressed_syms.end();
|
|
}
|
|
|
|
auto is_sym_released(xkb_keysym_t sym) const -> bool
|
|
{
|
|
return released_syms.find(sym) != released_syms.end();
|
|
}
|
|
|
|
auto mod_active(char const *name) const -> bool
|
|
{
|
|
return xkb_state_v
|
|
&& xkb_state_mod_name_is_active(
|
|
xkb_state_v, name, XKB_STATE_MODS_EFFECTIVE)
|
|
> 0;
|
|
}
|
|
|
|
auto ctrl() const -> bool { return mod_active("Control"); }
|
|
auto shift() const -> bool { return mod_active("Shift"); }
|
|
|
|
void clear_transients()
|
|
{
|
|
pressed_syms.clear();
|
|
released_syms.clear();
|
|
}
|
|
} m_kbd;
|
|
|
|
std::shared_ptr<TextRenderer> m_tr { nullptr };
|
|
FontHandle m_font;
|
|
std::shared_ptr<ImGui> m_gui { nullptr };
|
|
|
|
struct {
|
|
bool supported { false };
|
|
bool seat_focus { false };
|
|
bool enabled { false };
|
|
bool pending_done { false };
|
|
uint32_t pending_serial { 0 };
|
|
uint32_t sent_serial { 0 };
|
|
|
|
std::pmr::string *bound_text { nullptr };
|
|
usize bound_id { 0 };
|
|
Rectangle bound_rect {};
|
|
|
|
struct {
|
|
bool has_preedit { false };
|
|
std::string preedit_text;
|
|
int cursor_begin { 0 };
|
|
int cursor_end { 0 };
|
|
bool has_commit { false };
|
|
std::string commit_text;
|
|
bool has_delete { false };
|
|
uint32_t before { 0 };
|
|
uint32_t after { 0 };
|
|
} pending;
|
|
|
|
std::string last_surrounding;
|
|
int last_cursor { 0 };
|
|
int last_anchor { 0 };
|
|
Rectangle last_cursor_rect {};
|
|
bool last_cursor_visible { false };
|
|
bool surrounding_dirty { false };
|
|
} m_ime;
|
|
|
|
// NOTE: Canonicalize first!
|
|
std::unordered_map<std::filesystem::path, Texture2D> m_textures;
|
|
|
|
auto get_texture(std::filesystem::path const &path) -> Texture2D const &
|
|
{
|
|
if (m_textures.contains(path)) {
|
|
return m_textures[path];
|
|
}
|
|
auto fname = path.c_str();
|
|
assert(fname);
|
|
TraceLog(LOG_INFO, std::format("loading texture at {}", fname).c_str());
|
|
auto const tex = LoadTexture(fname);
|
|
assert(IsTextureValid(tex));
|
|
m_textures[path] = tex;
|
|
return m_textures[path];
|
|
}
|
|
|
|
enum_array<Theme, ColorScheme> m_themes { make_default_themes() };
|
|
Theme m_active_theme { Theme::Light };
|
|
IconRegistry m_ir;
|
|
|
|
int m_win_w { 800 };
|
|
int m_win_h { 600 };
|
|
bool m_running { true };
|
|
bool m_visible { true };
|
|
|
|
Color m_accent_color { 127, 127, 255, 255 };
|
|
|
|
int m_sfd { -1 };
|
|
};
|