This page provides an overview of the HTML-specific subsystems implemented in Libraries/LibWeb/HTML/ and related directories. It covers the navigable/browsing-context model, session history, the event handler, form controls, and the rich text editing API. For the detailed treatment of each subsystem, see the child pages:
The HTML specification defines two related concepts that Ladybird tracks separately.
| Concept | Class | File |
|---|---|---|
| Navigable | Navigable | Libraries/LibWeb/HTML/Navigable.h |
| Top-level traversable navigable | TraversableNavigable | Libraries/LibWeb/HTML/TraversableNavigable.h |
| Legacy browsing context | BrowsingContext | Libraries/LibWeb/HTML/BrowsingContext.h |
| Browsing context group | BrowsingContextGroup | Libraries/LibWeb/HTML/BrowsingContextGroup.h |
| Session history entry | SessionHistoryEntry | Libraries/LibWeb/HTML/SessionHistoryEntry.h |
| Document state | DocumentState | Libraries/LibWeb/HTML/DocumentState.h |
A Navigable is a GC-managed JS::Cell that represents a slot in the document sequence — either a top-level tab/window or an embedded frame. Every navigable holds:
SessionHistoryEntry), which in turn point to a DocumentState and ultimately to a DOM::Document.Navigable (or null for top-level).EventHandler instance for input processing.BackingStoreManager and a RenderingThread for GPU-accelerated compositing.TraversableNavigable extends Navigable to add the ordered list of SessionHistoryEntry objects that form the tab's history stack, plus a SessionHistoryTraversalQueue used to sequence asynchronous history traversals.
Navigable hierarchy diagram
Sources: Libraries/LibWeb/HTML/Navigable.h44-295 Libraries/LibWeb/HTML/TraversableNavigable.h1-100 Libraries/LibWeb/HTML/Navigable.cpp118-430
Each navigable exposes a chain of accessors to reach the currently displayed content:
Navigable::active_document()
└── m_active_session_history_entry->document()
Navigable::active_browsing_context()
└── active_document()->browsing_context()
Navigable::active_window_proxy()
└── active_browsing_context()->window_proxy()
Navigable::active_window()
└── active_window_proxy()->window()
The global set of all live navigables is maintained in all_navigables() (Libraries/LibWeb/HTML/Navigable.cpp118-122), a HashTable<GC::RawRef<Navigable>>. This allows looking up a navigable by its active document via Navigable::navigable_with_active_document().
Sources: Libraries/LibWeb/HTML/Navigable.cpp343-376 Libraries/LibWeb/HTML/Navigable.cpp259-266
The Navigable::navigate() method (Libraries/LibWeb/HTML/Navigable.h154) accepts a NavigateParams struct describing the target URL, source document, POST body, history handling behavior, and user-involvement level. Navigation proceeds through the following phases:
Navigation flow diagram
Sources: Libraries/LibWeb/HTML/Navigable.cpp805-900 Libraries/LibWeb/HTML/Navigable.h136-154
When a link or script targets a named frame (target="_blank", target="myframe", etc.), Navigable::choose_a_navigable() (Libraries/LibWeb/HTML/Navigable.cpp464-603) resolves the target. It handles the standard keyword targets (_self, _parent, _top, _blank) and calls find_a_navigable_by_target_name() for named targets. If no match is found, it requests a new top-level traversable from the page client via page_did_request_new_web_view().
The return type is ChosenNavigable, a struct holding the resolved GC::Ptr<Navigable> and a WindowType enum (ExistingOrNone, NewAndUnrestricted, NewWithNoOpener).
Sources: Libraries/LibWeb/HTML/Navigable.cpp464-603 Libraries/LibWeb/HTML/Navigable.h106-111
Each Navigable owns a RenderingThread (Libraries/LibWeb/HTML/RenderingThread.h) and a BackingStoreManager. The rendering thread is responsible for executing DisplayList objects on a Skia backend (CPU or GPU) independently of the main browser thread.
| Component | Role |
|---|---|
RenderingThread | Dedicated thread; executes DisplayList via DisplayListPlayerSkia |
BackingStoreManager | Allocates and swaps front/back PaintingSurface buffers |
SkiaBackendContext | GPU context (Metal on macOS, Vulkan on Linux) |
The GPU backend is initialized lazily in get_skia_backend_context() (Libraries/LibWeb/HTML/Navigable.cpp149-167). The Navigable constructor (Libraries/LibWeb/HTML/Navigable.cpp169-196) creates the DisplayListPlayerSkia and starts the rendering thread for non-SVG pages.
Rendering thread data flow
Sources: Libraries/LibWeb/HTML/RenderingThread.cpp1-200 Libraries/LibWeb/HTML/Navigable.cpp169-196
Each Navigable contains an EventHandler instance (Libraries/LibWeb/Page/EventHandler.h). The EventHandler receives raw input events from the platform layer and translates them into DOM events dispatched to the appropriate elements.
| Method | Dispatches |
|---|---|
handle_mousedown() | pointerdown, mousedown, selection start |
handle_mouseup() | pointerup, mouseup, click |
handle_mousemove() | pointermove, mousemove, hover, cursor update |
handle_mousewheel() | wheel, scroll |
handle_keydown() | keydown, keypress, text input |
handle_keyup() | keyup |
Hit-testing is performed by calling paint_root()->hit_test() on the active document's PaintableBox. The result provides both the Paintable and the DOM node for event dispatch.
Text selection is managed by apply_mouse_selection() (Libraries/LibWeb/Page/EventHandler.cpp424-521), which supports character, word, and paragraph selection modes depending on click count, and respects the CSS user-select property via set_user_selection().
Sources: Libraries/LibWeb/Page/EventHandler.h1-80 Libraries/LibWeb/Page/EventHandler.cpp535-560 Libraries/LibWeb/Page/EventHandler.cpp424-521
All interactive form elements participate in a shared infrastructure defined by FormAssociatedElement (Libraries/LibWeb/HTML/FormAssociatedElement.h), a mixin class that manages form owner association, constraint validation, and disabled state.
Form control class hierarchy
Sources: Libraries/LibWeb/HTML/FormAssociatedElement.h1-120 Libraries/LibWeb/HTML/HTMLInputElement.h54-260 Libraries/LibWeb/HTML/HTMLSelectElement.h22-100 Libraries/LibWeb/HTML/HTMLTextAreaElement.h1-80
HTMLInputElement implements all 22 type states defined by the HTML specification. The active type state is stored as TypeAttributeState m_type. Layout node creation (Libraries/LibWeb/HTML/HTMLInputElement.cpp123-164) dispatches on this state to produce different layout objects:
| Type state | Layout node |
|---|---|
Checkbox | Layout::CheckBox |
RadioButton | Layout::RadioButton |
Text, Email, Password, etc. | Layout::TextInputBox |
ImageButton | Layout::ImageBox |
SubmitButton, Button, ResetButton | Layout::BlockContainer |
Hidden | nullptr (no layout) |
When a picker is required (file, color), show_the_picker_if_applicable() (Libraries/LibWeb/HTML/HTMLInputElement.cpp378-448) verifies transient user activation and delegates to the Page client via did_request_file_picker() or did_request_color_picker().
Sources: Libraries/LibWeb/HTML/HTMLInputElement.cpp123-164 Libraries/LibWeb/HTML/HTMLInputElement.cpp378-478
HTMLSelectElement maintains a HTMLOptionsCollection (m_options) rooted at the <select> node. The list of options is lazily rebuilt via update_cached_list_of_options() (Libraries/LibWeb/HTML/HTMLSelectElement.cpp233-300) when the DOM changes, respecting nesting rules (nested <optgroup> elements are excluded from the flat options list).
Sources: Libraries/LibWeb/HTML/HTMLSelectElement.cpp133-230
The execCommand API is implemented across three files:
| File | Role |
|---|---|
Libraries/LibWeb/Editing/ExecCommand.cpp | Document::exec_command() dispatch |
Libraries/LibWeb/Editing/Commands.cpp | Per-command action/state/value functions |
Libraries/LibWeb/Editing/Internal/Algorithms.cpp | Shared editing algorithms |
Libraries/LibWeb/Editing/Commands.h | CommandDefinition registry struct |
ExecCommand dispatch flow
Each command is described by a CommandDefinition struct (Libraries/LibWeb/Editing/Commands.h17-33):
struct CommandDefinition {
FlyString const& command;
Function<bool(Document&, Utf16String const&)> action;
Function<bool(Document const&)> indeterminate;
Function<bool(Document const&)> state;
Function<Utf16String(Document const&)> value;
Optional<CSS::PropertyID> relevant_css_property;
bool preserves_overrides;
Vector<Utf16View> inline_activated_values;
FlyString mapped_value; // maps to InputEvent.inputType
};
Supported commands include bold, italic, underline, strikethrough, createLink, unlink, insertText, insertParagraph, insertLineBreak, insertOrderedList, insertUnorderedList, formatBlock, indent, outdent, justifyLeft/Right/Center/Full, foreColor, backColor, fontSize, fontName, delete, forwardDelete, selectAll, insertHTML, insertImage, removeFormat, subscript, superscript.
The core editing algorithms in Libraries/LibWeb/Editing/Internal/Algorithms.cpp include:
| Algorithm | Purpose |
|---|---|
canonicalize_whitespace() | Normalizes adjacent whitespace nodes around a boundary point |
delete_the_selection() | Removes selected content, merging surrounding blocks |
block_extend_a_range() | Expands a range to full block boundaries |
set_the_selections_value() | Applies a property value to all nodes in the selection |
force_the_value() | Wraps or unwraps inline elements to enforce a property |
justify_the_selection() | Applies text-align to block-level containers in selection |
Sources: Libraries/LibWeb/Editing/ExecCommand.cpp19-80 Libraries/LibWeb/Editing/Commands.h17-96 Libraries/LibWeb/Editing/Internal/Algorithms.h49-120
Session history is stored per traversable navigable as a Vector<GC::Ref<SessionHistoryEntry>>. Each entry holds:
URLDocumentState (which may hold a live GC::Ptr<DOM::Document> or a serialized state)int) used for back/forward navigationVector<NestedHistory>)Navigable::get_session_history_entries() (Libraries/LibWeb/HTML/Navigable.cpp672-708) traverses the traversable's flat history entries and their nested histories to find the entries relevant to a child navigable.
Navigable::get_the_target_history_entry(int target_step) (Libraries/LibWeb/HTML/Navigable.cpp296-314) selects the entry with the greatest step number ≤ target_step.
Sources: Libraries/LibWeb/HTML/Navigable.cpp672-708 Libraries/LibWeb/HTML/Navigable.cpp296-314
Sources: Libraries/LibWeb/HTML/Navigable.h44-295 Libraries/LibWeb/Page/EventHandler.h1-80 Libraries/LibWeb/HTML/FormAssociatedElement.h1-60 Libraries/LibWeb/Editing/ExecCommand.cpp1-80
Refresh this wiki