Skip to content

Selene Browser

kazah-png edited this page Aug 1, 2026 · 5 revisions

Selene — the NyxOS web browser

Selene is a web browser written as a kernel window (kernel/gui/apps/selene_win.c). It fetches real pages over HTTP and HTTPS, parses the HTML itself, lays it out as text with headings, lists, tables and inline images, and lets you follow links, submit forms, search the page, and keep several tabs open.

It is named after the moon, like the rest of NyxOS.

See also: Cryptography-and-TLS, Networking-Stack, Image-Decoders, GUI-Subsystem, Desktop-Applications

Opening it

  • Click the Selene desktop icon
  • Or run selene from the shell

The window has a toolbar (back button and URL box), a tab strip, the page view, and a status line.

What it does

Capability Detail
HTTP http_get(), which drives the network itself and runs DHCP first if there is no lease
HTTPS Full TLS 1.2 with certificate verification — see Cryptography-and-TLS
Streaming receive Pages larger than the record buffer load correctly
Redirects Follows 301/302/303/307/308 (Location:), ≤ 5 hops, absolute or relative
Links <a href> rendered coloured and underlined; relative and root-relative hrefs resolved against the current page
History 32-deep Back stack per tab
Tabs Up to 6 per window, with a [+] new-tab button
Forms GET and POST, application/x-www-form-urlencoded
Tables <table> with aligned, bordered columns, colspan/rowspan, and nested tables
Lists <ul> bullets and <ol> numbered, nested and indented per level
Block formatting <pre> (whitespace preserved) and <blockquote> (indented per level)
Entities ~30 named and numeric HTML entities decoded to readable text
Images PNG, BMP, GIF (static and animated, loop-count honoured) and baseline JPEG, fetched, decoded and drawn inline
Find in page Ctrl+F, with match counting and navigation
Text structure Headings, paragraphs, lists and horizontal rules

Controls

Input Action
Type in the URL box, Enter Load the URL
Tab / Shift+Tab Move the selection between links and form fields
Enter Follow the selected link, submit the focused form, or load the URL bar if nothing is selected
Click Follow the link, or focus the field, under the cursor
Backspace Go back
Ctrl+F Open the find bar; type a query, and matches are counted and highlighted
Scroll / arrows Move through the page

Tab order runs through the URL bar, then the page's links and fields by position, then back to the URL bar — so a search box a few tabs into a page is reachable without the mouse.

Rendering

Selene is a text-layout browser, not a CSS engine. HTML is parsed directly:

  • <script> and <style> contents are dropped
  • Tags are stripped, entities decoded, <title> extracted for the tab label
  • Block elements (<h1><h6>, <p>, <hr>) produce structure — headings stand out, rules are drawn
  • Text is word-wrapped to 86 columns
  • <img> renders as a framed box; once the image is fetched and decoded, the picture is drawn in place. An image that cannot be fetched or decoded keeps its box, showing the alt text or the filename

HTML element support

Element Rendering
<h1><h6> Emphasised headings (upper-cased)
<p>, <hr> Paragraph break, horizontal rule
<a href> Coloured, underlined, keyboard- and click-navigable; an in-page anchor href="#"/href="#section" is a real clickable link (v5.9.185)
<ul> / <ol> / <li> Bulleted (-) or numbered (1. 2. 3.), nested and indented 2 spaces per level, up to 8 deep
<table> / <tr> / <td> / <th> Aligned bordered columns; colspan/rowspan via an occupancy grid. Cells now carry full inline styling — coloured/bold/code/mark text (v5.9.182), clickable links (v5.9.183), word-wrapped multi-line content that grows the row (v5.9.184), and hard breaks from <br> or a block boundary (v5.9.186). <th> renders bold by default (v5.9.202)
nested <table> Rendered one row per line inside its cell (v5.9.187), with its own inner cells styled (v5.9.188), instead of the old flattened [ a b / c d ]
<div> / <fieldset> (bordered) A border: declaration draws a real border box (v5.9.189), stroked in the CSS border colour (v5.9.190) and filled with a subtle background tint (v5.9.193–194). <fieldset> renders as a card with its <legend> as a bold heading (v5.9.192, v5.9.195); a bordered box inside a table cell is boxed too (v5.9.191)
<main> / <aside> / <address> Recognised as HTML5 blocks (v5.9.196); <address> renders italic
<dialog> A <dialog> without the open attribute is display:none by default (v5.9.197)
<pre> Whitespace preserved literally — interior runs of spaces kept, \n a real break, tab → 4 spaces
<blockquote> Every line (hard break or soft wrap) indented 4 spaces per nesting level
<img> Framed box then inline picture — see Image-Decoders. A broken/undecoded image keeps its [img: …] placeholder (v5.9.203)
<form>, <input>, <button>, <textarea> GET/POST forms — see below. <button> draws as a filled pill honouring its own CSS background/text colour (v5.9.181); <textarea> is a multi-line editable field box (v5.9.204)

Entities

decode_entity is table-driven and can emit a multi-character string, so &mdash;--, &hellip;..., &copy;(c), &reg;(r), &trade;(tm), curly quotes → straight, &laquo;/&raquo;<</>>, &frac12;1/2, &euro;EUR, and &deg;° (the one real glyph — the 256-glyph CP437 VGA font). Numeric &#nn;/&#xhh; resolve through the same table by code point. An entity not in the table renders literally. Entities are also decoded in the page <title> (v5.9.205), so a title like Q&amp;A shows as Q&A in the tab label.

Inline CSS on flow text extends past colour and weight: font-style:italic (and oblique) render slanted (v5.9.198), and vertical-align:super/sub raise or lower a run (v5.9.199).

Note

Because the font is a single-byte VGA set, most symbols are ASCII approximations; only ° has a true glyph. This is a deliberate scope limit, not a bug.

Honest scope

Deep (3rd-level) nested tables collapse to a literal [..]; table horizontal rules stay full-width across a span boundary; a table or list inside a <blockquote> is not margin-shifted (only flowing text and links carry the indent); <ol> numbering is always decimal from 1 (no type=/start=); <pre> tabs are a flat 4 spaces, and very long <pre> lines still soft-wrap (no horizontal scroll).

Images

Fetching every image on a page would make a page load feel broken, so loading is lazy and progressive: the text renders immediately and only the images you can actually see are downloaded, decoding into place as they arrive.

Limit Value
<img> elements tracked per page 128
Images fetched and decoded per page load 8
Per-image download buffer 512 KB

Decoding is handled by Image-Decoders. Selene dispatches on the magic bytes: 89 50 4E 47 to PNG, 42 4D to BMP, GIF8 to GIF, FF D8 to JPEG. Because every decoder yields the same image_t, a new format is one else if in that dispatch.

Loading is also cooperative: Selene fetches at most one image per compositor frame, so an image-heavy page never freezes the UI. Animated GIFs play from the same per-frame tick.

Forms

<form action="/search" method="get">
  <input type="text" name="q">
  <input type="submit" value="Go">
</form>
Control kind Handling
text, search, email, url, password, tel, number Editable box, 22 columns wide
submit, <button> Submit button
hidden Carried into the submission, not shown

GET builds a query string onto the action URL; POST sends the encoded body with a Content-Length through tls_https_request(). formtest (14 cases) is the kernel-shell self-test for the whole render/form path — parsing, URL building, entities, tables, lists, <pre>/<blockquote>, and redirect-Location extraction.

Redirects

A 3xx response carrying a Location: header is followed automatically, up to 5 hops. The target is resolved against the current URL (so absolute, root-relative and relative Locations all work) and the URL bar updates to the final address at each hop. Method handling follows browsers: 301/302/303 downgrade to GET (body dropped); 307/308 keep the method and body. Past 5 hops Selene renders the last 3xx response as-is.

Note

Selene also retries a hop once: NyxOS's first brand-new TCP connection right after another fetch occasionally fails, and a redirect chain opens several back-to-back, so the retry keeps the last hop from spuriously failing.

Limits

Setting Value
Rendered lines per page 1200
Line width 96 columns (wrapped at 86)
Links per page 240
Forms / fields per page 16 / 64
Tabs per window 6
Back history per tab 32

Beyond those: no JavaScript, no CSS, no video or audio, no cookies, no persistent cache.

History

Selene first fetched and rendered a real page in v5.9.44. Links and Back followed in v5.9.45, document structure in v5.9.47. HTTPS arrived in v5.9.56 on top of the TLS arc, then forms (v5.9.68v5.9.69), find-in-page (v5.9.75), image placeholders (v5.9.76), tables (v5.9.77), tabs (v5.9.78), real inline images (v5.9.83v5.9.86), cooperative loading and animated GIF (v5.9.87v5.9.88), and JPEG photos (v5.9.89v5.9.91). The final render-polish arc before the maintenance pass added HTML entities (v5.9.94), redirect following (v5.9.95), colspan/rowspan (v5.9.96), nested tables (v5.9.97), ordered and nested lists (v5.9.98), and <pre>/<blockquote> (v5.9.99). From v5.9.100 a long, steady render-fidelity arc followed — the CSS colour parser grew to ~90 named colours, the table-alignment cascade (cell > row > column), <details>/<summary>, <progress>/<meter>, checkbox/radio glyphs, hundreds more HTML entities, and then (v5.9.181v5.9.205) styled buttons, fully-styled and multi-line table cells, nested-table rendering, <div>/<fieldset> border boxes, HTML5 <main>/<aside>/<dialog>, font-style/vertical-align, and <textarea>. Two security fixes landed in the middle of it — a chunked-transfer heap overflow and a DNS-encoder stack overflow (v5.9.200v5.9.201, see Security). See Version-History.

See also

External resources

Clone this wiki locally