diff --git a/src/core/context.zig b/src/core/context.zig index 13ac459..a583805 100644 --- a/src/core/context.zig +++ b/src/core/context.zig @@ -102,6 +102,10 @@ pub const Context = struct { /// Set by application for non-dirty panels to save CPU while keeping input working. suppress_commands: bool = false, + /// Burst detection: timestamp of last navigation event (selection change) + /// Used by drawPanelFrame to auto-suppress burst_sensitive panels during rapid navigation + last_navigation_time: i64 = 0, + /// Frame statistics stats: FrameStats, @@ -665,10 +669,24 @@ pub const Context = struct { draw_shadow: bool = true, /// Draw bevel effect (default true) draw_bevel: bool = true, + + // === Performance === + /// Si true, el panel se auto-suprime durante ráfagas de navegación. + /// Paneles principales (listas, fichas) deben ser false. + /// Paneles secundarios (documentos) pueden ser true para mejor rendimiento. + burst_sensitive: bool = true, + }; + + /// Result of drawPanelFrame for LEGO-style control flow + pub const PanelFrameResult = struct { + /// True if color transition is still animating + animating: bool, + /// False if panel was suppressed - caller should return immediately + should_draw: bool, }; /// Draw a complete panel frame with focus transition and 3D effects. - /// Returns true if the transition is still animating (need more frames). + /// Returns PanelFrameResult: check should_draw to know if panel content should be rendered. /// /// Supports two modes: /// - **Explicit**: Provide focus_bg, unfocus_bg, border_color directly @@ -678,7 +696,11 @@ pub const Context = struct { rect: Layout.Rect, transition: *ColorTransition, config: PanelFrameConfig, - ) bool { + ) PanelFrameResult { + // Auto-supresión LEGO: detectar si el panel debe suprimir operaciones costosas + // El frame SIEMPRE se dibuja, pero should_draw indica si continuar con widgets/BD + const burst_suppressed = config.burst_sensitive and self.isSelectionBurstActive(); + // Determine colors: Z-Design derivation or explicit const focus_bg: Style.Color = blk: { if (config.base_color) |base| { @@ -764,7 +786,8 @@ pub const Context = struct { } } - return animating; + // should_draw = false indica que el panel debe saltar operaciones costosas (BD, widgets) + return .{ .animating = animating, .should_draw = !burst_suppressed }; } /// Resize the context @@ -837,6 +860,23 @@ pub const Context = struct { } } + // ========================================================================= + // BURST DETECTION: Para auto-supresión de paneles durante navegación rápida + // ========================================================================= + + /// Marca que ocurrió un evento de navegación (cambio de selección). + /// Llamar desde DataManager cuando notifica cambios de selección. + pub fn markNavigationEvent(self: *Self) void { + self.last_navigation_time = std.time.milliTimestamp(); + } + + /// Devuelve true si estamos en medio de una ráfaga de navegación. + /// Se considera ráfaga si pasaron menos de 100ms desde el último evento. + pub fn isSelectionBurstActive(self: *Self) bool { + const now = std.time.milliTimestamp(); + return (now - self.last_navigation_time) < 100; + } + /// Get rectangles of all dirty panels (for renderer). /// Returns slice allocated from frame arena (valid until next beginFrame). pub fn getDirtyPanelRects(self: *Self) []const Layout.Rect { diff --git a/src/render/framebuffer.zig b/src/render/framebuffer.zig index 60f4557..8af7fe7 100644 --- a/src/render/framebuffer.zig +++ b/src/render/framebuffer.zig @@ -114,6 +114,7 @@ pub const Framebuffer = struct { /// Draw a filled rectangle /// Optimized with SIMD-friendly @memset for solid colors (alpha=255) pub fn fillRect(self: *Self, x: i32, y: i32, w: u32, h: u32, color: Color) void { + @setRuntimeSafety(false); // Hot path: bounds already validated below const x_start = @max(0, x); const y_start = @max(0, y); const x_end = @min(@as(i32, @intCast(self.width)), x + @as(i32, @intCast(w))); diff --git a/src/render/ttf.zig b/src/render/ttf.zig index 9a3ec58..49c9b9c 100644 --- a/src/render/ttf.zig +++ b/src/render/ttf.zig @@ -320,6 +320,7 @@ pub const TtfFont = struct { color: Color, clip: Rect, ) void { + @setRuntimeSafety(false); // Hot path: bounds validated in visible region calculation _ = self; const width: u32 = glyph.metrics.width;