From b7facf4b37c4f0f3b498566299498a5b02c9e3cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Lucas=20Golini?= Date: Mon, 6 Jul 2026 12:42:38 -0300 Subject: [PATCH] Fix isInlineBlock in UITextSpan: floated inline-block spans were no longer considered isInlineBlock() because UITextSpan::isInlineBlock() required float:none. --- src/eepp/ui/uitextspan.cpp | 2 +- src/tests/unit_tests/uihtml_tests.cpp | 187 ++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 1 deletion(-) diff --git a/src/eepp/ui/uitextspan.cpp b/src/eepp/ui/uitextspan.cpp index c971182d5..2627daef4 100644 --- a/src/eepp/ui/uitextspan.cpp +++ b/src/eepp/ui/uitextspan.cpp @@ -68,7 +68,7 @@ bool UITextSpan::isInline() const { } bool UITextSpan::isInlineBlock() const { - return mDisplay == CSSDisplay::InlineBlock && getCSSFloat() == CSSFloat::None && !isOutOfFlow(); + return mDisplay == CSSDisplay::InlineBlock && !isOutOfFlow(); } void UITextSpan::onDisplayChange() { diff --git a/src/tests/unit_tests/uihtml_tests.cpp b/src/tests/unit_tests/uihtml_tests.cpp index ada1af977..803fd7582 100644 --- a/src/tests/unit_tests/uihtml_tests.cpp +++ b/src/tests/unit_tests/uihtml_tests.cpp @@ -3809,6 +3809,193 @@ UTEST( UIHTML, FlexInfobarAvoidsRightFloat ) { Engine::destroySingleton(); } +UTEST( UIHTML, FloatedInlineBlockButtonKeepsTextInside ) { + auto win = Engine::instance()->createWindow( + WindowSettings( 800, 600, "floated inline-block button text", WindowStyle::Default, + WindowBackend::Default, 32, {}, 1, false, true ), + ContextSettings( false, 0, 0, GLv_default, true, false ) ); + FileSystem::changeWorkingDirectory( Sys::getProcessPath() ); + + UI::UISceneNode* sceneNode = init_test_inline_block(); + sceneNode->loadLayoutFromString( HTMLFormatter::HTMLtoXML( R"html( + + + + + +
+ Become a Redditor +

and subscribe to one of thousands of communities.

+
+ + + )html" ) ); + win->getInput()->update(); + SceneManager::instance()->update(); + sceneNode->updateDirtyLayouts(); + sceneNode->updateDirtyLayouts(); + + auto* button = sceneNode->getRoot()->find( "button" )->asType(); + ASSERT_TRUE( button != nullptr ); + auto* buttonRichText = button->getRichTextPtr(); + ASSERT_TRUE( buttonRichText != nullptr ); + ASSERT_EQ( buttonRichText->getLines().size(), (size_t)1 ); + ASSERT_FALSE( buttonRichText->getLines().front().spans.empty() ); + + const auto& textSpan = buttonRichText->getLines().front().spans.front(); + const Rectf padding = button->getPixelsPadding(); + EXPECT_LE( textSpan.position.x + textSpan.size.getWidth(), + button->getPixelsSize().getWidth() - padding.Left - padding.Right + 0.5f ); + EXPECT_LE( textSpan.position.y + textSpan.size.getHeight(), + button->getPixelsSize().getHeight() - padding.Top - padding.Bottom + 0.5f ); + + Engine::destroySingleton(); +} + +UTEST( UIHTML, ListingsSignupCtaTextSitsBesideFloatedButton ) { + auto win = Engine::instance()->createWindow( + WindowSettings( 800, 600, "listings signup cta float text", WindowStyle::Default, + WindowBackend::Default, 32, {}, 1, false, true ), + ContextSettings( false, 0, 0, GLv_default, true, false ) ); + FileSystem::changeWorkingDirectory( Sys::getProcessPath() ); + + UI::UISceneNode* sceneNode = init_test_inline_block(); + sceneNode->loadLayoutFromString( HTMLFormatter::HTMLtoXML( R"html( + + + + + +
+ +

Welcome to Reddit.

+

Where a community about your favorite things is waiting for you.

+
+ Become a Redditor +

and subscribe to one of thousands of communities.

+
+
+
+ + + )html" ) ); + win->getInput()->update(); + SceneManager::instance()->update(); + sceneNode->updateDirtyLayouts(); + sceneNode->updateDirtyLayouts(); + + auto* cta = sceneNode->getRoot()->find( "cta" )->asType(); + auto* button = sceneNode->getRoot()->find( "button" )->asType(); + auto* desc = sceneNode->getRoot()->find( "cta-desc" )->asType(); + ASSERT_TRUE( cta != nullptr ); + ASSERT_TRUE( button != nullptr ); + ASSERT_TRUE( desc != nullptr ); + auto* buttonRichText = button->getRichTextPtr(); + ASSERT_TRUE( buttonRichText != nullptr ); + ASSERT_EQ( buttonRichText->getLines().size(), (size_t)1 ); + ASSERT_FALSE( buttonRichText->getLines().front().spans.empty() ); + + const Vector2f buttonPos = button->convertToWorldSpace( { 0, 0 } ); + const Vector2f descPos = desc->convertToWorldSpace( { 0, 0 } ); + const auto& buttonTextSpan = buttonRichText->getLines().front().spans.front(); + ASSERT_TRUE( desc->getRichTextPtr() != nullptr ); + ASSERT_FALSE( desc->getRichTextPtr()->getLines().empty() ); + ASSERT_FALSE( desc->getRichTextPtr()->getLines().front().spans.empty() ); + const auto& firstDescSpan = desc->getRichTextPtr()->getLines().front().spans.front(); + + EXPECT_LE( buttonTextSpan.position.x, 1.f ); + EXPECT_LE( buttonTextSpan.position.x + buttonTextSpan.size.getWidth(), + button->getPixelsSize().getWidth() - button->getPixelsContentOffset().Left - + button->getPixelsContentOffset().Right + 0.5f ); + EXPECT_GE( descPos.x + firstDescSpan.position.x, + buttonPos.x + button->getPixelsSize().getWidth() - 0.5f ); + EXPECT_LT( std::abs( descPos.y - buttonPos.y ), button->getPixelsSize().getHeight() ); + + Engine::destroySingleton(); +} + UTEST( UIHTML, AnchorsSizing ) { auto win = Engine::instance()->createWindow( WindowSettings( 1024, 653, "anchors sizing", WindowStyle::Default, WindowBackend::Default,