Citadel Desktop Shell

Citadel is the desktop shell library for Aegis. It provides the top bar, application dock, and theme system that compose the desktop environment rendered by the Lumen compositor. Citadel also encompasses the Bastion display manager, which handles graphical login, session spawning, and screen locking.

v1 note: Citadel and Bastion are v1 software – functional and tested, but still evolving. Contributions are welcome – file issues or propose changes at exec/aegis.

 Citadel desktop shell components:
 +-------------------------------------------------------+
 | Top bar (taskbar.c)                    clock          |
 |  [*] Aegis                            HH:MM           |
 +-------------------------------------------------------+
 |                                                       |
 |          Desktop area (wallpaper + windows)           |
 |                                                       |
 |                                                       |
 +-------------------------------------------------------+
 |        +--[dock.c: frosted glass dock]--+             |
 |        | [gear] [folder] [>_] [grid]   |              |
 |        +-------------------------------+              |
 +-------------------------------------------------------+

Architecture

Citadel compiles to libcitadel.a, a static library linked by Lumen. It consists of two source files (dock.c, taskbar.c) and a theme header (theme.h). Citadel depends on libglyph.a for drawing primitives and font rendering.

SRCS = dock.c taskbar.c
OBJS = $(SRCS:.c=.o)

libcitadel.a: $(OBJS)
    ar rcs $@ $^

Lumen integrates Citadel via two compositor callbacks:

comp.on_draw_desktop = desktop_draw_cb;  /* draws top bar */
comp.on_draw_overlay = overlay_draw_cb;  /* draws dock + context menu */

The desktop callback runs after the background fill but before window rendering, placing the top bar beneath all windows. The overlay callback runs after window rendering but before the framebuffer flip, placing the dock and context menu above all windows.

Top Bar (taskbar.c)

The top bar is a frosted glass strip at the top of the screen.

Rendering

void topbar_draw(surface_t *s, int screen_w, const char *clock_str);

The rendering pipeline:

  1. Box blur the top TOPBAR_HEIGHT (28px) of the backbuffer at radius 8
  2. Dark tint via draw_blend_rect with TOPBAR_BG (0x001A1A2E) at alpha 128
  3. Bottom border: 1px white blend at alpha 20 for definition
  4. Accent dot: 4px filled circle at x=14 in C_ACCENT blue
  5. “Aegis” text: white, positioned at x=24 (TTF at 14px or bitmap fallback)
  6. Clock text: right-aligned with 12px margin, TOPBAR_TEXT color (0x00C0C0D0)

The clock string is passed in from Lumen’s main loop, which updates it approximately once per second by checking clock_gettime(CLOCK_REALTIME) every 60 frames.

Hit Testing

int topbar_hit_aegis(int mx, int my, int screen_w);

Returns true if the click is within the “Aegis” clickable area: x < AEGIS_AREA_W (80px) and y < TOPBAR_HEIGHT (28px). Clicking this area opens the system context menu.

Theme Constants

Defined in theme.h:

Constant Value Purpose
TOPBAR_HEIGHT 28 Top bar height in pixels
TOPBAR_BG 0x001A1A2E Top bar tint color
TOPBAR_TEXT 0x00C0C0D0 Top bar text color (clock, etc.)
AEGIS_AREA_W 80 Width of the clickable “Aegis” text area
DESKTOP_BG 0x001A1A2E Desktop background (when no wallpaper)

Application Dock (dock.c)

The dock is a centered, frosted-glass panel at the bottom of the screen containing application launcher icons.

Layout

 Dock geometry:
 +-------------------------------------------+
 |  24px  | icon | 12px | icon | ... | 24px  |
 |  pad   | 48px | gap  | 48px |     | pad   |
 +-------------------------------------------+
       ^                                  ^
       DOCK_PADDING_X                     DOCK_PADDING_X

 DOCK_HEIGHT = DOCK_ICON_SIZE + 2 * DOCK_PADDING_Y = 48 + 32 = 80

Layout constants:

Constant Value
DOCK_ICON_SIZE 48 pixels
DOCK_ICON_GAP 12 pixels
DOCK_PADDING_X 24 pixels
DOCK_PADDING_Y 16 pixels
DOCK_HEIGHT 80 pixels
DOCK_CORNER_R 16 pixels
DOCK_BOTTOM_MARGIN 10 pixels

The dock is horizontally centered: dock_x = (screen_w - dock_w) / 2. Vertically it sits DOCK_BOTTOM_MARGIN above the screen bottom.

Dock Items

Four items are defined:

Index Constant Key Icon Action
0 DOCK_ITEM_SETTINGS "settings" Gear (circles + rectangles) Stub (no action)
1 DOCK_ITEM_FILES "files" Folder (rounded rects) Stub (no action)
2 DOCK_ITEM_TERMINAL "terminal" Terminal (dark rect + “>_”) Spawns terminal window
3 DOCK_ITEM_WIDGETS "widgets" 2x2 colored grid Opens widget test window

Frosted Glass Rendering

The dock’s frosted glass is rendered in dock_draw:

 Dock frosted glass pipeline:
 +--------------------------------------------+
 | 1. draw_box_blur(back, x, y, w, h, 10)     |
 |    Blur the dock region in-place           |
 +--------------------------------------------+
 | 2. draw_blend_rect(x, y, w, h,             |
 |      DOCK_GLASS_TINT=0x1A1A2E, alpha=160)  |
 |    Dark translucent tint                   |
 +--------------------------------------------+
 | 3. Round corner masking                    |
 |    Pixels outside rounded rect restored    |
 |    by sampling 1px above dock              |
 +--------------------------------------------+
 | 4. Subtle border (top: white a=20,         |
 |    bottom: black a=40)                     |
 +--------------------------------------------+
 | 5. Draw icons with hover highlight         |
 |    Hover: white blend a=40 on icon area    |
 +--------------------------------------------+

The corner masking approximation samples the background color from one pixel above the dock. This avoids needing a saved pre-blur copy of the background.

Icon Rendering

Each dock icon is drawn programmatically (no image assets):

  • Settings (gear): Filled accent circle (r=18) with 8 rectangular teeth + hollow center
  • Files (folder): Two overlapping rounded rectangles in amber/brown
  • Terminal: Dark rounded rectangle with “>_” text in terminal foreground color
  • Widgets: Four small colored rounded rectangles arranged as a 2x2 grid (blue, green, orange, purple)

Hit Testing

int dock_hit_test(int mx, int my);  /* returns item index or -1 */

First checks if the point is within the dock bounds, then iterates items checking DOCK_ICON_SIZE x DOCK_ICON_SIZE bounding boxes.

Hover State

void dock_set_hover(int item);  /* -1 for no hover */

The hover item index is tracked as static state. When the hover changes, Lumen marks the dock region as a dirty rect. The hovered icon receives a DOCK_HOVER_BG (white) blend at DOCK_HOVER_ALPHA (40).

Context Menu

The system context menu is drawn by Lumen’s main.c (not Citadel) but uses Citadel’s theme colors. It opens when clicking the “Aegis” text in the top bar.

Index Label Action
0 “About Aegis” Opens the About window
1 “Settings…” Stub (no action)
2 “Lock Screen” Freezes input, signals Bastion
3 ”—” Separator
4 “Restart” syscall(169, 1) – system reboot
5 “Power Off” kill(1, SIGTERM) – signal init

The context menu uses the same frosted glass technique as the dock:

  1. Box blur at radius 10
  2. Dark tint (MENU_BG = 0x00222238, alpha 180)
  3. Rounded corner masking (radius 8)
  4. Subtle border highlights
  5. Items with hover highlight (MENU_HOVER_BG = 0x003A3A58, alpha 100)
  6. Separator rendered as a 1px line at alpha 120

Menu geometry: 160px wide, positioned at (4, TOPBAR_HEIGHT), item height 28px, separator height 10px, 8px top/bottom padding.

Bastion Display Manager

Bastion (user/bin/bastion/main.c) is the graphical login manager. It runs as a Vigil service with policy capabilities AUTH, FB, and SETUID granted via /etc/aegis/caps.d/ entries in the security policy engine.

Boot Flow

 Bastion lifecycle:
 +---------------------------+
 | Check /proc/cmdline for   |
 | "boot=graphical"          |
 | (or --force flag)         |
 +---------------------------+
          |
          v
 +---------------------------+
 | Map framebuffer (513)     |
 | Alloc backbuffer          |
 | Load logo, init fonts     |
 +---------------------------+
          |
          v
 +---------------------------+
 | Show greeter form         |
 | (username + password +    |
 |  login button)            |
 +---------------------------+
          |  (credentials)
          v
 +---------------------------+
 | auth_check() via libauth  |
 | auth_elevate_session()    |
 | auth_set_identity(uid,gid)|
 | auth_grant_shell_caps()   |
 +---------------------------+
          |
          v
 +---------------------------+
 | fork() + execve()         |
 | -> /bin/lumen             |
 +---------------------------+
          |
          v
 +---------------------------+
 | waitpid() for Lumen       |
 | Handle SIGUSR1 (lock)     |
 +---------------------------+

Login Form

The login form uses a horizontal layout: [username field] [password field] [Login button], centered at 75% screen height. The Aegis logo is displayed centered at the middle of the screen, loaded from /usr/share/logo.raw and rendered at 50% scale.

Network status is displayed in the top-left corner by querying SYS_NETCFG (syscall 500), showing IP address and MAC if available.

Session Spawn

Bastion uses fork+execve rather than sys_spawn to give Lumen an independent file descriptor table. Before execve, the child process:

  1. Calls auth_grant_shell_caps() to populate the child’s capability table with the appropriate capability kinds for shell use
  2. Sets environment variables (PATH, HOME, USER, TERM)
  3. Executes /bin/lumen

Lock Screen Protocol

  1. Lumen receives Ctrl+Alt+L or the “Lock Screen” menu item
  2. Lumen sets s_input_frozen = 1, sends SIGUSR1 to Bastion (parent)
  3. Bastion’s SIGUSR1 handler sets s_locked = 1
  4. Bastion re-enters its input loop, displaying the lock form (password only, username pre-filled)
  5. On successful re-authentication, Bastion sends SIGUSR2 to Lumen
  6. Lumen’s SIGUSR2 handler clears s_input_frozen, resuming normal operation

During lock, Bastion draws over the framebuffer directly. Lumen continues compositing in the background but discards all keyboard input.

Session Restart

When Lumen exits (process terminates), Bastion reopens /dev/kbd and /dev/mouse, restores raw terminal mode, and returns to the greeter loop. This provides automatic session recovery.

Crossfade Transitions

Both Bastion and Lumen implement pixel-by-pixel crossfade transitions:

  • Bastion -> Lumen: Lumen captures the framebuffer (Bastion’s login screen), composites the desktop, then fades from the old frame to the new over 15 steps (250ms)
  • Text console -> Bastion: Bastion captures whatever was on screen, draws the login form, then fades between them

The crossfade formula for each pixel:

result = (old_pixel * alpha + new_pixel * (255 - alpha)) / 255;

Where alpha decreases from 255 to 0 across the transition steps.

Component Relationship

 +-----------------------------------------------+
 |  Vigil (init)                                 |
 |    spawns Bastion as a graphical service      |
 +-----------------------------------------------+
          |
          v
 +-----------------------------------------------+
 |  Bastion (display manager)                    |
 |    user/bin/bastion/main.c                    |
 |    Links: libglyph.a (drawing + fonts)        |
 |    Policy capabilities: AUTH, FB, SETUID      |
 +-----------------------------------------------+
          |  fork+execve on login
          v
 +-----------------------------------------------+
 |  Lumen (compositor)                           |
 |    user/bin/lumen/                            |
 |    Links: libglyph.a + libcitadel.a           |
 |    Baseline capabilities (FB inherited)       |
 +-----------------------------------------------+
          |  uses
          v
 +-----------------------------------------------+
 |  libcitadel.a (desktop shell)                 |
 |    user/lib/citadel/                          |
 |    dock.c -- frosted glass dock               |
 |    taskbar.c -- top bar with clock            |
 |    theme.h -- shared visual constants         |
 +-----------------------------------------------+
          |  depends on
          v
 +-----------------------------------------------+
 |  libglyph.a (widget toolkit)                  |
 |    user/lib/glyph/                            |
 |    Drawing primitives, font rendering,        |
 |    widget tree, window management             |
 +-----------------------------------------------+

Source Files

File Path Purpose
dock.c user/lib/citadel/ Application dock: layout, frosted glass, icons, hit testing
dock.h user/lib/citadel/ Dock API, geometry constants, item definitions
taskbar.c user/lib/citadel/ Top bar: frosted glass, “Aegis” text, clock
taskbar.h user/lib/citadel/ Top bar API declarations
theme.h user/lib/citadel/ Shared theme constants (colors, dimensions)
Makefile user/lib/citadel/ Builds libcitadel.a
main.c user/bin/bastion/ Display manager: login, session spawn, lock screen
Makefile user/bin/bastion/ Builds bastion.elf