From b75cab5939520cc07b01c0efae38e90ea76202b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Sat, 6 Jun 2026 19:16:35 -0300 Subject: [PATCH] Fix html element sizing. --- src/eepp/ui/uirichtext.cpp | 14 +++++++ src/tests/unit_tests/uihtml_tests.cpp | 57 +++++++++++++++++++++++++++ 2 files changed, 71 insertions(+) diff --git a/src/eepp/ui/uirichtext.cpp b/src/eepp/ui/uirichtext.cpp index 0c2c09ad4..95c01c031 100644 --- a/src/eepp/ui/uirichtext.cpp +++ b/src/eepp/ui/uirichtext.cpp @@ -283,6 +283,20 @@ void UIHTMLBody::updateLayout() { } mSettingBodyHeight = false; + + if ( getParent() && getParent()->isType( UI_TYPE_HTML_HTML ) ) { + auto* html = getParent()->asType(); + const Float bodyBottom = getPixelsPosition().y + getPixelsSize().getHeight(); + if ( bodyBottom > html->getPixelsSize().getHeight() + 0.5f ) { + // The body has a special relationship with the root html element: after late + // resource/style changes, body can discover a content height while html is already + // walking its layout tree. The RichText re-entrancy guard intentionally absorbs that + // child notification to avoid rebuilding the same inline stream many times. Since + // browsers require the root html box to contain body, enqueue exactly the html + // layout for a normal later pass instead of forcing a synchronous parent recompute. + html->setLayoutDirty(); + } + } } } diff --git a/src/tests/unit_tests/uihtml_tests.cpp b/src/tests/unit_tests/uihtml_tests.cpp index 24d62b5c1..5372dd6fd 100644 --- a/src/tests/unit_tests/uihtml_tests.cpp +++ b/src/tests/unit_tests/uihtml_tests.cpp @@ -4049,6 +4049,63 @@ UTEST( UIHTML, TextureReplaceInvalidatesRichTextAncestors ) { Engine::destroySingleton(); } +UTEST( UIHTML, HtmlContainsTableBodyHeight ) { + auto win = Engine::instance()->createWindow( + WindowSettings( 1024, 768, "html contains table body height", WindowStyle::Default, + WindowBackend::Default, 32, {}, 1, false, true ), + ContextSettings( false, 0, 0, GLv_default, true, false ) ); + + UISceneNode* sceneNode = init_test_inline_block(); + + UIWebView* webView = UIWebView::New(); + webView->setParent( sceneNode->getRoot() ); + webView->setPixelsSize( win->getWidth(), win->getHeight() ); + webView->setLayoutSizePolicy( SizePolicy::Fixed, SizePolicy::Fixed ); + + FileSystem::changeWorkingDirectory( Sys::getProcessPath() ); + std::string html; + ASSERT_TRUE( FileSystem::fileGet( "assets/html/hn_frontpage.html", html ) ); + for ( std::string::size_type pos = 0; + ( pos = html.find( "", pos ); + ASSERT_TRUE( end != std::string::npos ); + html.erase( pos, end + 2 - pos ); + } + + sceneNode->setURI( "file://html-table-body-height.html" ); + sceneNode->loadLayoutFromString( HTMLFormatter::HTMLtoXML( html ), webView->getDocumentContainer(), + String::hash( "html-table-body-height" ) ); + + win->getInput()->update(); + SceneManager::instance()->update(); + sceneNode->updateDirtyLayouts(); + + std::string css; + ASSERT_TRUE( FileSystem::fileGet( "assets/html/base.css", css ) ); + css += "\n"; + std::string newsCss; + ASSERT_TRUE( FileSystem::fileGet( "assets/html/news.css", newsCss ) ); + css += newsCss; + sceneNode->runOnMainThread( [sceneNode, css = std::move( css )] { + sceneNode->combineStyleSheet( css, true, String::hash( "html-table-body-height-late-css" ) ); + } ); + SceneManager::instance()->update(); + sceneNode->updateDirtyLayouts(); + + auto* htmlNode = sceneNode->getRoot()->findByType( UI_TYPE_HTML_HTML )->asType(); + auto* body = sceneNode->getRoot()->findByType( UI_TYPE_HTML_BODY )->asType(); + auto* table = sceneNode->getRoot()->find( "hnmain" )->asType(); + ASSERT_TRUE( htmlNode != nullptr ); + ASSERT_TRUE( body != nullptr ); + ASSERT_TRUE( table != nullptr ); + + EXPECT_GE( htmlNode->getPixelsSize().getHeight(), body->getPixelsSize().getHeight() ); + EXPECT_GE( body->getPixelsSize().getHeight() + 4.f, table->getPixelsSize().getHeight() ); + EXPECT_GT( table->getPixelsSize().getHeight(), 500.f ); + + Engine::destroySingleton(); +} + UTEST( UIHTML, ImageCSSWidthOverridesHTMLWidthAttribute ) { auto win = Engine::instance()->createWindow( WindowSettings( 1024, 768, "img css width overrides html width attr", WindowStyle::Default,