Phase 4: SkyKit library + Rigel file manager; fix text centering

SkyKit (skykit/):
- Shared palette constants, font setup, and Xlib/Xft drawing utilities
- sk_fill, sk_rect, sk_line, sk_text, sk_text_clip, sk_textw, sk_baseline
- Builds as libskykit.a, consumed by Rigel and future shell components

Rigel (rigel/):
- Native C/Xlib file manager with SkyKit
- Sidebar with 8 bookmarks (Home, Desktop, Documents, Downloads, etc.)
- Editable path bar (Ctrl+L or '/' to activate, Enter to navigate)
- Sortable columns: Name / Size / Modified (click header to sort/reverse)
- Colored type badges: DIR, IMG, SND, VID, ZIP, SRC, PDF, TXT, EXE
- Double-click to open dirs or files (xdg-open)
- Keyboard: ↑↓ select, Enter open, Backspace back, Ctrl+H toggle hidden
- Right-click menu updated: "File Manager" now launches rigel

Text centering fix (deskbar + wm):
- Root cause: draw_str added glyph-specific ext.height/ext.y offset, and
  all callers used hardcoded (H-10)/2 magic numbers instead of font metrics
- Fix: draw_str now takes y as a direct baseline; str_baseline() computes
  (strip_y + strip_h + ascent - descent) / 2 for consistent centering
- WM titlebar: same fix using font_title->ascent/descent
- Affects: "Orion ▾" button, clock, date, app list, flyout menu items,
  letter icons, and all window titlebars

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 4.6 committed 2026-07-23 15:40:03 -04:00
1 parent e3bc761f25
commit 1340bf012c
11 files changed
+1113 -18

No files matched your search

+14 -11
View File
@@ -291,6 +291,7 @@ static int read_mem_percent(void) {
/* ── drawing ──────────────────────────────────────────────────────────── */
/* y = baseline; clip_x/clip_w are optional horizontal clip region */
static void draw_str(Deskbar *db, XftDraw *xd, XftFont *font,
unsigned long rgb, int x, int y,
const char *str, int clip_x, int clip_w) {
@@ -302,14 +303,16 @@ static void draw_str(Deskbar *db, XftDraw *xd, XftFont *font,
(unsigned short)db->bar_h };
XftDrawSetClipRectangles(xd, 0, 0, &r, 1);
}
XGlyphInfo ext;
XftTextExtentsUtf8(db->dpy, font, (const FcChar8 *)str, strlen(str), &ext);
XftDrawStringUtf8(xd, &col, font, x, y + ext.height - ext.y,
(const FcChar8 *)str, strlen(str));
XftDrawStringUtf8(xd, &col, font, x, y, (const FcChar8 *)str, strlen(str));
if (clip_w > 0) XftDrawSetClip(xd, None);
XftColorFree(db->dpy, db->visual, db->cmap, &col);
}
/* Compute baseline that visually centers text in a strip */
static int str_baseline(XftFont *font, int strip_y, int strip_h) {
return strip_y + (strip_h + font->ascent - font->descent) / 2;
}
static void draw_str_centered(Deskbar *db, XftDraw *xd, XftFont *font,
unsigned long rgb,
int strip_x, int strip_y, int strip_w, int strip_h,
@@ -317,7 +320,7 @@ static void draw_str_centered(Deskbar *db, XftDraw *xd, XftFont *font,
XGlyphInfo ext;
XftTextExtentsUtf8(db->dpy, font, (const FcChar8 *)str, strlen(str), &ext);
int tx = strip_x + (strip_w - (int)ext.width) / 2;
int ty = strip_y + (strip_h - (int)ext.height) / 2;
int ty = str_baseline(font, strip_y, strip_h);
draw_str(db, xd, font, rgb, tx, ty, str, 0, 0);
}
@@ -343,8 +346,8 @@ static void draw_letter_icon(Deskbar *db, XftDraw *xd,
unsigned long txt_col = mini ? DB_COL_ITEM_MINI : DB_COL_ITEM_HTXT;
XGlyphInfo ext;
XftTextExtentsUtf8(db->dpy, db->font_icon, (const FcChar8 *)letter, 1, &ext);
int lx = ix + (DB_ICON_SZ - ext.width) / 2;
int ly = iy + (DB_ICON_SZ - ext.height) / 2;
int lx = ix + (DB_ICON_SZ - (int)ext.width) / 2;
int ly = str_baseline(db->font_icon, iy, DB_ICON_SZ);
draw_str(db, xd, db->font_icon, txt_col, lx, ly, letter, 0, 0);
}
@@ -427,7 +430,7 @@ void db_draw(Deskbar *db) {
/* app name */
int name_x = icon_x + DB_ICON_SZ + 6;
int name_maxw = DB_W - name_x - 14;
int name_y = iy + (DB_ITEM_H - 10) / 2;
int name_y = str_baseline(db->font_ui, iy, DB_ITEM_H);
unsigned long tc = (hover || focus) ? DB_COL_ITEM_HTXT
: mini ? DB_COL_ITEM_MINI
@@ -636,7 +639,7 @@ static void menu_draw_panel(Deskbar *db, Window win, int is_sub,
}
unsigned long tc = (i == hov) ? DB_COL_ITEM_HTXT : DB_COL_ITEM_TEXT;
draw_str(db, xd, db->font_ui, tc,
DB_FLYOUT_LPD, iy + (DB_FLYOUT_IH - 10) / 2,
DB_FLYOUT_LPD, str_baseline(db->font_ui, iy, DB_FLYOUT_IH),
lbls[i], 0, 0);
}
} else {
@@ -654,13 +657,13 @@ static void menu_draw_panel(Deskbar *db, Window win, int is_sub,
}
unsigned long tc = (i == hov) ? DB_COL_ITEM_HTXT : DB_COL_ITEM_TEXT;
draw_str(db, xd, db->font_ui, tc,
DB_FLYOUT_LPD, iy + (DB_FLYOUT_IH - 10) / 2,
DB_FLYOUT_LPD, str_baseline(db->font_ui, iy, DB_FLYOUT_IH),
MENU[i].lbl, 0, 0);
if (MENU[i].has_sub) {
unsigned long ac = (i == hov) ? DB_COL_ITEM_HTXT : 0x30486A;
/* ▶ U+25B6 */
draw_str(db, xd, db->font_ui, ac,
ww - 15, iy + (DB_FLYOUT_IH - 10) / 2,
ww - 15, str_baseline(db->font_ui, iy, DB_FLYOUT_IH),
"\xe2\x96\xb6", 0, 0);
}
}