diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/editing/commands')
20 files changed, 703 insertions, 199 deletions
diff --git a/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc index 33898e3e187..d4d67a3a60b 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/apply_style_command.cc @@ -26,6 +26,7 @@ #include "third_party/blink/renderer/core/editing/commands/apply_style_command.h" #include "third_party/blink/renderer/core/css/css_computed_style_declaration.h" +#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h" #include "third_party/blink/renderer/core/css/css_primitive_value.h" #include "third_party/blink/renderer/core/css/css_property_names.h" #include "third_party/blink/renderer/core/css/css_property_value_set.h" @@ -48,7 +49,6 @@ #include "third_party/blink/renderer/core/editing/visible_selection.h" #include "third_party/blink/renderer/core/editing/visible_units.h" #include "third_party/blink/renderer/core/editing/writing_direction.h" -#include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/html/html_font_element.h" #include "third_party/blink/renderer/core/html/html_span_element.h" #include "third_party/blink/renderer/core/html_names.h" @@ -56,6 +56,7 @@ #include "third_party/blink/renderer/core/layout/layout_text.h" #include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/heap.h" +#include "third_party/blink/renderer/platform/instrumentation/use_counter.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" @@ -510,8 +511,8 @@ void ApplyStyleCommand::ApplyRelativeFontStyleChange( if (current_font_size != desired_font_size) { inline_style->SetProperty( CSSPropertyID::kFontSize, - *CSSPrimitiveValue::Create(desired_font_size, - CSSPrimitiveValue::UnitType::kPixels), + *CSSNumericLiteralValue::Create(desired_font_size, + CSSPrimitiveValue::UnitType::kPixels), false); SetNodeAttribute(element, kStyleAttr, AtomicString(inline_style->AsText())); @@ -532,11 +533,14 @@ void ApplyStyleCommand::ApplyRelativeFontStyleChange( } static ContainerNode* DummySpanAncestorForNode(const Node* node) { - while (node && (!node->IsElementNode() || - !IsStyleSpanOrSpanWithOnlyStyleAttribute(ToElement(node)))) - node = node->parentNode(); + if (!node) + return nullptr; - return node ? node->parentNode() : nullptr; + for (Node& current : NodeTraversal::InclusiveAncestorsOf(*node)) { + if (IsStyleSpanOrSpanWithOnlyStyleAttribute(DynamicTo<Element>(current))) + return current.parentNode(); + } + return nullptr; } void ApplyStyleCommand::CleanupUnstyledAppleStyleSpans( @@ -615,7 +619,7 @@ HTMLElement* ApplyStyleCommand::SplitAncestorsWithUnicodeBidi( // Split every ancestor through highest ancestor with embedding. Node* current_node = node; while (current_node) { - Element* parent = ToElement(current_node->parentNode()); + auto* parent = To<Element>(current_node->parentNode()); if (before ? current_node->previousSibling() : current_node->nextSibling()) SplitElement(parent, before ? current_node : current_node->nextSibling()); if (parent == highest_ancestor_with_unicode_bidi) @@ -639,7 +643,7 @@ void ApplyStyleCommand::RemoveEmbeddingUpToEnclosingBlock( if (!runner.IsStyledElement()) continue; - Element* element = ToElement(&runner); + auto* element = To<Element>(&runner); CSSValueID unicode_bidi = GetIdentifierValue( MakeGarbageCollected<CSSComputedStyleDeclaration>(element), CSSPropertyID::kUnicodeBidi); @@ -1283,7 +1287,7 @@ static Element* UnsplittableElementForPosition(const Position& p) { // Since enclosingNodeOfType won't search beyond the highest root editable // node, this code works even if the closest table cell was outside of the // root editable node. - Element* enclosing_cell = ToElement(EnclosingNodeOfType(p, &IsTableCell)); + auto* enclosing_cell = To<Element>(EnclosingNodeOfType(p, &IsTableCell)); if (enclosing_cell) return enclosing_cell; @@ -1376,8 +1380,8 @@ void ApplyStyleCommand::PushDownInlineStyleAroundNode( GetChildNodes(To<ContainerNode>(*current), current_children); Element* styled_element = nullptr; if (current->IsStyledElement() && - IsStyledInlineElementToRemove(ToElement(current))) { - styled_element = ToElement(current); + IsStyledInlineElementToRemove(To<Element>(current))) { + styled_element = To<Element>(current); elements_to_push_down.push_back(styled_element); } @@ -1699,8 +1703,8 @@ bool ApplyStyleCommand::MergeStartWithPreviousIfIdentical( if (previous_sibling && AreIdenticalElements(*start_node, *previous_sibling)) { - Element* previous_element = ToElement(previous_sibling); - Element* element = ToElement(start_node); + auto* previous_element = To<Element>(previous_sibling); + auto* element = To<Element>(start_node); Node* start_child = element->firstChild(); DCHECK(start_child); MergeIdenticalElements(previous_element, element, editing_state); @@ -1742,8 +1746,8 @@ bool ApplyStyleCommand::MergeEndWithNextIfIdentical( Node* next_sibling = end_node->nextSibling(); if (next_sibling && AreIdenticalElements(*end_node, *next_sibling)) { - Element* next_element = ToElement(next_sibling); - Element* element = ToElement(end_node); + auto* next_element = To<Element>(next_sibling); + auto* element = To<Element>(end_node); Node* next_child = next_element->firstChild(); MergeIdenticalElements(element, next_element, editing_state); @@ -1797,22 +1801,22 @@ void ApplyStyleCommand::SurroundNodeRangeWithElement( Node* next_sibling = element->nextSibling(); Node* previous_sibling = element->previousSibling(); - if (next_sibling && next_sibling->IsElementNode() && - HasEditableStyle(*next_sibling) && - AreIdenticalElements(*element, ToElement(*next_sibling))) { - MergeIdenticalElements(element, ToElement(next_sibling), editing_state); + auto* next_sibling_element = DynamicTo<Element>(next_sibling); + if (next_sibling_element && HasEditableStyle(*next_sibling) && + AreIdenticalElements(*element, *next_sibling_element)) { + MergeIdenticalElements(element, next_sibling_element, editing_state); if (editing_state->IsAborted()) return; } - if (previous_sibling && previous_sibling->IsElementNode() && - HasEditableStyle(*previous_sibling)) { - Node* merged_element = previous_sibling->nextSibling(); - if (merged_element->IsElementNode() && HasEditableStyle(*merged_element) && - AreIdenticalElements(ToElement(*previous_sibling), - ToElement(*merged_element))) { - MergeIdenticalElements(ToElement(previous_sibling), - ToElement(merged_element), editing_state); + auto* previous_sibling_element = DynamicTo<Element>(previous_sibling); + if (previous_sibling_element && HasEditableStyle(*previous_sibling)) { + auto* merged_element = DynamicTo<Element>(previous_sibling->nextSibling()); + if (merged_element && + HasEditableStyle(*(previous_sibling->nextSibling())) && + AreIdenticalElements(*previous_sibling_element, *merged_element)) { + MergeIdenticalElements(previous_sibling_element, merged_element, + editing_state); if (editing_state->IsAborted()) return; } @@ -2041,12 +2045,12 @@ float ApplyStyleCommand::ComputedFontSize(Node* node) { return 0; const auto* value = To<CSSPrimitiveValue>( - style->GetPropertyCSSValue(GetCSSPropertyFontSize())); + style->GetPropertyCSSValue(CSSPropertyID::kFontSize)); if (!value) return 0; // TODO(yosin): We should have printer for |CSSPrimitiveValue::UnitType|. - DCHECK(value->TypeWithCalcResolved() == CSSPrimitiveValue::UnitType::kPixels); + DCHECK(value->IsPx()); return value->GetFloatValue(); } diff --git a/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.h b/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.h index 4aa6f80477d..6e0f5518437 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/clipboard_commands.h @@ -33,7 +33,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_CLIPBOARD_COMMANDS_H_ #include "third_party/blink/renderer/core/editing/forward.h" -#include "third_party/blink/renderer/platform/wtf/allocator.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc index b8f011b43a7..8d641404bc9 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc @@ -365,9 +365,10 @@ void CompositeEditCommand::AppendNode(Node* node, // TODO(yosin): We should get rid of |canHaveChildrenForEditing()|, since // |cloneParagraphUnderNewElement()| attempt to clone non-well-formed HTML, // produced by JavaScript. - ABORT_EDITING_COMMAND_IF(!CanHaveChildrenForEditing(parent) && - !(parent->IsElementNode() && - ToElement(parent)->TagQName() == kObjectTag)); + auto* parent_element = DynamicTo<Element>(parent); + ABORT_EDITING_COMMAND_IF( + !CanHaveChildrenForEditing(parent) && + !(parent_element && parent_element->TagQName() == kObjectTag)); ABORT_EDITING_COMMAND_IF(!HasEditableStyle(*parent) && parent->InActiveDocument()); ApplyCommandToComposite(MakeGarbageCollected<AppendNodeCommand>(parent, node), @@ -1192,7 +1193,7 @@ void CompositeEditCommand::CloneParagraphUnderNewElement( for (wtf_size_t i = ancestors.size(); i != 0; --i) { Node* item = ancestors[i - 1].Get(); Node* child = item->cloneNode(IsDisplayInsideTable(item)); - AppendNode(child, ToElement(last_node), editing_state); + AppendNode(child, To<Element>(last_node), editing_state); if (editing_state->IsAborted()) return; last_node = child; @@ -1686,7 +1687,7 @@ bool CompositeEditCommand::BreakOutOfEmptyListItem( // should become // <ul><li> <div><br></div> hello</li></ul> // at the end - SplitElement(ToElement(block_enclosing_list), list_node); + SplitElement(To<Element>(block_enclosing_list), list_node); RemoveNodePreservingChildren(list_node->parentNode(), editing_state); if (editing_state->IsAborted()) return false; @@ -1713,7 +1714,7 @@ bool CompositeEditCommand::BreakOutOfEmptyListItem( // If emptyListItem follows another list item or nested list, split the list // node. if (IsListItem(previous_list_node) || IsHTMLListElement(previous_list_node)) - SplitElement(ToElement(list_node), empty_list_item); + SplitElement(To<Element>(list_node), empty_list_item); // If emptyListItem is followed by other list item or nested list, then // insert newBlock before the list node. Because we have splitted the diff --git a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_options.h b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_options.h index ef1038c5904..92377355d1c 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_options.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/delete_selection_options.h @@ -7,7 +7,7 @@ #include "base/macros.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc index abf10cdfc54..c8fe153b384 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/document_exec_command.cc @@ -36,10 +36,10 @@ #include "third_party/blink/renderer/core/editing/editing_tri_state.h" #include "third_party/blink/renderer/core/editing/editor.h" #include "third_party/blink/renderer/core/frame/local_frame.h" -#include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/html/forms/text_control_element.h" #include "third_party/blink/renderer/core/inspector/console_message.h" -#include "third_party/blink/renderer/platform/histogram.h" +#include "third_party/blink/renderer/platform/instrumentation/histogram.h" +#include "third_party/blink/renderer/platform/instrumentation/use_counter.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc index c24e8917608..e1bfe875c48 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/editing_command_test.cc @@ -7,8 +7,11 @@ #include "third_party/blink/renderer/core/editing/commands/editor_command.h" #include "third_party/blink/renderer/core/editing/commands/editor_command_names.h" #include "third_party/blink/renderer/core/editing/editor.h" +#include "third_party/blink/renderer/core/editing/frame_selection.h" +#include "third_party/blink/renderer/core/editing/selection_template.h" #include "third_party/blink/renderer/core/editing/testing/editing_test_base.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { @@ -38,7 +41,7 @@ class EditingCommandTest : public EditingTestBase {}; TEST_F(EditingCommandTest, EditorCommandOrder) { for (size_t i = 1; i < base::size(kCommandNameEntries); ++i) { EXPECT_GT(0, - WTF::CodePointCompareIgnoringASCIICase( + WTF::CodeUnitCompareIgnoringASCIICase( kCommandNameEntries[i - 1].name, kCommandNameEntries[i].name)) << "EDITOR_COMMAND_MAP must be case-folding ordered. Incorrect index:" << i; @@ -79,4 +82,64 @@ TEST_F(EditingCommandTest, CreateCommandFromInvalidString) { } } +TEST_F(EditingCommandTest, EnabledVisibleSelection) { + Editor& editor = GetDocument().GetFrame()->GetEditor(); + const EditorCommand command = + editor.CreateCommand("MoveRightAndModifySelection"); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable>a|b<div>"), + SetSelectionOptions()); + Element* div = GetDocument().QuerySelector("div"); + GetDocument().SetFocusedElement( + div, + FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); + EXPECT_TRUE(command.IsEnabled()); + div->removeAttribute("contenteditable"); + EXPECT_FALSE(command.IsEnabled()); + GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(true); + EXPECT_TRUE(command.IsEnabled()); +} + +TEST_F(EditingCommandTest, EnabledVisibleSelectionAndMark) { + Editor& editor = GetDocument().GetFrame()->GetEditor(); + const EditorCommand command = editor.CreateCommand("SelectToMark"); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable>a|b<div>"), + SetSelectionOptions()); + Element* div = GetDocument().QuerySelector("div"); + GetDocument().SetFocusedElement( + div, + FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); + EXPECT_FALSE(command.IsEnabled()); + editor.SetMark(); + EXPECT_TRUE(command.IsEnabled()); + div->removeAttribute("contenteditable"); + EXPECT_FALSE(command.IsEnabled()); + GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(true); + EXPECT_TRUE(command.IsEnabled()); +} + +TEST_F(EditingCommandTest, EnabledInEditableTextOrCaretBrowsing) { + Editor& editor = GetDocument().GetFrame()->GetEditor(); + const EditorCommand command = editor.CreateCommand("MoveRight"); + + SetBodyContent("<div>abc</div>"); + GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(false); + EXPECT_FALSE(command.IsEnabled()); + GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(true); + EXPECT_TRUE(command.IsEnabled()); + + GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(false); + Selection().SetSelection( + SetSelectionTextToBody("<div contenteditable>a|b<div>"), + SetSelectionOptions()); + Element* div = GetDocument().QuerySelector("div"); + GetDocument().SetFocusedElement( + div, + FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); + EXPECT_TRUE(command.IsEnabled()); + div->removeAttribute("contenteditable"); + EXPECT_FALSE(command.IsEnabled()); +} + } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc b/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc index 332305aba57..e00a5c11d4d 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/editing_commands_utilities.cc @@ -39,7 +39,6 @@ #include "third_party/blink/renderer/core/editing/visible_position.h" #include "third_party/blink/renderer/core/editing/visible_selection.h" #include "third_party/blink/renderer/core/frame/local_frame_client.h" -#include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/frame/web_feature_forward.h" #include "third_party/blink/renderer/core/html/html_body_element.h" #include "third_party/blink/renderer/core/html/html_html_element.h" @@ -47,6 +46,7 @@ #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_text.h" #include "third_party/blink/renderer/platform/heap/heap.h" +#include "third_party/blink/renderer/platform/instrumentation/use_counter.h" namespace blink { @@ -80,7 +80,7 @@ Node* HighestNodeToRemoveInPruning(Node* node, const Node* exclude_node) { } Element* EnclosingTableCell(const Position& p) { - return ToElement(EnclosingNodeOfType(p, IsTableCell)); + return To<Element>(EnclosingNodeOfType(p, IsTableCell)); } bool IsTableStructureNode(const Node* node) { @@ -132,18 +132,18 @@ Node* EnclosingEmptyListItem(const VisiblePosition& visible_pos) { } bool AreIdenticalElements(const Node& first, const Node& second) { - if (!first.IsElementNode() || !second.IsElementNode()) + const auto* first_element = DynamicTo<Element>(first); + const auto* second_element = DynamicTo<Element>(second); + if (!first_element || !second_element) return false; - const Element& first_element = ToElement(first); - const Element& second_element = ToElement(second); - if (!first_element.HasTagName(second_element.TagQName())) + if (!first_element->HasTagName(second_element->TagQName())) return false; - if (!first_element.HasEquivalentAttributes(second_element)) + if (!first_element->HasEquivalentAttributes(*second_element)) return false; - return HasEditableStyle(first_element) && HasEditableStyle(second_element); + return HasEditableStyle(*first_element) && HasEditableStyle(*second_element); } // FIXME: need to dump this diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h b/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h index e1840d17c0d..f5b63acbfe8 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/editing_state.h @@ -7,7 +7,7 @@ #include "base/macros.h" #include "third_party/blink/renderer/core/core_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc index 43530091ebe..4476c4673d6 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/editor_command.cc @@ -60,6 +60,7 @@ #include "third_party/blink/renderer/core/editing/visible_position.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" +#include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/html/html_br_element.h" #include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/input/event_handler.h" @@ -68,8 +69,8 @@ #include "third_party/blink/renderer/core/scroll/scrollbar.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/heap/heap.h" -#include "third_party/blink/renderer/platform/histogram.h" -#include "third_party/blink/renderer/platform/wtf/allocator.h" +#include "third_party/blink/renderer/platform/instrumentation/histogram.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h" #include <iterator> @@ -101,10 +102,10 @@ WebEditingCommandType WebEditingCommandTypeFromCommandName( const CommandNameEntry* result = std::lower_bound( std::begin(kCommandNameEntries), std::end(kCommandNameEntries), command_name, [](const CommandNameEntry& entry, const String& needle) { - return CodePointCompareIgnoringASCIICase(needle, entry.name) > 0; + return CodeUnitCompareIgnoringASCIICase(needle, entry.name) > 0; }); if (result != std::end(kCommandNameEntries) && - CodePointCompareIgnoringASCIICase(command_name, result->name) == 0) + CodeUnitCompareIgnoringASCIICase(command_name, result->name) == 0) return result->type; return WebEditingCommandType::kInvalid; } @@ -1046,11 +1047,13 @@ static bool EnabledVisibleSelection(LocalFrame& frame, !frame.Selection().SelectionHasFocus()) return false; - // The term "visible" here includes a caret in editable text or a range in any - // text. + // The term "visible" here includes a caret in editable text, a range in any + // text, or a caret in non-editable text when caret browsing is enabled. const VisibleSelection& selection = CreateVisibleSelection(frame.GetEditor().SelectionForCommand(event)); - return (selection.IsCaret() && selection.IsContentEditable()) || + return (selection.IsCaret() && + (selection.IsContentEditable() || + frame.GetSettings()->GetCaretBrowsingEnabled())) || selection.IsRange(); } @@ -1065,7 +1068,9 @@ static bool EnabledVisibleSelectionAndMark(LocalFrame& frame, const VisibleSelection& selection = CreateVisibleSelection(frame.GetEditor().SelectionForCommand(event)); - return ((selection.IsCaret() && selection.IsContentEditable()) || + return ((selection.IsCaret() && + (selection.IsContentEditable() || + frame.GetSettings()->GetCaretBrowsingEnabled())) || selection.IsRange()) && !frame.GetEditor().Mark().IsNone(); } @@ -1096,6 +1101,13 @@ static bool EnabledInEditableText(LocalFrame& frame, CreateVisiblePosition(selection.Base()).DeepEquivalent()); } +static bool EnabledInEditableTextOrCaretBrowsing(LocalFrame& frame, + Event* event, + EditorCommandSource source) { + return frame.GetSettings()->GetCaretBrowsingEnabled() || + EnabledInEditableText(frame, event, source); +} + static bool EnabledDelete(LocalFrame& frame, Event* event, EditorCommandSource source) { @@ -1480,184 +1492,198 @@ static const EditorInternalCommand* InternalCommand( StyleCommands::StateTextWritingDirectionRightToLeft, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveBackward, MoveCommands::ExecuteMoveBackward, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveBackwardAndModifySelection, MoveCommands::ExecuteMoveBackwardAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveDown, MoveCommands::ExecuteMoveDown, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveDownAndModifySelection, MoveCommands::ExecuteMoveDownAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveForward, MoveCommands::ExecuteMoveForward, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveForwardAndModifySelection, MoveCommands::ExecuteMoveForwardAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveLeft, MoveCommands::ExecuteMoveLeft, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveLeftAndModifySelection, MoveCommands::ExecuteMoveLeftAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMovePageDown, MoveCommands::ExecuteMovePageDown, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMovePageDownAndModifySelection, MoveCommands::ExecuteMovePageDownAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMovePageUp, MoveCommands::ExecuteMovePageUp, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMovePageUpAndModifySelection, MoveCommands::ExecuteMovePageUpAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveParagraphBackward, MoveCommands::ExecuteMoveParagraphBackward, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveParagraphBackwardAndModifySelection, MoveCommands::ExecuteMoveParagraphBackwardAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveParagraphForward, MoveCommands::ExecuteMoveParagraphForward, SupportedFromMenuOrKeyBinding, - EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, - CanNotExecuteWhenDisabled}, + EnabledInEditableTextOrCaretBrowsing, StateNone, ValueStateOrNull, + kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveParagraphForwardAndModifySelection, MoveCommands::ExecuteMoveParagraphForwardAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveRight, MoveCommands::ExecuteMoveRight, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveRightAndModifySelection, MoveCommands::ExecuteMoveRightAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToBeginningOfDocument, MoveCommands::ExecuteMoveToBeginningOfDocument, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToBeginningOfDocumentAndModifySelection, MoveCommands::ExecuteMoveToBeginningOfDocumentAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToBeginningOfLine, MoveCommands::ExecuteMoveToBeginningOfLine, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToBeginningOfLineAndModifySelection, MoveCommands::ExecuteMoveToBeginningOfLineAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToBeginningOfParagraph, MoveCommands::ExecuteMoveToBeginningOfParagraph, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToBeginningOfParagraphAndModifySelection, MoveCommands::ExecuteMoveToBeginningOfParagraphAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToBeginningOfSentence, MoveCommands::ExecuteMoveToBeginningOfSentence, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToBeginningOfSentenceAndModifySelection, MoveCommands::ExecuteMoveToBeginningOfSentenceAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToEndOfDocument, MoveCommands::ExecuteMoveToEndOfDocument, SupportedFromMenuOrKeyBinding, - EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, - CanNotExecuteWhenDisabled}, + EnabledInEditableTextOrCaretBrowsing, StateNone, ValueStateOrNull, + kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToEndOfDocumentAndModifySelection, MoveCommands::ExecuteMoveToEndOfDocumentAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToEndOfLine, MoveCommands::ExecuteMoveToEndOfLine, SupportedFromMenuOrKeyBinding, - EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, - CanNotExecuteWhenDisabled}, + EnabledInEditableTextOrCaretBrowsing, StateNone, ValueStateOrNull, + kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToEndOfLineAndModifySelection, MoveCommands::ExecuteMoveToEndOfLineAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToEndOfParagraph, MoveCommands::ExecuteMoveToEndOfParagraph, SupportedFromMenuOrKeyBinding, - EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, - CanNotExecuteWhenDisabled}, + EnabledInEditableTextOrCaretBrowsing, StateNone, ValueStateOrNull, + kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToEndOfParagraphAndModifySelection, MoveCommands::ExecuteMoveToEndOfParagraphAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToEndOfSentence, MoveCommands::ExecuteMoveToEndOfSentence, SupportedFromMenuOrKeyBinding, - EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, - CanNotExecuteWhenDisabled}, + EnabledInEditableTextOrCaretBrowsing, StateNone, ValueStateOrNull, + kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToEndOfSentenceAndModifySelection, MoveCommands::ExecuteMoveToEndOfSentenceAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToLeftEndOfLine, MoveCommands::ExecuteMoveToLeftEndOfLine, SupportedFromMenuOrKeyBinding, - EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, - CanNotExecuteWhenDisabled}, + EnabledInEditableTextOrCaretBrowsing, StateNone, ValueStateOrNull, + kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToLeftEndOfLineAndModifySelection, MoveCommands::ExecuteMoveToLeftEndOfLineAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToRightEndOfLine, MoveCommands::ExecuteMoveToRightEndOfLine, SupportedFromMenuOrKeyBinding, - EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, - CanNotExecuteWhenDisabled}, + EnabledInEditableTextOrCaretBrowsing, StateNone, ValueStateOrNull, + kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveToRightEndOfLineAndModifySelection, MoveCommands::ExecuteMoveToRightEndOfLineAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveUp, MoveCommands::ExecuteMoveUp, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveUpAndModifySelection, MoveCommands::ExecuteMoveUpAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveWordBackward, MoveCommands::ExecuteMoveWordBackward, SupportedFromMenuOrKeyBinding, - EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, - CanNotExecuteWhenDisabled}, + EnabledInEditableTextOrCaretBrowsing, StateNone, ValueStateOrNull, + kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveWordBackwardAndModifySelection, MoveCommands::ExecuteMoveWordBackwardAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveWordForward, MoveCommands::ExecuteMoveWordForward, SupportedFromMenuOrKeyBinding, - EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, - CanNotExecuteWhenDisabled}, + EnabledInEditableTextOrCaretBrowsing, StateNone, ValueStateOrNull, + kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveWordForwardAndModifySelection, MoveCommands::ExecuteMoveWordForwardAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveWordLeft, MoveCommands::ExecuteMoveWordLeft, - SupportedFromMenuOrKeyBinding, EnabledInEditableText, StateNone, - ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, + SupportedFromMenuOrKeyBinding, EnabledInEditableTextOrCaretBrowsing, + StateNone, ValueStateOrNull, kNotTextInsertion, + CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveWordLeftAndModifySelection, MoveCommands::ExecuteMoveWordLeftAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, ValueStateOrNull, kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveWordRight, MoveCommands::ExecuteMoveWordRight, SupportedFromMenuOrKeyBinding, - EnabledInEditableText, StateNone, ValueStateOrNull, kNotTextInsertion, - CanNotExecuteWhenDisabled}, + EnabledInEditableTextOrCaretBrowsing, StateNone, ValueStateOrNull, + kNotTextInsertion, CanNotExecuteWhenDisabled}, {WebEditingCommandType::kMoveWordRightAndModifySelection, MoveCommands::ExecuteMoveWordRightAndModifySelection, SupportedFromMenuOrKeyBinding, EnabledVisibleSelection, StateNone, diff --git a/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc index d4670e1891e..8f6215d8715 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/format_block_command.cc @@ -45,8 +45,8 @@ using namespace html_names; static Node* EnclosingBlockToSplitTreeTo(Node* start_node); static bool IsElementForFormatBlock(const QualifiedName& tag_name); static inline bool IsElementForFormatBlock(Node* node) { - return node->IsElementNode() && - IsElementForFormatBlock(ToElement(node)->TagQName()); + auto* element = DynamicTo<Element>(node); + return element && IsElementForFormatBlock(element->TagQName()); } static Element* EnclosingBlockFlowElement( @@ -170,8 +170,7 @@ Element* FormatBlockCommand::ElementForFormatBlockCommand( if (!element || common_ancestor->contains(element)) return nullptr; - return common_ancestor->IsElementNode() ? ToElement(common_ancestor) - : nullptr; + return DynamicTo<Element>(common_ancestor); } bool IsElementForFormatBlock(const QualifiedName& tag_name) { diff --git a/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc index e0c550f0bb0..ab283d72b39 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/indent_outdent_command.cc @@ -158,7 +158,7 @@ void IndentOutdentCommand::IndentIntoBlockquote(const Position& start, const Position& end, HTMLElement*& target_blockquote, EditingState* editing_state) { - Element* enclosing_cell = ToElement(EnclosingNodeOfType(start, &IsTableCell)); + auto* enclosing_cell = To<Element>(EnclosingNodeOfType(start, &IsTableCell)); Element* element_to_split_to; if (enclosing_cell) element_to_split_to = enclosing_cell; diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_commands.h b/chromium/third_party/blink/renderer/core/editing/commands/insert_commands.h index 19a633e0a66..0ac3d424ebc 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_commands.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_commands.h @@ -32,7 +32,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_INSERT_COMMANDS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_INSERT_COMMANDS_H_ -#include "third_party/blink/renderer/platform/wtf/allocator.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/forward.h" namespace blink { diff --git a/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc index ddf9e35d81a..c7fcbbbedd2 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/insert_list_command.cc @@ -402,7 +402,7 @@ bool InsertListCommand::DoApplyForSingleParagraph( list_element); Element* outer_block = first_child_in_list && IsBlockFlowElement(*first_child_in_list) - ? ToElement(first_child_in_list) + ? To<Element>(first_child_in_list) : list_element; MoveParagraphWithClones( diff --git a/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc b/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc index c9c11f8f260..b84a47076e3 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/move_commands.cc @@ -31,21 +31,29 @@ #include "third_party/blink/renderer/core/editing/commands/move_commands.h" +#include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/editing/editing_behavior.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" #include "third_party/blink/renderer/core/editing/editor.h" #include "third_party/blink/renderer/core/editing/frame_selection.h" #include "third_party/blink/renderer/core/editing/selection_modifier.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/layout/layout_box.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" namespace blink { unsigned MoveCommands::VerticalScrollDistance(LocalFrame& frame) { - const Element* const focused_element = frame.GetDocument()->FocusedElement(); - if (!focused_element) - return 0; + const Element* focused_element = frame.GetDocument()->FocusedElement(); + if (!focused_element) { + if (frame.GetSettings()->GetCaretBrowsingEnabled()) { + focused_element = frame.GetDocument()->ActiveElement(); + } + + if (!focused_element) + return 0; + } LayoutObject* const layout_object = focused_element->GetLayoutObject(); if (!layout_object || !layout_object->IsBox()) return 0; @@ -55,7 +63,8 @@ unsigned MoveCommands::VerticalScrollDistance(LocalFrame& frame) { return 0; if (!(style->OverflowY() == EOverflow::kScroll || style->OverflowY() == EOverflow::kAuto || - HasEditableStyle(*focused_element))) + HasEditableStyle(*focused_element) || + frame.GetSettings()->GetCaretBrowsingEnabled())) return 0; const ScrollableArea& scrollable_area = *frame.View()->LayoutViewport(); const int height = std::min<int>(layout_box.ClientHeight().ToInt(), @@ -71,6 +80,9 @@ bool MoveCommands::ModifySelectionWithPageGranularity( SelectionModifyAlteration alter, unsigned vertical_distance, SelectionModifyVerticalDirection direction) { + if (alter == SelectionModifyAlteration::kMove) + UpdateSelectionForCaretBrowsing(frame); + SelectionModifier selection_modifier( frame, frame.Selection().GetSelectionInDOMTree()); selection_modifier.SetSelectionIsDirectional( @@ -94,16 +106,87 @@ bool MoveCommands::ModifySelectionWithPageGranularity( .Behavior() .ShouldConsiderSelectionAsDirectional()) .Build()); + + UpdateFocusForCaretBrowsing(frame); + return true; } +bool MoveCommands::MoveSelection(LocalFrame& frame, + SelectionModifyDirection direction, + TextGranularity granularity) { + UpdateSelectionForCaretBrowsing(frame); + const bool modified = + frame.Selection().Modify(SelectionModifyAlteration::kMove, direction, + granularity, SetSelectionBy::kUser); + if (modified) + UpdateFocusForCaretBrowsing(frame); + + return modified; +} + +void MoveCommands::UpdateFocusForCaretBrowsing(LocalFrame& frame) { + if (!frame.GetSettings()->GetCaretBrowsingEnabled()) + return; + + SelectionInDOMTree selection = frame.Selection().GetSelectionInDOMTree(); + if (!selection.IsCaret()) + return; + + Node* node = selection.Extent().ComputeContainerNode(); + if (!node) + return; + + const ComputedStyle* style = node->GetComputedStyle(); + if (!style || style->UserModify() != EUserModify::kReadOnly) + return; + + Element* new_focused_element = nullptr; + + while (node) { + if (node->IsElementNode() && ToElement(node)->IsFocusable()) { + new_focused_element = ToElement(node); + break; + } + node = node->ParentOrShadowHostNode(); + } + + if (new_focused_element == frame.GetDocument()->FocusedElement()) + return; + + frame.GetDocument()->SetFocusedElement( + new_focused_element, + FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); +} + +void MoveCommands::UpdateSelectionForCaretBrowsing(LocalFrame& frame) { + if (!frame.GetSettings()->GetCaretBrowsingEnabled()) + return; + + if (frame.Selection().SelectionHasFocus()) + return; + + Element* activeElement = frame.GetDocument()->ActiveElement(); + if (!activeElement) + return; + + frame.Selection().SetSelection( + SelectionInDOMTree::Builder() + .Collapse(Position::FirstPositionInOrBeforeNode(*activeElement)) + .Build(), + SetSelectionOptions::Builder() + .SetShouldCloseTyping(true) + .SetShouldClearTypingStyle(true) + .SetDoNotSetFocus(true) + .Build()); +} + bool MoveCommands::ExecuteMoveBackward(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(SelectionModifyAlteration::kMove, - SelectionModifyDirection::kBackward, - TextGranularity::kCharacter, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kBackward, + TextGranularity::kCharacter); return true; } @@ -121,9 +204,8 @@ bool MoveCommands::ExecuteMoveDown(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - return frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kForward, - TextGranularity::kLine, SetSelectionBy::kUser); + return MoveSelection(frame, SelectionModifyDirection::kForward, + TextGranularity::kLine); } bool MoveCommands::ExecuteMoveDownAndModifySelection(LocalFrame& frame, @@ -140,9 +222,8 @@ bool MoveCommands::ExecuteMoveForward(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(SelectionModifyAlteration::kMove, - SelectionModifyDirection::kForward, - TextGranularity::kCharacter, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kForward, + TextGranularity::kCharacter); return true; } @@ -160,9 +241,8 @@ bool MoveCommands::ExecuteMoveLeft(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - return frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kLeft, - TextGranularity::kCharacter, SetSelectionBy::kUser); + return MoveSelection(frame, SelectionModifyDirection::kLeft, + TextGranularity::kCharacter); } bool MoveCommands::ExecuteMoveLeftAndModifySelection(LocalFrame& frame, @@ -227,9 +307,8 @@ bool MoveCommands::ExecuteMoveParagraphBackward(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(SelectionModifyAlteration::kMove, - SelectionModifyDirection::kBackward, - TextGranularity::kParagraph, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kBackward, + TextGranularity::kParagraph); return true; } @@ -248,9 +327,8 @@ bool MoveCommands::ExecuteMoveParagraphForward(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(SelectionModifyAlteration::kMove, - SelectionModifyDirection::kForward, - TextGranularity::kParagraph, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kForward, + TextGranularity::kParagraph); return true; } @@ -269,9 +347,8 @@ bool MoveCommands::ExecuteMoveRight(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - return frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kRight, - TextGranularity::kCharacter, SetSelectionBy::kUser); + return MoveSelection(frame, SelectionModifyDirection::kRight, + TextGranularity::kCharacter); } bool MoveCommands::ExecuteMoveRightAndModifySelection(LocalFrame& frame, @@ -288,9 +365,8 @@ bool MoveCommands::ExecuteMoveToBeginningOfDocument(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kBackward, - TextGranularity::kDocumentBoundary, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kBackward, + TextGranularity::kDocumentBoundary); return true; } @@ -309,9 +385,8 @@ bool MoveCommands::ExecuteMoveToBeginningOfLine(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kBackward, - TextGranularity::kLineBoundary, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kBackward, + TextGranularity::kLineBoundary); return true; } @@ -330,9 +405,8 @@ bool MoveCommands::ExecuteMoveToBeginningOfParagraph(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kBackward, - TextGranularity::kParagraphBoundary, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kBackward, + TextGranularity::kParagraphBoundary); return true; } @@ -351,9 +425,8 @@ bool MoveCommands::ExecuteMoveToBeginningOfSentence(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kBackward, - TextGranularity::kSentenceBoundary, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kBackward, + TextGranularity::kSentenceBoundary); return true; } @@ -372,9 +445,8 @@ bool MoveCommands::ExecuteMoveToEndOfDocument(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kForward, - TextGranularity::kDocumentBoundary, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kForward, + TextGranularity::kDocumentBoundary); return true; } @@ -393,9 +465,8 @@ bool MoveCommands::ExecuteMoveToEndOfLine(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kForward, - TextGranularity::kLineBoundary, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kForward, + TextGranularity::kLineBoundary); return true; } @@ -413,9 +484,8 @@ bool MoveCommands::ExecuteMoveToEndOfParagraph(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kForward, - TextGranularity::kParagraphBoundary, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kForward, + TextGranularity::kParagraphBoundary); return true; } @@ -434,9 +504,8 @@ bool MoveCommands::ExecuteMoveToEndOfSentence(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kForward, - TextGranularity::kSentenceBoundary, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kForward, + TextGranularity::kSentenceBoundary); return true; } @@ -455,9 +524,8 @@ bool MoveCommands::ExecuteMoveToLeftEndOfLine(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kLeft, - TextGranularity::kLineBoundary, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kLeft, + TextGranularity::kLineBoundary); return true; } @@ -476,9 +544,8 @@ bool MoveCommands::ExecuteMoveToRightEndOfLine(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kRight, - TextGranularity::kLineBoundary, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kRight, + TextGranularity::kLineBoundary); return true; } @@ -497,9 +564,8 @@ bool MoveCommands::ExecuteMoveUp(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - return frame.Selection().Modify( - SelectionModifyAlteration::kMove, SelectionModifyDirection::kBackward, - TextGranularity::kLine, SetSelectionBy::kUser); + return MoveSelection(frame, SelectionModifyDirection::kBackward, + TextGranularity::kLine); } bool MoveCommands::ExecuteMoveUpAndModifySelection(LocalFrame& frame, @@ -516,9 +582,8 @@ bool MoveCommands::ExecuteMoveWordBackward(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(SelectionModifyAlteration::kMove, - SelectionModifyDirection::kBackward, - TextGranularity::kWord, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kBackward, + TextGranularity::kWord); return true; } @@ -537,9 +602,8 @@ bool MoveCommands::ExecuteMoveWordForward(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(SelectionModifyAlteration::kMove, - SelectionModifyDirection::kForward, - TextGranularity::kWord, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kForward, + TextGranularity::kWord); return true; } @@ -557,9 +621,7 @@ bool MoveCommands::ExecuteMoveWordLeft(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(SelectionModifyAlteration::kMove, - SelectionModifyDirection::kLeft, - TextGranularity::kWord, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kLeft, TextGranularity::kWord); return true; } @@ -577,9 +639,8 @@ bool MoveCommands::ExecuteMoveWordRight(LocalFrame& frame, Event*, EditorCommandSource, const String&) { - frame.Selection().Modify(SelectionModifyAlteration::kMove, - SelectionModifyDirection::kRight, - TextGranularity::kWord, SetSelectionBy::kUser); + MoveSelection(frame, SelectionModifyDirection::kRight, + TextGranularity::kWord); return true; } diff --git a/chromium/third_party/blink/renderer/core/editing/commands/move_commands.h b/chromium/third_party/blink/renderer/core/editing/commands/move_commands.h index 4eaf2cc9868..062c6416e4f 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/move_commands.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/move_commands.h @@ -32,7 +32,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_MOVE_COMMANDS_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_MOVE_COMMANDS_H_ -#include "third_party/blink/renderer/platform/wtf/allocator.h" +#include "third_party/blink/renderer/core/core_export.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/forward.h" namespace blink { @@ -42,10 +43,12 @@ class LocalFrame; enum class EditorCommandSource; enum class SelectionModifyAlteration; +enum class SelectionModifyDirection; enum class SelectionModifyVerticalDirection; +enum class TextGranularity; // This class provides static functions about commands related to move. -class MoveCommands { +class CORE_EXPORT MoveCommands { STATIC_ONLY(MoveCommands); public: @@ -257,6 +260,26 @@ class MoveCommands { SelectionModifyAlteration, unsigned, SelectionModifyVerticalDirection); + + // Wraps FrameSelection::Modify for case where the selection is moved by the + // user. Returns false if the "selectstart" event is dispatched and canceled, + // otherwise returns true (return value does not indicate whether the + // selection was modified). + static bool MoveSelection(LocalFrame&, + SelectionModifyDirection, + TextGranularity); + + // If caret browsing is enabled and the caret is in a non-editable region then + // UpdateFocusForCaretBrowsing moves focus to the nearest focusable ancestor + // of the caret, if there is one. This will, for example, move focus to anchor + // elements when the caret enters an anchor. If there is no focusable ancestor + // then focus will move to the body. + static void UpdateFocusForCaretBrowsing(LocalFrame&); + + // If caret browsing is enabled and the caret/selection is not in focus then + // UpdateSelectionForCaretBrowsing moves the caret to the first position in + // the active element. + static void UpdateSelectionForCaretBrowsing(LocalFrame&); }; } // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/commands/move_commands_test.cc b/chromium/third_party/blink/renderer/core/editing/commands/move_commands_test.cc new file mode 100644 index 00000000000..7de107b8210 --- /dev/null +++ b/chromium/third_party/blink/renderer/core/editing/commands/move_commands_test.cc @@ -0,0 +1,327 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "build/build_config.h" +#include "third_party/blink/renderer/core/dom/element.h" +#include "third_party/blink/renderer/core/editing/commands/move_commands.h" +#include "third_party/blink/renderer/core/editing/editor.h" +#include "third_party/blink/renderer/core/editing/frame_selection.h" +#include "third_party/blink/renderer/core/editing/selection_template.h" +#include "third_party/blink/renderer/core/editing/testing/editing_test_base.h" +#include "third_party/blink/renderer/core/frame/settings.h" + +namespace blink { + +class MoveCommandsTest : public EditingTestBase { + protected: + void VerifyCaretBrowsingPositionAndFocusUpdate( + const std::string& initial_selection_text, + const AtomicString& initial_focus_element, + bool (*execute)(LocalFrame&, Event*, EditorCommandSource, const String&), + const std::string& final_selection_text, + const AtomicString& final_focus_element) { + Selection().SetSelection(SetSelectionTextToBody(initial_selection_text), + SetSelectionOptions()); + GetDocument().SetFocusedElement( + GetDocument().QuerySelector(initial_focus_element), + FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, + nullptr)); + GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(true); + execute(*GetDocument().GetFrame(), nullptr, + EditorCommandSource::kMenuOrKeyBinding, String()); + EXPECT_EQ(final_selection_text, GetSelectionTextFromBody()); + EXPECT_EQ(GetDocument().QuerySelector(final_focus_element), + GetDocument().ActiveElement()); + } +}; + +// The following CaretBrowsingPositionAndFocusUpdate_Move* tests verify that the +// move commands are using UpdateFocusForCaretBrowsing to adjust caret position +// and focus while caret browsing. + +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_MoveBackward) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">a</a>|b</div>", "body", + MoveCommands::ExecuteMoveBackward, "<div><a href=\"foo\">|a</a>b</div>", + "a"); +} + +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_MoveDown) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>a|b</div><div><a href=\"foo\">cd</a></div>", "body", + MoveCommands::ExecuteMoveDown, +#if !defined(OS_MACOSX) + "<div>ab</div><div><a href=\"foo\">c|d</a></div>", "a"); +#else // defined(OS_MACOSX) + // MoveDown navigates visually, placing caret at different position for + // macOS. + "<div>ab</div><div><a href=\"foo\">|cd</a></div>", "a"); +#endif // !defined(OS_MACOSX) +} + +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_MoveForward) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>a|<a href=\"foo\">b</a></div>", "body", + MoveCommands::ExecuteMoveForward, "<div>a<a href=\"foo\">b|</a></div>", + "a"); +} + +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_MoveLeft) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">a</a>|b</div>", "body", + MoveCommands::ExecuteMoveLeft, "<div><a href=\"foo\">|a</a>b</div>", "a"); +} + +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveParagraphBackward) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">a</a>|b</div>", "body", + MoveCommands::ExecuteMoveParagraphBackward, + "<div><a href=\"foo\">|a</a>b</div>", "a"); +} + +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveParagraphForward) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>a|<a href=\"foo\">b</a></div>", "body", + MoveCommands::ExecuteMoveParagraphForward, + "<div>a<a href=\"foo\">b|</a></div>", "a"); +} + +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_MoveRight) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>a|<a href=\"foo\">b</a></div>", "body", + MoveCommands::ExecuteMoveRight, "<div>a<a href=\"foo\">b|</a></div>", + "a"); +} + +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveToBeginningOfDocument) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">a</a>|b</div>", "body", + MoveCommands::ExecuteMoveToBeginningOfDocument, + "<div><a href=\"foo\">|a</a>b</div>", "a"); +} + +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveToBeginningOfLine) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">a</a>|b</div>", "body", + MoveCommands::ExecuteMoveToBeginningOfLine, + "<div><a href=\"foo\">|a</a>b</div>", "a"); +} + +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveToBeginningOfParagraph) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">a</a>|b</div>", "body", + MoveCommands::ExecuteMoveToBeginningOfParagraph, + "<div><a href=\"foo\">|a</a>b</div>", "a"); +} + +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveToBeginningOfSentence) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">a</a>|b</div>", "body", + MoveCommands::ExecuteMoveToBeginningOfSentence, + "<div><a href=\"foo\">|a</a>b</div>", "a"); +} + +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveToEndOfDocument) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>a|<a href=\"foo\">b</a></div>", "body", + MoveCommands::ExecuteMoveToEndOfDocument, + "<div>a<a href=\"foo\">b|</a></div>", "a"); +} + +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_MoveToEndOfLine) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>a|<a href=\"foo\">b</a></div>", "body", + MoveCommands::ExecuteMoveToEndOfLine, + "<div>a<a href=\"foo\">b|</a></div>", "a"); +} + +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveToEndOfParagraph) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>a|<a href=\"foo\">b</a></div>", "body", + MoveCommands::ExecuteMoveToEndOfParagraph, + "<div>a<a href=\"foo\">b|</a></div>", "a"); +} + +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveToEndOfSentence) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>a|<a href=\"foo\">b</a></div>", "body", + MoveCommands::ExecuteMoveToEndOfSentence, + "<div>a<a href=\"foo\">b|</a></div>", "a"); +} + +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveToLeftEndOfLine) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">a</a>|b</div>", "body", + MoveCommands::ExecuteMoveToLeftEndOfLine, + "<div><a href=\"foo\">|a</a>b</div>", "a"); +} + +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveToRightEndOfLine) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>a|<a href=\"foo\">b</a></div>", "body", + MoveCommands::ExecuteMoveToRightEndOfLine, + "<div>a<a href=\"foo\">b|</a></div>", "a"); +} + +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_MoveUp) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">ab</a></div><div>c|d</div>", "body", + MoveCommands::ExecuteMoveUp, +#if !defined(OS_MACOSX) + "<div><a href=\"foo\">a|b</a></div><div>cd</div>", "a"); +#else // defined(OS_MACOSX) + // MoveUp navigates visually, placing caret at different position for + // macOS. + "<div><a href=\"foo\">|ab</a></div><div>cd</div>", "a"); +#endif // !defined(OS_MACOSX) +} + +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_MoveWordBackward) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">a</a>|b</div>", "body", + MoveCommands::ExecuteMoveWordBackward, + "<div><a href=\"foo\">|a</a>b</div>", "a"); +} + +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_MoveWordForward) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>a|<a href=\"foo\">b</a></div>", "body", + MoveCommands::ExecuteMoveWordForward, + "<div>a<a href=\"foo\">b|</a></div>", "a"); +} + +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_MoveWordLeft) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">a</a>|b</div>", "body", + MoveCommands::ExecuteMoveWordLeft, "<div><a href=\"foo\">|a</a>b</div>", + "a"); +} + +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_MoveWordRight) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>a|<a href=\"foo\"> b</a></div>", "body", + MoveCommands::ExecuteMoveWordRight, "<div>a<a href=\"foo\"> b|</a></div>", + "a"); +} + +// This test verifies that focus returns to the body after browsing out of a +// focusable element. +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_ExitingFocusableElement) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div><a href=\"foo\">a|</a>b</div>", "a", MoveCommands::ExecuteMoveRight, + "<div><a href=\"foo\">a</a>b|</div>", "body"); +} + +// This test verifies that caret browsing into a focusable element does not +// move focus if inside an editable region. +TEST_F(MoveCommandsTest, CaretBrowsingPositionAndFocusUpdate_EditableElements) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div contenteditable>a|<a href=\"foo\">b</a>c</div>", "div", + MoveCommands::ExecuteMoveRight, + "<div contenteditable>a<a href=\"foo\">b|</a>c</div>", "div"); +} + +// This test verifies that another focusable element (the button element) can be +// moved into while caret browsing and gains focus, just like an anchor +// element. +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveRightButtonElement) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>Some text to the left of the button|<button>Click " + "Me!</button></div>", + "body", MoveCommands::ExecuteMoveRight, + "<div>Some text to the left of the button<button>C|lick " + "Me!</button></div>", + "button"); +} + +// This test verifies that an element with tabindex set can be moved +// into while caret browsing and gains focus, just like an anchor element. +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveRightElementWithTabIndex) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>Some text to the left of the span|<span tabindex=\"0\">Span with " + "tabindex set</span></div>", + "body", MoveCommands::ExecuteMoveRight, + "<div>Some text to the left of the span<span tabindex=\"0\">S|pan with " + "tabindex set</span></div>", + "span"); +} + +// This test verifies that an input element will be skipped when caret browsing +// and not gain focus. +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveRightInputElement) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>Some text to the left of the input element|<input type=\"text\" " + "value=\"This is some initial text\">Some text to the right of the input " + "element</div>", + "body", MoveCommands::ExecuteMoveRight, + "<div>Some text to the left of the input element<input type=\"text\" " + "value=\"This is some initial text\">|Some text to the right of the " + "input element</div>", + "body"); +} + +// This test verifies that a contentEditable element will be skipped when caret +// browsing and not gain focus. +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveRightContentEditableElement) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>Some text to the left of the contentEditable element|<span " + "contentEditable=\"true\">I am content editable</span>Some text to the " + "right of the contentEditable element</div>", + "body", MoveCommands::ExecuteMoveRight, + "<div>Some text to the left of the contentEditable element<span " + "contenteditable=\"true\">I am content editable</span>|Some text to the " + "right of the contentEditable element</div>", + "body"); +} + +// This test verifies that a textarea element will be skipped when caret +// browsing and not gain focus. +TEST_F(MoveCommandsTest, + CaretBrowsingPositionAndFocusUpdate_MoveRightTextAreaElement) { + VerifyCaretBrowsingPositionAndFocusUpdate( + "<div>Some text to the left of the textarea element|<textarea>I am in a " + "textarea</textarea>Some text to the " + "right of the textarea element</div>", + "body", MoveCommands::ExecuteMoveRight, + "<div>Some text to the left of the textarea element<textarea>I am in a " + "textarea</textarea>|Some text to the " + "right of the textarea element</div>", + "body"); +} + +// This test verifies that while caret browsing if you try to move the caret +// when it is not in focus then it jumps to the active element before moving. +TEST_F(MoveCommandsTest, CaretBrowsingSelectionUpdate) { + Selection().SetSelection( + SetSelectionTextToBody("<div>|a<a href=\"foo\">b</a></div>"), + SetSelectionOptions()); + GetDocument().SetFocusedElement( + GetDocument().QuerySelector("a"), + FocusParams(SelectionBehaviorOnFocus::kNone, kWebFocusTypeNone, nullptr)); + GetDocument().GetFrame()->GetSettings()->SetCaretBrowsingEnabled(true); + MoveCommands::ExecuteMoveRight(*GetDocument().GetFrame(), nullptr, + EditorCommandSource::kMenuOrKeyBinding, + String()); + EXPECT_EQ("<div>a<a href=\"foo\">b|</a></div>", GetSelectionTextFromBody()); +} + +} // namespace blink diff --git a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc index 16890313a8f..3e9be2f1704 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc @@ -52,7 +52,6 @@ #include "third_party/blink/renderer/core/editing/visible_units.h" #include "third_party/blink/renderer/core/events/before_text_inserted_event.h" #include "third_party/blink/renderer/core/frame/local_frame.h" -#include "third_party/blink/renderer/core/frame/use_counter.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/forms/html_select_element.h" #include "third_party/blink/renderer/core/html/html_br_element.h" @@ -67,6 +66,7 @@ #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" +#include "third_party/blink/renderer/platform/instrumentation/use_counter.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" #include "third_party/blink/renderer/platform/wtf/vector.h" @@ -556,7 +556,7 @@ void ReplaceSelectionCommand::RemoveRedundantStylesAndKeepStyleSpanInline( if (!node->IsStyledElement()) continue; - Element* element = ToElement(node); + auto* element = To<Element>(node); const CSSPropertyValueSet* inline_style = element->InlineStyle(); EditingStyle* new_inline_style = diff --git a/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_containing_element_command.cc b/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_containing_element_command.cc index 4fb767ba315..77a2d6368ac 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_containing_element_command.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/split_text_node_containing_element_command.cc @@ -55,10 +55,10 @@ void SplitTextNodeContainingElementCommand::DoApply(EditingState*) { LayoutObject* parent_layout_object = parent->GetLayoutObject(); if (!parent_layout_object || !parent_layout_object->IsInline()) { WrapContentsInDummySpan(parent); - Node* first_child = parent->firstChild(); - if (!first_child || !first_child->IsElementNode()) + auto* first_child_element = DynamicTo<Element>(parent->firstChild()); + if (!first_child_element) return; - parent = ToElement(first_child); + parent = first_child_element; } SplitElement(parent, text_.Get()); diff --git a/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc b/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc index 46a362991dd..00eef3d1f00 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc +++ b/chromium/third_party/blink/renderer/core/editing/commands/style_commands.cc @@ -85,7 +85,7 @@ bool StyleCommands::ApplyCommandToFrame(LocalFrame& frame, EditorCommandSource source, InputEvent::InputType input_type, CSSPropertyValueSet* style) { - // TODO(editnig-dev): We don't call shouldApplyStyle when the source is DOM; + // TODO(editing-dev): We don't call shouldApplyStyle when the source is DOM; // is there a good reason for that? switch (source) { case EditorCommandSource::kMenuOrKeyBinding: @@ -315,7 +315,7 @@ bool StyleCommands::ExecuteToggleStyleInList(LocalFrame& frame, const String new_style = ComputeToggleStyleInList(*selection_style, property_id, value); - // TODO(editnig-dev): We shouldn't be having to convert new style into text. + // TODO(editing-dev): We shouldn't be having to convert new style into text. // We should have setPropertyCSSValue. auto* const new_mutable_style = MakeGarbageCollected<MutableCSSPropertyValueSet>(kHTMLQuirksMode); @@ -444,7 +444,7 @@ WritingDirection StyleCommands::TextDirectionForSelection( const CSSComputedStyleDeclaration& style = *MakeGarbageCollected<CSSComputedStyleDeclaration>(&node); const CSSValue* unicode_bidi = - style.GetPropertyCSSValue(GetCSSPropertyUnicodeBidi()); + style.GetPropertyCSSValue(CSSPropertyID::kUnicodeBidi); auto* unicode_bidi_identifier_value = DynamicTo<CSSIdentifierValue>(unicode_bidi); if (!unicode_bidi_identifier_value) @@ -478,11 +478,11 @@ WritingDirection StyleCommands::TextDirectionForSelection( if (!runner.IsStyledElement()) continue; - Element* element = &ToElement(runner); + auto* element = To<Element>(&runner); const CSSComputedStyleDeclaration& style = *MakeGarbageCollected<CSSComputedStyleDeclaration>(element); const CSSValue* unicode_bidi = - style.GetPropertyCSSValue(GetCSSPropertyUnicodeBidi()); + style.GetPropertyCSSValue(CSSPropertyID::kUnicodeBidi); auto* unicode_bidi_identifier_value = DynamicTo<CSSIdentifierValue>(unicode_bidi); if (!unicode_bidi_identifier_value) @@ -499,7 +499,7 @@ WritingDirection StyleCommands::TextDirectionForSelection( DCHECK(EditingStyleUtilities::IsEmbedOrIsolate(unicode_bidi_value)) << static_cast<int>(unicode_bidi_value); const CSSValue* direction = - style.GetPropertyCSSValue(GetCSSPropertyDirection()); + style.GetPropertyCSSValue(CSSPropertyID::kDirection); auto* direction_identifier_value = DynamicTo<CSSIdentifierValue>(direction); if (!direction_identifier_value) continue; @@ -534,7 +534,7 @@ EditingTriState StyleCommands::StateTextWritingDirection( WritingDirection selection_direction = TextDirectionForSelection( frame.Selection().ComputeVisibleSelectionInDOMTreeDeprecated(), frame.GetEditor().TypingStyle(), has_nested_or_multiple_embeddings); - // TODO(editnig-dev): We should be returning MixedTriState when + // TODO(editing-dev): We should be returning MixedTriState when // selectionDirection == direction && hasNestedOrMultipleEmbeddings return (selection_direction == direction && !has_nested_or_multiple_embeddings) @@ -584,7 +584,7 @@ String StyleCommands::SelectionStartCSSPropertyValue( String StyleCommands::ValueStyle(LocalFrame& frame, CSSPropertyID property_id) { frame.GetDocument()->UpdateStyleAndLayout(); - // TODO(editnig-dev): Rather than retrieving the style at the start of the + // TODO(editing-dev): Rather than retrieving the style at the start of the // current selection, we should retrieve the style present throughout the // selection for non-Mac platforms. return SelectionStartCSSPropertyValue(frame, property_id); diff --git a/chromium/third_party/blink/renderer/core/editing/commands/style_commands.h b/chromium/third_party/blink/renderer/core/editing/commands/style_commands.h index cece1e2a9c7..0400ca28394 100644 --- a/chromium/third_party/blink/renderer/core/editing/commands/style_commands.h +++ b/chromium/third_party/blink/renderer/core/editing/commands/style_commands.h @@ -33,7 +33,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_STYLE_COMMANDS_H_ #include "third_party/blink/renderer/core/events/input_event.h" -#include "third_party/blink/renderer/platform/wtf/allocator.h" +#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/forward.h" namespace blink { |