1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/vr/content_input_delegate.h"
6 
7 #include <utility>
8 
9 #include "base/time/time.h"
10 #include "chrome/browser/vr/platform_input_handler.h"
11 
12 namespace vr {
13 
ContentInputDelegate()14 ContentInputDelegate::ContentInputDelegate() {}
15 
ContentInputDelegate(PlatformInputHandler * input_handler)16 ContentInputDelegate::ContentInputDelegate(PlatformInputHandler* input_handler)
17     : PlatformUiInputDelegate(input_handler) {}
18 
19 ContentInputDelegate::~ContentInputDelegate() = default;
20 
OnFocusChanged(bool focused)21 void ContentInputDelegate::OnFocusChanged(bool focused) {
22   // The call below tells the renderer to clear the focused element. Note that
23   // we don't need to do anything when focused is true because the renderer
24   // already knows about the focused element.
25   if (!focused)
26     input_handler()->ClearFocusedElement();
27 }
28 
OnWebInputEdited(const EditedText & info,bool commit)29 void ContentInputDelegate::OnWebInputEdited(const EditedText& info,
30                                             bool commit) {
31   if (!input_handler())
32     return;
33 
34   last_keyboard_edit_ = info;
35 
36   if (commit) {
37     input_handler()->SubmitWebInput();
38     return;
39   }
40 
41   input_handler()->OnWebInputEdited(info.GetDiff());
42 }
43 
OnSwapContents(int new_content_id)44 void ContentInputDelegate::OnSwapContents(int new_content_id) {
45   content_id_ = new_content_id;
46 }
47 
SendGestureToTarget(std::unique_ptr<InputEvent> event)48 void ContentInputDelegate::SendGestureToTarget(
49     std::unique_ptr<InputEvent> event) {
50   if (!event || !input_handler() || ContentGestureIsLocked(event->type()))
51     return;
52 
53   input_handler()->ForwardEventToContent(std::move(event), content_id_);
54 }
55 
ContentGestureIsLocked(InputEvent::Type type)56 bool ContentInputDelegate::ContentGestureIsLocked(InputEvent::Type type) {
57   // TODO (asimjour) create a new HoverEnter event when we swap webcontents and
58   // pointer is on the content quad.
59   if (type == InputEvent::kScrollBegin || type == InputEvent::kHoverMove ||
60       type == InputEvent::kButtonDown || type == InputEvent::kHoverEnter)
61     locked_content_id_ = content_id_;
62 
63   return locked_content_id_ != content_id_;
64 }
65 
OnWebInputIndicesChanged(int selection_start,int selection_end,int composition_start,int composition_end,TextInputUpdateCallback callback)66 void ContentInputDelegate::OnWebInputIndicesChanged(
67     int selection_start,
68     int selection_end,
69     int composition_start,
70     int composition_end,
71     TextInputUpdateCallback callback) {
72   // The purpose of this method is to determine if we need to query content for
73   // the text surrounding the currently focused web input field.
74 
75   // If the changed indices match with that from the last keyboard edit, then
76   // this is called in response to the user entering text using the keyboard, so
77   // we already know the text and don't need to ask content for it.
78   TextInputInfo i = last_keyboard_edit_.current;
79   if (i.selection_start == selection_start &&
80       i.selection_end == selection_end &&
81       i.composition_start == composition_start &&
82       i.composition_end == composition_end) {
83     std::move(callback).Run(i);
84     return;
85   }
86 
87   // Otherwise, queue up the callback
88   update_state_callbacks_.emplace(std::move(callback));
89 
90   // If there's no current request, create one
91   if (pending_text_request_state_ == kNoPendingRequest) {
92     TextInputInfo pending_text_input_info;
93     pending_text_input_info.selection_start = selection_start;
94     pending_text_input_info.selection_end = selection_end;
95     pending_text_input_info.composition_start = composition_start;
96     pending_text_input_info.composition_end = composition_end;
97     input_handler()->RequestWebInputText(base::BindOnce(
98         &ContentInputDelegate::OnWebInputTextChanged, base::Unretained(this),
99         std::move(pending_text_input_info)));
100     pending_text_request_state_ = kRequested;
101   }
102 }
103 
ClearTextInputState()104 void ContentInputDelegate::ClearTextInputState() {
105   pending_text_request_state_ = kNoPendingRequest;
106   last_keyboard_edit_ = EditedText();
107 }
108 
OnWebInputTextChanged(TextInputInfo pending_input_info,const base::string16 & text)109 void ContentInputDelegate::OnWebInputTextChanged(
110     TextInputInfo pending_input_info,
111     const base::string16& text) {
112   pending_input_info.text = text;
113   DCHECK(!update_state_callbacks_.empty());
114 
115   while (!update_state_callbacks_.empty()) {
116     auto update_state_callback = std::move(update_state_callbacks_.front());
117     update_state_callbacks_.pop();
118     std::move(update_state_callback).Run(pending_input_info);
119   }
120 
121   pending_text_request_state_ = kNoPendingRequest;
122 }
123 
124 }  // namespace vr
125