Mouse cursor

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-09-04 15:11:29 +03:00
parent 1af7357301
commit a6949eeda0
4 changed files with 340 additions and 47 deletions

19
flake.lock generated
View File

@@ -34,21 +34,6 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_2": {
"locked": {
"lastModified": 1751984180,
"narHash": "sha256-LwWRsENAZJKUdD3SpLluwDmdXY9F45ZEgCb0X+xgOL0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9807714d6944a957c2e036f84b0ff8caf9930bc0",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
}
},
"root": { "root": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils",
@@ -73,7 +58,9 @@
}, },
"wlroots-lunar": { "wlroots-lunar": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_2" "nixpkgs": [
"nixpkgs"
]
}, },
"locked": { "locked": {
"lastModified": 1754816070, "lastModified": 1754816070,

View File

@@ -4,7 +4,10 @@
inputs = { inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
wlroots-lunar.url = "github:slendidev/wlroots-lunar"; wlroots-lunar = {
url = "github:slendidev/wlroots-lunar";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = outputs =

View File

@@ -46,6 +46,16 @@
#include "vec.h" #include "vec.h"
static inline SphericalCoord get_forward_spherical_with_nearest(
Vector3 fwd, float r)
{
if (fabs(fwd.y) < 0.2f) {
fwd.y = 0;
}
auto vec = Vector3Scale(Vector3Normalize(fwd), r);
return Vector3ToSpherical(vec);
}
void toplevel_commit_notify(struct wl_listener *l, void *) void toplevel_commit_notify(struct wl_listener *l, void *)
{ {
auto *tl = wl_container_of(l, (LunarWM_Toplevel *)(NULL), commit); auto *tl = wl_container_of(l, (LunarWM_Toplevel *)(NULL), commit);
@@ -63,6 +73,22 @@ void toplevel_commit_notify(struct wl_listener *l, void *)
LunarWM_Toplevel_update(tl); LunarWM_Toplevel_update(tl);
} }
static void remove_windows_for_tl(LunarWM *wm, LunarWM_Toplevel *tl)
{
if (!wm || !tl)
return;
for (size_t ws = 0; ws < ARRAY_SZ(wm->wm.workspaces); ++ws) {
auto *vec = &wm->wm.workspaces[ws].v_windows;
for (size_t i = 0; i < vector_size(*vec);) {
if ((*vec)[i].tl == tl) {
vector_remove(*vec, i);
} else {
i++;
}
}
}
}
static void focus_fallback(LunarWM *wm); static void focus_fallback(LunarWM *wm);
void toplevel_destroy_notify(struct wl_listener *l, void *) void toplevel_destroy_notify(struct wl_listener *l, void *)
{ {
@@ -75,6 +101,8 @@ void toplevel_destroy_notify(struct wl_listener *l, void *)
} }
} }
remove_windows_for_tl(tl->server, tl);
focus_fallback(tl->server); focus_fallback(tl->server);
LunarWM_Toplevel_destroy(tl); LunarWM_Toplevel_destroy(tl);
@@ -137,7 +165,7 @@ static void toplevel_unmap_notify(struct wl_listener *l, void *data)
bool LunarWM_Toplevel_init_xdg( bool LunarWM_Toplevel_init_xdg(
LunarWM_Toplevel *tl, LunarWM *wm, struct wlr_xdg_toplevel *xdg) LunarWM_Toplevel *tl, LunarWM *wm, struct wlr_xdg_toplevel *xdg)
{ {
tl->id = vector_size(wm->wayland.v_toplevels) + 1; tl->id = LunarWM_get_new_id(wm);
tl->server = wm; tl->server = wm;
tl->is_xwayland = false; tl->is_xwayland = false;
tl->u.xdg = xdg; tl->u.xdg = xdg;
@@ -163,7 +191,7 @@ bool LunarWM_Toplevel_init_xdg(
bool LunarWM_Toplevel_init_xwayland( bool LunarWM_Toplevel_init_xwayland(
LunarWM_Toplevel *tl, LunarWM *wm, struct wlr_xwayland_surface *xwl) LunarWM_Toplevel *tl, LunarWM *wm, struct wlr_xwayland_surface *xwl)
{ {
tl->id = vector_size(wm->wayland.v_toplevels) + 1; tl->id = LunarWM_get_new_id(wm);
tl->server = wm; tl->server = wm;
tl->is_xwayland = true; tl->is_xwayland = true;
tl->u.xwl = xwl; tl->u.xwl = xwl;
@@ -309,6 +337,13 @@ static void handle_associate(struct wl_listener *ll, void *d)
if (LunarWM_Toplevel_init_xwayland(tl, wm2, x)) { if (LunarWM_Toplevel_init_xwayland(tl, wm2, x)) {
vector_add(&wm2->wayland.v_toplevels, tl); vector_add(&wm2->wayland.v_toplevels, tl);
LunarWM_Window window = {
.tl = tl,
.coord = get_forward_spherical_with_nearest(
wm2->renderer.camera.target, wm2->cman->cfg.space.radius),
};
vector_add(
&wm2->wm.workspaces[wm2->wm.active_workspace].v_windows, window);
} else { } else {
free(tl); free(tl);
} }
@@ -323,6 +358,7 @@ static void handle_dissociate(struct wl_listener *ll, void *d)
LunarWM_Toplevel *tl = wm2->wayland.v_toplevels[i]; LunarWM_Toplevel *tl = wm2->wayland.v_toplevels[i];
if (tl->is_xwayland && tl->u.xwl == x) { if (tl->is_xwayland && tl->u.xwl == x) {
vector_remove(wm2->wayland.v_toplevels, i); vector_remove(wm2->wayland.v_toplevels, i);
remove_windows_for_tl(wm2, tl);
LunarWM_Toplevel_destroy(tl); LunarWM_Toplevel_destroy(tl);
free(tl); free(tl);
break; break;
@@ -484,6 +520,7 @@ static void xwl_on_destroy(struct wl_listener *ll, void *data)
LunarWM_Toplevel *tl = wm->wayland.v_toplevels[i]; LunarWM_Toplevel *tl = wm->wayland.v_toplevels[i];
if (tl->is_xwayland && tl->u.xwl == x) { if (tl->is_xwayland && tl->u.xwl == x) {
vector_remove(wm->wayland.v_toplevels, i); vector_remove(wm->wayland.v_toplevels, i);
remove_windows_for_tl(wm, tl);
free(tl); free(tl);
break; break;
} }
@@ -729,9 +766,59 @@ static void Keyboard_key_notify(struct wl_listener *listener, void *data)
static void Keyboard_destroy_notify(struct wl_listener *listener, void *) static void Keyboard_destroy_notify(struct wl_listener *listener, void *)
{ {
auto *kbd = wl_container_of(listener, (LunarWM_Keyboard *)(NULL), destroy); auto *p = wl_container_of(listener, (LunarWM_Keyboard *)(NULL), destroy);
wl_list_remove(&kbd->modifiers.link); wl_list_remove(&p->modifiers.link);
wl_list_remove(&kbd->key.link); wl_list_remove(&p->key.link);
wl_list_remove(&p->destroy.link);
wl_list_remove(&p->link);
free(p);
}
static inline float wrap_pi(float a)
{
a = fmodf(a + PI, 2.0f * PI);
if (a < 0.0f)
a += 2.0f * PI;
return a - PI;
}
static void Pointer_motion_notify(struct wl_listener *listener, void *data)
{
LunarWM_Pointer *p
= wl_container_of(listener, (LunarWM_Pointer *)NULL, motion);
if (!p->server || !p->server->wayland.seat)
return;
struct wlr_pointer_motion_event *ev = data;
float const dx = (float)ev->delta_x;
float const dy = -(float)ev->delta_y;
float const R = p->server->cman->cfg.space.radius;
float const g = 0.0005f; // meters per pixel
float const POLE_GUARD = 6.0f * (float)M_PI / 180.0f;
float const MIN_SIN = sinf(POLE_GUARD);
float phi = p->server->wm.pointer.phi;
float theta = p->server->wm.pointer.theta;
float dphi = (-g * dy) / R;
float s = fmaxf(sinf(phi), MIN_SIN);
float dtheta = (g * dx) / (R * s);
phi = Clamp(phi + dphi, POLE_GUARD, (float)M_PI - POLE_GUARD);
theta = wrap_pi(theta + dtheta);
p->server->wm.pointer.phi = phi;
p->server->wm.pointer.theta = theta;
p->server->wm.pointer.r = R;
}
static void Pointer_destroy_notify(struct wl_listener *listener, void *)
{
auto *kbd = wl_container_of(listener, (LunarWM_Pointer *)(NULL), destroy);
wl_list_remove(&kbd->motion.link);
wl_list_remove(&kbd->destroy.link); wl_list_remove(&kbd->destroy.link);
wl_list_remove(&kbd->link); wl_list_remove(&kbd->link);
free(kbd); free(kbd);
@@ -777,7 +864,19 @@ static void new_input_listener_notify(struct wl_listener *listener, void *data)
wl_list_insert(&wm->wayland.keyboards, &keyboard->link); wl_list_insert(&wm->wayland.keyboards, &keyboard->link);
} else if (dev->type == WLR_INPUT_DEVICE_POINTER) { } else if (dev->type == WLR_INPUT_DEVICE_POINTER) {
wlr_cursor_attach_input_device(wm->wayland.cursor, dev); struct wlr_pointer *wlr_pointer = wlr_pointer_from_input_device(dev);
LunarWM_Pointer *pointer = calloc(1, sizeof(*pointer));
pointer->server = wm;
pointer->wlr_pointer = wlr_pointer;
pointer->destroy.notify = Pointer_destroy_notify;
wl_signal_add(&dev->events.destroy, &pointer->destroy);
pointer->motion.notify = Pointer_motion_notify;
wl_signal_add(&wlr_pointer->events.motion, &pointer->motion);
wl_list_insert(&wm->wayland.pointers, &pointer->link);
} }
uint32_t caps = WL_SEAT_CAPABILITY_POINTER; uint32_t caps = WL_SEAT_CAPABILITY_POINTER;
@@ -808,6 +907,13 @@ static void new_xdg_toplevel_listener_notify(
if (LunarWM_Toplevel_init_xdg(tl, wm, xdg_tl)) { if (LunarWM_Toplevel_init_xdg(tl, wm, xdg_tl)) {
vector_add(&wm->wayland.v_toplevels, tl); vector_add(&wm->wayland.v_toplevels, tl);
LunarWM_Window window = {
.tl = tl,
.coord = get_forward_spherical_with_nearest(
wm->renderer.camera.target, wm->cman->cfg.space.radius),
};
vector_add(
&wm->wm.workspaces[wm->wm.active_workspace].v_windows, window);
} else { } else {
wlr_log(WLR_ERROR, "Failed to initialize Toplevel."); wlr_log(WLR_ERROR, "Failed to initialize Toplevel.");
free(tl); free(tl);
@@ -1044,9 +1150,8 @@ static bool init_wayland(LunarWM *this)
wlr_log(WLR_ERROR, "Failed to create wlroots data device manager"); wlr_log(WLR_ERROR, "Failed to create wlroots data device manager");
} }
this->wayland.cursor = wlr_cursor_create();
wl_list_init(&this->wayland.keyboards); wl_list_init(&this->wayland.keyboards);
wl_list_init(&this->wayland.pointers);
this->wayland.new_input_listener.notify = new_input_listener_notify; this->wayland.new_input_listener.notify = new_input_listener_notify;
wl_signal_add(&this->wayland.backend->events.new_input, wl_signal_add(&this->wayland.backend->events.new_input,
@@ -1851,6 +1956,12 @@ bool LunarWM_init(LunarWM *this)
this->xr.recenter_rot = (Quaternion) { 0, 0, 0, 1 }; this->xr.recenter_rot = (Quaternion) { 0, 0, 0, 1 };
this->xr.recenter_trans = (Vector3) { 0, 0, 0 }; this->xr.recenter_trans = (Vector3) { 0, 0, 0 };
this->xr.recenter_active = false; this->xr.recenter_active = false;
this->counter = 0;
}
this->wm.active_workspace = 0;
for (size_t i = 0; i < ARRAY_SZ(this->wm.workspaces); i++) {
this->wm.workspaces[i].v_windows = vector_create();
} }
this->cman = config_manager_create(get_config_path()); this->cman = config_manager_create(get_config_path());
@@ -2049,11 +2160,6 @@ static void cleanup_wayland(LunarWM *this)
this->wayland.v_toplevels = NULL; this->wayland.v_toplevels = NULL;
} }
if (this->wayland.cursor) {
wlr_cursor_destroy(this->wayland.cursor);
this->wayland.cursor = NULL;
}
if (this->wayland.backend) { if (this->wayland.backend) {
wlr_backend_destroy(this->wayland.backend); wlr_backend_destroy(this->wayland.backend);
this->wayland.backend = NULL; this->wayland.backend = NULL;
@@ -2369,6 +2475,103 @@ void DrawTextureCyl(
rlEnableBackfaceCulling(); rlEnableBackfaceCulling();
} }
static void DrawTextureCyl2(Texture2D tex, Vector3 sphere_center,
SphericalCoord coord, float rad, float scale, bool y_flip)
{
if (!tex.id || scale <= 0.0f || rad == 0.0f)
return;
// midpoint on the sphere where the panel should sit (its center)
Vector3 fwd = SphericalToVector3(coord);
if (Vector3Length(fwd) < 1e-6f)
fwd = (Vector3) { 0, 0, 1 };
fwd = Vector3Normalize(fwd);
// build a local tangent frame at that point (right, up, forward)
Vector3 worldUp = (Vector3) { 0, 1, 0 };
if (fabsf(Vector3DotProduct(worldUp, fwd)) > 0.99f)
worldUp = (Vector3) { 1, 0, 0 };
Vector3 right = Vector3Normalize(Vector3CrossProduct(worldUp, fwd));
Vector3 up = Vector3Normalize(Vector3CrossProduct(fwd, right));
float r = fabsf(rad);
float arc_len = (float)tex.width * scale; // world units across
float theta = arc_len / r; // total horizontal FOV in radians
float half_t = 0.5f * theta;
float half_h = 0.5f * (float)tex.height * scale;
// shift so cylinder's surface midpoint lands exactly at coord.r from
// sphere_center
Vector3 delta = Vector3Add(sphere_center,
Vector3Add(Vector3Scale(fwd, coord.r - r), (Vector3) { 0, 0, 0 }));
// tessellation: about 3° per slice (min 8, max 1024)
int slices = (int)ceilf(fmaxf(theta * (180.0f / PI) / 3.0f, 8.0f));
if (slices > 1024)
slices = 1024;
float vt = y_flip ? 1.0f : 0.0f;
float vb = y_flip ? 0.0f : 1.0f;
rlDrawRenderBatchActive();
rlSetTexture(tex.id);
rlDisableBackfaceCulling();
rlColor4ub(255, 255, 255, 255);
rlBegin(RL_QUADS);
for (int i = 0; i < slices; ++i) {
float u0 = (float)i / (float)slices;
float u1 = (float)(i + 1) / (float)slices;
float aL = -half_t + theta * u0;
float aR = -half_t + theta * u1;
// local outward directions on the cylindrical surface
Vector3 nL = Vector3Add(
Vector3Scale(right, sinf(aL)), Vector3Scale(fwd, cosf(aL)));
Vector3 nR = Vector3Add(
Vector3Scale(right, sinf(aR)), Vector3Scale(fwd, cosf(aR)));
if (rad < 0.0f) {
nL = Vector3Negate(nL);
nR = Vector3Negate(nR);
}
// surface points (center band), then top/bottom by +/- up*half_h
Vector3 cL = Vector3Add(delta, Vector3Scale(nL, r));
Vector3 cR = Vector3Add(delta, Vector3Scale(nR, r));
Vector3 pLT = Vector3Add(cL, Vector3Scale(up, half_h));
Vector3 pLB = Vector3Add(cL, Vector3Scale(up, -half_h));
Vector3 pRT = Vector3Add(cR, Vector3Scale(up, half_h));
Vector3 pRB = Vector3Add(cR, Vector3Scale(up, -half_h));
// match the original horizontal flip so Wayland textures look correct
float U0 = 1.0f - u0;
float U1 = 1.0f - u1;
rlNormal3f(nL.x, nL.y, nL.z);
rlTexCoord2f(U0, vt);
rlVertex3f(pLT.x, pLT.y, pLT.z);
rlNormal3f(nR.x, nR.y, nR.z);
rlTexCoord2f(U1, vt);
rlVertex3f(pRT.x, pRT.y, pRT.z);
rlNormal3f(nR.x, nR.y, nR.z);
rlTexCoord2f(U1, vb);
rlVertex3f(pRB.x, pRB.y, pRB.z);
rlNormal3f(nL.x, nL.y, nL.z);
rlTexCoord2f(U0, vb);
rlVertex3f(pLB.x, pLB.y, pLB.z);
}
rlEnd();
rlSetTexture(0);
rlEnableBackfaceCulling();
}
static inline Vector3 RecenterPoint(LunarWM *wm, Vector3 p) static inline Vector3 RecenterPoint(LunarWM *wm, Vector3 p)
{ {
if (!wm->xr.recenter_active) if (!wm->xr.recenter_active)
@@ -2384,6 +2587,17 @@ static inline Quaternion RecenterOrient(LunarWM *wm, Quaternion q)
return QuaternionMultiply(wm->xr.recenter_rot, q); return QuaternionMultiply(wm->xr.recenter_rot, q);
} }
static LunarWM_Toplevel *find_toplevel(LunarWM *this, int id)
{
for (size_t i = 0; i < vector_size(this->wayland.v_toplevels); i++) {
auto *tl = this->wayland.v_toplevels[i];
if (tl->id == id)
return tl;
}
return NULL;
}
void render_hud(LunarWM *this, float /*dt*/, int hud_size) void render_hud(LunarWM *this, float /*dt*/, int hud_size)
{ {
ClearBackground((Color) { 0, 0, 0, 0 }); ClearBackground((Color) { 0, 0, 0, 0 });
@@ -2413,18 +2627,31 @@ void render_hud(LunarWM *this, float /*dt*/, int hud_size)
} }
} }
void render_3d(LunarWM *this, float /*dt*/) void render_windows(LunarWM *this, bool alpha_check)
{ {
for (size_t i = 0; i < vector_size(this->wayland.v_toplevels); i++) { for (size_t i = 0; i
auto *tl = this->wayland.v_toplevels[i]; < vector_size(this->wm.workspaces[this->wm.active_workspace].v_windows);
if (!tl || !tl->surface) i++) {
auto *window
= &this->wm.workspaces[this->wm.active_workspace].v_windows[i];
auto *tl = window->tl;
if (!tl || !tl->surface) {
continue; continue;
if (tl->gles_texture && !tl->gles_texture->has_alpha) { }
float rad = this->cman->cfg.space.radius - 0.01f * (float)i; if (tl->gles_texture) {
DrawTextureCyl(tl->rl_texture, (Vector3) { 0, 0, rad }, rad, if (alpha_check && tl->gles_texture->has_alpha) {
continue;
}
float rad = window->coord.r - 0.01f * (float)i;
DrawTextureCyl2(tl->rl_texture, Vector3Zero(), window->coord, rad,
this->cman->cfg.space.window_scale, false); this->cman->cfg.space.window_scale, false);
} }
} }
}
void render_3d(LunarWM *this, float /*dt*/)
{
render_windows(this, true);
for (int h = 0; h < 2; ++h) { for (int h = 0; h < 2; ++h) {
auto *hand_info = &this->xr.hands[h]; auto *hand_info = &this->xr.hands[h];
@@ -2444,15 +2671,35 @@ void render_3d(LunarWM *this, float /*dt*/)
rlEnableColorBlend(); rlEnableColorBlend();
rlDisableDepthMask(); // don't write depth rlDisableDepthMask(); // don't write depth
for (size_t i = 0; i < vector_size(this->wayland.v_toplevels); i++) { render_windows(this, false);
auto *tl = this->wayland.v_toplevels[i]; // TODO: Replace with actual cursor texture.
if (!tl || !tl->surface) { // Cursor
continue; Vector3 tip = SphericalToVector3(this->wm.pointer);
if (tl->gles_texture && tl->gles_texture->has_alpha) {
float rad = this->cman->cfg.space.radius - 0.01f * (float)i; Vector3 n = Vector3Normalize(
DrawTextureCyl(tl->rl_texture, (Vector3) { 0, 0, rad }, rad, Vector3Subtract(this->renderer.camera.position, tip));
this->cman->cfg.space.window_scale, false); Vector3 up_hint = (Vector3) { 0, 1, 0 };
if (fabsf(Vector3DotProduct(up_hint, n)) > 0.98f)
up_hint = (Vector3) { 1, 0, 0 };
Vector3 right = Vector3Normalize(Vector3CrossProduct(up_hint, n));
Vector3 up = Vector3Normalize(Vector3CrossProduct(n, right));
Vector3 down = Vector3Negate(up);
float const s = 0.03f;
Vector3 v1 = tip;
Vector3 v2 = Vector3Add(tip, Vector3Scale(down, s));
Vector3 v3 = Vector3Add(tip, Vector3Scale(right, s));
Vector3 normal = Vector3CrossProduct(
Vector3Subtract(v2, v1), Vector3Subtract(v3, v1));
if (Vector3DotProduct(normal, n) < 0.0f) {
Vector3 tmp = v2;
v2 = v3;
v3 = tmp;
} }
DrawTriangle3D(v1, v2, v3, RED);
} }
rlEnableDepthMask(); rlEnableDepthMask();
@@ -2714,6 +2961,8 @@ static bool render_layer(LunarWM *this, LunarWM_RenderLayerInfo *info, float dt)
l_recenter(this->cman->L); l_recenter(this->cman->L);
lua_pop(this->cman->L, 1); lua_pop(this->cman->L, 1);
this->renderer.first_frame = false; this->renderer.first_frame = false;
this->wm.pointer = get_forward_spherical_with_nearest(
this->renderer.camera.target, this->cman->cfg.space.radius);
} }
return true; return true;

View File

@@ -37,6 +37,34 @@
struct LunarWM; struct LunarWM;
typedef struct {
float r, theta, phi;
} SphericalCoord;
static inline SphericalCoord Vector3ToSpherical(Vector3 v)
{
SphericalCoord s;
s.r = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
if (s.r > 0.0f) {
s.theta = atan2f(v.z, v.x); // azimuth around Y axis
s.phi = acosf(v.y / s.r); // polar angle from Y+
} else {
s.theta = 0.0f;
s.phi = 0.0f;
}
return s;
}
static inline Vector3 SphericalToVector3(SphericalCoord s)
{
Vector3 v;
float sin_phi = sinf(s.phi);
v.x = s.r * cosf(s.theta) * sin_phi;
v.y = s.r * cosf(s.phi);
v.z = s.r * sinf(s.theta) * sin_phi;
return v;
}
typedef struct virtual_output { typedef struct virtual_output {
struct wl_global *global; struct wl_global *global;
struct wl_display *display; struct wl_display *display;
@@ -65,6 +93,16 @@ typedef struct {
struct wl_listener destroy; struct wl_listener destroy;
} LunarWM_Keyboard; } LunarWM_Keyboard;
typedef struct {
struct LunarWM *server;
struct wl_list link;
struct wlr_pointer *wlr_pointer;
struct wl_listener motion;
struct wl_listener destroy;
} LunarWM_Pointer;
typedef struct { typedef struct {
uint32_t id; uint32_t id;
@@ -91,6 +129,11 @@ typedef struct {
Texture2D rl_texture; Texture2D rl_texture;
} LunarWM_Toplevel; } LunarWM_Toplevel;
typedef struct {
LunarWM_Toplevel *tl;
SphericalCoord coord;
} LunarWM_Window;
bool LunarWM_Toplevel_init_xdg( bool LunarWM_Toplevel_init_xdg(
LunarWM_Toplevel *tl, struct LunarWM *wm, struct wlr_xdg_toplevel *xdg); LunarWM_Toplevel *tl, struct LunarWM *wm, struct wlr_xdg_toplevel *xdg);
bool LunarWM_Toplevel_init_xwayland( bool LunarWM_Toplevel_init_xwayland(
@@ -148,14 +191,13 @@ typedef struct LunarWM {
struct wlr_seat *seat; struct wlr_seat *seat;
struct wl_list keyboards; struct wl_list keyboards;
struct wl_list pointers;
struct wl_listener new_input_listener; struct wl_listener new_input_listener;
struct wlr_xdg_shell *xdg_shell; struct wlr_xdg_shell *xdg_shell;
struct wl_listener new_xdg_toplevel_listener; struct wl_listener new_xdg_toplevel_listener;
struct wl_listener new_xdg_popup_listener; struct wl_listener new_xdg_popup_listener;
struct wlr_cursor *cursor;
struct wlr_xwayland *xwayland; struct wlr_xwayland *xwayland;
struct wl_listener xwayland_ready; struct wl_listener xwayland_ready;
@@ -212,8 +254,18 @@ typedef struct LunarWM {
bool first_frame; bool first_frame;
} renderer; } renderer;
struct {
SphericalCoord pointer;
int active_workspace;
struct {
LunarWM_Window *v_windows;
} workspaces[10];
} wm;
ConfigManager *cman; ConfigManager *cman;
_Atomic(int) counter;
bool initialized; bool initialized;
bool running; bool running;
} LunarWM; } LunarWM;
@@ -224,6 +276,8 @@ void LunarWM_destroy(LunarWM *this);
void LunarWM_terminate(LunarWM *this); void LunarWM_terminate(LunarWM *this);
void LunarWM_run(LunarWM *this); void LunarWM_run(LunarWM *this);
static inline bool LunarWM_get_new_id(LunarWM *this) { return ++this->counter; }
extern LunarWM g_wm; extern LunarWM g_wm;
#endif // LUNAR_WM_H #endif // LUNAR_WM_H