Commit 8b89eefd authored by Anupam Snigdha's avatar Anupam Snigdha Committed by Commit Bot

EditContext prototype implementation

This change contains the prototype implementation of EditContext APIs.
EditContext simplifies the process of integrating a web app with advanced
text input methods such as IME, VK shape-writing, speech recognition etc.
EditContext decouples text input from the HTML DOM view.
Rather than having the web platform infer the data required to enable
sophisticated text input mechanisms from the HTML DOM, the author will
provide that data explicitly through the API surface of the EditContext.
Additionally, EditContext communicates events driven from text input UI
to JavaScript.

Explainer: https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/
           master/EditContext/explainer.md

Test: run_web_tests web_tests/editing/input/edit-context.html

Bug: 999184

Change-Id: I36f115bf37e6ea2adb64c2f42e024dc800b56480
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1868848
Commit-Queue: Anupam Snigdha <snianu@microsoft.com>
Reviewed-by: default avatarYoshifumi Inoue <yosin@chromium.org>
Reviewed-by: default avatarKent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#713160}
parent 1badd783
......@@ -80,6 +80,13 @@ class WebInputMethodController {
virtual bool GetCompositionCharacterBounds(WebVector<WebRect>& bounds) {
return false;
}
// Populate |control_bounds| and |selection_bounds| with the bounds fetched
// from the active EditContext
virtual void GetLayoutBounds(WebRect& control_bounds,
WebRect& selection_bounds) = 0;
// Returns true if there is an active EditContext
virtual bool IsEditContextActive() const = 0;
};
} // namespace blink
......
......@@ -143,6 +143,7 @@ core_idl_files =
"trustedtypes/trusted_type_policy.idl",
"trustedtypes/trusted_type_policy_factory.idl",
"editing/selection.idl",
"editing/ime/edit_context.idl",
"editing/ime/text_update_event.idl",
"editing/ime/text_format_update_event.idl",
"events/animation_event.idl",
......@@ -626,6 +627,7 @@ core_dictionary_idl_files =
"dom/events/event_init.idl",
"dom/events/event_listener_options.idl",
"dom/events/event_modifier_init.idl",
"editing/ime/edit_context_init.idl",
"editing/ime/text_update_event_init.idl",
"editing/ime/text_format_update_event_init.idl",
"events/animation_event_init.idl",
......
......@@ -144,6 +144,8 @@ blink_core_sources("editing") {
"frame_selection.h",
"granularity_strategy.cc",
"granularity_strategy.h",
"ime/edit_context.cc",
"ime/edit_context.h",
"ime/ime_text_span.cc",
"ime/ime_text_span.h",
"ime/ime_text_span_vector_builder.cc",
......
This diff is collapsed.
This diff is collapsed.
// 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.
// The goal of the EditContext is to expose the lower-level APIs provided by
// modern operating systems to facilitate various input modalities to unlock
// advanced editing scenarios. For more information please refer
// https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/master/EditContext/explainer.md
[
Constructor(optional EditContextInit options),
ConstructorCallWith=ScriptState,
Exposed=Window,
RuntimeEnabled=EditContext
] interface EditContext : EventTarget {
void focus();
void blur();
[RaisesException] void updateSelection(unsigned long start, unsigned long end);
void updateLayout(DOMRect controlBounds, DOMRect selectionBounds);
[RaisesException] void updateText(unsigned long start, unsigned long end, DOMString newText);
attribute DOMString text;
[RaisesException=Setter] attribute unsigned long selectionStart;
[RaisesException=Setter] attribute unsigned long selectionEnd;
attribute EditContextInputMode inputMode;
attribute EditContextInputPanelPolicy inputPanelPolicy;
attribute EditContextEnterKeyHint enterKeyHint;
// Event handler attributes
attribute EventHandler ontextupdate;
attribute EventHandler ontextformatupdate;
attribute EventHandler oncompositionstart;
attribute EventHandler oncompositionend;
};
// 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.
enum EditContextInputMode { "none", "text", "decimal", "search", "email", "numeric", "tel", "url", "password" };
enum EditContextEnterKeyHint { "enter", "done", "go", "next", "previous", "search", "send" };
enum EditContextInputPanelPolicy { "auto", "manual" };
dictionary EditContextInit {
DOMString text;
unsigned long selectionStart;
unsigned long selectionEnd;
EditContextInputMode inputMode;
EditContextInputPanelPolicy inputPanelPolicy;
EditContextEnterKeyHint enterKeyHint;
};
......@@ -38,6 +38,7 @@
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/ime/edit_context.h"
#include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
#include "third_party/blink/renderer/core/editing/markers/suggestion_marker_properties.h"
#include "third_party/blink/renderer/core/editing/reveal_selection_scope.h"
......@@ -1555,6 +1556,7 @@ void InputMethodController::WillChangeFocus() {
void InputMethodController::Trace(Visitor* visitor) {
visitor->Trace(frame_);
visitor->Trace(composition_range_);
visitor->Trace(active_edit_context_);
DocumentShutdownObserver::Trace(visitor);
}
......
......@@ -42,6 +42,7 @@
namespace blink {
class Editor;
class EditContext;
class LocalFrame;
class Range;
enum class TypingContinuation;
......@@ -113,6 +114,12 @@ class CORE_EXPORT InputMethodController final
// Call this when we will change focus.
void WillChangeFocus();
// Returns the |EditContext| that is currently active
EditContext* GetActiveEditContext() const { return active_edit_context_; }
void SetActiveEditContext(EditContext* edit_context) {
active_edit_context_ = edit_context;
}
private:
friend class InputMethodControllerTest;
......@@ -121,6 +128,7 @@ class CORE_EXPORT InputMethodController final
Member<LocalFrame> frame_;
Member<Range> composition_range_;
Member<EditContext> active_edit_context_;
bool has_composition_;
Editor& GetEditor() const;
......
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_TEXT_FORMAT_UPDATE_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_TEXT_FORMAT_UPDATE_EVENT_H_
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_TEXT_FORMAT_UPDATE_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_TEXT_FORMAT_UPDATE_EVENT_H_
#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
......@@ -56,4 +56,4 @@ class CORE_EXPORT TextFormatUpdateEvent final : public Event {
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_TEXT_FORMAT_UPDATE_EVENT_H_
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_TEXT_FORMAT_UPDATE_EVENT_H_
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_TEXT_UPDATE_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_TEXT_UPDATE_EVENT_H_
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_TEXT_UPDATE_EVENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_TEXT_UPDATE_EVENT_H_
#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
......@@ -59,4 +59,4 @@ class CORE_EXPORT TextUpdateEvent final : public Event {
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_TEXT_UPDATE_EVENT_H_
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_IME_TEXT_UPDATE_EVENT_H_
......@@ -11,6 +11,7 @@
"AccessibleNode",
"Animation",
"Clipboard",
"EditContext",
"FontFaceSet",
"MediaQueryList",
"BroadcastChannel",
......
......@@ -15,6 +15,7 @@
#include "third_party/blink/renderer/core/editing/editor.h"
#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/ime/edit_context.h"
#include "third_party/blink/renderer/core/editing/ime/ime_text_span_vector_builder.h"
#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
#include "third_party/blink/renderer/core/editing/plain_text_range.h"
......@@ -37,12 +38,22 @@ void WebInputMethodControllerImpl::Trace(blink::Visitor* visitor) {
visitor->Trace(web_frame_);
}
bool WebInputMethodControllerImpl::IsEditContextActive() const {
return GetInputMethodController().GetActiveEditContext();
}
bool WebInputMethodControllerImpl::SetComposition(
const WebString& text,
const WebVector<WebImeTextSpan>& ime_text_spans,
const WebRange& replacement_range,
int selection_start,
int selection_end) {
if (IsEditContextActive()) {
return GetInputMethodController().GetActiveEditContext()->SetComposition(
text, ime_text_spans, replacement_range, selection_start,
selection_end);
}
if (WebPlugin* plugin = FocusedPluginIfInputMethodSupported()) {
return plugin->SetComposition(text, ime_text_spans, replacement_range,
selection_start, selection_end);
......@@ -94,6 +105,12 @@ bool WebInputMethodControllerImpl::FinishComposingText(
// in WebViewImpl::focusedLocalFrameInWidget(), we will reach here with
// |web_frame_| not focused on page.
if (IsEditContextActive()) {
return GetInputMethodController()
.GetActiveEditContext()
->FinishComposingText(selection_behavior);
}
if (WebPlugin* plugin = FocusedPluginIfInputMethodSupported())
return plugin->FinishComposingText(selection_behavior);
......@@ -115,6 +132,11 @@ bool WebInputMethodControllerImpl::CommitText(
std::unique_ptr<UserGestureIndicator> gesture_indicator =
LocalFrame::NotifyUserActivation(GetFrame());
if (IsEditContextActive()) {
return GetInputMethodController().GetActiveEditContext()->CommitText(
text, ime_text_spans, replacement_range, relative_caret_position);
}
if (WebPlugin* plugin = FocusedPluginIfInputMethodSupported()) {
return plugin->CommitText(text, ime_text_spans, replacement_range,
relative_caret_position);
......@@ -136,6 +158,9 @@ bool WebInputMethodControllerImpl::CommitText(
}
WebTextInputInfo WebInputMethodControllerImpl::TextInputInfo() {
if (IsEditContextActive())
return GetInputMethodController().GetActiveEditContext()->TextInputInfo();
return GetFrame()->GetInputMethodController().TextInputInfo();
}
......@@ -146,10 +171,27 @@ int WebInputMethodControllerImpl::ComputeWebTextInputNextPreviousFlags() {
}
WebTextInputType WebInputMethodControllerImpl::TextInputType() {
if (IsEditContextActive())
return GetInputMethodController().GetActiveEditContext()->TextInputType();
return GetFrame()->GetInputMethodController().TextInputType();
}
void WebInputMethodControllerImpl::GetLayoutBounds(WebRect& control_bounds,
WebRect& selection_bounds) {
if (IsEditContextActive()) {
return GetInputMethodController().GetActiveEditContext()->GetLayoutBounds(
control_bounds, selection_bounds);
}
}
WebRange WebInputMethodControllerImpl::CompositionRange() {
if (IsEditContextActive()) {
return GetInputMethodController()
.GetActiveEditContext()
->CompositionRange();
}
EphemeralRange range =
GetFrame()->GetInputMethodController().CompositionEphemeralRange();
......@@ -166,6 +208,9 @@ WebRange WebInputMethodControllerImpl::CompositionRange() {
bool WebInputMethodControllerImpl::GetCompositionCharacterBounds(
WebVector<WebRect>& bounds) {
if (IsEditContextActive())
return false;
WebRange range = CompositionRange();
if (range.IsEmpty())
return false;
......@@ -187,6 +232,12 @@ bool WebInputMethodControllerImpl::GetCompositionCharacterBounds(
}
WebRange WebInputMethodControllerImpl::GetSelectionOffsets() const {
if (IsEditContextActive()) {
return GetInputMethodController()
.GetActiveEditContext()
->GetSelectionOffsets();
}
// TODO(editing-dev): The use of UpdateStyleAndLayout
// needs to be audited. See http://crbug.com/590369 for more details.
GetFrame()->GetDocument()->UpdateStyleAndLayout();
......
......@@ -49,6 +49,10 @@ class CORE_EXPORT WebInputMethodControllerImpl
WebRange GetSelectionOffsets() const override;
void GetLayoutBounds(WebRect& control_bounds,
WebRect& selection_bounds) override;
bool IsEditContextActive() const override;
void Trace(blink::Visitor*);
private:
......
......@@ -160,6 +160,7 @@
#include "third_party/blink/renderer/core/editing/finder/find_in_page_coordinates.h"
#include "third_party/blink/renderer/core/editing/finder/text_finder.h"
#include "third_party/blink/renderer/core/editing/frame_selection.h"
#include "third_party/blink/renderer/core/editing/ime/edit_context.h"
#include "third_party/blink/renderer/core/editing/ime/ime_text_span_vector_builder.h"
#include "third_party/blink/renderer/core/editing/ime/input_method_controller.h"
#include "third_party/blink/renderer/core/editing/iterators/text_iterator.h"
......@@ -1352,6 +1353,12 @@ bool WebLocalFrameImpl::SetCompositionFromExistingText(
int composition_end,
const WebVector<WebImeTextSpan>& ime_text_spans) {
TRACE_EVENT0("blink", "WebLocalFrameImpl::setCompositionFromExistingText");
if (EditContext* edit_context =
GetFrame()->GetInputMethodController().GetActiveEditContext()) {
return edit_context->SetCompositionFromExistingText(
composition_start, composition_end, ime_text_spans);
}
if (!GetFrame()->GetEditor().CanEdit())
return false;
......@@ -1371,6 +1378,12 @@ bool WebLocalFrameImpl::SetCompositionFromExistingText(
void WebLocalFrameImpl::ExtendSelectionAndDelete(int before, int after) {
TRACE_EVENT0("blink", "WebLocalFrameImpl::extendSelectionAndDelete");
if (EditContext* edit_context =
GetFrame()->GetInputMethodController().GetActiveEditContext()) {
edit_context->ExtendSelectionAndDelete(before, after);
return;
}
if (WebPlugin* plugin = FocusedPluginIfInputMethodSupported()) {
plugin->ExtendSelectionAndDelete(before, after);
return;
......
This diff is collapsed.
......@@ -1953,6 +1953,34 @@ interface DynamicsCompressorNode : AudioNode
getter release
getter threshold
method constructor
interface EditContext : EventTarget
attribute @@toStringTag
getter enterKeyHint
getter inputMode
getter inputPanelPolicy
getter oncompositionend
getter oncompositionstart
getter ontextformatupdate
getter ontextupdate
getter selectionEnd
getter selectionStart
getter text
method blur
method constructor
method focus
method updateLayout
method updateSelection
method updateText
setter enterKeyHint
setter inputMode
setter inputPanelPolicy
setter oncompositionend
setter oncompositionstart
setter ontextformatupdate
setter ontextupdate
setter selectionEnd
setter selectionStart
setter text
interface Element : Node
attribute @@toStringTag
attribute @@unscopables
......
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