Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 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 | #ifndef CHROME_BROWSER_VR_UI_H_ |
| 6 | #define CHROME_BROWSER_VR_UI_H_ |
| 7 | |
| 8 | #include <memory> |
| 9 | |
| 10 | #include "base/macros.h" |
| 11 | #include "base/memory/weak_ptr.h" |
Ian Vollick | 8e4a824f | 2018-01-06 05:15:12 | [diff] [blame] | 12 | #include "base/version.h" |
| 13 | #include "chrome/browser/vr/assets_load_status.h" |
Ian Vollick | a39bafec | 2017-09-28 02:27:55 | [diff] [blame] | 14 | #include "chrome/browser/vr/browser_ui_interface.h" |
Yash Malik | d862b31c | 2017-12-02 02:09:32 | [diff] [blame] | 15 | #include "chrome/browser/vr/keyboard_ui_interface.h" |
Tibor Goldschwendt | df2bf01 | 2018-05-08 01:02:13 | [diff] [blame] | 16 | #include "chrome/browser/vr/model/tab_model.h" |
Ian Vollick | 3f6c9804 | 2017-11-06 19:40:50 | [diff] [blame] | 17 | #include "chrome/browser/vr/platform_controller.h" |
| 18 | #include "chrome/browser/vr/ui_element_renderer.h" |
bsheedy | bfabd61d | 2018-04-16 19:02:59 | [diff] [blame] | 19 | #include "chrome/browser/vr/ui_test_input.h" |
Christopher Grant | 7e73a4f | 2018-05-30 21:13:14 | [diff] [blame] | 20 | #include "chrome/browser/vr/vr_export.h" |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 21 | |
| 22 | namespace vr { |
bsheedy | bfabd61d | 2018-04-16 19:02:59 | [diff] [blame] | 23 | |
Christopher Grant | 764281a9 | 2018-03-10 00:48:25 | [diff] [blame] | 24 | class AudioDelegate; |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 25 | class BrowserUiInterface; |
Michael Thiessen | bc382ac | 2018-04-20 20:39:17 | [diff] [blame] | 26 | class ContentElement; |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 27 | class ContentInputDelegate; |
Biao She | 41db7d2 | 2018-05-14 14:08:33 | [diff] [blame] | 28 | class PlatformInputHandler; |
Yash Malik | d862b31c | 2017-12-02 02:09:32 | [diff] [blame] | 29 | class KeyboardDelegate; |
Biao She | 41db7d2 | 2018-05-14 14:08:33 | [diff] [blame] | 30 | class PlatformUiInputDelegate; |
Tibor Goldschwendt | 3d8447c | 2017-11-09 05:30:50 | [diff] [blame] | 31 | class SkiaSurfaceProvider; |
Yash Malik | d862b31c | 2017-12-02 02:09:32 | [diff] [blame] | 32 | class TextInputDelegate; |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 33 | class UiBrowserInterface; |
| 34 | class UiInputManager; |
| 35 | class UiRenderer; |
| 36 | class UiScene; |
Ian Vollick | 8e4a824f | 2018-01-06 05:15:12 | [diff] [blame] | 37 | struct Assets; |
Ian Vollick | 3f6c9804 | 2017-11-06 19:40:50 | [diff] [blame] | 38 | struct ControllerModel; |
Ian Vollick | a39bafec | 2017-09-28 02:27:55 | [diff] [blame] | 39 | struct Model; |
Kenneth Russell | 4c50a16 | 2017-11-08 23:29:07 | [diff] [blame] | 40 | struct OmniboxSuggestions; |
Tibor Goldschwendt | 3d8447c | 2017-11-09 05:30:50 | [diff] [blame] | 41 | struct ReticleModel; |
Christopher Grant | 12ed8a7 | 2017-10-31 17:41:44 | [diff] [blame] | 42 | |
Christopher Grant | 7e73a4f | 2018-05-30 21:13:14 | [diff] [blame] | 43 | struct VR_EXPORT UiInitialState { |
Michael Thiessen | f7f98818 | 2018-04-27 01:16:43 | [diff] [blame] | 44 | UiInitialState(); |
| 45 | UiInitialState(const UiInitialState& other); |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 46 | bool in_cct = false; |
| 47 | bool in_web_vr = false; |
| 48 | bool web_vr_autopresentation_expected = false; |
Michael Thiessen | a0cdfa5 | 2017-10-16 16:23:38 | [diff] [blame] | 49 | bool browsing_disabled = false; |
Amirhossein Simjour | ed1b0d2 | 2017-11-08 15:19:05 | [diff] [blame] | 50 | bool has_or_can_request_audio_permission = true; |
Ian Vollick | 2067330 | 2017-11-22 20:43:31 | [diff] [blame] | 51 | bool skips_redraw_when_not_dirty = false; |
Tibor Goldschwendt | 4dafc60 | 2018-03-06 17:39:44 | [diff] [blame] | 52 | bool assets_supported = false; |
Christopher Grant | 6df268d | 2018-02-13 16:55:54 | [diff] [blame] | 53 | bool supports_selection = true; |
Yash Malik | d68a05a | 2018-03-02 01:06:54 | [diff] [blame] | 54 | bool needs_keyboard_update = false; |
Michael Thiessen | f7f98818 | 2018-04-27 01:16:43 | [diff] [blame] | 55 | bool is_standalone_vr_device = false; |
Tibor Goldschwendt | df2bf01 | 2018-05-08 01:02:13 | [diff] [blame] | 56 | bool create_tabs_view = false; |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 57 | }; |
| 58 | |
| 59 | // This class manages all GLThread owned objects and GL rendering for VrShell. |
| 60 | // It is not threadsafe and must only be used on the GL thread. |
Christopher Grant | 7e73a4f | 2018-05-30 21:13:14 | [diff] [blame] | 61 | class VR_EXPORT Ui : public BrowserUiInterface, public KeyboardUiInterface { |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 62 | public: |
| 63 | Ui(UiBrowserInterface* browser, |
Biao She | 41db7d2 | 2018-05-14 14:08:33 | [diff] [blame] | 64 | PlatformInputHandler* content_input_forwarder, |
Christopher Grant | 764281a9 | 2018-03-10 00:48:25 | [diff] [blame] | 65 | KeyboardDelegate* keyboard_delegate, |
| 66 | TextInputDelegate* text_input_delegate, |
| 67 | AudioDelegate* audio_delegate, |
Ian Vollick | 3f6c9804 | 2017-11-06 19:40:50 | [diff] [blame] | 68 | const UiInitialState& ui_initial_state); |
Ian Vollick | f8030c5 | 2017-11-22 17:14:14 | [diff] [blame] | 69 | |
| 70 | Ui(UiBrowserInterface* browser, |
| 71 | std::unique_ptr<ContentInputDelegate> content_input_delegate, |
Christopher Grant | 764281a9 | 2018-03-10 00:48:25 | [diff] [blame] | 72 | KeyboardDelegate* keyboard_delegate, |
| 73 | TextInputDelegate* text_input_delegate, |
| 74 | AudioDelegate* audio_delegate, |
Ian Vollick | f8030c5 | 2017-11-22 17:14:14 | [diff] [blame] | 75 | const UiInitialState& ui_initial_state); |
| 76 | |
Ian Vollick | a39bafec | 2017-09-28 02:27:55 | [diff] [blame] | 77 | ~Ui() override; |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 78 | |
| 79 | // TODO(crbug.com/767957): Refactor to hide these behind the UI interface. |
| 80 | UiScene* scene() { return scene_.get(); } |
Ian Vollick | 826f56b0 | 2017-11-13 19:53:57 | [diff] [blame] | 81 | UiElementRenderer* ui_element_renderer() { |
| 82 | return ui_element_renderer_.get(); |
| 83 | } |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 84 | UiRenderer* ui_renderer() { return ui_renderer_.get(); } |
| 85 | UiInputManager* input_manager() { return input_manager_.get(); } |
| 86 | |
Christopher Grant | 764281a9 | 2018-03-10 00:48:25 | [diff] [blame] | 87 | base::WeakPtr<BrowserUiInterface> GetBrowserUiWeakPtr(); |
Ian Vollick | a39bafec | 2017-09-28 02:27:55 | [diff] [blame] | 88 | |
| 89 | // BrowserUiInterface |
Christopher Grant | bd2f269 | 2018-03-29 20:52:16 | [diff] [blame] | 90 | void SetWebVrMode(bool enabled) override; |
Ian Vollick | a39bafec | 2017-09-28 02:27:55 | [diff] [blame] | 91 | void SetFullscreen(bool enabled) override; |
| 92 | void SetToolbarState(const ToolbarState& state) override; |
| 93 | void SetIncognito(bool enabled) override; |
Ian Vollick | a39bafec | 2017-09-28 02:27:55 | [diff] [blame] | 94 | void SetLoading(bool loading) override; |
| 95 | void SetLoadProgress(float progress) override; |
| 96 | void SetIsExiting() override; |
| 97 | void SetHistoryButtonsEnabled(bool can_go_back, bool can_go_forward) override; |
Ian Vollick | 1cf746c | 2018-03-23 22:17:25 | [diff] [blame] | 98 | void SetCapturingState(const CapturingStateModel& state) override; |
Michael Thiessen | 8a9a102 | 2018-02-21 22:17:16 | [diff] [blame] | 99 | void ShowExitVrPrompt(UiUnsupportedMode reason) override; |
Biao She | c8521874 | 2017-10-26 21:48:15 | [diff] [blame] | 100 | void SetSpeechRecognitionEnabled(bool enabled) override; |
Biao She | 537a729 | 2017-11-10 18:18:42 | [diff] [blame] | 101 | void SetRecognitionResult(const base::string16& result) override; |
Biao She | c8521874 | 2017-10-26 21:48:15 | [diff] [blame] | 102 | void OnSpeechRecognitionStateChanged(int new_state) override; |
Christopher Grant | b38b120c | 2017-11-17 19:51:22 | [diff] [blame] | 103 | void SetOmniboxSuggestions( |
| 104 | std::unique_ptr<OmniboxSuggestions> suggestions) override; |
Ian Vollick | 8e4a824f | 2018-01-06 05:15:12 | [diff] [blame] | 105 | void OnAssetsLoaded(AssetsLoadStatus status, |
| 106 | std::unique_ptr<Assets> assets, |
Tibor Goldschwendt | 444261f | 2018-03-01 22:36:37 | [diff] [blame] | 107 | const base::Version& component_version) override; |
| 108 | void OnAssetsUnavailable() override; |
Tibor Goldschwendt | f3cd1b0 | 2018-05-14 22:42:46 | [diff] [blame] | 109 | void WaitForAssets() override; |
Michael Thiessen | ee351c1 | 2018-04-11 16:29:58 | [diff] [blame] | 110 | void SetOverlayTextureEmpty(bool empty) override; |
Tibor Goldschwendt | df2bf01 | 2018-05-08 01:02:13 | [diff] [blame] | 111 | void ShowSoftInput(bool show) override; |
| 112 | void UpdateWebInputIndices(int selection_start, |
| 113 | int selection_end, |
| 114 | int composition_start, |
| 115 | int composition_end) override; |
| 116 | void AddOrUpdateTab(int id, |
| 117 | bool incognito, |
| 118 | const base::string16& title) override; |
| 119 | void RemoveTab(int id, bool incognito) override; |
| 120 | void RemoveAllTabs() override; |
Ian Vollick | a39bafec | 2017-09-28 02:27:55 | [diff] [blame] | 121 | |
Yash Malik | 7fc0c95 | 2018-01-23 18:01:32 | [diff] [blame] | 122 | // TODO(ymalik): We expose this to stop sending VSync to the WebVR page until |
| 123 | // the splash screen has been visible for its minimum duration. The visibility |
| 124 | // logic currently lives in the UI, and it'd be much cleaner if the UI didn't |
| 125 | // have to worry about this, and if it were told to hide the splash screen |
| 126 | // like other WebVR phases (e.g. OnWebVrFrameAvailable below). |
| 127 | bool CanSendWebVrVSync(); |
Yash Malik | 58e7aa5 | 2018-02-02 00:11:12 | [diff] [blame] | 128 | |
Amirhossein Simjour | d78bbcf | 2018-02-02 16:23:39 | [diff] [blame] | 129 | void SetAlertDialogEnabled(bool enabled, |
Biao She | 41db7d2 | 2018-05-14 14:08:33 | [diff] [blame] | 130 | PlatformUiInputDelegate* delegate, |
Amirhossein Simjour | 813c71e | 2018-03-29 18:49:46 | [diff] [blame] | 131 | float width, |
| 132 | float height); |
| 133 | void SetAlertDialogSize(float width, float height); |
| 134 | void SetDialogLocation(float x, float y); |
Amirhossein Simjour | fb0c86e | 2018-04-23 22:44:55 | [diff] [blame] | 135 | void SetDialogFloating(bool floating); |
Biao She | 4a304be1 | 2018-03-29 22:25:41 | [diff] [blame] | 136 | void ShowPlatformToast(const base::string16& text); |
| 137 | void CancelPlatformToast(); |
Ian Vollick | 3f6c9804 | 2017-11-06 19:40:50 | [diff] [blame] | 138 | bool ShouldRenderWebVr(); |
Yash Malik | 7fc0c95 | 2018-01-23 18:01:32 | [diff] [blame] | 139 | |
Michael Thiessen | 6396120 | 2018-01-23 01:17:53 | [diff] [blame] | 140 | void OnGlInitialized( |
| 141 | unsigned int content_texture_id, |
| 142 | UiElementRenderer::TextureLocation content_location, |
| 143 | unsigned int content_overlay_texture_id, |
| 144 | UiElementRenderer::TextureLocation content_overlay_location, |
Amirhossein Simjour | d78bbcf | 2018-02-02 16:23:39 | [diff] [blame] | 145 | unsigned int ui_texture_id, |
Michael Thiessen | 6396120 | 2018-01-23 01:17:53 | [diff] [blame] | 146 | bool use_ganesh); |
Yash Malik | 7fc0c95 | 2018-01-23 18:01:32 | [diff] [blame] | 147 | |
Ian Vollick | 3f6c9804 | 2017-11-06 19:40:50 | [diff] [blame] | 148 | void OnAppButtonClicked(); |
Ian Vollick | e4bfb43 | 2018-03-27 03:19:26 | [diff] [blame] | 149 | void OnAppButtonSwipePerformed(PlatformController::SwipeDirection direction); |
Ian Vollick | a5cc802 | 2017-11-01 14:04:47 | [diff] [blame] | 150 | void OnControllerUpdated(const ControllerModel& controller_model, |
Ian Vollick | 3f6c9804 | 2017-11-06 19:40:50 | [diff] [blame] | 151 | const ReticleModel& reticle_model); |
| 152 | void OnProjMatrixChanged(const gfx::Transform& proj_matrix); |
| 153 | void OnWebVrFrameAvailable(); |
| 154 | void OnWebVrTimedOut(); |
| 155 | void OnWebVrTimeoutImminent(); |
| 156 | bool IsControllerVisible() const; |
Ian Vollick | e4bfb43 | 2018-03-27 03:19:26 | [diff] [blame] | 157 | bool IsAppButtonLongPressed() const; |
Ian Vollick | 2067330 | 2017-11-22 20:43:31 | [diff] [blame] | 158 | bool SkipsRedrawWhenNotDirty() const; |
Ian Vollick | 3f6c9804 | 2017-11-06 19:40:50 | [diff] [blame] | 159 | void OnSwapContents(int new_content_id); |
| 160 | void OnContentBoundsChanged(int width, int height); |
| 161 | void OnPlatformControllerInitialized(PlatformController* controller); |
Yash Malik | 1a10273 | 2017-12-22 22:01:55 | [diff] [blame] | 162 | void OnUiRequestedNavigation(); |
Brandon Jones | e44b8a8 | 2018-05-24 23:32:13 | [diff] [blame] | 163 | void SetFloorHeight(float floor_height); |
Ian Vollick | a39bafec | 2017-09-28 02:27:55 | [diff] [blame] | 164 | |
Ian Vollick | 0375ab8 | 2017-11-20 19:58:05 | [diff] [blame] | 165 | Model* model_for_test() { return model_.get(); } |
| 166 | |
Ian Vollick | 1b1360a | 2017-11-25 17:12:19 | [diff] [blame] | 167 | void ReinitializeForTest(const UiInitialState& ui_initial_state); |
Yash Malik | b78e72a7 | 2018-02-21 09:14:10 | [diff] [blame] | 168 | ContentInputDelegate* GetContentInputDelegateForTest() { |
| 169 | return content_input_delegate_.get(); |
| 170 | } |
Ian Vollick | 1b1360a | 2017-11-25 17:12:19 | [diff] [blame] | 171 | |
Ian Vollick | 70a8889 | 2018-01-02 15:29:57 | [diff] [blame] | 172 | void Dump(bool include_bindings); |
Ian Vollick | f8030c5 | 2017-11-22 17:14:14 | [diff] [blame] | 173 | |
Yash Malik | d862b31c | 2017-12-02 02:09:32 | [diff] [blame] | 174 | // Keyboard input related. |
| 175 | void RequestFocus(int element_id); |
Christopher Grant | f4e347f2 | 2017-12-07 23:26:05 | [diff] [blame] | 176 | void RequestUnfocus(int element_id); |
Christopher Grant | aa96b3e | 2018-02-07 19:56:48 | [diff] [blame] | 177 | void OnInputEdited(const EditedText& info) override; |
| 178 | void OnInputCommitted(const EditedText& info) override; |
Yash Malik | d862b31c | 2017-12-02 02:09:32 | [diff] [blame] | 179 | void OnKeyboardHidden() override; |
| 180 | |
Michael Thiessen | c49a9fd | 2018-02-22 15:05:58 | [diff] [blame] | 181 | void AcceptDoffPromptForTesting(); |
bsheedy | bfabd61d | 2018-04-16 19:02:59 | [diff] [blame] | 182 | void PerformUiActionForTesting(UiTestInput test_input); |
Michael Thiessen | c49a9fd | 2018-02-22 15:05:58 | [diff] [blame] | 183 | |
Michael Thiessen | bc382ac | 2018-04-20 20:39:17 | [diff] [blame] | 184 | bool IsContentVisibleAndOpaque(); |
| 185 | bool IsContentOverlayTextureEmpty(); |
| 186 | void SetContentUsesQuadLayer(bool uses_quad_buffers); |
| 187 | gfx::Transform GetContentWorldSpaceTransform(); |
| 188 | |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 189 | private: |
Christopher Grant | 27d7cd5c | 2018-05-02 21:00:03 | [diff] [blame] | 190 | void OnSpeechRecognitionEnded(); |
Ian Vollick | 1b1360a | 2017-11-25 17:12:19 | [diff] [blame] | 191 | void InitializeModel(const UiInitialState& ui_initial_state); |
Ian Vollick | d1389be | 2017-11-17 04:26:38 | [diff] [blame] | 192 | UiBrowserInterface* browser_; |
Michael Thiessen | bc382ac | 2018-04-20 20:39:17 | [diff] [blame] | 193 | ContentElement* GetContentElement(); |
Tibor Goldschwendt | df2bf01 | 2018-05-08 01:02:13 | [diff] [blame] | 194 | std::vector<TabModel>::iterator FindTab(int id, std::vector<TabModel>* tabs); |
Ian Vollick | d1389be | 2017-11-17 04:26:38 | [diff] [blame] | 195 | |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 196 | // This state may be further abstracted into a SkiaUi object. |
Christopher Grant | 764281a9 | 2018-03-10 00:48:25 | [diff] [blame] | 197 | std::unique_ptr<UiScene> scene_; |
| 198 | std::unique_ptr<Model> model_; |
| 199 | std::unique_ptr<ContentInputDelegate> content_input_delegate_; |
| 200 | std::unique_ptr<UiElementRenderer> ui_element_renderer_; |
| 201 | std::unique_ptr<UiInputManager> input_manager_; |
| 202 | std::unique_ptr<UiRenderer> ui_renderer_; |
Tibor Goldschwendt | 3d8447c | 2017-11-09 05:30:50 | [diff] [blame] | 203 | std::unique_ptr<SkiaSurfaceProvider> provider_; |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 204 | |
Michael Thiessen | bc382ac | 2018-04-20 20:39:17 | [diff] [blame] | 205 | // Cache the content element so we don't have to get it multiple times per |
| 206 | // frame. |
| 207 | ContentElement* content_element_ = nullptr; |
| 208 | |
Christopher Grant | 764281a9 | 2018-03-10 00:48:25 | [diff] [blame] | 209 | AudioDelegate* audio_delegate_ = nullptr; |
| 210 | |
Ian Vollick | a39bafec | 2017-09-28 02:27:55 | [diff] [blame] | 211 | base::WeakPtrFactory<Ui> weak_ptr_factory_; |
| 212 | |
Christopher Grant | ea69a47 | 2017-09-25 15:23:32 | [diff] [blame] | 213 | DISALLOW_COPY_AND_ASSIGN(Ui); |
| 214 | }; |
| 215 | |
| 216 | } // namespace vr |
| 217 | |
| 218 | #endif // CHROME_BROWSER_VR_UI_H_ |