Commit 3c4c13ac authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

Move LayoutMenuList::DidUpdateActiveOption() to HTMLSelectElement

Also,
 - Remove LayoutMenuList::DidSelectOption().
 - Add HTMLFormControlElement::UpdateFromElement() to add
  DidUpdateMenuListActiveOption() to each of
  LayoutMenuList::UpdateFromElement() calls.

This CL is a preparation to build a LayoutNG counterpart of LayoutMenuList.
This CL has no behavior changes.

Bug: 1040828
Change-Id: If7917af101119a830e899a50711a6c1491e22eb3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2003164Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#732313}
parent ca51fa99
...@@ -205,13 +205,15 @@ const AtomicString& HTMLFormControlElement::autocapitalize() const { ...@@ -205,13 +205,15 @@ const AtomicString& HTMLFormControlElement::autocapitalize() const {
void HTMLFormControlElement::AttachLayoutTree(AttachContext& context) { void HTMLFormControlElement::AttachLayoutTree(AttachContext& context) {
HTMLElement::AttachLayoutTree(context); HTMLElement::AttachLayoutTree(context);
if (!GetLayoutObject()) // The call to UpdateFromElement() needs to go after the call through
return;
// The call to updateFromElement() needs to go after the call through
// to the base class's attachLayoutTree() because that can sometimes do a // to the base class's attachLayoutTree() because that can sometimes do a
// close on the layoutObject. // close on the LayoutObject.
GetLayoutObject()->UpdateFromElement(); UpdateFromElement();
}
void HTMLFormControlElement::UpdateFromElement() {
if (auto* layout_object = GetLayoutObject())
layout_object->UpdateFromElement();
} }
void HTMLFormControlElement::DidMoveToNewDocument(Document& old_document) { void HTMLFormControlElement::DidMoveToNewDocument(Document& old_document) {
......
...@@ -150,6 +150,10 @@ class CORE_EXPORT HTMLFormControlElement : public HTMLElement, ...@@ -150,6 +150,10 @@ class CORE_EXPORT HTMLFormControlElement : public HTMLElement,
virtual void ResetImpl() {} virtual void ResetImpl() {}
// This is called just after attaching a LayoutObject. However,
// GetLayoutObject() can be nullptr.
virtual void UpdateFromElement();
private: private:
bool IsFormControlElement() const final { return true; } bool IsFormControlElement() const final { return true; }
bool AlwaysCreateUserAgentShadowRoot() const override { return true; } bool AlwaysCreateUserAgentShadowRoot() const override { return true; }
......
...@@ -357,7 +357,7 @@ void HTMLSelectElement::OptionElementChildrenChanged( ...@@ -357,7 +357,7 @@ void HTMLSelectElement::OptionElementChildrenChanged(
if (GetLayoutObject()) { if (GetLayoutObject()) {
if (option.Selected() && UsesMenuList()) if (option.Selected() && UsesMenuList())
GetLayoutObject()->UpdateFromElement(); UpdateFromElement();
if (AXObjectCache* cache = if (AXObjectCache* cache =
GetLayoutObject()->GetDocument().ExistingAXObjectCache()) GetLayoutObject()->GetDocument().ExistingAXObjectCache())
cache->ChildrenChanged(this); cache->ChildrenChanged(this);
...@@ -903,8 +903,8 @@ void HTMLSelectElement::SetSuggestedOption(HTMLOptionElement* option) { ...@@ -903,8 +903,8 @@ void HTMLSelectElement::SetSuggestedOption(HTMLOptionElement* option) {
return; return;
suggested_option_ = option; suggested_option_ = option;
if (LayoutObject* layout_object = GetLayoutObject()) { if (GetLayoutObject()) {
layout_object->UpdateFromElement(); UpdateFromElement();
ScrollToOption(option); ScrollToOption(option);
} }
if (PopupIsVisible()) if (PopupIsVisible())
...@@ -1078,8 +1078,7 @@ void HTMLSelectElement::SelectOption(HTMLOptionElement* element, ...@@ -1078,8 +1078,7 @@ void HTMLSelectElement::SelectOption(HTMLOptionElement* element,
} }
// For the menu list case, this is what makes the selected element appear. // For the menu list case, this is what makes the selected element appear.
if (LayoutObject* layout_object = GetLayoutObject()) UpdateFromElement();
layout_object->UpdateFromElement();
// PopupMenu::UpdateFromElement() posts an O(N) task. // PopupMenu::UpdateFromElement() posts an O(N) task.
if (PopupIsVisible() && should_update_popup) if (PopupIsVisible() && should_update_popup)
popup_->UpdateFromElement(PopupMenu::kBySelectionChange); popup_->UpdateFromElement(PopupMenu::kBySelectionChange);
...@@ -1096,8 +1095,9 @@ void HTMLSelectElement::SelectOption(HTMLOptionElement* element, ...@@ -1096,8 +1095,9 @@ void HTMLSelectElement::SelectOption(HTMLOptionElement* element,
// Need to check UsesMenuList() again because event handlers might // Need to check UsesMenuList() again because event handlers might
// change the status. // change the status.
if (UsesMenuList()) { if (UsesMenuList()) {
// DidSelectOption() is O(N) because of HTMLOptionElement::index(). // DidUpdateMenuListActiveOption() is O(N) because of
ToLayoutMenuList(layout_object)->DidSelectOption(element); // HTMLOptionElement::index().
DidUpdateMenuListActiveOption(element);
} }
} }
} }
...@@ -1510,6 +1510,27 @@ void HTMLSelectElement::UpdateSelectedState(HTMLOptionElement* clicked_option, ...@@ -1510,6 +1510,27 @@ void HTMLSelectElement::UpdateSelectedState(HTMLOptionElement* clicked_option,
UpdateListBoxSelection(!multi_select); UpdateListBoxSelection(!multi_select);
} }
void HTMLSelectElement::DidUpdateMenuListActiveOption(
HTMLOptionElement* option) {
if (!GetDocument().ExistingAXObjectCache())
return;
int option_index = option ? option->index() : -1;
if (ax_menulist_last_active_index_ == option_index)
return;
ax_menulist_last_active_index_ = option_index;
// We skip sending accessiblity notifications for the very first option,
// otherwise we get extra focus and select events that are undesired.
if (!has_updated_menulist_active_option_) {
has_updated_menulist_active_option_ = true;
return;
}
GetDocument().ExistingAXObjectCache()->HandleUpdateActiveMenuOption(
ToLayoutMenuList(GetLayoutObject()), option_index);
}
HTMLOptionElement* HTMLSelectElement::EventTargetOption(const Event& event) { HTMLOptionElement* HTMLSelectElement::EventTargetOption(const Event& event) {
return DynamicTo<HTMLOptionElement>(event.target()->ToNode()); return DynamicTo<HTMLOptionElement>(event.target()->ToNode());
} }
...@@ -2002,8 +2023,7 @@ void HTMLSelectElement::PopupDidHide() { ...@@ -2002,8 +2023,7 @@ void HTMLSelectElement::PopupDidHide() {
void HTMLSelectElement::SetIndexToSelectOnCancel(int list_index) { void HTMLSelectElement::SetIndexToSelectOnCancel(int list_index) {
index_to_select_on_cancel_ = list_index; index_to_select_on_cancel_ = list_index;
if (GetLayoutObject()) UpdateFromElement();
GetLayoutObject()->UpdateFromElement();
} }
HTMLOptionElement* HTMLSelectElement::OptionToBeShown() const { HTMLOptionElement* HTMLSelectElement::OptionToBeShown() const {
...@@ -2203,6 +2223,20 @@ void HTMLSelectElement::ChangeRendering() { ...@@ -2203,6 +2223,20 @@ void HTMLSelectElement::ChangeRendering() {
DetachLayoutTree(); DetachLayoutTree();
SetNeedsStyleRecalc(kLocalStyleChange, StyleChangeReasonForTracing::Create( SetNeedsStyleRecalc(kLocalStyleChange, StyleChangeReasonForTracing::Create(
style_change_reason::kControl)); style_change_reason::kControl));
if (UsesMenuList()) {
ax_menulist_last_active_index_ = -1;
has_updated_menulist_active_option_ = false;
}
}
void HTMLSelectElement::UpdateFromElement() {
auto* layout_object = GetLayoutObject();
if (!layout_object)
return;
layout_object->UpdateFromElement();
if (UsesMenuList())
DidUpdateMenuListActiveOption(OptionToBeShown());
} }
} // namespace blink } // namespace blink
...@@ -179,6 +179,7 @@ class CORE_EXPORT HTMLSelectElement final ...@@ -179,6 +179,7 @@ class CORE_EXPORT HTMLSelectElement final
private: private:
const AtomicString& FormControlType() const override; const AtomicString& FormControlType() const override;
void UpdateFromElement() override;
bool MayTriggerVirtualKeyboard() const override; bool MayTriggerVirtualKeyboard() const override;
...@@ -242,6 +243,7 @@ class CORE_EXPORT HTMLSelectElement final ...@@ -242,6 +243,7 @@ class CORE_EXPORT HTMLSelectElement final
void ParseMultipleAttribute(const AtomicString&); void ParseMultipleAttribute(const AtomicString&);
HTMLOptionElement* LastSelectedOption() const; HTMLOptionElement* LastSelectedOption() const;
void UpdateSelectedState(HTMLOptionElement*, bool multi, bool shift); void UpdateSelectedState(HTMLOptionElement*, bool multi, bool shift);
void DidUpdateMenuListActiveOption(HTMLOptionElement*);
void MenuListDefaultEventHandler(Event&); void MenuListDefaultEventHandler(Event&);
void HandlePopupOpenKeyboardEvent(Event&); void HandlePopupOpenKeyboardEvent(Event&);
bool ShouldOpenPopupForKeyDownEvent(const KeyboardEvent&); bool ShouldOpenPopupForKeyDownEvent(const KeyboardEvent&);
...@@ -303,6 +305,8 @@ class CORE_EXPORT HTMLSelectElement final ...@@ -303,6 +305,8 @@ class CORE_EXPORT HTMLSelectElement final
Member<HTMLOptionElement> active_selection_end_; Member<HTMLOptionElement> active_selection_end_;
Member<HTMLOptionElement> option_to_scroll_to_; Member<HTMLOptionElement> option_to_scroll_to_;
Member<HTMLOptionElement> suggested_option_; Member<HTMLOptionElement> suggested_option_;
int ax_menulist_last_active_index_ = -1;
bool has_updated_menulist_active_option_ = false;
bool is_multiple_; bool is_multiple_;
bool is_in_non_contiguous_selection_; bool is_in_non_contiguous_selection_;
bool active_selection_state_; bool active_selection_state_;
......
...@@ -46,10 +46,8 @@ LayoutMenuList::LayoutMenuList(Element* element) ...@@ -46,10 +46,8 @@ LayoutMenuList::LayoutMenuList(Element* element)
button_text_(nullptr), button_text_(nullptr),
inner_block_(nullptr), inner_block_(nullptr),
is_empty_(false), is_empty_(false),
has_updated_active_option_(false),
inner_block_height_(LayoutUnit()), inner_block_height_(LayoutUnit()),
options_width_(0), options_width_(0) {
last_active_index_(-1) {
DCHECK(IsA<HTMLSelectElement>(element)); DCHECK(IsA<HTMLSelectElement>(element));
} }
...@@ -266,8 +264,6 @@ void LayoutMenuList::UpdateFromElement() { ...@@ -266,8 +264,6 @@ void LayoutMenuList::UpdateFromElement() {
SetText(text.StripWhiteSpace()); SetText(text.StripWhiteSpace());
DidUpdateActiveOption(option);
DCHECK(inner_block_); DCHECK(inner_block_);
if (HasOptionStyleChanged(inner_block_->StyleRef())) if (HasOptionStyleChanged(inner_block_->StyleRef()))
UpdateInnerStyle(); UpdateInnerStyle();
...@@ -339,30 +335,6 @@ void LayoutMenuList::ComputeLogicalHeight( ...@@ -339,30 +335,6 @@ void LayoutMenuList::ComputeLogicalHeight(
LayoutBox::ComputeLogicalHeight(logical_height, logical_top, computed_values); LayoutBox::ComputeLogicalHeight(logical_height, logical_top, computed_values);
} }
void LayoutMenuList::DidSelectOption(HTMLOptionElement* option) {
DidUpdateActiveOption(option);
}
void LayoutMenuList::DidUpdateActiveOption(HTMLOptionElement* option) {
if (!GetDocument().ExistingAXObjectCache())
return;
int option_index = option ? option->index() : -1;
if (last_active_index_ == option_index)
return;
last_active_index_ = option_index;
// We skip sending accessiblity notifications for the very first option,
// otherwise we get extra focus and select events that are undesired.
if (!has_updated_active_option_) {
has_updated_active_option_ = true;
return;
}
GetDocument().ExistingAXObjectCache()->HandleUpdateActiveMenuOption(
this, option_index);
}
LayoutUnit LayoutMenuList::ClientPaddingLeft() const { LayoutUnit LayoutMenuList::ClientPaddingLeft() const {
return PaddingLeft() + inner_block_->PaddingLeft(); return PaddingLeft() + inner_block_->PaddingLeft();
} }
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
namespace blink { namespace blink {
class HTMLOptionElement;
class HTMLSelectElement; class HTMLSelectElement;
class LayoutText; class LayoutText;
...@@ -41,7 +40,6 @@ class CORE_EXPORT LayoutMenuList final : public LayoutFlexibleBox { ...@@ -41,7 +40,6 @@ class CORE_EXPORT LayoutMenuList final : public LayoutFlexibleBox {
~LayoutMenuList() override; ~LayoutMenuList() override;
HTMLSelectElement* SelectElement() const; HTMLSelectElement* SelectElement() const;
void DidSelectOption(HTMLOptionElement*);
String GetText() const; String GetText() const;
const char* GetName() const override { return "LayoutMenuList"; } const char* GetName() const override { return "LayoutMenuList"; }
...@@ -103,20 +101,15 @@ class CORE_EXPORT LayoutMenuList final : public LayoutFlexibleBox { ...@@ -103,20 +101,15 @@ class CORE_EXPORT LayoutMenuList final : public LayoutFlexibleBox {
void UpdateOptionsWidth() const; void UpdateOptionsWidth() const;
void SetIndexToSelectOnCancel(int list_index); void SetIndexToSelectOnCancel(int list_index);
void DidUpdateActiveOption(HTMLOptionElement*);
LayoutText* button_text_; LayoutText* button_text_;
LayoutBlock* inner_block_; LayoutBlock* inner_block_;
bool is_empty_ : 1; bool is_empty_ : 1;
bool has_updated_active_option_ : 1;
LayoutUnit inner_block_height_; LayoutUnit inner_block_height_;
// m_optionsWidth is calculated and cached on demand. // m_optionsWidth is calculated and cached on demand.
// updateOptionsWidth() should be called before reading them. // updateOptionsWidth() should be called before reading them.
mutable int options_width_; mutable int options_width_;
int last_active_index_;
scoped_refptr<const ComputedStyle> option_style_; scoped_refptr<const ComputedStyle> option_style_;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment