Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 var vrShellUi = (function() { | 5 var vrShellUi = (function() { |
| 6 'use strict'; | 6 'use strict'; |
| 7 | 7 |
| 8 let ui = new scene.Scene(); | 8 let ui = new scene.Scene(); |
| 9 let uiManager; | 9 let uiManager; |
| 10 let nativeCommandHandler; | 10 let nativeCommandHandler; |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 35 /** @const */ this.CSS_WIDTH_PIXELS = 960.0; | 35 /** @const */ this.CSS_WIDTH_PIXELS = 960.0; |
| 36 /** @const */ this.CSS_HEIGHT_PIXELS = 640.0; | 36 /** @const */ this.CSS_HEIGHT_PIXELS = 640.0; |
| 37 /** @const */ this.DPR = 1.2; | 37 /** @const */ this.DPR = 1.2; |
| 38 /** @const */ this.MENU_MODE_SCREEN_DISTANCE = 1.2; | 38 /** @const */ this.MENU_MODE_SCREEN_DISTANCE = 1.2; |
| 39 /** @const */ this.MENU_MODE_SCREEN_HEIGHT = 0.5; | 39 /** @const */ this.MENU_MODE_SCREEN_HEIGHT = 0.5; |
| 40 /** @const */ this.MENU_MODE_SCREEN_ELEVATION = 0.1; | 40 /** @const */ this.MENU_MODE_SCREEN_ELEVATION = 0.1; |
| 41 | 41 |
| 42 this.menuMode = false; | 42 this.menuMode = false; |
| 43 this.fullscreen = false; | 43 this.fullscreen = false; |
| 44 | 44 |
| 45 let element = new api.UiElement(0, 0, 0, 0); | 45 this.uiElement = new DomUiElement('#content-quad-element'); |
|
cjgrant
2017/02/15 16:34:28
This is where we tie the content quad to its dummy
| |
| 46 element.setFill(new api.Content()); | 46 this.elementId = this.uiElement.uiElementId; |
| 47 element.setVisible(false); | 47 |
| 48 element.setSize( | 48 let update = new api.UiElementUpdate(); |
| 49 this.SCREEN_HEIGHT * this.SCREEN_RATIO, this.SCREEN_HEIGHT); | 49 update.setFill(new api.Content()); |
| 50 element.setTranslation(0, 0, -this.BROWSING_SCREEN_DISTANCE); | 50 update.setVisible(false); |
| 51 this.elementId = ui.addElement(element); | 51 ui.updateElement(this.elementId, update); |
| 52 } | 52 } |
| 53 | 53 |
| 54 setEnabled(enabled) { | 54 setEnabled(enabled) { |
| 55 let update = new api.UiElementUpdate(); | 55 let update = new api.UiElementUpdate(); |
| 56 update.setVisible(enabled); | 56 update.setVisible(enabled); |
| 57 ui.updateElement(this.elementId, update); | 57 ui.updateElement(this.elementId, update); |
| 58 if (enabled) { | 58 if (enabled) { |
| 59 api.setContentCssSize( | 59 api.setContentCssSize( |
| 60 this.CSS_WIDTH_PIXELS, this.CSS_HEIGHT_PIXELS, this.DPR); | 60 this.CSS_WIDTH_PIXELS, this.CSS_HEIGHT_PIXELS, this.DPR); |
| 61 } else { | 61 } else { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 72 } | 72 } |
| 73 | 73 |
| 74 setFullscreen(enabled) { | 74 setFullscreen(enabled) { |
| 75 if (this.fullscreen == enabled) | 75 if (this.fullscreen == enabled) |
| 76 return; | 76 return; |
| 77 this.fullscreen = enabled; | 77 this.fullscreen = enabled; |
| 78 this.updateState() | 78 this.updateState() |
| 79 } | 79 } |
| 80 | 80 |
| 81 updateState() { | 81 updateState() { |
| 82 // Defaults content quad parameters. | |
| 83 let y = 0; | |
| 84 let z = -this.BROWSING_SCREEN_DISTANCE; | |
| 85 let height = this.SCREEN_HEIGHT; | |
| 86 | 82 |
| 87 // Mode-specific overrides. | 83 // Set style according to mode. |
|
cjgrant
2017/02/15 16:34:28
Here, we're taking the app button presses, and pus
| |
| 84 this.uiElement.domElement.classList.remove('menu'); | |
| 85 this.uiElement.domElement.classList.remove('fullscreen'); | |
| 88 if (this.menuMode) { | 86 if (this.menuMode) { |
| 89 y = this.MENU_MODE_SCREEN_ELEVATION; | 87 this.uiElement.domElement.classList.add('menu'); |
| 90 z = -this.MENU_MODE_SCREEN_DISTANCE; | |
| 91 height = this.MENU_MODE_SCREEN_HEIGHT; | |
| 92 } else if (this.fullscreen) { | 88 } else if (this.fullscreen) { |
| 93 z = -this.FULLSCREEN_DISTANCE; | 89 this.uiElement.domElement.classList.add('fullscreen'); |
| 94 } | 90 } |
| 95 | 91 |
| 96 let anim; | 92 // let anim; |
| 97 anim = new api.Animation(this.elementId, ANIM_DURATION); | 93 // anim = new api.Animation(this.elementId, ANIM_DURATION); |
| 98 anim.setTranslation(0, y, z); | 94 // anim.setTranslation(0, y, z); |
| 99 ui.addAnimation(anim); | 95 // ui.addAnimation(anim); |
| 100 anim = new api.Animation(this.elementId, ANIM_DURATION); | 96 // anim = new api.Animation(this.elementId, ANIM_DURATION); |
| 101 anim.setSize(height * this.SCREEN_RATIO, height); | 97 // anim.setSize(height * this.SCREEN_RATIO, height); |
| 102 ui.addAnimation(anim); | 98 // ui.addAnimation(anim); |
| 103 } | 99 } |
| 104 | 100 |
| 105 // TODO(crbug/643815): Add a method setting aspect ratio (and possible | 101 // TODO(crbug/643815): Add a method setting aspect ratio (and possible |
| 106 // animation of changing it). | 102 // animation of changing it). |
| 107 | 103 |
| 108 getElementId() { | 104 getElementId() { |
| 109 return this.elementId; | 105 return this.elementId; |
| 110 } | 106 } |
| 111 }; | 107 }; |
| 112 | 108 |
| 113 class DomUiElement { | 109 class DomUiElement { |
| 114 constructor(domId) { | 110 constructor(domId) { |
| 115 let domElement = document.querySelector(domId); | 111 let domElement = document.querySelector(domId); |
| 116 | 112 |
| 113 // Attach a mutation observer to catch our custom scene style changes. | |
|
cjgrant
2017/02/15 16:34:28
Every UI element will have an observer.
| |
| 114 this.observer = new MutationObserver(function(mutations) { | |
| 115 let update = new api.UiElementUpdate(); | |
| 116 let modifications = false; | |
| 117 | |
| 118 mutations.forEach(function(update, mutation) { | |
| 119 modifications = modifications || this.parseCustomStyle(mutation.target , update); | |
| 120 }.bind(this, update)); | |
| 121 | |
| 122 if (modifications) { | |
| 123 ui.updateElement(this.uiElementId, update); | |
| 124 } | |
| 125 }.bind(this)); | |
| 126 var config = { | |
| 127 attributes: true, | |
| 128 subtree: true, | |
|
tiborg
2017/02/15 18:36:11
As discussed offline, listening to the sub tree is
| |
| 129 //attributeFilter: ['style'] // TODO: Better filtering? | |
|
cjgrant
2017/02/15 16:34:27
The mutation observer tells us about a lot of stuf
| |
| 130 }; | |
| 131 this.observer.observe(domElement, config); | |
| 132 | |
| 117 // Pull copy rectangle from the position of the element. | 133 // Pull copy rectangle from the position of the element. |
| 118 let rect = domElement.getBoundingClientRect(); | 134 let rect = domElement.getBoundingClientRect(); |
| 119 let pixelX = Math.floor(rect.left); | 135 let pixelX = Math.floor(rect.left); |
| 120 let pixelY = Math.floor(rect.top); | 136 let pixelY = Math.floor(rect.top); |
| 121 let pixelWidth = Math.ceil(rect.right) - pixelX; | 137 let pixelWidth = Math.ceil(rect.right) - pixelX; |
| 122 let pixelHeight = Math.ceil(rect.bottom) - pixelY; | 138 let pixelHeight = Math.ceil(rect.bottom) - pixelY; |
| 123 | 139 |
| 124 let element = new api.UiElement(pixelX, pixelY, pixelWidth, pixelHeight); | 140 let element = new api.UiElement(pixelX, pixelY, pixelWidth, pixelHeight); |
| 125 element.setSize(pixelWidth / 1000, pixelHeight / 1000); | 141 element.setSize(pixelWidth / 1000, pixelHeight / 1000); |
| 126 | 142 |
| 127 // Pull additional custom properties from CSS. | 143 // Grab initial custom scene styling. |
|
cjgrant
2017/02/15 16:34:28
Here's the initial extraction of element propertie
| |
| 128 let style = window.getComputedStyle(domElement); | 144 this.parseCustomStyle(domElement, element); |
| 129 this.translationX = getStyleFloat(style, '--tranX'); | 145 var items = domElement.getElementsByTagName("*"); |
| 130 this.translationY = getStyleFloat(style, '--tranY'); | 146 for (var i = 0; i < items.length; i++) { |
| 131 this.translationZ = getStyleFloat(style, '--tranZ'); | 147 this.parseCustomStyle(items[i], element); |
| 132 element.setTranslation( | 148 } |
| 133 this.translationX, this.translationY, this.translationZ); | |
| 134 | 149 |
| 135 this.uiElementId = ui.addElement(element); | 150 this.uiElementId = ui.addElement(element); |
| 136 this.uiAnimationId = -1; | 151 this.uiAnimationId = -1; |
| 137 this.domElement = domElement; | 152 this.domElement = domElement; |
| 138 } | 153 } |
| 154 | |
| 155 parseCustomStyle(element, update) { | |
| 156 let propertyMap = { | |
| 157 '--tranX': 'translationX', | |
|
cjgrant
2017/02/15 16:34:28
This list is all custom properties that can enact
| |
| 158 '--tranY': 'translationY', | |
| 159 '--tranZ': 'translationZ', | |
| 160 '--sizeX': 'sizeX', | |
| 161 '--sizeY': 'sizeY', | |
| 162 '--scaleX': 'scaleX', | |
| 163 '--scaleY': 'scaleY', | |
| 164 '--scaleZ': 'scaleZ', | |
| 165 '--rotationX': 'rotationX', | |
| 166 '--rotationY': 'rotationY', | |
| 167 '--rotationZ': 'rotationZ', | |
| 168 '--rotationAngle': 'rotationAngle', | |
| 169 '--opacity': 'opacity', | |
| 170 }; | |
| 171 | |
| 172 // For each custom property we recognize, apply its value to the | |
| 173 // corresponding UI element property. | |
| 174 let cs = window.getComputedStyle(element); | |
| 175 let keys = Object.keys(propertyMap); | |
| 176 let len = keys.length; | |
| 177 let modifications = false; | |
| 178 for (var i = 0; i < len; i++) { | |
| 179 let item = keys[i]; | |
| 180 | |
| 181 let value = parseFloat(cs.getPropertyValue(item)); | |
| 182 if (isNaN(value)) | |
| 183 continue; | |
| 184 update.properties[propertyMap[item]] = value; | |
| 185 modifications = true; | |
| 186 } | |
| 187 return modifications; | |
| 188 } | |
| 139 }; | 189 }; |
| 140 | 190 |
| 141 class RoundButton extends DomUiElement { | 191 class RoundButton extends DomUiElement { |
| 142 constructor(domId, callback) { | 192 constructor(domId, callback) { |
| 143 super(domId); | 193 super(domId); |
| 144 | 194 |
| 145 let button = this.domElement.querySelector('.button'); | 195 let button = this.domElement.querySelector('.button'); |
| 146 button.addEventListener('mouseenter', this.onMouseEnter.bind(this)); | 196 button.addEventListener('mouseenter', this.onMouseEnter.bind(this)); |
| 147 button.addEventListener('mouseleave', this.onMouseLeave.bind(this)); | 197 button.addEventListener('mouseleave', this.onMouseLeave.bind(this)); |
| 148 button.addEventListener('click', callback); | 198 button.addEventListener('click', callback); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 189 api.doAction(api.Action.RELOAD, {}); | 239 api.doAction(api.Action.RELOAD, {}); |
| 190 } | 240 } |
| 191 ], | 241 ], |
| 192 [ | 242 [ |
| 193 '#forward', | 243 '#forward', |
| 194 function() { | 244 function() { |
| 195 api.doAction(api.Action.HISTORY_FORWARD, {}); | 245 api.doAction(api.Action.HISTORY_FORWARD, {}); |
| 196 } | 246 } |
| 197 ], | 247 ], |
| 198 ]; | 248 ]; |
| 199 | 249 |
|
cjgrant
2017/02/15 16:34:28
This kind of stuff is hard to put in CSS. It desc
| |
| 200 /** @const */ var BUTTON_Y = -0.27; | 250 /** @const */ var BUTTON_Y = -0.27; |
| 201 /** @const */ var BUTTON_Z = -1; | 251 /** @const */ var BUTTON_Z = -1; |
| 202 /** @const */ var BUTTON_SPACING = 0.11; | 252 /** @const */ var BUTTON_SPACING = 0.11; |
| 203 | 253 |
| 204 let startPosition = -BUTTON_SPACING * (descriptors.length / 2.0 - 0.5); | 254 let startPosition = -BUTTON_SPACING * (descriptors.length / 2.0 - 0.5); |
| 205 for (let i = 0; i < descriptors.length; i++) { | 255 for (let i = 0; i < descriptors.length; i++) { |
| 206 // Use an invisible parent to simplify Z-axis movement on hover. | 256 // Use an invisible parent to simplify Z-axis movement on hover. |
| 207 let position = new api.UiElement(0, 0, 0, 0); | 257 let position = new api.UiElement(0, 0, 0, 0); |
| 208 position.setVisible(false); | 258 position.setVisible(false); |
| 209 position.setTranslation( | 259 position.setTranslation( |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 484 !this.loading && this.visibilityTimeout > 0 && !this.visibilityTimer; | 534 !this.loading && this.visibilityTimeout > 0 && !this.visibilityTimer; |
| 485 if (shouldBeHidden != this.hidden) { | 535 if (shouldBeHidden != this.hidden) { |
| 486 // Make the box fade away if it's disappearing. | 536 // Make the box fade away if it's disappearing. |
| 487 this.hidden = shouldBeHidden; | 537 this.hidden = shouldBeHidden; |
| 488 | 538 |
| 489 // Fade-out or fade-in the box. | 539 // Fade-out or fade-in the box. |
| 490 let opacityAnimation = | 540 let opacityAnimation = |
| 491 new api.Animation(this.domUiElement.uiElementId, this.fadeTimeMs); | 541 new api.Animation(this.domUiElement.uiElementId, this.fadeTimeMs); |
| 492 opacityAnimation.setOpacity(this.hidden ? 0.0 : this.opacity); | 542 opacityAnimation.setOpacity(this.hidden ? 0.0 : this.opacity); |
| 493 ui.addAnimation(opacityAnimation); | 543 ui.addAnimation(opacityAnimation); |
| 494 | |
| 495 // Drop the position as it fades, or raise the position if appearing. | |
| 496 let yOffset = this.hidden ? this.fadeYOffset : 0; | |
| 497 let positionAnimation = | |
| 498 new api.Animation(this.domUiElement.uiElementId, this.fadeTimeMs); | |
| 499 positionAnimation.setTranslation( | |
| 500 this.domUiElement.translationX, | |
| 501 this.domUiElement.translationY + yOffset, | |
| 502 this.domUiElement.translationZ); | |
| 503 ui.addAnimation(positionAnimation); | |
| 504 } | 544 } |
| 505 | 545 |
| 506 ui.flush(); | 546 ui.flush(); |
| 507 } | 547 } |
| 508 | 548 |
| 509 setNativeVisibility(visible) { | 549 setNativeVisibility(visible) { |
| 510 if (visible == this.nativeState.visible) { | 550 if (visible == this.nativeState.visible) { |
| 511 return; | 551 return; |
| 512 } | 552 } |
| 513 this.nativeState.visible = visible; | 553 this.nativeState.visible = visible; |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 779 setEnabled(enabled) { | 819 setEnabled(enabled) { |
| 780 let visibilityUpdate = new api.UiElementUpdate(); | 820 let visibilityUpdate = new api.UiElementUpdate(); |
| 781 visibilityUpdate.setVisible(enabled); | 821 visibilityUpdate.setVisible(enabled); |
| 782 ui.updateElement(this.tabContainerElement.uiElementId, visibilityUpdate); | 822 ui.updateElement(this.tabContainerElement.uiElementId, visibilityUpdate); |
| 783 } | 823 } |
| 784 }; | 824 }; |
| 785 | 825 |
| 786 class UiManager { | 826 class UiManager { |
| 787 constructor() { | 827 constructor() { |
| 788 this.mode = api.Mode.UNKNOWN; | 828 this.mode = api.Mode.UNKNOWN; |
| 789 this.menuMode = false; | 829 // this.menuMode = false; |
| 830 this.menuMode = true; | |
| 790 this.fullscreen = false; | 831 this.fullscreen = false; |
| 791 | 832 |
| 792 this.background = new Background(); | 833 this.background = new Background(); |
| 793 this.contentQuad = new ContentQuad(); | 834 this.contentQuad = new ContentQuad(); |
| 794 let contentId = this.contentQuad.getElementId(); | 835 let contentId = this.contentQuad.getElementId(); |
| 795 | 836 |
| 796 this.controls = new Controls(contentId); | 837 this.controls = new Controls(contentId); |
| 797 this.secureOriginWarnings = new SecureOriginWarnings(); | 838 this.secureOriginWarnings = new SecureOriginWarnings(); |
| 798 this.urlIndicator = new UrlIndicator(); | 839 this.urlIndicator = new UrlIndicator(); |
| 799 this.omnibox = new Omnibox(); | 840 this.omnibox = new Omnibox(); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 949 nativeCommandHandler.handleCommand(dict); | 990 nativeCommandHandler.handleCommand(dict); |
| 950 } | 991 } |
| 951 | 992 |
| 952 return { | 993 return { |
| 953 initialize: initialize, | 994 initialize: initialize, |
| 954 command: command, | 995 command: command, |
| 955 }; | 996 }; |
| 956 })(); | 997 })(); |
| 957 | 998 |
| 958 window.addEventListener('load', vrShellUi.initialize); | 999 window.addEventListener('load', vrShellUi.initialize); |
| OLD | NEW |