From 5352bf50fdf0db53711cefeb6e5adf3d3095acd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Arrufat?= Date: Fri, 17 Apr 2026 12:08:05 +0200 Subject: [PATCH] StyleManager: add `check_display` --- src/browser/StyleManager.zig | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/browser/StyleManager.zig b/src/browser/StyleManager.zig index 25c01c6a..82e50bbc 100644 --- a/src/browser/StyleManager.zig +++ b/src/browser/StyleManager.zig @@ -240,18 +240,16 @@ pub fn hasDisplayNone(self: *StyleManager, el: *Element) bool { return self.isElementHidden(el, .{}); } -/// Computed visibility:hidden for an element, walking ancestors since `visibility` -/// inherits by default. Only considers visibility-level hidden (not display:none) -/// — display:none on an ancestor means the element isn't rendered, but its -/// computed `visibility` still reflects inherited visibility chain. +/// Computed visibility:hidden for an element, considering only the `visibility` +/// chain (walks ancestors since `visibility` inherits by default). Ignores +/// display:none: an ancestor with display:none means the element isn't +/// rendered, but its computed `visibility` still reflects inherited visibility. pub fn hasVisibilityHiddenInherited(self: *StyleManager, el: *Element) bool { self.rebuildIfDirty() catch return false; var current: ?*Element = el; while (current) |elem| { - const combined = self.isElementHidden(elem, .{ .check_visibility = true }); - if (combined) { - const display_only = self.isElementHidden(elem, .{}); - if (!display_only) return true; + if (self.isElementHidden(elem, .{ .check_display = false, .check_visibility = true })) { + return true; } current = elem.parentElement(); } @@ -273,11 +271,16 @@ fn isElementHidden(self: *StyleManager, el: *Element, options: CheckVisibilityOp var opacity_priority: u64 = 0; // Check inline styles FIRST - they use INLINE_PRIORITY so no stylesheet can beat them - if (getInlineStyleProperty(el, comptime .wrap("display"), self.page)) |property| { - if (property._value.eql(comptime .wrap("none"))) { - return true; // Early exit for hiding value + if (options.check_display) { + if (getInlineStyleProperty(el, comptime .wrap("display"), self.page)) |property| { + if (property._value.eql(comptime .wrap("none"))) { + return true; // Early exit for hiding value + } + display_none = false; + display_priority = INLINE_PRIORITY; } - display_none = false; + } else { + // Pin to INLINE_PRIORITY so rule-matching skips display entirely. display_priority = INLINE_PRIORITY; } @@ -712,8 +715,9 @@ const VisibilityRule = struct { }; const CheckVisibilityOptions = struct { - check_opacity: bool = false, + check_display: bool = true, check_visibility: bool = false, + check_opacity: bool = false, }; // Inline styles always win over stylesheets - use max u64 as sentinel