Commit b0384ac4 authored by Christopher Grant's avatar Christopher Grant Committed by Commit Bot

VR: Improve the text input field element.

This change does the following:
- Splits the input field into text, hint and cursor elements.
- Removes the need to re-render text when the cursor blinks.
- Supports a text hint, shown when the field is empty.

BUG=

Cq-Include-Trybots: master.tryserver.chromium.android:android_optional_gpu_tests_rel;master.tryserver.chromium.linux:linux_optional_gpu_tests_rel;master.tryserver.chromium.mac:mac_optional_gpu_tests_rel;master.tryserver.chromium.win:win_optional_gpu_tests_rel
Change-Id: Ifbf32560cb7003f4d8951bea871680facd5c0a81
Reviewed-on: https://chromium-review.googlesource.com/804114Reviewed-by: default avatarYash Malik <ymalik@chromium.org>
Commit-Queue: Christopher Grant <cjgrant@chromium.org>
Cr-Commit-Position: refs/heads/master@{#521497}
parent e9b6002c
...@@ -13,6 +13,10 @@ ...@@ -13,6 +13,10 @@
#include "ui/gfx/geometry/vector2d.h" #include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/render_text.h" #include "ui/gfx/render_text.h"
namespace {
constexpr float kCursorWidthRatio = 0.07f;
}
namespace vr { namespace vr {
class TextTexture : public UiTexture { class TextTexture : public UiTexture {
...@@ -29,11 +33,20 @@ class TextTexture : public UiTexture { ...@@ -29,11 +33,20 @@ class TextTexture : public UiTexture {
} }
void SetMultiLine(bool multiline) { SetAndDirty(&multiline_, multiline); } void SetMultiLine(bool multiline) { SetAndDirty(&multiline_, multiline); }
void SetCursorEnabled(bool enabled) {
SetAndDirty(&cursor_enabled_, enabled);
}
void SetCursorPosition(int position) {
SetAndDirty(&cursor_position_, position);
}
void SetTextWidth(float width) { SetAndDirty(&text_width_, width); } void SetTextWidth(float width) { SetAndDirty(&text_width_, width); }
gfx::SizeF GetDrawnSize() const override { return size_; } gfx::SizeF GetDrawnSize() const override { return size_; }
gfx::Rect get_cursor_bounds() { return cursor_bounds_; }
// This method does all text preparation for the element other than drawing to // This method does all text preparation for the element other than drawing to
// the texture. This allows for deeper unit testing of the Text element // the texture. This allows for deeper unit testing of the Text element
// without having to mock canvases and simulate frame rendering. The state of // without having to mock canvases and simulate frame rendering. The state of
...@@ -56,6 +69,9 @@ class TextTexture : public UiTexture { ...@@ -56,6 +69,9 @@ class TextTexture : public UiTexture {
TextAlignment alignment_ = kTextAlignmentCenter; TextAlignment alignment_ = kTextAlignmentCenter;
bool multiline_ = true; bool multiline_ = true;
SkColor color_ = SK_ColorBLACK; SkColor color_ = SK_ColorBLACK;
bool cursor_enabled_ = false;
int cursor_position_ = 0;
gfx::Rect cursor_bounds_;
DISALLOW_COPY_AND_ASSIGN(TextTexture); DISALLOW_COPY_AND_ASSIGN(TextTexture);
}; };
...@@ -81,6 +97,25 @@ void Text::SetMultiLine(bool multiline) { ...@@ -81,6 +97,25 @@ void Text::SetMultiLine(bool multiline) {
texture_->SetMultiLine(multiline); texture_->SetMultiLine(multiline);
} }
void Text::SetCursorEnabled(bool enabled) {
texture_->SetCursorEnabled(enabled);
}
void Text::SetCursorPosition(int position) {
texture_->SetCursorPosition(position);
}
gfx::RectF Text::GetCursorBounds() {
// Note that gfx:: cursor bounds always indicate a one-pixel width, so we
// override the width here to be a percentage of height for the sake of
// arbitrary texture sizes.
gfx::Rect bounds = texture_->get_cursor_bounds();
float scale = size().width() / texture_->GetDrawnSize().width();
return gfx::RectF(
bounds.CenterPoint().x() * scale, bounds.CenterPoint().y() * scale,
bounds.height() * scale * kCursorWidthRatio, bounds.height() * scale);
}
void Text::OnSetSize(gfx::SizeF size) { void Text::OnSetSize(gfx::SizeF size) {
texture_->SetTextWidth(size.width()); texture_->SetTextWidth(size.width());
} }
...@@ -113,6 +148,13 @@ std::vector<std::unique_ptr<gfx::RenderText>> TextTexture::LayOutText( ...@@ -113,6 +148,13 @@ std::vector<std::unique_ptr<gfx::RenderText>> TextTexture::LayOutText(
text_, fonts, color_, &text_bounds, alignment_, text_, fonts, color_, &text_bounds, alignment_,
multiline_ ? kWrappingBehaviorWrap : kWrappingBehaviorNoWrap); multiline_ ? kWrappingBehaviorWrap : kWrappingBehaviorNoWrap);
if (cursor_enabled_) {
DCHECK(!multiline_);
lines.front()->SetCursorEnabled(true);
lines.front()->SetCursorPosition(cursor_position_);
cursor_bounds_ = lines.front()->GetUpdatedCursorBounds();
}
// Note, there is no padding here whatsoever. // Note, there is no padding here whatsoever.
size_ = gfx::SizeF(text_bounds.size()); size_ = gfx::SizeF(text_bounds.size());
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "chrome/browser/vr/elements/textured_element.h" #include "chrome/browser/vr/elements/textured_element.h"
#include "chrome/browser/vr/elements/ui_texture.h" #include "chrome/browser/vr/elements/ui_texture.h"
#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkRect.h"
namespace gfx { namespace gfx {
class RenderText; class RenderText;
...@@ -30,6 +31,16 @@ class Text : public TexturedElement { ...@@ -30,6 +31,16 @@ class Text : public TexturedElement {
void SetTextAlignment(UiTexture::TextAlignment alignment); void SetTextAlignment(UiTexture::TextAlignment alignment);
void SetMultiLine(bool multiline); void SetMultiLine(bool multiline);
// This text element does not typically feature a cursor, but since the cursor
// position is deterined while laying out text, a parent may wish to supply
// cursor parameters and determine where the cursor was last drawn.
void SetCursorEnabled(bool enabled);
void SetCursorPosition(int position);
// Returns the most recently computed cursor position, in DMM, relative to the
// corner of the element.
gfx::RectF GetCursorBounds();
void OnSetSize(gfx::SizeF size) override; void OnSetSize(gfx::SizeF size) override;
std::vector<std::unique_ptr<gfx::RenderText>> LayOutTextForTest( std::vector<std::unique_ptr<gfx::RenderText>> LayOutTextForTest(
......
...@@ -5,93 +5,59 @@ ...@@ -5,93 +5,59 @@
#include "chrome/browser/vr/elements/text_input.h" #include "chrome/browser/vr/elements/text_input.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "cc/paint/skia_paint_canvas.h" #include "chrome/browser/vr/elements/rect.h"
#include "chrome/browser/vr/elements/text.h"
#include "chrome/browser/vr/elements/ui_texture.h" #include "chrome/browser/vr/elements/ui_texture.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/render_text.h"
namespace vr { namespace {
constexpr int kCursorBlinkHalfPeriodMs = 600;
}
class TextInputTexture : public UiTexture { namespace vr {
public:
TextInputTexture(float font_height, float text_width)
: font_height_(font_height), text_width_(text_width) {}
~TextInputTexture() override {}
void SetText(const base::string16& text) { SetAndDirty(&text_, text); }
void SetCursorPosition(int position) {
SetAndDirty(&cursor_position_, position);
}
void SetColor(SkColor color) { SetAndDirty(&color_, color); }
void SetCursorVisible(bool visible) {
SetAndDirty(&cursor_visible_, visible);
}
void Draw(SkCanvas* sk_canvas, const gfx::Size& texture_size) override {
cc::SkiaPaintCanvas paint_canvas(sk_canvas);
gfx::Canvas gfx_canvas(&paint_canvas, 1.0f);
gfx::Canvas* canvas = &gfx_canvas;
gfx::FontList font_list;
float pixels_per_meter = texture_size.width() / text_width_;
int pixel_font_height = static_cast<int>(font_height_ * pixels_per_meter);
GetDefaultFontList(pixel_font_height, text_, &font_list);
gfx::Rect text_bounds(texture_size.width(), pixel_font_height);
size_ = gfx::SizeF(text_bounds.size());
std::unique_ptr<gfx::RenderText> render_text(CreateRenderText());
render_text->SetText(text_);
render_text->SetFontList(font_list);
render_text->SetColor(color_);
render_text->SetHorizontalAlignment(gfx::ALIGN_LEFT);
render_text->SetDisplayRect(text_bounds);
if (cursor_visible_) {
render_text->SetCursorEnabled(true);
render_text->SetCursorPosition(cursor_position_);
}
render_text->Draw(canvas);
if (cursor_visible_) {
auto bounds = render_text->GetUpdatedCursorBounds();
canvas->DrawRect(gfx::RectF(bounds), 0xFF000080);
}
}
private:
gfx::Size GetPreferredTextureSize(int width) const override {
return gfx::Size(width, width * font_height_ / text_width_);
}
gfx::SizeF GetDrawnSize() const override { return size_; }
gfx::SizeF size_;
base::string16 text_;
int cursor_position_ = 0;
float font_height_;
float text_width_;
SkColor color_ = SK_ColorBLACK;
bool cursor_visible_ = false;
DISALLOW_COPY_AND_ASSIGN(TextInputTexture);
};
TextInput::TextInput(int maximum_width_pixels, TextInput::TextInput(int maximum_width_pixels,
float font_height_meters, float font_height_meters,
float text_width_meters,
OnFocusChangedCallback focus_changed_callback, OnFocusChangedCallback focus_changed_callback,
OnInputEditedCallback input_edit_callback) OnInputEditedCallback input_edit_callback)
: TexturedElement(maximum_width_pixels), : focus_changed_callback_(focus_changed_callback),
texture_(base::MakeUnique<TextInputTexture>(font_height_meters,
text_width_meters)),
focus_changed_callback_(focus_changed_callback),
input_edit_callback_(input_edit_callback) { input_edit_callback_(input_edit_callback) {
SetSize(text_width_meters, font_height_meters); auto text = base::MakeUnique<Text>(maximum_width_pixels, font_height_meters);
text->set_type(kTypeTextInputHint);
text->set_draw_phase(kPhaseForeground);
text->set_hit_testable(false);
text->set_x_anchoring(LEFT);
text->set_x_centering(LEFT);
text->SetSize(1, 1);
text->SetMultiLine(false);
text->SetTextAlignment(UiTexture::kTextAlignmentLeft);
hint_element_ = text.get();
this->AddChild(std::move(text));
text = base::MakeUnique<Text>(maximum_width_pixels, font_height_meters);
text->set_type(kTypeTextInputText);
text->set_draw_phase(kPhaseForeground);
text->set_hit_testable(false);
text->set_x_anchoring(LEFT);
text->set_x_centering(LEFT);
text->SetSize(1, 1);
text->SetMultiLine(false);
text->SetTextAlignment(UiTexture::kTextAlignmentLeft);
text->SetCursorEnabled(true);
text_element_ = text.get();
this->AddChild(std::move(text));
auto cursor = base::MakeUnique<Rect>();
cursor->set_type(kTypeTextInputCursor);
cursor->set_draw_phase(kPhaseForeground);
cursor->set_hit_testable(false);
cursor->set_x_anchoring(LEFT);
cursor->set_y_anchoring(BOTTOM);
cursor->SetColor(SK_ColorBLUE);
cursor_element_ = cursor.get();
text_element_->AddChild(std::move(cursor));
set_bounds_contain_children(true);
} }
TextInput::~TextInput() {} TextInput::~TextInput() {}
...@@ -105,15 +71,12 @@ bool TextInput::IsEditable() { ...@@ -105,15 +71,12 @@ bool TextInput::IsEditable() {
} }
void TextInput::OnButtonUp(const gfx::PointF& position) { void TextInput::OnButtonUp(const gfx::PointF& position) {
if (!delegate_) RequestFocus();
return;
delegate_->RequestFocus(id());
} }
void TextInput::OnFocusChanged(bool focused) { void TextInput::OnFocusChanged(bool focused) {
focused_ = focused; focused_ = focused;
texture_->SetCursorVisible(focused);
// Update the keyboard with the current text. // Update the keyboard with the current text.
if (delegate_ && focused) if (delegate_ && focused)
delegate_->UpdateInput(text_info_); delegate_->UpdateInput(text_info_);
...@@ -121,39 +84,78 @@ void TextInput::OnFocusChanged(bool focused) { ...@@ -121,39 +84,78 @@ void TextInput::OnFocusChanged(bool focused) {
focus_changed_callback_.Run(focused); focus_changed_callback_.Run(focused);
} }
void TextInput::RequestFocus() {
if (!delegate_)
return;
delegate_->RequestFocus(id());
}
void TextInput::SetHintText(const base::string16& text) {
hint_element_->SetText(text);
}
void TextInput::OnInputEdited(const TextInputInfo& info) { void TextInput::OnInputEdited(const TextInputInfo& info) {
input_edit_callback_.Run(info); input_edit_callback_.Run(info);
} }
void TextInput::OnInputCommitted(const TextInputInfo& info) {} void TextInput::OnInputCommitted(const TextInputInfo& info) {}
void TextInput::SetColor(SkColor color) { void TextInput::SetTextColor(SkColor color) {
texture_->SetColor(color); text_element_->SetColor(color);
}
void TextInput::SetCursorColor(SkColor color) {
cursor_element_->SetColor(color);
} }
void TextInput::UpdateInput(const TextInputInfo& info) { void TextInput::UpdateInput(const TextInputInfo& info) {
if (text_info_ == info) if (text_info_ == info)
return; return;
text_info_ = info; text_info_ = info;
texture_->SetText(info.text);
texture_->SetCursorPosition(info.selection_end);
if (delegate_ && focused_) if (delegate_ && focused_)
delegate_->UpdateInput(info); delegate_->UpdateInput(info);
text_element_->SetText(info.text);
text_element_->SetCursorPosition(info.selection_end);
hint_element_->SetVisible(info.text.empty());
} }
bool TextInput::OnBeginFrame(const base::TimeTicks& time, bool TextInput::OnBeginFrame(const base::TimeTicks& time,
const gfx::Vector3dF& look_at) { const gfx::Vector3dF& look_at) {
base::TimeDelta delta = time - base::TimeTicks(); return SetCursorBlinkState(time);
if (focused_) }
texture_->SetCursorVisible(delta.InMilliseconds() / 500 % 2);
void TextInput::OnSetSize(gfx::SizeF size) {
hint_element_->SetSize(size.width(), size.height());
text_element_->SetSize(size.width(), size.height());
}
return false; void TextInput::OnSetName() {
hint_element_->set_owner_name_for_test(name());
text_element_->set_owner_name_for_test(name());
cursor_element_->set_owner_name_for_test(name());
} }
UiTexture* TextInput::GetTexture() const { void TextInput::LayOutChildren() {
return texture_.get(); // To avoid re-rendering a texture when the cursor blinks, the texture is a
// separate element. Once the text has been laid out, we can position the
// cursor appropriately relative to the text field.
gfx::RectF bounds = text_element_->GetCursorBounds();
cursor_element_->SetTranslate(bounds.x(), bounds.y(), 0);
cursor_element_->SetSize(bounds.width(), bounds.height());
}
bool TextInput::SetCursorBlinkState(const base::TimeTicks& time) {
base::TimeDelta delta = time - base::TimeTicks();
bool visible =
focused_ && delta.InMilliseconds() / kCursorBlinkHalfPeriodMs % 2;
if (cursor_visible_ == visible)
return false;
cursor_visible_ = visible;
cursor_element_->SetVisible(visible);
return true;
} }
} // namespace vr } // namespace vr
...@@ -5,9 +5,8 @@ ...@@ -5,9 +5,8 @@
#ifndef CHROME_BROWSER_VR_ELEMENTS_TEXT_INPUT_H_ #ifndef CHROME_BROWSER_VR_ELEMENTS_TEXT_INPUT_H_
#define CHROME_BROWSER_VR_ELEMENTS_TEXT_INPUT_H_ #define CHROME_BROWSER_VR_ELEMENTS_TEXT_INPUT_H_
#include <memory>
#include "base/callback.h" #include "base/callback.h"
#include "base/macros.h"
#include "chrome/browser/vr/elements/textured_element.h" #include "chrome/browser/vr/elements/textured_element.h"
#include "chrome/browser/vr/elements/ui_texture.h" #include "chrome/browser/vr/elements/ui_texture.h"
#include "chrome/browser/vr/model/text_input_info.h" #include "chrome/browser/vr/model/text_input_info.h"
...@@ -16,12 +15,10 @@ ...@@ -16,12 +15,10 @@
namespace vr { namespace vr {
class TextInputTexture; class Rect;
class Text;
// TODO(cjgrant): This class must be refactored to reuse Text and Rect elements class TextInput : public UiElement {
// for the text and cursor. It exists as-is to facilitate initial integration of
// the keyboard and omnibox.
class TextInput : public TexturedElement {
public: public:
// Called when this element recieves focus. // Called when this element recieves focus.
typedef base::RepeatingCallback<void(bool)> OnFocusChangedCallback; typedef base::RepeatingCallback<void(bool)> OnFocusChangedCallback;
...@@ -30,7 +27,6 @@ class TextInput : public TexturedElement { ...@@ -30,7 +27,6 @@ class TextInput : public TexturedElement {
OnInputEditedCallback; OnInputEditedCallback;
TextInput(int maximum_width_pixels, TextInput(int maximum_width_pixels,
float font_height_meters, float font_height_meters,
float text_width_meters,
OnFocusChangedCallback focus_changed_callback, OnFocusChangedCallback focus_changed_callback,
OnInputEditedCallback input_edit_callback); OnInputEditedCallback input_edit_callback);
~TextInput() override; ~TextInput() override;
...@@ -41,22 +37,33 @@ class TextInput : public TexturedElement { ...@@ -41,22 +37,33 @@ class TextInput : public TexturedElement {
void OnInputEdited(const TextInputInfo& info) override; void OnInputEdited(const TextInputInfo& info) override;
void OnInputCommitted(const TextInputInfo& info) override; void OnInputCommitted(const TextInputInfo& info) override;
void SetTextInputDelegate(TextInputDelegate* text_input_delegate); void RequestFocus();
void SetColor(SkColor color);
void UpdateInput(const TextInputInfo& info); void UpdateInput(const TextInputInfo& info);
void SetHintText(const base::string16& text);
void SetTextColor(SkColor color);
void SetCursorColor(SkColor color);
void SetTextInputDelegate(TextInputDelegate* text_input_delegate);
bool OnBeginFrame(const base::TimeTicks& time, bool OnBeginFrame(const base::TimeTicks& time,
const gfx::Vector3dF& look_at) override; const gfx::Vector3dF& look_at) final;
void OnSetSize(gfx::SizeF size) final;
void OnSetName() final;
private: private:
UiTexture* GetTexture() const override; void LayOutChildren() final;
bool SetCursorBlinkState(const base::TimeTicks& time);
std::unique_ptr<TextInputTexture> texture_;
OnFocusChangedCallback focus_changed_callback_; OnFocusChangedCallback focus_changed_callback_;
OnInputEditedCallback input_edit_callback_; OnInputEditedCallback input_edit_callback_;
TextInputDelegate* delegate_ = nullptr; TextInputDelegate* delegate_ = nullptr;
TextInputInfo text_info_; TextInputInfo text_info_;
bool focused_ = false; bool focused_ = false;
bool cursor_visible_ = false;
Text* hint_element_ = nullptr;
Text* text_element_ = nullptr;
Rect* cursor_element_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(TextInput); DISALLOW_COPY_AND_ASSIGN(TextInput);
}; };
......
...@@ -24,6 +24,9 @@ static const char* g_ui_element_type_strings[] = { ...@@ -24,6 +24,9 @@ static const char* g_ui_element_type_strings[] = {
"kTypeOmniboxSuggestionIcon", "kTypeOmniboxSuggestionIcon",
"kTypeOmniboxSuggestionContentText", "kTypeOmniboxSuggestionContentText",
"kTypeOmniboxSuggestionDescriptionText", "kTypeOmniboxSuggestionDescriptionText",
"kTypeTextInputHint",
"kTypeTextInputText",
"kTypeTextInputCursor",
}; };
static_assert( static_assert(
......
...@@ -24,6 +24,9 @@ enum UiElementType { ...@@ -24,6 +24,9 @@ enum UiElementType {
kTypeOmniboxSuggestionIcon, kTypeOmniboxSuggestionIcon,
kTypeOmniboxSuggestionContentText, kTypeOmniboxSuggestionContentText,
kTypeOmniboxSuggestionDescriptionText, kTypeOmniboxSuggestionDescriptionText,
kTypeTextInputHint,
kTypeTextInputText,
kTypeTextInputCursor,
// This must be last. // This must be last.
kNumUiElementTypes, kNumUiElementTypes,
......
...@@ -116,6 +116,7 @@ void InitializeColorSchemes() { ...@@ -116,6 +116,7 @@ void InitializeColorSchemes() {
normal_scheme.omnibox_text = 0xFF595959; normal_scheme.omnibox_text = 0xFF595959;
normal_scheme.omnibox_suggestion_content = 0xFF595959; normal_scheme.omnibox_suggestion_content = 0xFF595959;
normal_scheme.omnibox_suggestion_description = 0xFF5595FE; normal_scheme.omnibox_suggestion_description = 0xFF5595FE;
normal_scheme.cursor = 0xFF5595FE;
g_fullscreen_scheme.Get() = normal_scheme; g_fullscreen_scheme.Get() = normal_scheme;
ColorScheme& fullscreen_scheme = g_fullscreen_scheme.Get(); ColorScheme& fullscreen_scheme = g_fullscreen_scheme.Get();
......
...@@ -108,6 +108,8 @@ struct ColorScheme { ...@@ -108,6 +108,8 @@ struct ColorScheme {
SkColor omnibox_text; SkColor omnibox_text;
SkColor omnibox_suggestion_content; SkColor omnibox_suggestion_content;
SkColor omnibox_suggestion_description; SkColor omnibox_suggestion_description;
SkColor cursor;
}; };
} // namespace vr } // namespace vr
......
...@@ -11,11 +11,13 @@ ...@@ -11,11 +11,13 @@
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "chrome/browser/vr/controller_mesh.h" #include "chrome/browser/vr/controller_mesh.h"
#include "chrome/browser/vr/keyboard_delegate.h"
#include "chrome/browser/vr/model/model.h" #include "chrome/browser/vr/model/model.h"
#include "chrome/browser/vr/model/omnibox_suggestions.h" #include "chrome/browser/vr/model/omnibox_suggestions.h"
#include "chrome/browser/vr/model/toolbar_state.h" #include "chrome/browser/vr/model/toolbar_state.h"
#include "chrome/browser/vr/speech_recognizer.h" #include "chrome/browser/vr/speech_recognizer.h"
#include "chrome/browser/vr/test/constants.h" #include "chrome/browser/vr/test/constants.h"
#include "chrome/browser/vr/text_input_delegate.h"
#include "chrome/browser/vr/ui.h" #include "chrome/browser/vr/ui.h"
#include "chrome/browser/vr/ui_element_renderer.h" #include "chrome/browser/vr/ui_element_renderer.h"
#include "chrome/browser/vr/ui_input_manager.h" #include "chrome/browser/vr/ui_input_manager.h"
...@@ -56,6 +58,31 @@ void RotateToward(const gfx::Vector3dF& fwd, gfx::Transform* transform) { ...@@ -56,6 +58,31 @@ void RotateToward(const gfx::Vector3dF& fwd, gfx::Transform* transform) {
} // namespace } // namespace
// This stub delegate does nothing today, but can be expanded to offer
// legitimate keyboard support if required.
class TestKeyboardDelegate : KeyboardDelegate {
public:
// KeyboardDelegate implemenation.
void ShowKeyboard() override {}
void HideKeyboard() override {}
void SetTransform(const gfx::Transform&) override {}
bool HitTest(const gfx::Point3F& ray_origin,
const gfx::Point3F& ray_target,
gfx::Point3F* hit_position) override {
return false;
}
void Draw(const CameraModel&) override {}
// Testapp-specific hooks.
void SetUiInterface(vr::KeyboardUiInterface* keyboard) {
keyboard_interface_ = keyboard;
}
void UpdateInput(const vr::TextInputInfo& info) {}
private:
vr::KeyboardUiInterface* keyboard_interface_ = nullptr;
};
VrTestContext::VrTestContext() : view_scale_factor_(kDefaultViewScaleFactor) { VrTestContext::VrTestContext() : view_scale_factor_(kDefaultViewScaleFactor) {
base::FilePath pak_path; base::FilePath pak_path;
PathService::Get(base::DIR_MODULE, &pak_path); PathService::Get(base::DIR_MODULE, &pak_path);
...@@ -64,7 +91,19 @@ VrTestContext::VrTestContext() : view_scale_factor_(kDefaultViewScaleFactor) { ...@@ -64,7 +91,19 @@ VrTestContext::VrTestContext() : view_scale_factor_(kDefaultViewScaleFactor) {
base::i18n::InitializeICU(); base::i18n::InitializeICU();
ui_ = base::MakeUnique<Ui>(this, nullptr, nullptr, nullptr, UiInitialState()); text_input_delegate_ = base::MakeUnique<vr::TextInputDelegate>();
keyboard_delegate_ = base::MakeUnique<vr::TestKeyboardDelegate>();
ui_ = base::MakeUnique<Ui>(this, nullptr, nullptr, text_input_delegate_.get(),
UiInitialState());
text_input_delegate_->SetRequestFocusCallback(
base::BindRepeating(&vr::Ui::RequestFocus, base::Unretained(ui_.get())));
text_input_delegate_->SetUpdateInputCallback(
base::BindRepeating(&TestKeyboardDelegate::UpdateInput,
base::Unretained(keyboard_delegate_.get())));
keyboard_delegate_->SetUiInterface(ui_.get());
model_ = ui_->model_for_test(); model_ = ui_->model_for_test();
ToolbarState state(GURL("https://dangerous.com/dir/file.html"), ToolbarState state(GURL("https://dangerous.com/dir/file.html"),
...@@ -107,8 +146,6 @@ void VrTestContext::DrawFrame() { ...@@ -107,8 +146,6 @@ void VrTestContext::DrawFrame() {
if (model_->web_vr_has_produced_frames()) { if (model_->web_vr_has_produced_frames()) {
ui_->ui_renderer()->DrawWebVrOverlayForeground(render_info); ui_->ui_renderer()->DrawWebVrOverlayForeground(render_info);
} }
// TODO(cjgrant): Render viewport-aware elements.
} }
void VrTestContext::HandleInput(ui::Event* event) { void VrTestContext::HandleInput(ui::Event* event) {
...@@ -149,6 +186,10 @@ void VrTestContext::HandleInput(ui::Event* event) { ...@@ -149,6 +186,10 @@ void VrTestContext::HandleInput(ui::Event* event) {
case ui::DomCode::US_R: case ui::DomCode::US_R:
ui_->OnWebVrFrameAvailable(); ui_->OnWebVrFrameAvailable();
break; break;
case ui::DomCode::US_A: {
CreateFakeTextInput();
break;
}
default: default:
break; break;
} }
...@@ -307,10 +348,24 @@ unsigned int VrTestContext::CreateFakeContentTexture() { ...@@ -307,10 +348,24 @@ unsigned int VrTestContext::CreateFakeContentTexture() {
return texture_id; return texture_id;
} }
void VrTestContext::CreateFakeTextInput() {
// Every time this method is called, change the number of suggestions shown.
const std::string text =
"what is the actual meaning of life when considering all factors";
static int len = 0;
len = (len + 1) % text.size();
TextInputInfo info;
info.text = base::UTF8ToUTF16(text.substr(0, len));
info.selection_start = len;
info.selection_end = len;
ui_->OnInputEdited(info);
}
void VrTestContext::CreateFakeOmniboxSuggestions() { void VrTestContext::CreateFakeOmniboxSuggestions() {
// Every time this method is called, change the number of suggestions shown. // Every time this method is called, change the number of suggestions shown.
static int num_suggestions = 0; static int num_suggestions = 0;
num_suggestions = (num_suggestions + 1) % 4;
auto result = base::MakeUnique<OmniboxSuggestions>(); auto result = base::MakeUnique<OmniboxSuggestions>();
for (int i = 0; i < num_suggestions; i++) { for (int i = 0; i < num_suggestions; i++) {
...@@ -323,6 +378,9 @@ void VrTestContext::CreateFakeOmniboxSuggestions() { ...@@ -323,6 +378,9 @@ void VrTestContext::CreateFakeOmniboxSuggestions() {
} }
model_->omnibox_input_active = true; model_->omnibox_input_active = true;
ui_->SetOmniboxSuggestions(std::move(result)); ui_->SetOmniboxSuggestions(std::move(result));
num_suggestions++;
num_suggestions %= 5;
} }
void VrTestContext::CreateFakeVoiceSearchResult() { void VrTestContext::CreateFakeVoiceSearchResult() {
......
...@@ -20,6 +20,8 @@ class Event; ...@@ -20,6 +20,8 @@ class Event;
namespace vr { namespace vr {
class TextInputDelegate;
class TestKeyboardDelegate;
class Ui; class Ui;
struct Model; struct Model;
...@@ -56,6 +58,7 @@ class VrTestContext : public vr::UiBrowserInterface { ...@@ -56,6 +58,7 @@ class VrTestContext : public vr::UiBrowserInterface {
unsigned int CreateFakeContentTexture(); unsigned int CreateFakeContentTexture();
void CreateFakeOmniboxSuggestions(); void CreateFakeOmniboxSuggestions();
void CreateFakeVoiceSearchResult(); void CreateFakeVoiceSearchResult();
void CreateFakeTextInput();
void CycleWebVrModes(); void CycleWebVrModes();
void ToggleSplashScreen(); void ToggleSplashScreen();
gfx::Transform ProjectionMatrix() const; gfx::Transform ProjectionMatrix() const;
...@@ -86,6 +89,9 @@ class VrTestContext : public vr::UiBrowserInterface { ...@@ -86,6 +89,9 @@ class VrTestContext : public vr::UiBrowserInterface {
ControllerModel last_controller_model_; ControllerModel last_controller_model_;
std::unique_ptr<TextInputDelegate> text_input_delegate_;
std::unique_ptr<TestKeyboardDelegate> keyboard_delegate_;
DISALLOW_COPY_AND_ASSIGN(VrTestContext); DISALLOW_COPY_AND_ASSIGN(VrTestContext);
}; };
......
...@@ -85,7 +85,7 @@ class TextInputTest : public UiTest { ...@@ -85,7 +85,7 @@ class TextInputTest : public UiTest {
base::MakeUnique<StrictMock<MockTextInputDelegate>>(); base::MakeUnique<StrictMock<MockTextInputDelegate>>();
text_input_info_ = base::MakeUnique<TextInputInfo>(); text_input_info_ = base::MakeUnique<TextInputInfo>();
auto text_input = UiSceneCreator::CreateTextInput( auto text_input = UiSceneCreator::CreateTextInput(
512, 1, 1, model_, text_input_info_.get(), text_input_delegate_.get()); 512, 1, model_, text_input_info_.get(), text_input_delegate_.get());
text_input_ = text_input.get(); text_input_ = text_input.get();
scene_->AddUiElement(k2dBrowsingForeground, std::move(text_input)); scene_->AddUiElement(k2dBrowsingForeground, std::move(text_input));
EXPECT_TRUE(OnBeginFrame()); EXPECT_TRUE(OnBeginFrame());
......
...@@ -56,7 +56,6 @@ class MockTextInput : public TextInput { ...@@ -56,7 +56,6 @@ class MockTextInput : public TextInput {
public: public:
MockTextInput() MockTextInput()
: TextInput(512, : TextInput(512,
1,
1, 1,
base::RepeatingCallback<void(bool)>(), base::RepeatingCallback<void(bool)>(),
base::RepeatingCallback<void(const TextInputInfo&)>()) {} base::RepeatingCallback<void(const TextInputInfo&)>()) {}
......
...@@ -982,12 +982,11 @@ void UiSceneCreator::CreateController() { ...@@ -982,12 +982,11 @@ void UiSceneCreator::CreateController() {
std::unique_ptr<TextInput> UiSceneCreator::CreateTextInput( std::unique_ptr<TextInput> UiSceneCreator::CreateTextInput(
int maximum_width_pixels, int maximum_width_pixels,
float font_height_meters, float font_height_meters,
float text_width_meters,
Model* model, Model* model,
TextInputInfo* text_input_model, TextInputInfo* text_input_model,
TextInputDelegate* text_input_delegate) { TextInputDelegate* text_input_delegate) {
auto text_input = base::MakeUnique<TextInput>( auto text_input = base::MakeUnique<TextInput>(
maximum_width_pixels, font_height_meters, text_width_meters, maximum_width_pixels, font_height_meters,
base::BindRepeating( base::BindRepeating(
[](Model* model, bool focused) { model->editing_input = focused; }, [](Model* model, bool focused) { model->editing_input = focused; },
base::Unretained(model)), base::Unretained(model)),
...@@ -996,9 +995,8 @@ std::unique_ptr<TextInput> UiSceneCreator::CreateTextInput( ...@@ -996,9 +995,8 @@ std::unique_ptr<TextInput> UiSceneCreator::CreateTextInput(
*model = text_input_info; *model = text_input_info;
}, },
base::Unretained(text_input_model))); base::Unretained(text_input_model)));
text_input->set_draw_phase(kPhaseForeground); text_input->set_draw_phase(kPhaseNone);
text_input->SetTextInputDelegate(text_input_delegate); text_input->SetTextInputDelegate(text_input_delegate);
text_input->set_hit_testable(true);
text_input->AddBinding(base::MakeUnique<Binding<TextInputInfo>>( text_input->AddBinding(base::MakeUnique<Binding<TextInputInfo>>(
base::BindRepeating([](TextInputInfo* info) { return *info; }, base::BindRepeating([](TextInputInfo* info) { return *info; },
base::Unretained(text_input_model)), base::Unretained(text_input_model)),
...@@ -1121,7 +1119,7 @@ void UiSceneCreator::CreateOmnibox() { ...@@ -1121,7 +1119,7 @@ void UiSceneCreator::CreateOmnibox() {
float width = kOmniboxWidthDMM - 2 * kOmniboxTextMarginDMM; float width = kOmniboxWidthDMM - 2 * kOmniboxTextMarginDMM;
auto omnibox_text_field = auto omnibox_text_field =
CreateTextInput(1024, kOmniboxTextHeightDMM, width, model_, CreateTextInput(1024, kOmniboxTextHeightDMM, model_,
&model_->omnibox_text_field_info, text_input_delegate_); &model_->omnibox_text_field_info, text_input_delegate_);
omnibox_text_field->AddBinding( omnibox_text_field->AddBinding(
VR_BIND(TextInputInfo, Model, model_, omnibox_text_field_info, VR_BIND(TextInputInfo, Model, model_, omnibox_text_field_info,
...@@ -1131,6 +1129,21 @@ void UiSceneCreator::CreateOmnibox() { ...@@ -1131,6 +1129,21 @@ void UiSceneCreator::CreateOmnibox() {
omnibox_text_field->set_x_anchoring(LEFT); omnibox_text_field->set_x_anchoring(LEFT);
omnibox_text_field->set_x_centering(LEFT); omnibox_text_field->set_x_centering(LEFT);
omnibox_text_field->SetTranslate(kOmniboxTextMarginDMM, 0, 0); omnibox_text_field->SetTranslate(kOmniboxTextMarginDMM, 0, 0);
omnibox_text_field->AddBinding(base::MakeUnique<Binding<bool>>(
base::BindRepeating([](Model* m) { return m->omnibox_input_active; },
base::Unretained(model_)),
base::BindRepeating(
[](TextInput* e, const bool& v) {
if (v) {
e->RequestFocus();
}
},
base::Unretained(omnibox_text_field.get()))));
BindColor(model_, omnibox_text_field.get(), &ColorScheme::omnibox_text,
&TextInput::SetTextColor);
BindColor(model_, omnibox_text_field.get(), &ColorScheme::cursor,
&TextInput::SetCursorColor);
scene_->AddUiElement(kOmniboxContainer, std::move(omnibox_text_field)); scene_->AddUiElement(kOmniboxContainer, std::move(omnibox_text_field));
auto close_button = Create<Button>( auto close_button = Create<Button>(
......
...@@ -33,7 +33,6 @@ class UiSceneCreator { ...@@ -33,7 +33,6 @@ class UiSceneCreator {
static std::unique_ptr<TextInput> CreateTextInput( static std::unique_ptr<TextInput> CreateTextInput(
int maximum_width_pixels, int maximum_width_pixels,
float font_height_meters, float font_height_meters,
float text_width_meters,
Model* model, Model* model,
TextInputInfo* text_input_model, TextInputInfo* text_input_model,
TextInputDelegate* text_input_delegate); TextInputDelegate* text_input_delegate);
......
...@@ -122,7 +122,9 @@ const std::vector<std::string> kElementsInDrawOrder = { ...@@ -122,7 +122,9 @@ const std::vector<std::string> kElementsInDrawOrder = {
"kAudioPermissionPromptShadow", "kAudioPermissionPromptShadow",
"kAudioPermissionPrompt", "kAudioPermissionPrompt",
"kOmniboxContainer", "kOmniboxContainer",
"kOmniboxTextField", "kOmniboxTextField:kTypeTextInputHint",
"kOmniboxTextField:kTypeTextInputText",
"kOmniboxTextField:kTypeTextInputCursor",
"kOmniboxCloseButton", "kOmniboxCloseButton",
"kOmniboxCloseButton:kTypeButtonBackground", "kOmniboxCloseButton:kTypeButtonBackground",
"kOmniboxCloseButton:kTypeButtonForeground", "kOmniboxCloseButton:kTypeButtonForeground",
......
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