mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-10-01 10:40:20 +03:00
Fix HTML input styling and internal control layout
Treat UIHTMLInput as the stable HTML/CSS host while keeping its native control as an anonymous implementation detail. Prevent author CSS from matching internal control widgets, avoiding duplicated backgrounds and other styles. Keep valid input types such as email intact for attribute selectors while falling back to compatible native implementations. Synchronize the internal control with the host content box after layout, including flex sizing, and preserve intrinsic measurement for size and font changes. Preserve input state across dynamic type changes and make hidden transitions reversible. Also fix border-radius calculations and add regressions for CSS ownership, anonymous widget isolation, dynamic type changes, input sizing, and the Causality newsletter form.
This commit is contained in:
@@ -1467,6 +1467,7 @@ UTEST( UIHTMLTable, nestedSpecifiedWidth ) {
|
||||
UTEST( UIHTMLInput, sizeAttribute ) {
|
||||
init_ui_test();
|
||||
auto* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
sceneNode->combineStyleSheet( "* { background-color: #fedcba; border-width: 2px; }" );
|
||||
sceneNode->loadLayoutFromString( R"html(
|
||||
<vbox layout_width="wrap_content" layout_height="wrap_content">
|
||||
<input id="i1" size="10" />
|
||||
@@ -1969,6 +1970,77 @@ UTEST( UIHTML, FormControlsDefaultInlineBlock ) {
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIHTMLInput, hostOwnsCSSBox ) {
|
||||
init_ui_test();
|
||||
auto* sceneNode = SceneManager::instance()->getUISceneNode();
|
||||
sceneNode->loadLayoutFromString( R"html(
|
||||
<vbox layout_width="wrap_content" layout_height="wrap_content">
|
||||
<input id="styled_input" type="text"
|
||||
style="background-color: #123456; border: 3px solid #abcdef; padding: 5px;" />
|
||||
</vbox>
|
||||
)html" );
|
||||
sceneNode->updateDirtyLayouts();
|
||||
|
||||
auto* input = sceneNode->getRoot()->find( "styled_input" )->asType<UIHTMLInput>();
|
||||
ASSERT_TRUE( input != nullptr );
|
||||
auto* implementation = input->getChildWidget();
|
||||
ASSERT_TRUE( implementation != nullptr );
|
||||
|
||||
EXPECT_TRUE( input->hasBackground() );
|
||||
EXPECT_TRUE( input->hasBorder() );
|
||||
EXPECT_FALSE( implementation->hasBackground() );
|
||||
EXPECT_FALSE( implementation->hasBorder() );
|
||||
EXPECT_TRUE( 0 == ( implementation->getFlags() & UI_HTML_ELEMENT ) );
|
||||
EXPECT_NEAR( input->getPixelsPadding().Left, 5.f, 0.01f );
|
||||
EXPECT_NEAR( input->getPixelsPadding().Top, 5.f, 0.01f );
|
||||
EXPECT_NEAR( input->getPixelsPadding().Right, 5.f, 0.01f );
|
||||
EXPECT_NEAR( input->getPixelsPadding().Bottom, 5.f, 0.01f );
|
||||
EXPECT_TRUE( implementation->getPadding() == Rectf() );
|
||||
EXPECT_NEAR( implementation->getPixelsPosition().x, 8.f, 0.01f );
|
||||
EXPECT_NEAR( implementation->getPixelsPosition().y, 8.f, 0.01f );
|
||||
EXPECT_NEAR( implementation->getPixelsSize().getWidth(),
|
||||
input->getPixelsSize().getWidth() - 16.f, 0.01f );
|
||||
EXPECT_NEAR( implementation->getPixelsSize().getHeight(),
|
||||
input->getPixelsSize().getHeight() - 16.f, 0.01f );
|
||||
|
||||
input->setInputType( "email" );
|
||||
EXPECT_STDSTREQ( input->getInputType(), "email" );
|
||||
EXPECT_TRUE( input->getChildWidget()->isType( UI_TYPE_TEXTINPUT ) );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIHTMLInput, dynamicTypeKeepsHostAndState ) {
|
||||
init_ui_test();
|
||||
auto* input = UIHTMLInput::New();
|
||||
input->setParent( SceneManager::instance()->getUISceneNode()->getRoot() );
|
||||
static_cast<UITextInput*>( input->getChildWidget() )->setText( "edited value" );
|
||||
|
||||
UIHTMLInput* originalHost = input;
|
||||
input->setInputType( "checkbox" );
|
||||
EXPECT_EQ( input, originalHost );
|
||||
EXPECT_TRUE( input->getChildWidget()->isType( UI_TYPE_CHECKBOX ) );
|
||||
|
||||
input->setInputType( "hidden" );
|
||||
EXPECT_FALSE( input->isVisible() );
|
||||
EXPECT_FALSE( input->isEnabled() );
|
||||
EXPECT_EQ( input->getDisplay(), CSSDisplay::None );
|
||||
|
||||
input->setInputType( "text" );
|
||||
EXPECT_EQ( input, originalHost );
|
||||
EXPECT_TRUE( input->isVisible() );
|
||||
EXPECT_TRUE( input->isEnabled() );
|
||||
EXPECT_EQ( input->getDisplay(), CSSDisplay::InlineBlock );
|
||||
ASSERT_TRUE( input->getChildWidget()->isType( UI_TYPE_TEXTINPUT ) );
|
||||
EXPECT_TRUE( static_cast<UITextInput*>( input->getChildWidget() )->getText() ==
|
||||
"edited value" );
|
||||
|
||||
input->setInputType( "unsupported-type" );
|
||||
EXPECT_STDSTREQ( input->getInputType(), "text" );
|
||||
|
||||
Engine::destroySingleton();
|
||||
}
|
||||
|
||||
UTEST( UIHTMLTable, tableLayoutFixed ) {
|
||||
Engine::instance()->createWindow( WindowSettings( 1024, 650, "HTML Tables Test",
|
||||
WindowStyle::Default, WindowBackend::Default,
|
||||
@@ -4886,6 +4958,26 @@ UTEST( UIHTML, FlexMediaQueriesLayout ) {
|
||||
EXPECT_GT( essayNavWidget->getPixelsSize().getHeight(), 10.f );
|
||||
EXPECT_GT( essayNavWidget->getPixelsSize().getWidth(), 10.f );
|
||||
|
||||
// Valid input types that use the text implementation must retain their state for attribute
|
||||
// selectors. Collapsing "email" to "text" loses this rule and exposes the white UA default.
|
||||
auto* newsletter = bodyWidget->findByClass( "newsletter-form" );
|
||||
ASSERT_TRUE( newsletter != nullptr );
|
||||
auto* emailInput = newsletter->findByTag( "input" )->asType<UIHTMLInput>();
|
||||
ASSERT_TRUE( emailInput != nullptr );
|
||||
EXPECT_STDSTREQ( emailInput->getInputType(), "email" );
|
||||
EXPECT_TRUE( emailInput->getBackgroundColor() == Color( "#1C1917" ) );
|
||||
auto* emailImplementation = emailInput->getChildWidget();
|
||||
ASSERT_TRUE( emailImplementation != nullptr );
|
||||
const Rectf emailContentOffset = emailInput->getPixelsContentOffset();
|
||||
EXPECT_NEAR( emailImplementation->getPixelsSize().getWidth(),
|
||||
emailInput->getPixelsSize().getWidth() - emailContentOffset.Left -
|
||||
emailContentOffset.Right,
|
||||
0.01f );
|
||||
EXPECT_NEAR( emailImplementation->getPixelsSize().getHeight(),
|
||||
emailInput->getPixelsSize().getHeight() - emailContentOffset.Top -
|
||||
emailContentOffset.Bottom,
|
||||
0.01f );
|
||||
|
||||
// The essay-nav link contains two spans: label and title
|
||||
// They should stack vertically (flex-direction: column on the <a>)
|
||||
// so the link height should be at least the sum of both span heights
|
||||
|
||||
Reference in New Issue
Block a user