Commit ac9be4e3 authored by Shimi Zhang's avatar Shimi Zhang Committed by Commit Bot

Cursor Control: Register listener for content editable element

In this CL, we register listener for content editable element
including <input> and <textarea> elements.

This is used to notify that the browser side that there will be a
handler for touchstart event, so it needs to send the event to the
renderer.

Please refer to the bug for more information about the overall design.

Bug: 1126778
Change-Id: I35457d5f1ca02c943b5bf594c06a6a70e2c6e3bf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2401786
Commit-Queue: Shimi Zhang <ctzsm@chromium.org>
Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#808475}
parent 1f081d80
...@@ -38,6 +38,7 @@ ...@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/renderer/core/dom/shadow_root.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/frame/local_frame.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/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/frame/settings.h"
...@@ -65,6 +66,7 @@ ...@@ -65,6 +66,7 @@
#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/transforms/transform_operations.h" #include "third_party/blink/renderer/platform/transforms/transform_operations.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h" #include "third_party/blink/renderer/platform/wtf/assertions.h"
#include "ui/base/ui_base_features.h"
namespace blink { namespace blink {
...@@ -74,6 +76,22 @@ bool IsOverflowClipOrVisible(EOverflow overflow) { ...@@ -74,6 +76,22 @@ bool IsOverflowClipOrVisible(EOverflow overflow) {
return overflow == EOverflow::kClip || overflow == EOverflow::kVisible; return overflow == EOverflow::kClip || overflow == EOverflow::kVisible;
} }
bool IsEditableElement(Element* element, const ComputedStyle& style) {
if (style.UserModify() != EUserModify::kReadOnly)
return true;
if (!element)
return false;
if (auto* textarea = DynamicTo<HTMLTextAreaElement>(*element))
return !textarea->IsDisabledOrReadOnly();
if (auto* input = DynamicTo<HTMLInputElement>(*element))
return !input->IsDisabledOrReadOnly() && input->IsTextField();
return false;
}
TouchAction AdjustTouchActionForElement(TouchAction touch_action, TouchAction AdjustTouchActionForElement(TouchAction touch_action,
const ComputedStyle& style, const ComputedStyle& style,
Element* element) { Element* element) {
...@@ -571,6 +589,13 @@ static void AdjustEffectiveTouchAction(ComputedStyle& style, ...@@ -571,6 +589,13 @@ static void AdjustEffectiveTouchAction(ComputedStyle& style,
TouchAction enforced_by_policy = TouchAction::kNone; TouchAction enforced_by_policy = TouchAction::kNone;
if (element->GetDocument().IsVerticalScrollEnforced()) if (element->GetDocument().IsVerticalScrollEnforced())
enforced_by_policy = TouchAction::kPanY; enforced_by_policy = TouchAction::kPanY;
if (base::FeatureList::IsEnabled(::features::kSwipeToMoveCursor) &&
IsEditableElement(element, style)) {
EventHandlerRegistry& registry =
element->GetDocument().GetFrame()->GetEventHandlerRegistry();
registry.DidAddEventHandler(
*element, EventHandlerRegistry::kTouchStartOrMoveEventBlocking);
}
// Apply the adjusted parent effective touch actions. // Apply the adjusted parent effective touch actions.
style.SetEffectiveTouchAction((element_touch_action & inherited_action) | style.SetEffectiveTouchAction((element_touch_action & inherited_action) |
......
...@@ -2,10 +2,13 @@ ...@@ -2,10 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/test/scoped_feature_list.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/frame/event_handler_registry.h"
#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
#include "ui/base/ui_base_features.h"
namespace blink { namespace blink {
...@@ -158,4 +161,76 @@ TEST_F(StyleAdjusterTest, AdjustOverflow) { ...@@ -158,4 +161,76 @@ TEST_F(StyleAdjusterTest, AdjustOverflow) {
EXPECT_EQ(EOverflow::kAuto, target->GetComputedStyle()->OverflowY()); EXPECT_EQ(EOverflow::kAuto, target->GetComputedStyle()->OverflowY());
} }
TEST_F(StyleAdjusterTest, SetListenerForContentEditableArea) {
base::test::ScopedFeatureList feature_list;
feature_list.InitWithFeatures({::features::kSwipeToMoveCursor}, {});
ASSERT_TRUE(base::FeatureList::IsEnabled(::features::kSwipeToMoveCursor));
GetDocument().SetBaseURLOverride(KURL("http://test.com"));
SetBodyInnerHTML(R"HTML(
<div id='target' contenteditable='false'></div>
)HTML");
UpdateAllLifecyclePhasesForTest();
EventHandlerRegistry& registry =
GetDocument().GetFrame()->GetEventHandlerRegistry();
Element* target = GetDocument().getElementById("target");
EXPECT_FALSE(registry.HasEventHandlers(
EventHandlerRegistry::kTouchStartOrMoveEventBlocking));
target->setAttribute(html_names::kContenteditableAttr, "true");
UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(registry.HasEventHandlers(
EventHandlerRegistry::kTouchStartOrMoveEventBlocking));
}
TEST_F(StyleAdjusterTest, SetListenerForInputElement) {
base::test::ScopedFeatureList feature_list;
feature_list.InitWithFeatures({::features::kSwipeToMoveCursor}, {});
ASSERT_TRUE(base::FeatureList::IsEnabled(::features::kSwipeToMoveCursor));
GetDocument().SetBaseURLOverride(KURL("http://test.com"));
SetBodyInnerHTML(R"HTML(
<input type="text" id='target' disabled>
)HTML");
UpdateAllLifecyclePhasesForTest();
EventHandlerRegistry& registry =
GetDocument().GetFrame()->GetEventHandlerRegistry();
Element* target = GetDocument().getElementById("target");
EXPECT_FALSE(registry.HasEventHandlers(
EventHandlerRegistry::kTouchStartOrMoveEventBlocking));
target->removeAttribute(html_names::kDisabledAttr);
UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(registry.HasEventHandlers(
EventHandlerRegistry::kTouchStartOrMoveEventBlocking));
}
TEST_F(StyleAdjusterTest, SetListenerForTextAreaElement) {
base::test::ScopedFeatureList feature_list;
feature_list.InitWithFeatures({::features::kSwipeToMoveCursor}, {});
ASSERT_TRUE(base::FeatureList::IsEnabled(::features::kSwipeToMoveCursor));
GetDocument().SetBaseURLOverride(KURL("http://test.com"));
SetBodyInnerHTML(R"HTML(
<textarea id="target" readonly></textarea>
)HTML");
UpdateAllLifecyclePhasesForTest();
EventHandlerRegistry& registry =
GetDocument().GetFrame()->GetEventHandlerRegistry();
Element* target = GetDocument().getElementById("target");
EXPECT_FALSE(registry.HasEventHandlers(
EventHandlerRegistry::kTouchStartOrMoveEventBlocking));
target->removeAttribute(html_names::kReadonlyAttr);
UpdateAllLifecyclePhasesForTest();
EXPECT_TRUE(registry.HasEventHandlers(
EventHandlerRegistry::kTouchStartOrMoveEventBlocking));
}
} // namespace blink } // namespace blink
...@@ -255,4 +255,7 @@ const char kPredictorNameEmpty[] = "empty"; ...@@ -255,4 +255,7 @@ const char kPredictorNameEmpty[] = "empty";
const char kFilterNameEmpty[] = "empty_filter"; const char kFilterNameEmpty[] = "empty_filter";
const char kFilterNameOneEuro[] = "one_euro_filter"; const char kFilterNameOneEuro[] = "one_euro_filter";
const base::Feature kSwipeToMoveCursor{"SwipeToMoveCursor",
base::FEATURE_DISABLED_BY_DEFAULT};
} // namespace features } // namespace features
...@@ -142,6 +142,10 @@ COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kPredictorNameEmpty[]; ...@@ -142,6 +142,10 @@ COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kPredictorNameEmpty[];
COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kFilterNameEmpty[]; COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kFilterNameEmpty[];
COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kFilterNameOneEuro[]; COMPONENT_EXPORT(UI_BASE_FEATURES) extern const char kFilterNameOneEuro[];
// Android only feature, for swipe to move cursor.
COMPONENT_EXPORT(UI_BASE_FEATURES)
extern const base::Feature kSwipeToMoveCursor;
} // namespace features } // namespace features
#endif // UI_BASE_UI_BASE_FEATURES_H_ #endif // UI_BASE_UI_BASE_FEATURES_H_
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