Commit 12ed8a7b authored by Christopher Grant's avatar Christopher Grant Committed by Commit Bot

VR: Add initial rendering of omnibox suggestions.

This CL does not cover generation of suggestions, but rather rendering
of suggestions that exist in the UI model. Suggestions are also not yet
properly rendered WRT to alignment, sizing, etc. Proper formatting and
layout can be added after supporting capabilities are added to the UI.

BUG=777542

Change-Id: Ib10b7a1bf05be629322a3db81650324102e2fbfa
Reviewed-on: https://chromium-review.googlesource.com/734222Reviewed-by: default avatarJustin Donnelly <jdonnelly@chromium.org>
Reviewed-by: default avatarIan Vollick <vollick@chromium.org>
Commit-Queue: Christopher Grant <cjgrant@chromium.org>
Cr-Commit-Position: refs/heads/master@{#512865}
parent 10092082
......@@ -102,7 +102,10 @@ static_library("vr_common") {
"gltf_asset.h",
"gltf_parser.cc",
"gltf_parser.h",
"model/model.cc",
"model/model.h",
"model/omnibox_suggestions.cc",
"model/omnibox_suggestions.h",
"service/vr_device_manager.cc",
"service/vr_device_manager.h",
"service/vr_display_host.cc",
......@@ -151,6 +154,7 @@ static_library("vr_common") {
"//chrome/browser/resources:vr_shell_resources",
"//chrome/browser/vr/vector_icons",
"//chrome/common:constants",
"//components/omnibox/browser",
"//components/security_state/core",
"//components/strings",
"//components/toolbar",
......
......@@ -68,6 +68,7 @@ enum UiElementName {
kSpeechRecognitionPromptInnerCircle,
kSpeechRecognitionPromptMicrophoneIcon,
kSpeechRecognitionPromptBackplane,
kSuggestionLayout,
};
} // namespace vr
......
// 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/model/model.h"
namespace vr {
Model::Model() {}
Model::~Model() {}
} // namespace vr
......@@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_VR_MODEL_MODEL_H_
#define CHROME_BROWSER_VR_MODEL_MODEL_H_
#include "chrome/browser/vr/model/omnibox_suggestions.h"
namespace vr {
// As we wait for WebVR frames, we may pass through the following states.
......@@ -24,6 +26,9 @@ enum WebVrTimeoutState {
};
struct Model {
Model();
~Model();
bool loading = false;
float load_progress = 0.0f;
......@@ -32,6 +37,8 @@ struct Model {
bool recognizing_speech = false;
int speech_recognition_state = 0;
std::vector<OmniboxSuggestion> omnibox_suggestions;
};
} // namespace vr
......
// 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/model/omnibox_suggestions.h"
namespace vr {
OmniboxSuggestion::OmniboxSuggestion(const base::string16& new_content,
const base::string16& new_description,
AutocompleteMatch::Type new_type)
: content(new_content), description(new_description), type(new_type) {}
OmniboxSuggestions::OmniboxSuggestions() {}
OmniboxSuggestions::~OmniboxSuggestions() {}
} // namespace vr
// 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.
#ifndef CHROME_BROWSER_VR_MODEL_OMNIBOX_SUGGESTIONS_H_
#define CHROME_BROWSER_VR_MODEL_OMNIBOX_SUGGESTIONS_H_
#include "base/strings/string16.h"
#include "components/omnibox/browser/autocomplete_match.h"
namespace vr {
struct OmniboxSuggestion {
OmniboxSuggestion(const base::string16& new_content,
const base::string16& new_description,
AutocompleteMatch::Type new_type);
base::string16 content;
base::string16 description;
AutocompleteMatch::Type type;
};
struct OmniboxSuggestions {
OmniboxSuggestions();
~OmniboxSuggestions();
std::vector<OmniboxSuggestion> suggestions;
};
} // namespace vr
#endif // CHROME_BROWSER_VR_MODEL_OMNIBOX_SUGGESTIONS_H_
......@@ -120,6 +120,21 @@ bool UiSceneManagerTest::VerifyVisibility(const std::set<UiElementName>& names,
return true;
}
int UiSceneManagerTest::NumVisibleChildren(UiElementName name) const {
auto* root = scene_->GetUiElementByName(name);
EXPECT_NE(root, nullptr);
if (!root) {
return 0;
}
int visible = 0;
for (const auto& element : *root) {
if (element.IsVisible()) {
visible++;
}
}
return visible;
}
bool UiSceneManagerTest::VerifyRequiresLayout(
const std::set<UiElementName>& names,
bool requires_layout) const {
......
......@@ -59,6 +59,9 @@ class UiSceneManagerTest : public testing::Test {
bool VerifyVisibility(const std::set<UiElementName>& names,
bool visible) const;
// Count the number of elements in the named element's subtree.
int NumVisibleChildren(UiElementName name) const;
// Return false if not all elements in the set match the specified requires
// layout state. Other elements are ignored.
bool VerifyRequiresLayout(const std::set<UiElementName>& names,
......
......@@ -8,7 +8,10 @@
#include "base/memory/ptr_util.h"
#include "base/numerics/ranges.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/vr/model/model.h"
#include "chrome/browser/vr/model/omnibox_suggestions.h"
#include "chrome/browser/vr/test/constants.h"
#include "chrome/browser/vr/toolbar_state.h"
#include "chrome/browser/vr/ui.h"
......@@ -18,6 +21,7 @@
#include "chrome/browser/vr/ui_scene.h"
#include "chrome/browser/vr/ui_scene_manager.h"
#include "chrome/browser/vr/vr_shell_renderer.h"
#include "components/omnibox/browser/vector_icons.h"
#include "components/security_state/core/security_state.h"
#include "components/toolbar/vector_icons.h"
#include "third_party/WebKit/public/platform/WebGestureEvent.h"
......@@ -118,6 +122,10 @@ void VrTestContext::HandleInput(ui::Event* event) {
incognito_ = !incognito_;
ui_->SetIncognito(incognito_);
break;
case ui::DomCode::US_S: {
CreateFakeOmniboxSuggestions();
break;
}
default:
break;
}
......@@ -211,6 +219,21 @@ unsigned int VrTestContext::CreateFakeContentTexture() {
return texture_id;
}
void VrTestContext::CreateFakeOmniboxSuggestions() {
// Every time this method is called, change the number of suggestions shown.
static int num_suggestions = 0;
num_suggestions = (num_suggestions + 1) % 4;
auto result = base::MakeUnique<OmniboxSuggestions>();
for (int i = 0; i < num_suggestions; i++) {
result->suggestions.emplace_back(OmniboxSuggestion(
base::UTF8ToUTF16("Suggestion ") + base::IntToString16(i + 1),
base::UTF8ToUTF16("Description text"),
AutocompleteMatch::Type::VOICE_SUGGEST));
}
ui_->SetOmniboxSuggestions(std::move(result));
}
void VrTestContext::OnContentEnter(const gfx::PointF& normalized_hit_point) {}
void VrTestContext::OnContentLeave() {}
......
......@@ -64,6 +64,7 @@ class VrTestContext : public vr::ContentInputDelegate,
private:
unsigned int CreateFakeContentTexture();
void CreateFakeOmniboxSuggestions();
std::unique_ptr<Ui> ui_;
gfx::Size window_size_;
......
......@@ -7,6 +7,7 @@
#include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/vr/model/model.h"
#include "chrome/browser/vr/model/omnibox_suggestions.h"
#include "chrome/browser/vr/speech_recognizer.h"
#include "chrome/browser/vr/ui_input_manager.h"
#include "chrome/browser/vr/ui_interface.h"
......@@ -106,6 +107,11 @@ void Ui::OnSpeechRecognitionStateChanged(int new_state) {
model_->speech_recognition_state = new_state;
}
void Ui::SetOmniboxSuggestions(
std::unique_ptr<OmniboxSuggestions> suggestions) {
model_->omnibox_suggestions = suggestions->suggestions;
}
bool Ui::ShouldRenderWebVr() {
return scene_manager_->ShouldRenderWebVr();
}
......
......@@ -26,6 +26,8 @@ struct Model;
namespace vr {
struct OmniboxSuggestions;
struct UiInitialState {
bool in_cct = false;
bool in_web_vr = false;
......@@ -80,6 +82,8 @@ class Ui : public BrowserUiInterface, public UiInterface {
void OnWebVrTimedOut() override;
void OnWebVrTimeoutImminent() override;
void SetOmniboxSuggestions(std::unique_ptr<OmniboxSuggestions> suggestions);
private:
// This state may be further abstracted into a SkiaUi object.
std::unique_ptr<vr::UiScene> scene_;
......
......@@ -38,8 +38,11 @@ void UiScene::AddUiElement(UiElementName parent,
CHECK_GE(element->id(), 0);
CHECK_EQ(GetUiElementById(element->id()), nullptr);
CHECK_GE(element->draw_phase(), 0);
if (gl_initialized_)
element->Initialize();
if (gl_initialized_) {
for (auto& child : *element) {
child.Initialize();
}
}
GetUiElementByName(parent)->AddChild(std::move(element));
is_dirty_ = true;
}
......
......@@ -167,6 +167,14 @@ static constexpr float kScreenDimmerOpacity = 0.9f;
static constexpr float kVoiceSearchButtonXOffset = 0.25f;
static constexpr float kSuggestionGap = 0.01f;
static constexpr float kSuggestionLineGap = 0.01f;
static constexpr float kSuggestionIconGap = 0.01f;
static constexpr float kSuggestionIconSize = 0.1f;
static constexpr float kSuggestionTextFieldWidth = 0.3f;
static constexpr float kSuggestionContentTextHeight = 0.02f;
static constexpr float kSuggestionDescriptionTextHeight = 0.015f;
} // namespace vr
#endif // CHROME_BROWSER_VR_UI_SCENE_CONSTANTS_H_
......@@ -10,6 +10,7 @@
#include "base/memory/ptr_util.h"
#include "base/numerics/math_constants.h"
#include "chrome/browser/vr/databinding/binding.h"
#include "chrome/browser/vr/databinding/vector_binding.h"
#include "chrome/browser/vr/elements/button.h"
#include "chrome/browser/vr/elements/content_element.h"
#include "chrome/browser/vr/elements/draw_phase.h"
......@@ -72,6 +73,66 @@ void BindColor(UiSceneManager* model, Text* text, P p) {
base::Unretained(text))));
}
typedef LinearLayout SuggestionItem;
typedef VectorBinding<OmniboxSuggestion, SuggestionItem> SuggestionSetBinding;
typedef typename SuggestionSetBinding::ElementBinding SuggestionBinding;
void OnSuggestionModelAdded(UiScene* scene,
SuggestionBinding* element_binding) {
auto icon = base::MakeUnique<VectorIcon>(100);
icon->SetVisible(true);
icon->SetSize(kSuggestionIconSize, kSuggestionIconSize);
icon->set_draw_phase(kPhaseForeground);
VectorIcon* p_icon = icon.get();
auto content_text = base::MakeUnique<Text>(512, kSuggestionContentTextHeight,
kSuggestionTextFieldWidth);
content_text->set_draw_phase(kPhaseForeground);
content_text->SetVisible(true);
content_text->SetTextAlignment(UiTexture::kTextAlignmentLeft);
Text* p_content_text = content_text.get();
auto description_text = base::MakeUnique<Text>(
512, kSuggestionDescriptionTextHeight, kSuggestionTextFieldWidth);
description_text->set_draw_phase(kPhaseForeground);
description_text->SetVisible(true);
description_text->SetTextAlignment(UiTexture::kTextAlignmentLeft);
Text* p_description_text = description_text.get();
auto text_layout = base::MakeUnique<LinearLayout>(LinearLayout::kDown);
text_layout->set_hit_testable(false);
text_layout->set_margin(kSuggestionLineGap);
text_layout->AddChild(std::move(content_text));
text_layout->AddChild(std::move(description_text));
text_layout->SetVisible(true);
auto suggestion_layout = base::MakeUnique<LinearLayout>(LinearLayout::kRight);
suggestion_layout->set_hit_testable(false);
suggestion_layout->set_margin(kSuggestionIconGap);
suggestion_layout->SetVisible(true);
suggestion_layout->AddChild(std::move(icon));
suggestion_layout->AddChild(std::move(text_layout));
element_binding->set_view(suggestion_layout.get());
element_binding->bindings().push_back(
VR_BIND_FUNC(base::string16, SuggestionBinding, element_binding,
model()->content, Text, p_content_text, SetText));
element_binding->bindings().push_back(
VR_BIND_FUNC(base::string16, SuggestionBinding, element_binding,
model()->description, Text, p_description_text, SetText));
element_binding->bindings().push_back(
VR_BIND(AutocompleteMatch::Type, SuggestionBinding, element_binding,
model()->type, VectorIcon, p_icon,
SetIcon(AutocompleteMatch::TypeToVectorIcon(value))));
scene->AddUiElement(kSuggestionLayout, std::move(suggestion_layout));
}
void OnSuggestionModelRemoved(UiScene* scene, SuggestionBinding* binding) {
scene->RemoveUiElement(binding->view()->id());
}
} // namespace
UiSceneManager::UiSceneManager(UiBrowserInterface* browser,
......@@ -96,6 +157,7 @@ UiSceneManager::UiSceneManager(UiBrowserInterface* browser,
CreateWebVRExitWarning();
CreateSystemIndicators();
CreateUrlBar(model);
CreateSuggestionList(model);
CreateWebVrUrlToast();
CreateCloseButton();
CreateScreenDimmer();
......@@ -614,6 +676,27 @@ void UiSceneManager::CreateUrlBar(Model* model) {
scene_->AddUiElement(kLoadingIndicator, std::move(indicator_fg));
}
void UiSceneManager::CreateSuggestionList(Model* model) {
auto layout = base::MakeUnique<LinearLayout>(LinearLayout::kDown);
layout->set_name(kSuggestionLayout);
layout->set_hit_testable(false);
layout->set_y_anchoring(YAnchoring::YTOP);
layout->SetTranslate(0, 0.5, 0.2);
layout->set_margin(kSuggestionGap);
layout->SetVisible(true);
SuggestionSetBinding::ModelAddedCallback added_callback =
base::Bind(&OnSuggestionModelAdded, base::Unretained(scene_));
SuggestionSetBinding::ModelRemovedCallback removed_callback =
base::Bind(&OnSuggestionModelRemoved, base::Unretained(scene_));
auto binding = base::MakeUnique<SuggestionSetBinding>(
&model->omnibox_suggestions, added_callback, removed_callback);
layout->AddBinding(std::move(binding));
scene_->AddUiElement(kUrlBar, std::move(layout));
}
TransientElement* UiSceneManager::AddTransientParent(UiElementName name,
UiElementName parent_name,
int timeout_seconds,
......
......@@ -63,6 +63,8 @@ struct UiInitialState;
// kExitButton
// kUnderDevelopmentNotice
// kVoiceSearchButton
// kSuggestionLayout
// (variable number of suggestions)
// kScreenDimmer
// k2dBrowsingViewportAwareRoot
// kExitWarning
......@@ -148,6 +150,7 @@ class UiSceneManager {
void CreateBackground();
void CreateViewportAwareRoot();
void CreateUrlBar(Model* model);
void CreateSuggestionList(Model* model);
void CreateWebVrUrlToast();
void CreateCloseButton();
void CreateExitPrompt();
......
......@@ -686,4 +686,26 @@ TEST_F(UiSceneManagerTest, SpeechRecognitionPromptBindings) {
EXPECT_TRUE(IsVisible(k2dBrowsingForeground));
}
TEST_F(UiSceneManagerTest, OmniboxSuggestionBindings) {
MakeManager(kNotInCct, kNotInWebVr);
UiElement* container = scene_->GetUiElementByName(kSuggestionLayout);
ASSERT_NE(container, nullptr);
OnBeginFrame();
EXPECT_EQ(container->children().size(), 0u);
int initially_visible = NumVisibleChildren(kSuggestionLayout);
model_->omnibox_suggestions.emplace_back(
OmniboxSuggestion(base::string16(), base::string16(),
AutocompleteMatch::Type::VOICE_SUGGEST));
OnBeginFrame();
EXPECT_EQ(container->children().size(), 1u);
EXPECT_GT(NumVisibleChildren(kSuggestionLayout), initially_visible);
model_->omnibox_suggestions.clear();
OnBeginFrame();
EXPECT_EQ(container->children().size(), 0u);
EXPECT_EQ(NumVisibleChildren(kSuggestionLayout), initially_visible);
}
} // namespace vr
......@@ -2,6 +2,8 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//build/buildflag_header.gni")
import("//device/vr/features/features.gni")
import("//third_party/protobuf/proto_library.gni")
import("//components/vector_icons/vector_icons.gni")
......@@ -9,6 +11,11 @@ if (is_android) {
import("//build/config/android/rules.gni")
}
buildflag_header("build_features") {
header = "features.h"
flags = [ "ENABLE_VR=$enable_vr" ]
}
aggregate_vector_icons("omnibox_vector_icons") {
icon_directory = "vector_icons"
......@@ -56,6 +63,7 @@ static_library("browser") {
"clipboard_url_provider.h",
"contextual_suggestions_service.cc",
"contextual_suggestions_service.h",
"features.h",
"history_match.cc",
"history_match.h",
"history_provider.cc",
......@@ -140,6 +148,7 @@ static_library("browser") {
"//third_party/metrics_proto",
]
deps = [
":build_features",
":in_memory_url_index_cache_proto",
"//base",
"//base:i18n",
......@@ -173,7 +182,7 @@ static_library("browser") {
"//url",
]
if (!is_android && !is_ios) {
if ((!is_android || enable_vr) && !is_ios) {
sources += get_target_outputs(":omnibox_vector_icons")
deps += [
":omnibox_vector_icons",
......
......@@ -20,6 +20,7 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "components/omnibox/browser/autocomplete_provider.h"
#include "components/omnibox/browser/features.h"
#include "components/omnibox/browser/omnibox_field_trial.h"
#include "components/omnibox/browser/suggestion_answer.h"
#include "components/search_engines/template_url.h"
......@@ -28,7 +29,7 @@
#include "ui/gfx/vector_icon_types.h"
#include "url/third_party/mozilla/url_parse.h"
#if !defined(OS_ANDROID) && !defined(OS_IOS)
#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS)
#include "components/omnibox/browser/vector_icons.h" // nogncheck
#include "components/vector_icons/vector_icons.h" // nogncheck
#endif
......@@ -185,7 +186,7 @@ AutocompleteMatch& AutocompleteMatch::operator=(
// static
const gfx::VectorIcon& AutocompleteMatch::TypeToVectorIcon(Type type) {
#if !defined(OS_ANDROID) && !defined(OS_IOS)
#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS)
switch (type) {
case Type::URL_WHAT_YOU_TYPED:
case Type::HISTORY_URL:
......
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