Azul GUI Framework
repository·master·Indexed 27 days ago
https://github.com/fschutt/azulA functional, reactive desktop GUI framework for Rust, C, and C++ that utilizes WebRender and a CSS/HTML-like DOM for rendering. The project includes azul-core (v0.0.12) and a comprehensive toolset called azul-doc for managing the public API via api.json, generating FFI language bindings (Rust, C, C++, Python), and performing visual reference testing against Google Chrome.
What's inside Azul
- Azul is a free, functional, and reactive GUI framework designed for Rust, C, and C++. It utilizes the WebRender rendering engine and a CSS/HTML-like Document Object Model (DOM) to enable rapid development of native desktop applications.
Overview of ScrollManager capabilities
masterThe
ScrollManager(located inlayout/src/managers/) serves as the single source of truth for scroll offsets within the AZUL framework. It manages:- Queuing wheel and trackpad input for physics-based movement (momentum/rubber-band).
- Scrollbar geometry, hit-testing, and thumb dragging.
- Easing animations and
scroll-into-viewlogic. - Feeding scroll offsets to renderers.
Note: Platform support varies. For example, macOS has full support for trackpad continuous scrolling and momentum, while Windows support is currently limited to discrete wheel events and lacks trackpad/gesture support.
Overview of Azul Crate Organization
masterAzul is modularized into several key crates, each handling a specific domain of the GUI framework:
- core: Contains fundamental data structures like
Dom,RefAny,StyledDom, events, and resources. - css: Handles CSS parsing, properties (
Css,CssProperty), and styling logic. - layout: Contains the layout engine (
solver3), text shaping (text3), managers, and theLayoutWindow. - dll: Provides platform-specific shells (Windows, macOS, X11, Wayland) and WebRender integration.
- webrender: A fork of Mozilla's WebRender GPU rendering engine.
- core: Contains fundamental data structures like
Understand the Scroll Physics Timer Architecture
masterThe scroll physics system follows a specific lifecycle to handle momentum and rubber-banding:
- Input Capture: A platform event handler (macOS/Windows/X11/Wayland) calls
ScrollManager.record_scroll_from_hit_testand pushes aScrollInputto theScrollInputQueue. This starts theSCROLL_MOMENTUM_TIMER_IDtimer. - Timer Execution: Every ~16ms, the
scroll_physics_timer_callback(inlayout/src/scroll_timer.rs) executes:- Consumes pending inputs from the queue.
- Performs physics integration (velocity, friction, etc.).
- Pushes
CallbackChange::ScrollTofor updated nodes. - Returns an
Updatestatus (e.g.,Update::RefreshDomorUpdate::DoNothing).
- Result Flow: The timer result is collected via
run_single_timer()into aCallCallbacksResult. This result is then processed by the platform's timer handler (e.g.,tick_timers()), which callsprocess_callback_result_v2()to triggerscroll_manager.scroll_to()and eventuallyscroll_all_nodes(txn)to update WebRender offsets.
- Input Capture: A platform event handler (macOS/Windows/X11/Wayland) calls
Current status of Smalltalk bindings
masterThe Smalltalk bindings for Azul are currently not functional and cannot be loaded into any Smalltalk system (Pharo or GNU Smalltalk).
Critical issues include:
- Unloadable Artifacts: The generated
Azul.stfile uses a single-file Tonel format that is incompatible with Pharo'sfileIn(which expects chunk-format) and requires a per-package directory layout that is not currently provided. GNU Smalltalk (gst) also fails to parse the file. - Missing Features: There is no bridge for converting Smalltalk Strings to
AzString, and no support for callbacks (typedefs are erased tovoid*). - Documentation Errors: Existing installation guides in
api.jsonandexamples/smalltalk/README.mdcontain incorrect steps and false claims regarding compatibility with GNU Smalltalk.
- Unloadable Artifacts: The generated
Understand the TextInputManager workflow
masterThe
TextInputManager(located inlayout/src/managers/text_input.rs) manages text-edit changesets using a two-phase process:- Record Phase: Captures keyboard, IME, accessibility, or programmatic insertions as
PendingTextEditobjects. - Emit Phase: Emits
EventType::Inputvia theEventProvider. - Apply Phase: Applies the changes (or clears them if
preventDefaultis called) usingLayoutWindow::apply_text_changeset.
This manager is designed with a minimal surface area; the primary logic resides in
LayoutWindowandTextEditManager.- Record Phase: Captures keyboard, IME, accessibility, or programmatic insertions as
Use CSS Animation Interpolation
masterCSS transitions and animations are driven by theAnimationInterpolationFunction. The pipeline flows from CSS definitions throughcss/definitions, intocore/src/svg.rs, and finally tolayout/src/xml/svg.rsfor SVG geometry animation.Understand CSS Transforms in the rendering pipeline
masterCSS transforms follow a specific pipeline to move from style definitions to hardware-accelerated rendering:
StyleTransform(CSS definition)ComputedTransform3D(Resolved value)- WebRender matrix pipeline (Final rendering)
The system utilizes SIMD acceleration and supports various coordinate systems and rotation modes.
Understand the azul-mini.wasm loading architecture
masterThe
azul-mini.wasmdeployment follows a layered loading strategy to minimize initial Time to Interactive (TTI):- Boot Module: Contains
hydrate,dispatchEvent,hit-test,patch-builder, and allocator/libc shims. Target size: < 500 KB. - Layout Module: Contains
solver3andtext3measurement. This is loaded lazily upon the first event that requires layout mutation. - Callback Shards: Individual WASM modules for application-specific callbacks.
- On-demand Shards: Any code required by the call graph that was not in the initial closure is fetched via a
missing_blocktrap (lazy lift-and-fetch).
- Boot Module: Contains
Understand the Rendering Pipeline
masterAzul uses the Mozilla WebRender engine for high-performance, GPU-accelerated rendering. The pipeline follows these steps:
- Display List Generation: After layout,
LayoutWindowcallslayout_and_generate_display_list()to create aDisplayListcontaining primitives likeRect,Border,Text,Image, andPushStackingContext. - WebRender Translation: The
compositor2module translates Azul primitives into WebRender formats (e.g., converting font hashes intoFontKeyandFontInstanceKey). - Resource Synchronization: The translation generates
ResourceUpdatemessages (such asAddFontorAddImage) to inform the GPU thread of new assets. - Transaction Submission: All commands, resource updates, and scroll offsets are packaged into a WebRender
Transactionand sent to the Render Backend thread. - Scene Building: The Render Backend builds the stacking context tree and scene primitives, then signals the main thread when the frame is ready.
- Presentation: The main thread triggers a buffer swap (via OS events like
WM_PAINT) to present the frame. Note that GPU-accelerated properties likeopacityandtransformcan update the frame without a full layout pass.
- Display List Generation: After layout,
Understand the GestureAndDragManager capabilities
masterThe
GestureAndDragManager(located inlayout/src/managers/gesture.rs) is responsible for recording mouse/pen input sessions and detecting multi-frame gestures such as drags, double/triple-clicks, long-presses, swipes, pinches, and rotations. It also manages the unifiedDragContextfor node and window drags, pen state, and Wacom-pad state.Key Capabilities
- Input Session Recording: Uses
PlatformWindow::record_input_sample(defined incommon/event.rs) to feed input data to the manager. - Pointer Capture: Supports keeping motion delivery active even when the pointer moves outside the window boundaries (implementation varies by platform).
- Gesture Detection:
- Drag: Detects
DragStart,Drag,DragEnd, andDropevents using a 5px threshold (detect_dragingesture.rs:117). - Clicks: Detects double/triple-clicks via
detect_double_clickanddetect_click_count. - Long-press: Detects
LongPressevents viadetect_long_press. - Swipe: Detects
SwipeLeft,SwipeRight,SwipeUp, andSwipeDownusing velocity heuristics viadetect_swipe_direction. - Pinch/Rotate: Detects pinch and rotation gestures via
detect_pinchanddetect_rotation(requires two concurrent sessions).
- Drag: Detects
- Drag-and-Drop (DnD):
- Node DnD: Automatically activates via
activate_node_dragon aDragStartover a draggable node. - Window Move: Provides context for window dragging via
activate_window_drag, though actual movement is often handled by titlebar callbacks usingget_drag_delta_screen_incremental.
- Node DnD: Automatically activates via
- Pen/Stylus Support: Tracks pen state (pressure, tilt, twist, eraser) via
update_pen_state_full, emittingPenEnter,PenLeave,PenDown,PenUp, andPenMoveevents. - Wacom Tablet-Pad Support: Provides interfaces for
update_pad_state,get_pad_state, express keys, and touch rings (Note: availability depends on backend implementation).
- Input Session Recording: Uses
Understand the XmlComponent System
masterThe current component system in Azul is based on the
XmlComponentTraitdefined incore/src/xml.rs. This system allows for defining components that can render a DOM and compile to Rust code.Key concepts include:
XmlComponentTrait: A Rust trait requiring implementations forget_type_id,get_xml_node,get_available_arguments,render_dom, andcompile_to_rust_code.XmlComponent: A struct containing an ID, a boxed renderer implementing the trait, and inherited variables.XmlComponentMap: A flatBTreeMapthat stores components by name. Note that this system currently lacks namespacing and uses a single global namespace.DynamicXmlComponent: Components defined via XML (e.g.,<component name="..." args="a: String">). These use a system-defined implementation where the system walks the XML template tree to generate code.ComponentArguments: Defines the arguments a component accepts, including their names, types, and whether it accepts text content.