blob: 74981bbdf36f11cc8288fd8b77f604db781ea3be [file] [log] [blame]
// Copyright 2017 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 "chrome/browser/vr/content_input_delegate.h"
#include <utility>
#include "base/time/time.h"
#include "chrome/browser/vr/platform_input_handler.h"
namespace vr {
ContentInputDelegate::ContentInputDelegate() {}
ContentInputDelegate::ContentInputDelegate(PlatformInputHandler* input_handler)
: PlatformUiInputDelegate(input_handler) {}
ContentInputDelegate::~ContentInputDelegate() = default;
void ContentInputDelegate::OnFocusChanged(bool focused) {
// The call below tells the renderer to clear the focused element. Note that
// we don't need to do anything when focused is true because the renderer
// already knows about the focused element.
if (!focused)
input_handler()->ClearFocusedElement();
}
void ContentInputDelegate::OnWebInputEdited(const EditedText& info,
bool commit) {
if (!input_handler())
return;
last_keyboard_edit_ = info;
if (commit) {
input_handler()->SubmitWebInput();
return;
}
input_handler()->OnWebInputEdited(info.GetDiff());
}
void ContentInputDelegate::OnSwapContents(int new_content_id) {
content_id_ = new_content_id;
}
void ContentInputDelegate::SendGestureToTarget(
std::unique_ptr<InputEvent> event) {
if (!event || !input_handler() || ContentGestureIsLocked(event->type()))
return;
input_handler()->ForwardEventToContent(std::move(event), content_id_);
}
bool ContentInputDelegate::ContentGestureIsLocked(InputEvent::Type type) {
// TODO (asimjour) create a new HoverEnter event when we swap webcontents and
// pointer is on the content quad.
if (type == InputEvent::kScrollBegin || type == InputEvent::kHoverMove ||
type == InputEvent::kButtonDown || type == InputEvent::kHoverEnter)
locked_content_id_ = content_id_;
return locked_content_id_ != content_id_;
}
void ContentInputDelegate::OnWebInputIndicesChanged(
int selection_start,
int selection_end,
int composition_start,
int composition_end,
TextInputUpdateCallback callback) {
// The purpose of this method is to determine if we need to query content for
// the text surrounding the currently focused web input field.
// If the changed indices match with that from the last keyboard edit, then
// this is called in response to the user entering text using the keyboard, so
// we already know the text and don't need to ask content for it.
TextInputInfo i = last_keyboard_edit_.current;
if (i.selection_start == selection_start &&
i.selection_end == selection_end &&
i.composition_start == composition_start &&
i.composition_end == composition_end) {
std::move(callback).Run(i);
return;
}
// Otherwise, queue up the callback
update_state_callbacks_.emplace(std::move(callback));
// If there's no current request, create one
if (pending_text_request_state_ == kNoPendingRequest) {
TextInputInfo pending_text_input_info;
pending_text_input_info.selection_start = selection_start;
pending_text_input_info.selection_end = selection_end;
pending_text_input_info.composition_start = composition_start;
pending_text_input_info.composition_end = composition_end;
input_handler()->RequestWebInputText(base::BindOnce(
&ContentInputDelegate::OnWebInputTextChanged, base::Unretained(this),
std::move(pending_text_input_info)));
pending_text_request_state_ = kRequested;
}
}
void ContentInputDelegate::ClearTextInputState() {
pending_text_request_state_ = kNoPendingRequest;
last_keyboard_edit_ = EditedText();
}
void ContentInputDelegate::OnWebInputTextChanged(
TextInputInfo pending_input_info,
const base::string16& text) {
pending_input_info.text = text;
DCHECK(!update_state_callbacks_.empty());
while (!update_state_callbacks_.empty()) {
auto update_state_callback = std::move(update_state_callbacks_.front());
update_state_callbacks_.pop();
std::move(update_state_callback).Run(pending_input_info);
}
pending_text_request_state_ = kNoPendingRequest;
}
} // namespace vr