Expand description
llimphi-compositor — el núcleo declarativo de Llimphi, sin winit.
Aquí vive el árbol de vista View<Msg> (DSL declarativo), su instalación
sobre taffy (mount), el pintado a vello::Scene (paint/paint_gpu) y
el hit-test. Nada de esto necesita una ventana ni llimphi-hal: la
composición view → layout → scene es pura y reutilizable.
El runtime que la maneja vive aparte:
llimphi-uila corre sobre winit (run<A: App>()).- a futuro, un runtime sobre el framebuffer del kernel
wawapuede reusar exactamente este compositor sin arrastrar winit.
wgpu entra sólo por la firma de GpuPaintFn (tipos de Device/Queue/
Encoder/TextureView); wgpu no depende de winit, así que el compositor
sigue libre de windowing.
Structs§
- Anim
- Declara que las props visuales de paint de este nodo se animan de forma
implícita.
keydebe ser estable entre rebuilds delView(índice de item, hash de id, etc.) — es lo que enlaza “el mismo nodo” entre frames. - Anim
Registry - Registro de animaciones implícitas, vivo entre frames. El runtime mantiene
una instancia y llama
Self::reconcileen cada redraw. - Backdrop
Blur - Datos de un backdrop blur listos para que el runtime lo aplique sobre
la intermediate vía
llimphi_hal::BlurCompositor::blur. - Border
- Borde (stroke) pintado sobre el contorno redondeado del nodo, inset
hacia adentro media línea para que el grosor quede dentro del rect
(convención CSS
box-sizing: border-box). Se pinta después del relleno. - Constraints
- Restricciones de tamaño que un
LayoutBuilderFnrecibe: las dimensiones del slot que el layout le asignó al nodo (en px físicos). Análogo a lasBoxConstraintsde FlutterLayoutBuilder/ alMediaQuerypero local al nodo (no a la ventana). El builder construye su subárbol en función de esto — p. ej. una columna simax_width < 600, dos si es ancho. - Filter
Pass - Una operación de
filterlista para que el runtime la aplique sobre la intermediate, restringida arect. EspejaBackdropBlurpero lleva unaFilterOpgenérica (el runtime hace match por variante). Fase 7.1232. - Hero
- Declara un nodo como hero: la
keyenlaza la identidad entre frames; si el rect cambia, el runtime anima la transición. - Hero
Registry - Registro de heroes, vivo entre frames. Guarda el último rect por
keypara detectar el delta y un tween activo si está animando. - Mask
Placement - Encaje y modo de una máscara (CSS
mask-size+mask-position+mask-repeat+mask-mode), resuelto contra el rect del nodo en el paint, con la misma aritmética quebackground-image. En elMountedNodeviaja comoOption:None= estirar la máscara al border-box en modo luminancia (comportamiento de la Fase 7.1226). Fase 7.1227 (encaje), 7.1228 (modo). - Mounted
- Versión “instalada” del árbol: cada nodo tiene su NodeId de taffy, color y handler. Se mantiene en orden de inserción (recorrido pre-orden), así el hit-test puede iterar al revés para honrar el orden de pintado.
- Mounted
Node - Paint
Rect - Rect absoluto del nodo (en coordenadas físicas del frame). Lo
recibe el callback de
View::paint_withpara que pueda posicionar sus primitivas custom dentro del nodo. - Ripple
- Declara que este nodo emite un ripple (salpicadura Material) al recibir
un press.
keydebe ser estable entre rebuilds delView(igual que la key decrate::Anim) — es lo que enlaza la salpicadura retenida con el nodo entre frames.colores el tinte de la onda (típicamente semitransparente, p. ej. blanco a alpha ~0.25 sobre superficies oscuras o negro a alpha ~0.12 sobre claras); su alpha se multiplica por el fade. - Ripple
Registry - Registro de ripples vivos, retenido por el runtime entre frames. Una
instancia por ventana; el runtime llama
Self::triggeren el press ySelf::painttras el paint del contenido. - Semantics
Flags - Banderas booleanas del nodo accesible. Todas opcionales (
None= no aplica, que es distinto de “aplica pero es false”). Mantienelas en None salvo que el widget realmente las exponga — los lectores diferencian “no es checkable” de “es checkable y no checked”. - Semantics
Spec - Especificación semántica completa de un nodo. Lo que el runtime traduce a
un
accesskit::Nodecada frame. - Shadow
- Sombra proyectada detrás del rect del nodo (drop shadow), rasterizada
con el
draw_blurred_rounded_rectnativo de vello. Se pinta antes del relleno, así el fill (si es opaco) tapa la parte solapada y la sombra sólo asoma por el desenfoque + el offset. El radio sigue al del nodo (másspread). - Size
Anim - Declara que el tamaño de este nodo (CSS
width/height/ FlutterAnimatedSize/ComposeanimateContentSize()) se anima de forma implícita cuando cambia entre frames. Bloque 15 de PARIDAD-FLUTTER (extensión faltante del Bloque 4). - Size
Anim Registry - Registro de animaciones implícitas de tamaño, vivo entre
frames. El runtime mantiene una instancia y llama
reconcile_size_animen cada redraw antes del mount/layout. - Text
Measure - Datos de un nodo-hoja de texto necesarios para medirlo (shaping +
line-break) sin volver a tocar el
View. Lo consume el runtime en la función de medición que le pasa aLayoutTree::compute_with_measure. - Text
Spec - Texto a pintar dentro de un nodo. Alineación por defecto
Center(horizontal y vertical), apta para labels de botón. Para layouts tipo editor o párrafo, usar.text_aligned(...)conAlignment::Start. - Transform
Pivot - Punto de pivote de
transform(CSStransform-origin). Cada eje se resuelve contra el rect del nodo comopx + frac · tamaño:px(ya escalado por zoom por el caller) cubre offsets absolutos yfraclos porcentuales (0.5= 50% del ancho/alto). El default CSS50% 50%(centro) es{ px: (0.0, 0.0), frac: (0.5, 0.5) }; un nodo contransform_origin: Noneusa ese centro. Modelapx + %por eje igual quetransform_relmodela eltranslate(<%>)— necesario porque el % depende del layout, desconocido hastapaint. - View
- Nodo de la vista declarativa. Estilo de layout (taffy) + relleno opcional (vello) + texto opcional (skrifa+vello) + Msg al click opcional + hijos.
Enums§
- Cursor
- Forma del puntero del mouse. Subconjunto práctico, llimphi-native (el
compositor no depende de winit). El runtime (
llimphi-ui) mapea 1:1 awinit::window::CursorIcon. Nombres alineados con CSS/winit. - Drag
Phase - Fase de un drag activo.
Movese emite por cadaCursorMovedcon el delta desde el evento anterior;Endse emite al soltar el botón. - Filter
Op - Una operación de filtro CSS (
filter: blur()/brightness()/…) aplicada al propio subárbol del nodo. A diferencia debackdrop_blur(que afecta lo pintado debajo), unFilterOpmodifica el contenido del nodo. El runtime los aplica como post-pasada GPU sobre la intermediate, restringidos al rect del nodo, en el orden de la lista. La lista crece por fase (CSS Filter Effects 1):Blur(7.1232) +ColorMatrix(7.1233). Fase 7.1232. - Gesture
Phase - Fase de un gesto continuo (pinch-to-zoom de momento; rotación a futuro).
El runtime emite
Beginal iniciar el gesto,Updatepor cada cambio incremental yEndal terminar. El camino de Ctrl+rueda (universal, sin trackpad) emite un únicoUpdatepor click de rueda — no hay un “inicio” ni “fin” naturales, así que el handler debe tolerarUpdates sueltos sinBeginprevio (es lo común en desktop). El camino de trackpad (PinchGesture, sólo macOS/iOS) sí entregaBegin/Update*/End. - Image
Fit - Cómo encajar una imagen en el rect del nodo (CSS
object-fit/ FlutterBoxFit). El runtime calcula la escala y el origen correspondientes a esta política y siempre recorta alnode_rrectdel nodo, así el clip respetaradius/corner_radii. - Mask
Compose - Operador de combinación entre capas de máscara (CSS
mask-composite). Mapea a unComposePorter-Duff de vello cuando una capa extra se compone sobre las de abajo. Fase 7.1231. - MaskLen
- Longitud de un eje de
MaskSize/posición de máscara, sin resolver — el paint la resuelve contra el rect del nodo. Neutral respecto de CSS: el frontend (p. ej. puriy) traducemask-size/mask-positiona esto. Fase 7.1227. - Mask
Mode - Modo de una máscara (CSS
mask-mode). Decide qué canal del píxel-máscara modula el alpha del contenido. Fase 7.1228. - Mask
Size mask-sizeneutral (espejo deBackgroundSize). VerMaskPlacement. Fase 7.1227.- Role
- Rol semántico del nodo. Los nombres y la granularidad siguen los roles de AccessKit / ARIA. Subset acotado: agregamos lo que falte cuando aparezca un caller real (regla del repo — no diseñamos para lo hipotético).
Functions§
- collect_
backdrop_ blurs - Recolecta los nodos con
MountedNode::backdrop_bluractivo del árbol montado, junto con el sigma y el rect absoluto al cual restringir el blur. El runtime (llimphi-ui::eventloop) los aplica como post-pasada después de la rasterización vello, sobre la intermediate. - collect_
builder_ constraints - Lee las
Constraints(tamaño del slot) de cada nodois_layout_builderdel árbol montado, en pre-orden. El runtime las pasa aexpand_layout_builders. Un nodo sin rect computado (fuera del layout) cae a0×0. - collect_
filters - Recolecta los nodos con
MountedNode::filterno vacío y los aplana en una lista deFilterPassen orden de árbol y en orden de la lista de cada nodo — así el runtime aplica la cadenafilter: a b cen secuencia sobre el rect (a, luego b, luego c). El runtime las consume tras la rasterización vello, igual quecollect_backdrop_blurs. - ease_
out_ cubic - Ease-out cúbico, el default razonable para transiciones implícitas
(arranca rápido, frena suave). Copia local para no acoplar el compositor a
llimphi-theme; el caller puede pasar cualquierfn(f32)->f32. - expand_
layout_ builders - Expande los
layout_builderdeview(pre-orden) usandocons— unaConstraintspor builder, en el orden que produjocollect_builder_constraints. Cada builder se reemplaza por un nodo contenedor (su mismoStyle) cuyo único hijo es lo que devolvió la closure invocada con sus constraints. Builders sin constraint correspondiente (más builders quecons, p. ej. uno anidado recién producido) caen a0×0y se resuelven igual, pero su tamaño será nulo (límite v1: sin anidamiento). Consumeview. - focus_
order - Ids enfocables en orden de Tab (pre-orden del árbol = orden de
inserción de
Mounted::nodes). Sólo nodos con rect computado (presentes en el layout). Es el orden DOM-like de tabulación. - has_
gpu_ painter - Pasada GPU directo: recorre el
Mounteden pre-orden DFS (mismo orden quepaint) e invoca cadagpu_paintercon el encoder y laTextureViewdel frame. Se ejecuta DESPUÉS de la pasada vello — la intermediate ya tiene fill/image/painter/text encima cuando los callbacks corren, así que suLoadOpdebe serLoad. Devuelve si se invocó al menos un painter (para que el caller decida si vale la pena finalizar y submitir el encoder).truesi algún nodo del árbol registró ungpu_painter(p. ej. el video de media víagpu_paint_with). El eventloop lo usa para decidir si la capa de overlay necesita componerse aparte (sobre el contenido gpu) en vez de pintarse en la escena principal. - has_
layout_ builder truesiviewo algún descendiente declara uncrate::View::layout_builder. El runtime lo usa para decidir si vale la pena la resolución en dos pasadas; cuando esfalse(lo normal) el camino diferido se evita por completo.- has_
over_ painter truesi algún nodo del árbol registró unover_painter(vello “over” víaView::paint_over). El eventloop lo usa para decidir si vale la pena montar la pasada vello final + el composite sobre la intermedia. Coste cero (loop barato) cuando nadie usa el over-layer.- hit_
test_ click - Hit-test específico para clicks (incluye nodos draggables).
- hit_
test_ cursor - Hit-test específico para la forma del cursor: devuelve el
Cursordel nodo más al frente bajo el punto que declare uno. Como un hijo sin cursor no matchea el predicado, el cursor “cae” al ancestro más cercano que lo declare — herencia estilo CSS sin recorrer el árbol a mano.None= ningún nodo bajo el punto declara cursor (el runtime usa el default de la ventana). Lo invocallimphi-uien la transición de hover. - hit_
test_ double_ tap - Hit-test para doble-tap: el nodo más al frente bajo el punto que
declaró
on_double_tap/on_double_tap_at. El runtime lo usa al detectar dos presses rápidos y cercanos. - hit_
test_ drop - Hit-test específico para drop targets (nodos con
on_drop). Usado durante un drag activo para resaltar el destino y para invocar el handler al soltar. - hit_
test_ focusable - Hit-test para foco: el id
focusabledel nodo más al frente bajo el cursor (click-to-focus).Nonesi no se clickeó nada enfocable. - hit_
test_ hover - Hit-test específico para hover (nodos con
hover_fill). - hit_
test_ long_ press - Hit-test para long-press: el nodo más al frente bajo el punto que
declaró
on_long_press/on_long_press_at. El runtime lo usa al armar el gesto en el press (que vence por tiempo si no hay movimiento ni release). - hit_
test_ middle_ click - Hit-test específico para middle-click. Mismo modelo que right-click:
sólo nodos que declararon
on_middle_clickreaccionan. - hit_
test_ pointer_ move - Hit-test para movimiento posicional del cursor (nodos con
on_pointer_move_at). El runtime lo invoca en cadaCursorMovedpara reportar la posición local al nodo más al frente que lo declare. - hit_
test_ pred - Hit-test parametrizado por elegibilidad. Devuelve el índice del nodo
más al frente (último en pre-orden) cuyo rect contiene
(x, y)y para el cualpreddevuelvetrue, respetandoclip: si el punto cae afuera de un nodo con clip, el subárbol entero es invisible. - hit_
test_ right_ click - Hit-test específico para right-click. Sólo considera nodos que
declararon
on_right_clickoon_right_click_at— un right-click sobre un nodo sin handler no hace nada (no se “filtra” al click izquierdo). - hit_
test_ ripple - Hit-test para ripple: el nodo más al frente bajo el punto que declaró
un
Ripple(víaView::ripple). El runtime lo usa en el press para disparar la salpicadura. Aditivo — no compite con click/drag. - hit_
test_ rotate - Hit-test específico para gestos de rotación (trackpad): el nodo más al
frente bajo el punto que declaró un
on_rotate. Análogo ahit_test_scale; el runtime lo invoca al recibir unRotationGesture.None= ningún nodo rotable bajo el cursor. - hit_
test_ scale - Hit-test específico para gestos de escala (pinch-to-zoom): el nodo más
al frente bajo el punto que declaró un
on_scale. Como un hijo sin handler no matchea el predicado, el gesto “cae” al ancestro más cercano que lo declare (un canvas grande zoomeable con widgets encima que no zoomean). El runtime lo invoca al recibir Ctrl+rueda o un pinch de trackpad.None= ningún nodo zoomeable bajo el cursor (el evento cae al scroll/on_wheel). - hit_
test_ scroll - Hit-test específico para áreas de scroll (nodos con
on_scroll). El runtime lo usa al recibir la rueda: el nodo más al frente bajo el cursor con handler de scroll consume el evento antes delon_wheelglobal. - hit_
test_ scroll_ chain - Cadena de scroll anidado: devuelve todos los nodos con
on_scrollque contienen el punto, ordenados front→back (el primero es el más al frente, igual quehit_test_scroll; los siguientes son sus ancestros scrollables). El runtime itera la cadena al recibir la rueda y se queda con el primer handler que devuelvaSome: si un scroll interno está en el extremo del eje y devuelveNone, el evento “pasa” al ancestro scrollable más cercano (lista dentro de panel, etc.). Recorrido idéntico al dehit_test_predpero acumulando todos los hits en vez de pisar. - hit_
test_ selectable - Hit-test para selección de texto: el índice del nodo de texto
seleccionable (
text_select_key) más al frente bajo el cursor. El runtime lo usa para arrancar/extender una selección; devuelve el índice (no la key) para que el caller acceda altext+ rect del nodo.Nonesi no hay texto seleccionable bajo el punto. - measure_
text_ node - Mide una hoja de texto para taffy: shaping + line-break con parley contra
el ancho disponible, devolviendo el bounding box. Si el ancho ya está
resuelto (
known.width) se usa ese; si no, se deriva delavailable(Definite → ese ancho; MaxContent → sin límite = una línea; MinContent → 0 = envuelve a la palabra más ancha). Elline_heightsale del propioTextMeasure, el mismo que usapaint, así medida y pintado coinciden. - mount
- mount_
recursive - Mount en pre-orden directo sobre
out: pusheamos el padre como placeholder (id real desconocido hasta crear el taffy node), recursamos hijos sobre el mismoout, y al volver completamosid+subtree_end. - next_
focus - Próximo id de foco al pulsar Tab (o Shift+Tab si
reverse), dado elorder(defocus_order) y elcurrent. Envuelve en los extremos. Si no hay enfocables devuelveNone; sicurrentya no existe en el orden, arranca por el primero (Tab) o el último (Shift+Tab). - paint
- paint_
gpu - paint_
over - Pinta la pasada vello “over” en
scene: recorre el árbol en orden DFS pre-orden e invoca cadaover_paintercon elTypesettercompartido y el rect absoluto del nodo. Espejo depaint_gpupero del lado vello — la diferencia de timing la pone el caller, que rasteriza estasceneDESPUÉS del pase GPU y la compone sobre la intermedia. No reseteascene(el caller decide); sólo agrega primitivas. Comopaint_gpu, usa rects absolutos (no compone lostransformde ancestros — el over-layer es contenido posicionado en coordenadas de pantalla, igual que el pintor GPU). - paint_
range - reconcile_
size_ anim - Recorre el
Viewtree y, para cada nodo conSizeAnim, reconcila sustyle.sizecon el registry: si cambió el objetivo, arranca un tween; si está animando, parchastyle.sizecon el valor interpolado. Devuelvetruesi alguna animación de tamaño sigue viva → el runtime debe pedir otro redraw.
Type Aliases§
- Click
AtFn - Handler de click con posición. Recibe
(x_local, y_local, rect_w, rect_h): las dos primeras son la posición del cursor relativa a la esquina superior-izquierda del nodo y las dos últimas son el ancho/alto actual del nodo en pixels — útil cuando el caller necesita centrar o normalizar. DevolverNoneno dispara update. - Drag
AtFn - Variante de
DragFnque conoce la posición inicial del press relativa al rect del nodo. Útil cuando el caller necesita identificar qué entidad (Concepto, lemming, etc.) bajo el cursor agarró el drag. Recibe(phase, dx, dy, initial_lx, initial_ly). - DragFn
- Handler de drag. Recibe la fase + delta (
dx,dy) desde el evento anterior (no acumulado desde el press). DevolverNonedeja el drag activo sin disparar Msg.Arc<dyn Fn>para que el runtime pueda clonarlo barato al iniciar el drag y mantenerlo vivo aunque el cache de la vista se regenere mientras tanto. - Drag
Velocity Fn - Variante de
DragFnque recibe la velocidad del drag al soltarlo (vx,vyen px/s). El runtime mide el desplazamiento sobre los últimos ~100 ms de movimiento (ventana móvil de hasta ocho samples) y la pasa enDragPhase::End. DuranteDragPhase::Moveambas son0.0— la velocidad sólo es significativa al final. Permite fling-desde-drag: el caller arranca un ticker con esa velocidad y la decae confling_stephasta asentar. Reemplaza la estimación manual que antes tenía que llevar el caller conInstant::now()por su cuenta. - DropFn
- Handler de drop. El runtime lo invoca cuando un drag activo se suelta
sobre este nodo. Recibe el
payloadu64que el origen del drag declaró víaView::drag_payload. DevolverNoneignora el drop. - GpuPaint
Fn - Callback de pintura GPU directo, sin vello intermedio. Recibe el
device/queueya construidos por el runtime más unCommandEncodery laTextureViewdel frame (la intermediateRgba8UnormdeWinitSurface), todo durante el paint del nodo. - Layout
Builder Fn - Constructor diferido de subárbol sensible al tamaño (Flutter
LayoutBuilder). El runtime resuelve el tamaño del slot del nodo en una primera pasada de layout y luego invoca esta closure con esasConstraintspara producir los hijos — así “construir distinto según el espacio disponible” deja de exigir conocer el tamaño al armar elView. VerView::layout_builder. - Over
Paint Fn - Callback de pintura vello “over”: idéntico en firma a
PaintFn(&mut Scene, &mut Typesetter, PaintRect), pero el runtime lo invoca en una pasada vello FINAL, después de todos losgpu_painterdel frame. Sus primitivas se rasterizan sobre fondo transparente y se componen con alpha encima de la intermedia (que ya tiene vello-base + GPU directo). Resuelve el z-order inverso al deGpuPaintFn: permite pintar texto/sprites AA por vello encima de celdas instanciadas por GPU (dominium grid, futuro motor voxel). - PaintFn
- Callback de pintura custom. El runtime lo invoca durante el paint
del nodo (entre el
fill/imagey eltext) con elScenevivo - Rotate
Fn - Handler de gesto de rotación (trackpad, sólo macOS — winit no emite
RotationGestureen Wayland/Windows). Análogo aScaleFnpero el segundo argumento es el delta de ángulo incremental en radianes (positivo = horario) en lugar del factor de escala;(focal_x, focal_y)es el punto bajo el cursor relativo al rect del nodo. El nodo más al frente bajo el cursor que declare unon_rotateconsume el gesto. Base para rotar canvases/imágenes con dos dedos. VerView::on_rotate. - ScaleFn
- Handler de gesto de escala (pinch-to-zoom). Recibe
(phase, factor, focal_x, focal_y): - Scroll
Fn - Handler de rueda local a un nodo. Recibe el delta
(dx, dy)en líneas lógicas (misma normalización queApp::on_wheel:dypositivo = scroll hacia abajo). El runtime lo invoca cuando la rueda gira con el cursor sobre este nodo, ANTES de caer alApp::on_wheelglobal: si el handler devuelveSome(Msg), el evento se consume acá. Permite áreas de scroll autocontenidas (el widgetscrolllo usa) sin que cada app rutee la rueda a mano por suModel. DevolverNonedeja pasar el evento alon_wheelglobal.