mirror of
https://github.com/SerenityOS/serenity.git
synced 2025-01-22 17:31:58 -05:00
LibWeb: Create BlockContainer layout node for <input type="button">
...and shadow tree with TextNode for "value" attribute is created. This means InlineFormattingContext is used, and button's text now respects CSS text-decoration properties and unicode-ranges. (cherry picked from commit 8feaecd5c8d02a2fdb989a9a9671e008d1c3a7de)
This commit is contained in:
parent
7b47c57c54
commit
c6e3c0a339
11 changed files with 16 additions and 183 deletions
|
@ -12,7 +12,6 @@ source_set("Layout") {
|
||||||
"Box.cpp",
|
"Box.cpp",
|
||||||
"BoxModelMetrics.cpp",
|
"BoxModelMetrics.cpp",
|
||||||
"BreakNode.cpp",
|
"BreakNode.cpp",
|
||||||
"ButtonBox.cpp",
|
|
||||||
"CanvasBox.cpp",
|
"CanvasBox.cpp",
|
||||||
"CheckBox.cpp",
|
"CheckBox.cpp",
|
||||||
"FlexFormattingContext.cpp",
|
"FlexFormattingContext.cpp",
|
||||||
|
|
|
@ -12,7 +12,6 @@ source_set("Painting") {
|
||||||
"BorderRadiiData.cpp",
|
"BorderRadiiData.cpp",
|
||||||
"BorderRadiusCornerClipper.cpp",
|
"BorderRadiusCornerClipper.cpp",
|
||||||
"BordersData.cpp",
|
"BordersData.cpp",
|
||||||
"ButtonPaintable.cpp",
|
|
||||||
"CanvasPaintable.cpp",
|
"CanvasPaintable.cpp",
|
||||||
"CheckBoxPaintable.cpp",
|
"CheckBoxPaintable.cpp",
|
||||||
"ClippableAndScrollable.cpp",
|
"ClippableAndScrollable.cpp",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
wfh :^) PASS wfh :^) wfh :^) FAIL PASS FAIL wfh :^) FAIL FAIL PASS PASS wfh :^) wfh :^) PASS PASSwfh :^) FAIL wfh :^) FAIL wfh :^) wfh :^) FAIL wfh :^) wfh :^) defaultButton: click button=PASS
|
wfh :^) PASS wfh :^) PASS wfh :^) FAIL PASS FAIL wfh :^) FAIL FAIL PASS PASS wfh :^) wfh :^) PASS PASSwfh :^) FAIL wfh :^) FAIL wfh :^) wfh :^) FAIL wfh :^) wfh :^) defaultButton: click button=PASS
|
||||||
defaultButton: submit
|
defaultButton: submit
|
||||||
defaultButton: handledEvent=true
|
defaultButton: handledEvent=true
|
||||||
defaultButtonAsInput: click button=PASS
|
defaultButtonAsInput: click button=PASS
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pass Select file...No file selected. text: "pass"
|
pass pass Select file...No file selected. text: "pass"
|
||||||
hidden: "pass"
|
hidden: "pass"
|
||||||
button: "pass"
|
button: "pass"
|
||||||
checkbox: "pass"
|
checkbox: "pass"
|
||||||
|
|
|
@ -470,7 +470,6 @@ set(SOURCES
|
||||||
Layout/Box.cpp
|
Layout/Box.cpp
|
||||||
Layout/BoxModelMetrics.cpp
|
Layout/BoxModelMetrics.cpp
|
||||||
Layout/BreakNode.cpp
|
Layout/BreakNode.cpp
|
||||||
Layout/ButtonBox.cpp
|
|
||||||
Layout/CanvasBox.cpp
|
Layout/CanvasBox.cpp
|
||||||
Layout/CheckBox.cpp
|
Layout/CheckBox.cpp
|
||||||
Layout/FlexFormattingContext.cpp
|
Layout/FlexFormattingContext.cpp
|
||||||
|
@ -536,7 +535,6 @@ set(SOURCES
|
||||||
Painting/BorderPainting.cpp
|
Painting/BorderPainting.cpp
|
||||||
Painting/BorderRadiusCornerClipper.cpp
|
Painting/BorderRadiusCornerClipper.cpp
|
||||||
Painting/BordersData.cpp
|
Painting/BordersData.cpp
|
||||||
Painting/ButtonPaintable.cpp
|
|
||||||
Painting/CanvasPaintable.cpp
|
Painting/CanvasPaintable.cpp
|
||||||
Painting/Command.cpp
|
Painting/Command.cpp
|
||||||
Painting/CommandExecutorCPU.cpp
|
Painting/CommandExecutorCPU.cpp
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
#include <LibWeb/Infra/CharacterTypes.h>
|
#include <LibWeb/Infra/CharacterTypes.h>
|
||||||
#include <LibWeb/Infra/Strings.h>
|
#include <LibWeb/Infra/Strings.h>
|
||||||
#include <LibWeb/Layout/BlockContainer.h>
|
#include <LibWeb/Layout/BlockContainer.h>
|
||||||
#include <LibWeb/Layout/ButtonBox.h>
|
|
||||||
#include <LibWeb/Layout/CheckBox.h>
|
#include <LibWeb/Layout/CheckBox.h>
|
||||||
#include <LibWeb/Layout/ImageBox.h>
|
#include <LibWeb/Layout/ImageBox.h>
|
||||||
#include <LibWeb/Layout/RadioButton.h>
|
#include <LibWeb/Layout/RadioButton.h>
|
||||||
|
@ -100,7 +99,7 @@ JS::GCPtr<Layout::Node> HTMLInputElement::create_layout_node(NonnullRefPtr<CSS::
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (type_state() == TypeAttributeState::SubmitButton || type_state() == TypeAttributeState::Button || type_state() == TypeAttributeState::ResetButton)
|
if (type_state() == TypeAttributeState::SubmitButton || type_state() == TypeAttributeState::Button || type_state() == TypeAttributeState::ResetButton)
|
||||||
return heap().allocate_without_realm<Layout::ButtonBox>(document(), *this, move(style));
|
return heap().allocate_without_realm<Layout::BlockContainer>(document(), this, move(style));
|
||||||
|
|
||||||
if (type_state() == TypeAttributeState::ImageButton)
|
if (type_state() == TypeAttributeState::ImageButton)
|
||||||
return heap().allocate_without_realm<Layout::ImageBox>(document(), *this, move(style), *this);
|
return heap().allocate_without_realm<Layout::ImageBox>(document(), *this, move(style), *this);
|
||||||
|
@ -740,9 +739,12 @@ void HTMLInputElement::create_shadow_tree_if_needed()
|
||||||
case TypeAttributeState::Hidden:
|
case TypeAttributeState::Hidden:
|
||||||
case TypeAttributeState::RadioButton:
|
case TypeAttributeState::RadioButton:
|
||||||
case TypeAttributeState::Checkbox:
|
case TypeAttributeState::Checkbox:
|
||||||
|
break;
|
||||||
case TypeAttributeState::Button:
|
case TypeAttributeState::Button:
|
||||||
case TypeAttributeState::SubmitButton:
|
case TypeAttributeState::SubmitButton:
|
||||||
case TypeAttributeState::ResetButton:
|
case TypeAttributeState::ResetButton:
|
||||||
|
create_button_input_shadow_tree();
|
||||||
|
break;
|
||||||
case TypeAttributeState::ImageButton:
|
case TypeAttributeState::ImageButton:
|
||||||
break;
|
break;
|
||||||
case TypeAttributeState::Color:
|
case TypeAttributeState::Color:
|
||||||
|
@ -779,6 +781,15 @@ void HTMLInputElement::update_shadow_tree()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HTMLInputElement::create_button_input_shadow_tree()
|
||||||
|
{
|
||||||
|
auto shadow_root = heap().allocate<DOM::ShadowRoot>(realm(), document(), *this, Bindings::ShadowRootMode::Closed);
|
||||||
|
set_shadow_root(shadow_root);
|
||||||
|
|
||||||
|
m_text_node = heap().allocate<DOM::Text>(realm(), document(), value());
|
||||||
|
MUST(shadow_root->append_child(*m_text_node));
|
||||||
|
}
|
||||||
|
|
||||||
void HTMLInputElement::create_text_input_shadow_tree()
|
void HTMLInputElement::create_text_input_shadow_tree()
|
||||||
{
|
{
|
||||||
auto shadow_root = heap().allocate<DOM::ShadowRoot>(realm(), document(), *this, Bindings::ShadowRootMode::Closed);
|
auto shadow_root = heap().allocate<DOM::ShadowRoot>(realm(), document(), *this, Bindings::ShadowRootMode::Closed);
|
||||||
|
|
|
@ -243,6 +243,7 @@ private:
|
||||||
static TypeAttributeState parse_type_attribute(StringView);
|
static TypeAttributeState parse_type_attribute(StringView);
|
||||||
void create_shadow_tree_if_needed();
|
void create_shadow_tree_if_needed();
|
||||||
void update_shadow_tree();
|
void update_shadow_tree();
|
||||||
|
void create_button_input_shadow_tree();
|
||||||
void create_text_input_shadow_tree();
|
void create_text_input_shadow_tree();
|
||||||
void create_color_input_shadow_tree();
|
void create_color_input_shadow_tree();
|
||||||
void create_file_input_shadow_tree();
|
void create_file_input_shadow_tree();
|
||||||
|
|
|
@ -1,40 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <LibGfx/Font/Font.h>
|
|
||||||
#include <LibWeb/DOM/Document.h>
|
|
||||||
#include <LibWeb/Layout/ButtonBox.h>
|
|
||||||
#include <LibWeb/Painting/ButtonPaintable.h>
|
|
||||||
|
|
||||||
namespace Web::Layout {
|
|
||||||
|
|
||||||
JS_DEFINE_ALLOCATOR(ButtonBox);
|
|
||||||
|
|
||||||
ButtonBox::ButtonBox(DOM::Document& document, HTML::HTMLInputElement& element, NonnullRefPtr<CSS::StyleProperties> style)
|
|
||||||
: FormAssociatedLabelableNode(document, element, move(style))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
ButtonBox::~ButtonBox() = default;
|
|
||||||
|
|
||||||
void ButtonBox::prepare_for_replaced_layout()
|
|
||||||
{
|
|
||||||
// For <input type="submit" /> and <input type="button" />, the contents of
|
|
||||||
// the button does not appear as the contents of the element but as the
|
|
||||||
// value attribute. This is not the case with <button />, which contains
|
|
||||||
// its contents normally.
|
|
||||||
if (is<HTML::HTMLInputElement>(dom_node())) {
|
|
||||||
set_natural_width(CSSPixels::nearest_value_for(first_available_font().width(static_cast<HTML::HTMLInputElement&>(dom_node()).value())));
|
|
||||||
set_natural_height(first_available_font().pixel_size_rounded_up());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::GCPtr<Painting::Paintable> ButtonBox::create_paintable() const
|
|
||||||
{
|
|
||||||
return Painting::ButtonPaintable::create(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <LibWeb/HTML/HTMLInputElement.h>
|
|
||||||
#include <LibWeb/Layout/FormAssociatedLabelableNode.h>
|
|
||||||
|
|
||||||
namespace Web::Layout {
|
|
||||||
|
|
||||||
class ButtonBox final : public FormAssociatedLabelableNode {
|
|
||||||
JS_CELL(ButtonBox, FormAssociatedLabelableNode);
|
|
||||||
JS_DECLARE_ALLOCATOR(ButtonBox);
|
|
||||||
|
|
||||||
public:
|
|
||||||
ButtonBox(DOM::Document&, HTML::HTMLInputElement&, NonnullRefPtr<CSS::StyleProperties>);
|
|
||||||
virtual ~ButtonBox() override;
|
|
||||||
|
|
||||||
virtual void prepare_for_replaced_layout() override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
virtual JS::GCPtr<Painting::Paintable> create_paintable() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,77 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2018-2022, Andreas Kling <kling@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <LibWeb/HTML/BrowsingContext.h>
|
|
||||||
#include <LibWeb/HTML/HTMLImageElement.h>
|
|
||||||
#include <LibWeb/Layout/ButtonBox.h>
|
|
||||||
#include <LibWeb/Layout/Label.h>
|
|
||||||
#include <LibWeb/Painting/ButtonPaintable.h>
|
|
||||||
|
|
||||||
namespace Web::Painting {
|
|
||||||
|
|
||||||
JS_DEFINE_ALLOCATOR(ButtonPaintable);
|
|
||||||
|
|
||||||
JS::NonnullGCPtr<ButtonPaintable> ButtonPaintable::create(Layout::ButtonBox const& layout_box)
|
|
||||||
{
|
|
||||||
return layout_box.heap().allocate_without_realm<ButtonPaintable>(layout_box);
|
|
||||||
}
|
|
||||||
|
|
||||||
ButtonPaintable::ButtonPaintable(Layout::ButtonBox const& layout_box)
|
|
||||||
: LabelablePaintable(layout_box)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Layout::ButtonBox const& ButtonPaintable::layout_box() const
|
|
||||||
{
|
|
||||||
return static_cast<Layout::ButtonBox const&>(layout_node());
|
|
||||||
}
|
|
||||||
|
|
||||||
Layout::ButtonBox& ButtonPaintable::layout_box()
|
|
||||||
{
|
|
||||||
return static_cast<Layout::ButtonBox&>(layout_node());
|
|
||||||
}
|
|
||||||
|
|
||||||
void ButtonPaintable::paint(PaintContext& context, PaintPhase phase) const
|
|
||||||
{
|
|
||||||
if (!is_visible())
|
|
||||||
return;
|
|
||||||
|
|
||||||
PaintableBox::paint(context, phase);
|
|
||||||
|
|
||||||
auto const& dom_node = layout_box().dom_node();
|
|
||||||
if (is<HTML::HTMLInputElement>(dom_node) && phase == PaintPhase::Foreground) {
|
|
||||||
auto button_rect = context.enclosing_device_rect(absolute_rect());
|
|
||||||
auto text_rect = button_rect;
|
|
||||||
|
|
||||||
// Apply CSS text-indent property to text rect
|
|
||||||
// FIXME: The second parameter to to_px() needs to be the block container’s own inline-axis inner size:
|
|
||||||
// https://drafts.csswg.org/css-text-3/#propdef-text-indent
|
|
||||||
auto text_indent = computed_values().text_indent().to_px(layout_box(), CSSPixels());
|
|
||||||
text_rect.translate_by(context.rounded_device_pixels(text_indent), 0);
|
|
||||||
|
|
||||||
// Apply button pressed state offset
|
|
||||||
if (being_pressed()) {
|
|
||||||
auto offset = context.rounded_device_pixels(1);
|
|
||||||
text_rect.translate_by(offset, offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Paint button text clipped to button rect
|
|
||||||
auto& painter = context.recording_painter();
|
|
||||||
painter.save();
|
|
||||||
auto clip_rect = absolute_rect();
|
|
||||||
clip_rect.translate_by(enclosing_scroll_frame_offset().value_or({}));
|
|
||||||
painter.add_clip_rect(context.enclosing_device_rect(clip_rect).to_type<int>());
|
|
||||||
painter.draw_text(
|
|
||||||
text_rect.to_type<int>(),
|
|
||||||
static_cast<HTML::HTMLInputElement const&>(dom_node).value(),
|
|
||||||
layout_box().scaled_font(context.device_pixels_per_css_pixel()),
|
|
||||||
Gfx::TextAlignment::Center,
|
|
||||||
computed_values().color());
|
|
||||||
painter.restore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,30 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2022, Andreas Kling <kling@serenityos.org>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <LibWeb/Layout/ButtonBox.h>
|
|
||||||
#include <LibWeb/Painting/LabelablePaintable.h>
|
|
||||||
|
|
||||||
namespace Web::Painting {
|
|
||||||
|
|
||||||
class ButtonPaintable final : public LabelablePaintable {
|
|
||||||
JS_CELL(ButtonPaintable, LabelablePaintable);
|
|
||||||
JS_DECLARE_ALLOCATOR(ButtonPaintable);
|
|
||||||
|
|
||||||
public:
|
|
||||||
static JS::NonnullGCPtr<ButtonPaintable> create(Layout::ButtonBox const&);
|
|
||||||
|
|
||||||
virtual void paint(PaintContext&, PaintPhase) const override;
|
|
||||||
|
|
||||||
Layout::ButtonBox const& layout_box() const;
|
|
||||||
Layout::ButtonBox& layout_box();
|
|
||||||
|
|
||||||
private:
|
|
||||||
ButtonPaintable(Layout::ButtonBox const&);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in a new issue