Viewports & Virtual Content Space
In TUIX v0.6, widgets can act as viewport owners that maintain a virtual coordinate system larger than the physical terminal screen. The compositor, geometry resolver, clipping engine, and hitmap router all understand virtual content dimensions, scroll offsets, and inner insets.
Screen Space vs Content Space
Regular widgets calculate their position and bounds as floating-point fractions of the terminal dimensions. Viewport owners (such as `ScrollContainer`, `ListView`, `TextArea`, and `Dialog`) establish a virtual content space measured in absolute cell coordinates `(content_x, content_y, content_w, content_h)`.
| Coordinate Space | Units | Usage |
|---|---|---|
| Screen / Terminal Space | Floating-point fractions (0.0 to 1.0) | Proportional layout, scene root containers, split panes, and grids. |
| Virtual Content Space | Integer cell coordinates (x, y, w, h) | Virtual scroll lists, multiline document editing, canvas charts, and game worlds. |
Native Viewport Protocol
A native builder becomes a viewport owner by implementing three core callbacks in its `TuixBuilder` descriptor: 1. `get_viewport_offset`: Returns the current `(offset_x, offset_y)` translation. 2. `get_viewport_insets`: Returns border and title margins `(left, top, right, bottom)`. 3. `get_viewport_content_size`: Returns total virtual dimensions `(content_w, content_h)`.
Viewport Clipping & Hitmap Translation
During scene compositing, child buffers positioned outside the visible viewport rect are automatically clipped at the C level. When a mouse event occurs, the hitmap router translates terminal screen coordinates through the viewport offset so that interactive children receive clicks in their local content space.
from tuix.core import object as objects, content_builder, viewport
# Create a scroll container viewport
uid = objects.create_object(content_builder.SCROLL_CONTAINER, b'Main', 0.8, 0.6, 0.1, 0.1)
scroll = objects.get_object_by_uid(uid)
# Configure virtual canvas: 200 columns by 500 rows
objects.tuix_scroll_container_set_content_size(scroll, 200, 500)
objects.tuix_scroll_container_set_offset(scroll, 0, 50)
# Query viewport properties via modular viewport package
is_vp = viewport.tuix_object_is_viewport(scroll)
offset = viewport.tuix_object_get_viewport_offset(scroll)
size = viewport.tuix_object_get_viewport_content_size(scroll)