19
flake.lock
generated
19
flake.lock
generated
@@ -34,21 +34,6 @@
|
||||
"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": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
@@ -73,7 +58,9 @@
|
||||
},
|
||||
"wlroots-lunar": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1754816070,
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||
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 =
|
||||
|
||||
305
src/LunarWM.c
305
src/LunarWM.c
@@ -46,6 +46,16 @@
|
||||
|
||||
#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 *)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
LunarWM_Toplevel_destroy(tl);
|
||||
@@ -137,7 +165,7 @@ static void toplevel_unmap_notify(struct wl_listener *l, void *data)
|
||||
bool LunarWM_Toplevel_init_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->is_xwayland = false;
|
||||
tl->u.xdg = xdg;
|
||||
@@ -163,7 +191,7 @@ bool LunarWM_Toplevel_init_xdg(
|
||||
bool LunarWM_Toplevel_init_xwayland(
|
||||
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->is_xwayland = true;
|
||||
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)) {
|
||||
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 {
|
||||
free(tl);
|
||||
}
|
||||
@@ -323,6 +358,7 @@ static void handle_dissociate(struct wl_listener *ll, void *d)
|
||||
LunarWM_Toplevel *tl = wm2->wayland.v_toplevels[i];
|
||||
if (tl->is_xwayland && tl->u.xwl == x) {
|
||||
vector_remove(wm2->wayland.v_toplevels, i);
|
||||
remove_windows_for_tl(wm2, tl);
|
||||
LunarWM_Toplevel_destroy(tl);
|
||||
free(tl);
|
||||
break;
|
||||
@@ -484,6 +520,7 @@ static void xwl_on_destroy(struct wl_listener *ll, void *data)
|
||||
LunarWM_Toplevel *tl = wm->wayland.v_toplevels[i];
|
||||
if (tl->is_xwayland && tl->u.xwl == x) {
|
||||
vector_remove(wm->wayland.v_toplevels, i);
|
||||
remove_windows_for_tl(wm, tl);
|
||||
free(tl);
|
||||
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 *)
|
||||
{
|
||||
auto *kbd = wl_container_of(listener, (LunarWM_Keyboard *)(NULL), destroy);
|
||||
wl_list_remove(&kbd->modifiers.link);
|
||||
wl_list_remove(&kbd->key.link);
|
||||
auto *p = wl_container_of(listener, (LunarWM_Keyboard *)(NULL), destroy);
|
||||
wl_list_remove(&p->modifiers.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->link);
|
||||
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);
|
||||
} 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;
|
||||
@@ -808,6 +907,13 @@ static void new_xdg_toplevel_listener_notify(
|
||||
|
||||
if (LunarWM_Toplevel_init_xdg(tl, wm, xdg_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 {
|
||||
wlr_log(WLR_ERROR, "Failed to initialize Toplevel.");
|
||||
free(tl);
|
||||
@@ -1044,9 +1150,8 @@ static bool init_wayland(LunarWM *this)
|
||||
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.pointers);
|
||||
|
||||
this->wayland.new_input_listener.notify = new_input_listener_notify;
|
||||
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_trans = (Vector3) { 0, 0, 0 };
|
||||
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());
|
||||
@@ -2049,11 +2160,6 @@ static void cleanup_wayland(LunarWM *this)
|
||||
this->wayland.v_toplevels = NULL;
|
||||
}
|
||||
|
||||
if (this->wayland.cursor) {
|
||||
wlr_cursor_destroy(this->wayland.cursor);
|
||||
this->wayland.cursor = NULL;
|
||||
}
|
||||
|
||||
if (this->wayland.backend) {
|
||||
wlr_backend_destroy(this->wayland.backend);
|
||||
this->wayland.backend = NULL;
|
||||
@@ -2369,6 +2475,103 @@ void DrawTextureCyl(
|
||||
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)
|
||||
{
|
||||
if (!wm->xr.recenter_active)
|
||||
@@ -2384,6 +2587,17 @@ static inline Quaternion RecenterOrient(LunarWM *wm, Quaternion 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)
|
||||
{
|
||||
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++) {
|
||||
auto *tl = this->wayland.v_toplevels[i];
|
||||
if (!tl || !tl->surface)
|
||||
for (size_t i = 0; i
|
||||
< vector_size(this->wm.workspaces[this->wm.active_workspace].v_windows);
|
||||
i++) {
|
||||
auto *window
|
||||
= &this->wm.workspaces[this->wm.active_workspace].v_windows[i];
|
||||
auto *tl = window->tl;
|
||||
if (!tl || !tl->surface) {
|
||||
continue;
|
||||
if (tl->gles_texture && !tl->gles_texture->has_alpha) {
|
||||
float rad = this->cman->cfg.space.radius - 0.01f * (float)i;
|
||||
DrawTextureCyl(tl->rl_texture, (Vector3) { 0, 0, rad }, rad,
|
||||
}
|
||||
if (tl->gles_texture) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void render_3d(LunarWM *this, float /*dt*/)
|
||||
{
|
||||
render_windows(this, true);
|
||||
|
||||
for (int h = 0; h < 2; ++h) {
|
||||
auto *hand_info = &this->xr.hands[h];
|
||||
@@ -2444,15 +2671,35 @@ void render_3d(LunarWM *this, float /*dt*/)
|
||||
|
||||
rlEnableColorBlend();
|
||||
rlDisableDepthMask(); // don't write depth
|
||||
for (size_t i = 0; i < vector_size(this->wayland.v_toplevels); i++) {
|
||||
auto *tl = this->wayland.v_toplevels[i];
|
||||
if (!tl || !tl->surface)
|
||||
continue;
|
||||
if (tl->gles_texture && tl->gles_texture->has_alpha) {
|
||||
float rad = this->cman->cfg.space.radius - 0.01f * (float)i;
|
||||
DrawTextureCyl(tl->rl_texture, (Vector3) { 0, 0, rad }, rad,
|
||||
this->cman->cfg.space.window_scale, false);
|
||||
render_windows(this, false);
|
||||
// TODO: Replace with actual cursor texture.
|
||||
{ // Cursor
|
||||
Vector3 tip = SphericalToVector3(this->wm.pointer);
|
||||
|
||||
Vector3 n = Vector3Normalize(
|
||||
Vector3Subtract(this->renderer.camera.position, tip));
|
||||
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();
|
||||
|
||||
@@ -2714,6 +2961,8 @@ static bool render_layer(LunarWM *this, LunarWM_RenderLayerInfo *info, float dt)
|
||||
l_recenter(this->cman->L);
|
||||
lua_pop(this->cman->L, 1);
|
||||
this->renderer.first_frame = false;
|
||||
this->wm.pointer = get_forward_spherical_with_nearest(
|
||||
this->renderer.camera.target, this->cman->cfg.space.radius);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -37,6 +37,34 @@
|
||||
|
||||
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 {
|
||||
struct wl_global *global;
|
||||
struct wl_display *display;
|
||||
@@ -65,6 +93,16 @@ typedef struct {
|
||||
struct wl_listener destroy;
|
||||
} 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 {
|
||||
uint32_t id;
|
||||
|
||||
@@ -91,6 +129,11 @@ typedef struct {
|
||||
Texture2D rl_texture;
|
||||
} LunarWM_Toplevel;
|
||||
|
||||
typedef struct {
|
||||
LunarWM_Toplevel *tl;
|
||||
SphericalCoord coord;
|
||||
} LunarWM_Window;
|
||||
|
||||
bool LunarWM_Toplevel_init_xdg(
|
||||
LunarWM_Toplevel *tl, struct LunarWM *wm, struct wlr_xdg_toplevel *xdg);
|
||||
bool LunarWM_Toplevel_init_xwayland(
|
||||
@@ -148,14 +191,13 @@ typedef struct LunarWM {
|
||||
|
||||
struct wlr_seat *seat;
|
||||
struct wl_list keyboards;
|
||||
struct wl_list pointers;
|
||||
struct wl_listener new_input_listener;
|
||||
|
||||
struct wlr_xdg_shell *xdg_shell;
|
||||
struct wl_listener new_xdg_toplevel_listener;
|
||||
struct wl_listener new_xdg_popup_listener;
|
||||
|
||||
struct wlr_cursor *cursor;
|
||||
|
||||
struct wlr_xwayland *xwayland;
|
||||
|
||||
struct wl_listener xwayland_ready;
|
||||
@@ -212,8 +254,18 @@ typedef struct LunarWM {
|
||||
bool first_frame;
|
||||
} renderer;
|
||||
|
||||
struct {
|
||||
SphericalCoord pointer;
|
||||
int active_workspace;
|
||||
struct {
|
||||
LunarWM_Window *v_windows;
|
||||
} workspaces[10];
|
||||
} wm;
|
||||
|
||||
ConfigManager *cman;
|
||||
|
||||
_Atomic(int) counter;
|
||||
|
||||
bool initialized;
|
||||
bool running;
|
||||
} LunarWM;
|
||||
@@ -224,6 +276,8 @@ void LunarWM_destroy(LunarWM *this);
|
||||
void LunarWM_terminate(LunarWM *this);
|
||||
void LunarWM_run(LunarWM *this);
|
||||
|
||||
static inline bool LunarWM_get_new_id(LunarWM *this) { return ++this->counter; }
|
||||
|
||||
extern LunarWM g_wm;
|
||||
|
||||
#endif // LUNAR_WM_H
|
||||
|
||||
Reference in New Issue
Block a user