|
@@ -22,10 +22,11 @@
|
22
|
22
|
|
23
|
23
|
import Speedy from 'speedy-vision';
|
24
|
24
|
import { SpeedySize } from 'speedy-vision/types/core/speedy-size';
|
|
25
|
+import { SpeedyPromise } from 'speedy-vision/types/core/speedy-promise';
|
25
|
26
|
import { Nullable } from '../utils/utils';
|
26
|
27
|
import { Resolution } from './resolution';
|
27
|
28
|
import { Utils } from '../utils/utils';
|
28
|
|
-import { IllegalArgumentError, IllegalOperationError } from '../utils/errors';
|
|
29
|
+import { IllegalArgumentError, IllegalOperationError, NotSupportedError, AccessDeniedError } from '../utils/errors';
|
29
|
30
|
import { HUD, HUDContainer } from './hud';
|
30
|
31
|
import { AREvent, AREventTarget, AREventListener } from '../utils/ar-events';
|
31
|
32
|
|
|
@@ -68,12 +69,21 @@ export interface Viewport extends ViewportEventTarget
|
68
|
69
|
/** HUD */
|
69
|
70
|
readonly hud: HUD;
|
70
|
71
|
|
|
72
|
+ /** Fullscreen mode */
|
|
73
|
+ readonly fullscreen: boolean;
|
|
74
|
+
|
71
|
75
|
/** Canvas on which the virtual scene will be drawn */
|
72
|
76
|
readonly canvas: HTMLCanvasElement;
|
73
|
77
|
|
74
|
78
|
/** Size of the drawing buffer of the foreground canvas */
|
75
|
79
|
readonly virtualSize: SpeedySize;
|
76
|
80
|
|
|
81
|
+ /** Request fullscreen mode */
|
|
82
|
+ requestFullscreen(): SpeedyPromise<void>;
|
|
83
|
+
|
|
84
|
+ /** Exit fullscreen mode */
|
|
85
|
+ exitFullscreen(): SpeedyPromise<void>;
|
|
86
|
+
|
77
|
87
|
/** Canvas on which the physical scene will be drawn @internal */
|
78
|
88
|
readonly _backgroundCanvas: HTMLCanvasElement;
|
79
|
89
|
|
|
@@ -210,6 +220,96 @@ export class BaseViewport extends ViewportEventTarget implements Viewport
|
210
|
220
|
}
|
211
|
221
|
|
212
|
222
|
/**
|
|
223
|
+ * Make a request to the user agent so that the viewport container is
|
|
224
|
+ * displayed in fullscreen mode. The container must be a compatible element[1]
|
|
225
|
+ * and the user must interact with the page in order to comply with browser
|
|
226
|
+ * policies[2]. In case of error, the returned promise is rejected.
|
|
227
|
+ * [1] https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullscreen#compatible_elements
|
|
228
|
+ * [2] https://developer.mozilla.org/en-US/docs/Web/API/Element/requestFullscreen#security
|
|
229
|
+ */
|
|
230
|
+ requestFullscreen(): SpeedyPromise<void>
|
|
231
|
+ {
|
|
232
|
+ const container = this._container;
|
|
233
|
+
|
|
234
|
+ // fallback for older WebKit versions
|
|
235
|
+ if(container.requestFullscreen === undefined) {
|
|
236
|
+ if((container as any).webkitRequestFullscreen === undefined)
|
|
237
|
+ return Speedy.Promise.reject(new NotSupportedError());
|
|
238
|
+ else if(!(document as any).webkitFullscreenEnabled)
|
|
239
|
+ return Speedy.Promise.reject(new AccessDeniedError());
|
|
240
|
+
|
|
241
|
+ // webkitRequestFullscreen() does not return a value
|
|
242
|
+ (container as any).webkitRequestFullscreen();
|
|
243
|
+
|
|
244
|
+ return new Speedy.Promise<void>((resolve, reject) => {
|
|
245
|
+ setTimeout(() => {
|
|
246
|
+ if(container === (document as any).webkitFullscreenElement)
|
|
247
|
+ resolve();
|
|
248
|
+ else
|
|
249
|
+ reject(new AccessDeniedError());
|
|
250
|
+ }, 100);
|
|
251
|
+ });
|
|
252
|
+ }
|
|
253
|
+
|
|
254
|
+ // check if fullscreen is supported
|
|
255
|
+ if(!document.fullscreenEnabled)
|
|
256
|
+ return Speedy.Promise.reject(new AccessDeniedError());
|
|
257
|
+
|
|
258
|
+ // request fullscreen
|
|
259
|
+ return new Speedy.Promise<void>((resolve, reject) => {
|
|
260
|
+ container.requestFullscreen({
|
|
261
|
+ navigationUI: 'hide'
|
|
262
|
+ }).then(resolve, reject);
|
|
263
|
+ });
|
|
264
|
+ }
|
|
265
|
+
|
|
266
|
+ /**
|
|
267
|
+ * Exit fullscreen mode
|
|
268
|
+ */
|
|
269
|
+ exitFullscreen(): SpeedyPromise<void>
|
|
270
|
+ {
|
|
271
|
+ // fallback for older WebKit versions
|
|
272
|
+ if(document.exitFullscreen === undefined) {
|
|
273
|
+ const doc = document as any;
|
|
274
|
+
|
|
275
|
+ if(doc.webkitExitFullscreen === undefined)
|
|
276
|
+ return Speedy.Promise.reject(new NotSupportedError());
|
|
277
|
+ else if(doc.webkitFullscreenElement === null)
|
|
278
|
+ return Speedy.Promise.reject(new TypeError('Not in fullscreen mode'));
|
|
279
|
+
|
|
280
|
+ // webkitExitFullscreen() does not return a value
|
|
281
|
+ doc.webkitExitFullscreen();
|
|
282
|
+
|
|
283
|
+ return new Speedy.Promise<void>((resolve, reject) => {
|
|
284
|
+ setTimeout(() => {
|
|
285
|
+ if(doc.webkitFullscreenElement === null)
|
|
286
|
+ resolve();
|
|
287
|
+ else
|
|
288
|
+ reject(new TypeError());
|
|
289
|
+ }, 100);
|
|
290
|
+ });
|
|
291
|
+ }
|
|
292
|
+
|
|
293
|
+ // exit fullscreen
|
|
294
|
+ return new Speedy.Promise<void>((resolve, reject) => {
|
|
295
|
+ document.exitFullscreen().then(resolve, reject);
|
|
296
|
+ });
|
|
297
|
+ }
|
|
298
|
+
|
|
299
|
+ /**
|
|
300
|
+ * True if the viewport is being displayed in fullscreen mode
|
|
301
|
+ */
|
|
302
|
+ get fullscreen(): boolean
|
|
303
|
+ {
|
|
304
|
+ if(document.fullscreenElement !== undefined)
|
|
305
|
+ return document.fullscreenElement === this._container;
|
|
306
|
+ else if((document as any).webkitFullscreenElement !== undefined)
|
|
307
|
+ return (document as any).webkitFullscreenElement === this._container;
|
|
308
|
+ else
|
|
309
|
+ return false;
|
|
310
|
+ }
|
|
311
|
+
|
|
312
|
+ /**
|
213
|
313
|
* Viewport container
|
214
|
314
|
*/
|
215
|
315
|
get container(): ViewportContainer
|
|
@@ -302,6 +402,8 @@ export class BaseViewport extends ViewportEventTarget implements Viewport
|
302
|
402
|
|
303
|
403
|
// setup CSS
|
304
|
404
|
this._container.style.touchAction = 'none';
|
|
405
|
+ this._container.style.backgroundColor = 'black';
|
|
406
|
+ this._container.style.zIndex = String(CONTAINER_ZINDEX);
|
305
|
407
|
|
306
|
408
|
// initialize the HUD
|
307
|
409
|
this._hud._init(HUD_ZINDEX);
|
|
@@ -485,6 +587,14 @@ abstract class ViewportDecorator extends ViewportEventTarget implements Viewport
|
485
|
587
|
}
|
486
|
588
|
|
487
|
589
|
/**
|
|
590
|
+ * Fullscreen mode
|
|
591
|
+ */
|
|
592
|
+ get fullscreen(): boolean
|
|
593
|
+ {
|
|
594
|
+ return this._base.fullscreen;
|
|
595
|
+ }
|
|
596
|
+
|
|
597
|
+ /**
|
488
|
598
|
* Resolution of the virtual scene
|
489
|
599
|
*/
|
490
|
600
|
get resolution(): Resolution
|
|
@@ -510,6 +620,22 @@ abstract class ViewportDecorator extends ViewportEventTarget implements Viewport
|
510
|
620
|
}
|
511
|
621
|
|
512
|
622
|
/**
|
|
623
|
+ * Request fullscreen mode
|
|
624
|
+ */
|
|
625
|
+ requestFullscreen(): SpeedyPromise<void>
|
|
626
|
+ {
|
|
627
|
+ return this._base.requestFullscreen();
|
|
628
|
+ }
|
|
629
|
+
|
|
630
|
+ /**
|
|
631
|
+ * Exit fullscreen mode
|
|
632
|
+ */
|
|
633
|
+ exitFullscreen(): SpeedyPromise<void>
|
|
634
|
+ {
|
|
635
|
+ return this._base.exitFullscreen();
|
|
636
|
+ }
|
|
637
|
+
|
|
638
|
+ /**
|
513
|
639
|
* Background canvas
|
514
|
640
|
* @internal
|
515
|
641
|
*/
|
|
@@ -688,18 +814,6 @@ abstract class ResizableViewport extends ViewportDecorator
|
688
|
814
|
export class ImmersiveViewport extends ResizableViewport
|
689
|
815
|
{
|
690
|
816
|
/**
|
691
|
|
- * Initialize the viewport
|
692
|
|
- * @internal
|
693
|
|
- */
|
694
|
|
- _init(): void
|
695
|
|
- {
|
696
|
|
- super._init();
|
697
|
|
-
|
698
|
|
- this.container.style.zIndex = String(CONTAINER_ZINDEX);
|
699
|
|
- this.container.style.backgroundColor = 'black';
|
700
|
|
- }
|
701
|
|
-
|
702
|
|
- /**
|
703
|
817
|
* Release the viewport
|
704
|
818
|
* @internal
|
705
|
819
|
*/
|
|
@@ -769,9 +883,6 @@ export class InlineViewport extends ResizableViewport
|
769
|
883
|
{
|
770
|
884
|
super._init();
|
771
|
885
|
this.style = 'inline';
|
772
|
|
-
|
773
|
|
- this.container.style.zIndex = String(CONTAINER_ZINDEX);
|
774
|
|
- this.container.style.backgroundColor = 'black';
|
775
|
886
|
}
|
776
|
887
|
|
777
|
888
|
/**
|
|
@@ -786,7 +897,7 @@ export class InlineViewport extends ResizableViewport
|
786
|
897
|
|
787
|
898
|
/**
|
788
|
899
|
* Resize the inline viewport
|
789
|
|
- * (we still take into account orientation changes)
|
|
900
|
+ * (we still take orientation changes into account)
|
790
|
901
|
*/
|
791
|
902
|
protected _onResize(): void
|
792
|
903
|
{
|