Commit 1089a4c4 authored by Ryan Daum's avatar Ryan Daum Committed by Commit Bot

[chromecast] Webview text input focus events

  * Registers and watch for text input focus events within webview
    content.

  * Defines a new gRPC payload for said events, and broadcasts them.

Bug: internal b/161811385
Test: manually with wayland client tool
Change-Id: Ie6d5167bc21f40d603e990b08a3e27b3802eeafd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2422501Reviewed-by: default avatarDaniel Nicoara <dnicoara@chromium.org>
Reviewed-by: default avatarKevin Schoedel <kpschoedel@chromium.org>
Commit-Queue: Ryan Daum <rdaum@chromium.org>
Cr-Commit-Position: refs/heads/master@{#815585}
parent cd5015ec
...@@ -480,7 +480,10 @@ void WebviewClient::SendKeyEvent(const Webview* webview, ...@@ -480,7 +480,10 @@ void WebviewClient::SendKeyEvent(const Webview* webview,
key_input->set_key_code(keyboard_code); key_input->set_key_code(keyboard_code);
key_input->set_dom_code(static_cast<int32_t>(dom_code)); key_input->set_dom_code(static_cast<int32_t>(dom_code));
key_input->set_dom_key(static_cast<int32_t>(dom_key)); key_input->set_dom_key(static_cast<int32_t>(dom_key));
key_input->set_is_char(dom_key.IsCharacter());
// Hardcoded to true for our purposes, as IsCharacter doesn't seem to work
// here. Just means we can't test with modifier keys.
key_input->set_is_char(true);
auto key_event = std::make_unique<InputEvent>(); auto key_event = std::make_unique<InputEvent>();
key_event->set_event_type(down ? ui::EventType::ET_KEY_PRESSED key_event->set_event_type(down ? ui::EventType::ET_KEY_PRESSED
......
...@@ -249,6 +249,58 @@ message ResizeRequest { ...@@ -249,6 +249,58 @@ message ResizeRequest {
int32 height = 2; int32 height = 2;
} }
// Represents the input mode of a focused text input field
// Corresponds with:
// http://www.whatwg.org/specs/web-apps/current-work/#attr-fe-inputmode
enum TextInputMode {
TEXT_INPUT_MODE_DEFAULT = 0;
TEXT_INPUT_MODE_NONE = 1;
TEXT_INPUT_MODE_TEXT = 2;
TEXT_INPUT_MODE_TEL = 3;
TEXT_INPUT_MODE_URL = 4;
TEXT_INPUT_MODE_EMAIL = 5;
TEXT_INPUT_MODE_NUMERIC = 6;
TEXT_INPUT_MODE_DECIMAL = 7;
TEXT_INPUT_MODE_SEARCH = 8;
};
// Represents the type of a focused text input field.
// Corresponds with blink's public/platform/WebTextInputType.h
// Reference that source for more extended commentary on meaning of each value.
enum TextInputType {
// Input caret is not in an editable node, no input method shall be used.
TEXT_INPUT_TYPE_NONE = 0;
TEXT_INPUT_TYPE_TEXT = 1;
TEXT_INPUT_TYPE_PASSWORD = 2;
TEXT_INPUT_TYPE_SEARCH = 3;
TEXT_INPUT_TYPE_EMAIL = 4;
TEXT_INPUT_TYPE_NUMBER = 5;
TEXT_INPUT_TYPE_TELEPHONE = 6;
TEXT_INPUT_TYPE_URL = 7;
TEXT_INPUT_TYPE_DATE = 8;
TEXT_INPUT_TYPE_DATE_TIME = 9;
TEXT_INPUT_TYPE_DATE_TIME_LOCAL = 10;
TEXT_INPUT_TYPE_MONTH = 11;
TEXT_INPUT_TYPE_TIME = 12;
TEXT_INPUT_TYPE_WEEK = 13;
TEXT_INPUT_TYPE_TEXT_AREA = 14;
TEXT_INPUT_TYPE_CONTENT_EDITABLE = 15;
TEXT_INPUT_TYPE_DATE_TIME_FIELD = 16;
// Input caret is in an editable node which doesn't support rich editing.
TEXT_INPUT_TYPE_NULL = 17;
}
// Represents a focus event for an input field within the webview's contents.
message TextInputFocusEvent {
TextInputType type = 1;
// Flagged attributes of the focused text input field.
// Corresponds with those described in blink::WebTextInputFlags in
// public/platform/WebTextInputType.h
int32 flags = 2;
}
message WebviewRequest { message WebviewRequest {
// Unique identifier for the request. For requests that will have a response, // Unique identifier for the request. For requests that will have a response,
// the response id will match the request id. // the response id will match the request id.
...@@ -317,6 +369,7 @@ message WebviewResponse { ...@@ -317,6 +369,7 @@ message WebviewResponse {
// channels via AddJavascriptChannelsRequest. // channels via AddJavascriptChannelsRequest.
JavascriptChannelMessage javascript_channel_message = 10; JavascriptChannelMessage javascript_channel_message = 10;
ClearCookiesResponse clear_cookies = 11; ClearCookiesResponse clear_cookies = 11;
TextInputFocusEvent input_focus_event = 12;
AssociateCastAppWindowResponse associate = 20; AssociateCastAppWindowResponse associate = 20;
} }
} }
......
...@@ -25,10 +25,136 @@ ...@@ -25,10 +25,136 @@
#include "third_party/blink/public/common/input/web_touch_event.h" #include "third_party/blink/public/common/input/web_touch_event.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/aura/window_delegate.h" #include "ui/aura/window_delegate.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/ime/constants.h" #include "ui/base/ime/constants.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/input_method_observer.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/text_input_type.h"
#include "ui/events/event.h" #include "ui/events/event.h"
#include "ui/events/event_constants.h" #include "ui/events/event_constants.h"
namespace {
chromecast::webview::TextInputType ConvertTextInputType(
const ui::TextInputType text_input_type) {
switch (text_input_type) {
case ui::TEXT_INPUT_TYPE_NONE:
return chromecast::webview::TEXT_INPUT_TYPE_NONE;
break;
case ui::TEXT_INPUT_TYPE_TEXT:
return chromecast::webview::TEXT_INPUT_TYPE_TEXT;
break;
case ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE:
return chromecast::webview::TEXT_INPUT_TYPE_CONTENT_EDITABLE;
break;
case ui::TEXT_INPUT_TYPE_PASSWORD:
return chromecast::webview::TEXT_INPUT_TYPE_PASSWORD;
break;
case ui::TEXT_INPUT_TYPE_SEARCH:
return chromecast::webview::TEXT_INPUT_TYPE_SEARCH;
break;
case ui::TEXT_INPUT_TYPE_EMAIL:
return chromecast::webview::TEXT_INPUT_TYPE_EMAIL;
break;
case ui::TEXT_INPUT_TYPE_NUMBER:
return chromecast::webview::TEXT_INPUT_TYPE_NUMBER;
break;
case ui::TEXT_INPUT_TYPE_TELEPHONE:
return chromecast::webview::TEXT_INPUT_TYPE_TELEPHONE;
break;
case ui::TEXT_INPUT_TYPE_DATE:
return chromecast::webview::TEXT_INPUT_TYPE_DATE;
break;
case ui::TEXT_INPUT_TYPE_DATE_TIME:
return chromecast::webview::TEXT_INPUT_TYPE_DATE_TIME;
break;
case ui::TEXT_INPUT_TYPE_MONTH:
return chromecast::webview::TEXT_INPUT_TYPE_MONTH;
break;
case ui::TEXT_INPUT_TYPE_TIME:
return chromecast::webview::TEXT_INPUT_TYPE_TIME;
break;
case ui::TEXT_INPUT_TYPE_URL:
return chromecast::webview::TEXT_INPUT_TYPE_URL;
break;
case ui::TEXT_INPUT_TYPE_WEEK:
return chromecast::webview::TEXT_INPUT_TYPE_WEEK;
break;
case ui::TEXT_INPUT_TYPE_TEXT_AREA:
return chromecast::webview::TEXT_INPUT_TYPE_TEXT_AREA;
break;
case ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD:
return chromecast::webview::TEXT_INPUT_TYPE_DATE_TIME_FIELD;
break;
case ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL:
return chromecast::webview::TEXT_INPUT_TYPE_DATE_TIME_LOCAL;
break;
case ui::TEXT_INPUT_TYPE_NULL:
return chromecast::webview::TEXT_INPUT_TYPE_NULL;
break;
}
LOG(ERROR) << "Unmapped TextInputType: " << text_input_type;
return chromecast::webview::TEXT_INPUT_TYPE_NULL;
}
// Used to watch for text field input focus changes and notify the client
// accordingly.
class WebviewInputMethodObserver : public ui::InputMethodObserver {
public:
WebviewInputMethodObserver(chromecast::WebContentController::Client* client,
ui::InputMethod* input_method);
~WebviewInputMethodObserver() override;
WebviewInputMethodObserver(const WebviewInputMethodObserver&) = delete;
WebviewInputMethodObserver& operator=(const WebviewInputMethodObserver&) =
delete;
// ui::InputMethodObserver
void OnFocus() override {}
void OnBlur() override {}
void OnCaretBoundsChanged(const ui::TextInputClient* client) override {}
void OnTextInputStateChanged(const ui::TextInputClient* client) override;
void OnInputMethodDestroyed(const ui::InputMethod* input_method) override;
void OnShowVirtualKeyboardIfEnabled() override {}
private:
chromecast::WebContentController::Client* client_;
ui::InputMethod* input_method_;
};
void WebviewInputMethodObserver::OnTextInputStateChanged(
const ui::TextInputClient* client) {
if (!client)
return;
std::unique_ptr<chromecast::webview::WebviewResponse> focus_event_response =
std::make_unique<chromecast::webview::WebviewResponse>();
auto* focus_event = focus_event_response->mutable_input_focus_event();
focus_event->set_flags(client->GetTextInputFlags());
focus_event->set_type(ConvertTextInputType(client->GetTextInputType()));
client_->EnqueueSend(std::move(focus_event_response));
}
WebviewInputMethodObserver::WebviewInputMethodObserver(
chromecast::WebContentController::Client* client,
ui::InputMethod* input_method)
: client_(client), input_method_(input_method) {
input_method_->AddObserver(this);
}
WebviewInputMethodObserver::~WebviewInputMethodObserver() {
if (input_method_) {
input_method_->RemoveObserver(this);
}
}
void WebviewInputMethodObserver::OnInputMethodDestroyed(
const ui::InputMethod* input_method) {
input_method_ = nullptr;
}
} // namespace
namespace chromecast { namespace chromecast {
WebContentController::WebContentController(Client* client) : client_(client) { WebContentController::WebContentController(Client* client) : client_(client) {
...@@ -168,6 +294,10 @@ void WebContentController::AttachTo(aura::Window* window, int window_id) { ...@@ -168,6 +294,10 @@ void WebContentController::AttachTo(aura::Window* window, int window_id) {
surface_->SetEmbeddedSurfaceId(base::BindRepeating( surface_->SetEmbeddedSurfaceId(base::BindRepeating(
&WebContentController::GetSurfaceId, base::Unretained(this))); &WebContentController::GetSurfaceId, base::Unretained(this)));
HandleResize(contents_window->bounds().size()); HandleResize(contents_window->bounds().size());
// Register for IME events
input_method_observer_ = std::make_unique<WebviewInputMethodObserver>(
client_, contents_window->GetHost()->GetInputMethod());
} }
void WebContentController::ProcessInputEvent(const webview::InputEvent& ev) { void WebContentController::ProcessInputEvent(const webview::InputEvent& ev) {
......
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include "components/exo/surface_observer.h" #include "components/exo/surface_observer.h"
#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_observer.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/input_method_observer.h"
#include "ui/events/gestures/gesture_recognizer_impl.h" #include "ui/events/gestures/gesture_recognizer_impl.h"
namespace aura { namespace aura {
...@@ -139,6 +141,9 @@ class WebContentController ...@@ -139,6 +141,9 @@ class WebContentController
std::set<content::RenderFrameHost*> current_render_frame_set_; std::set<content::RenderFrameHost*> current_render_frame_set_;
std::set<content::RenderWidgetHost*> current_render_widget_set_; std::set<content::RenderWidgetHost*> current_render_widget_set_;
// Used to watch key focus events.
std::unique_ptr<ui::InputMethodObserver> input_method_observer_;
base::WeakPtrFactory<WebContentController> weak_ptr_factory_{this}; base::WeakPtrFactory<WebContentController> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WebContentController); DISALLOW_COPY_AND_ASSIGN(WebContentController);
......
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