diff --git a/CHANGELOG.md b/CHANGELOG.md index 4befe3617..03314b75a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Fixed +- Add defense around middling Safari fullscreen support and update documentation - Fixed issue where non-standard gamepad buttons would not be emitted by Excalibur - Fixed issue where Realistic solver would not sort contacts by distance causing some artifacts on seams - Fixed issue with CompositeCollider where large TileMaps would sometimes causes odd collision behavior in the Realistic Solver when the body & collider components are far apart in a TileMap. diff --git a/sandbox/src/game.ts b/sandbox/src/game.ts index d46a5da8d..3337e9e66 100644 --- a/sandbox/src/game.ts +++ b/sandbox/src/game.ts @@ -151,10 +151,10 @@ game.on('fallbackgraphicscontext', (ctx) => { // game.graphicsContext.addPostProcessor(colorblind); fullscreenButton.addEventListener('click', () => { - if (game.screen.isFullScreen) { - game.screen.exitFullScreen(); + if (game.screen.isFullscreen) { + game.screen.exitFullscreen(); } else { - game.screen.goFullScreen('container'); + game.screen.enterFullscreen('container'); } }); game.showDebug(true); diff --git a/site/docs/03-screen-viewport/screens-display-modes.mdx b/site/docs/03-screen-viewport/screens-display-modes.mdx index bcaa247ce..0bf86178e 100644 --- a/site/docs/03-screen-viewport/screens-display-modes.mdx +++ b/site/docs/03-screen-viewport/screens-display-modes.mdx @@ -39,7 +39,7 @@ const game = new ex.Engine({ [[DisplayMode.FitScreen]] Fit to screen using as much space as possible while maintaining aspect ratio and resolution. -This is not the same as [[Screen.goFullScreen]], which uses the fullscreen api, but behaves in a similar way maintaining aspect ratio. +This is not the same as [[Screen.enterFullscreen]], which uses the fullscreen api, but behaves in a similar way maintaining aspect ratio. You may want to center your game and fit to the screen here is an example: @@ -75,7 +75,7 @@ Click and drag right corner to resize! ### Fill Screen Display Mode -[[DisplayMode.FillScreen]] Fill the entire screen's css width/height for the game resolution dynamically. This means the resolution of the game will change dynamically as the window is resized. This is not the same as [[Screen.goFullScreen]] +[[DisplayMode.FillScreen]] Fill the entire screen's css width/height for the game resolution dynamically. This means the resolution of the game will change dynamically as the window is resized. This is not the same as [[Screen.enterFullscreen]] ```ts twoslash {1} // @include: ex @@ -141,7 +141,7 @@ Click and drag right corner to resize! ### Fill Container Display Mode -[[DisplayMode.FillContainer]] will fill the entire screen's css width/height for the game resolution dynamically. This means the resolution of the game will change dynamically as the window is resized. This is not the same as [[Screen.goFullScreen]] +[[DisplayMode.FillContainer]] will fill the entire screen's css width/height for the game resolution dynamically. This means the resolution of the game will change dynamically as the window is resized. This is not the same as [[Screen.enterFullscreen]] ```css .container { @@ -206,6 +206,11 @@ Click and drag right corner to resize! Click and drag right corner to resize! ## Fullscreen API +:::warning + +Currently Apple does not support fullscreen API on iPhones, it does however work on later model iPads. + +::: The screen abstraction now supports the [browser fullscreen api](https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API). This will cause the game to be displayed fullscreen until the user exits (usually with the escape key or by gesturing to the exit button at the top of the browser window). @@ -225,17 +230,17 @@ This requires an explicit user gesture due to browser security, so wiring it int ```typescript document.getElementById('go-fullscreen')!.addEventListener('click', () => { - game.screen.goFullScreen(); + game.screen.enterFullscreen(); }); ``` ```typescript -await game.screen.goFullScreen(); +await game.screen.enterFullscreen(); -await game.screen.exitFullScreen(); +await game.screen.exitFullscreen(); ``` -By default `goFullScreen()` will use the canvas element as the root of full screen mode. If your game uses [HTML based UI](/docs/ui#html-based-ui), the HTML UI will not be included because it is not a child of the canvas element. +By default `enterFullscreen()` will use the canvas element as the root of full screen mode. If your game uses [HTML based UI](/docs/ui#html-based-ui), the HTML UI will not be included because it is not a child of the canvas element. -To include both the HTML based game UI as well as the game canvas, pass an id of an element that is the parent of both the canvas and UI. For example `goFullScreen('root')` +To include both the HTML based game UI as well as the game canvas, pass an id of an element that is the parent of both the canvas and UI. For example `enterFullscreen('root')` diff --git a/src/engine/Director/Loader.ts b/src/engine/Director/Loader.ts index be0f4a452..c7092c296 100644 --- a/src/engine/Director/Loader.ts +++ b/src/engine/Director/Loader.ts @@ -272,7 +272,7 @@ export class Loader extends DefaultLoader { if (this._originalOptions.fullscreenContainer instanceof HTMLElement) { this._originalOptions.fullscreenContainer.requestFullscreen(); } else { - this.engine.screen.goFullScreen(this._originalOptions.fullscreenContainer); + this.engine.screen.enterFullscreen(this._originalOptions.fullscreenContainer); } } catch (error) { this._logger.error('could not go fullscreen', error); diff --git a/src/engine/Screen.ts b/src/engine/Screen.ts index 81d58e0c0..74c5cccf0 100644 --- a/src/engine/Screen.ts +++ b/src/engine/Screen.ts @@ -52,7 +52,7 @@ export enum DisplayMode { /** * Fit to screen using as much space as possible while maintaining aspect ratio and resolution. - * This is not the same as {@apilink Screen.goFullScreen} but behaves in a similar way maintaining aspect ratio. + * This is not the same as {@apilink Screen.enterFullscreen} but behaves in a similar way maintaining aspect ratio. * * You may want to center your game here is an example * ```html @@ -79,7 +79,7 @@ export enum DisplayMode { /** * Fill the entire screen's css width/height for the game resolution dynamically. This means the resolution of the game will - * change dynamically as the window is resized. This is not the same as {@apilink Screen.goFullScreen} + * change dynamically as the window is resized. This is not the same as {@apilink Screen.enterFullscreen} */ FillScreen = 'FillScreen', @@ -347,7 +347,7 @@ export class Screen { this._isFullscreen = !this._isFullscreen; this._logger.debug('Fullscreen Change', this._isFullscreen); this.events.emit('fullscreen', { - fullscreen: this.isFullScreen + fullscreen: this.isFullscreen } satisfies FullScreenChangeEvent); }; @@ -639,16 +639,26 @@ export class Screen { public enterFullscreen(elementId?: string): Promise { if (elementId) { const maybeElement = document.getElementById(elementId); - if (maybeElement) { + // workaround for safari partial support + if (maybeElement?.requestFullscreen || (maybeElement as any)?.webkitRequestFullscreen) { if (!maybeElement.getAttribute('ex-fullscreen-listener')) { maybeElement.setAttribute('ex-fullscreen-listener', 'true'); maybeElement.addEventListener('fullscreenchange', this._fullscreenChangeHandler); } - const fullscreenPromise = maybeElement.requestFullscreen(); - return fullscreenPromise; + if (maybeElement.requestFullscreen) { + return maybeElement.requestFullscreen() ?? Promise.resolve(); + } else if ((maybeElement as any).webkitRequestFullscreen) { + return (maybeElement as any).webkitRequestFullscreen() ?? Promise.resolve(); + } } } - return this._canvas.requestFullscreen(); + if (this._canvas?.requestFullscreen) { + return this._canvas?.requestFullscreen() ?? Promise.resolve(); + } else if ((this._canvas as any).webkitRequestFullscreen) { + return (this._canvas as any).webkitRequestFullscreen() ?? Promise.resolve(); + } + this._logger.warnOnce('Could not go fullscreen, is this an iPhone? Currently Apple does not support fullscreen on iPhones'); + return Promise.resolve(); } /** diff --git a/src/spec/ScreenSpec.ts b/src/spec/ScreenSpec.ts index f8ea47681..6356a4954 100644 --- a/src/spec/ScreenSpec.ts +++ b/src/spec/ScreenSpec.ts @@ -439,7 +439,7 @@ describe('A Screen', () => { viewport: { width: 800, height: 600 } }); - sut.goFullScreen(); + sut.enterFullscreen(); expect(mockCanvas.requestFullscreen).toHaveBeenCalled(); }); @@ -461,7 +461,7 @@ describe('A Screen', () => { const fakeElement = jasmine.createSpyObj('element', ['requestFullscreen', 'getAttribute', 'setAttribute', 'addEventListener']); spyOn(document, 'getElementById').and.returnValue(fakeElement); - sut.goFullScreen('some-id'); + sut.enterFullscreen('some-id'); expect(document.getElementById).toHaveBeenCalledWith('some-id'); expect(fakeElement.getAttribute).toHaveBeenCalledWith('ex-fullscreen-listener');