diff --git a/CHANGELOG.md b/CHANGELOG.md index fba1716b2..b3daa505b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- The `ex.Engine` had a new `enableCanvasContextMenu` arg that can be used to enable the right click context menu, by default the context menu is disabled which is what most games seem to want. - Child `ex.Actor` inherits opacity of parents - `ex.Engine.timeScale` values of 0 are now supported - `ex.Trigger` now supports all valid actor constructor parameters from `ex.ActorArgs` in addition to `ex.TriggerOptions` diff --git a/sandbox/src/game.ts b/sandbox/src/game.ts index 22e6e8600..35b697fde 100644 --- a/sandbox/src/game.ts +++ b/sandbox/src/game.ts @@ -768,6 +768,9 @@ game.input.keyboard.on('up', (e?: ex.KeyEvent) => { player.on('pointerdown', (e?: ex.PointerEvent) => { // alert('Player clicked!'); + if (e.button === ex.PointerButton.Right) { + console.log('right click'); + } }); player.on('pointerdown', () => { console.log('pointer down'); diff --git a/src/engine/Engine.ts b/src/engine/Engine.ts index fe84486c7..ce56c2a1f 100644 --- a/src/engine/Engine.ts +++ b/src/engine/Engine.ts @@ -220,6 +220,13 @@ export interface EngineOptions { */ canvasElement?: HTMLCanvasElement; + /** + * Optionally enable the right click context menu on the canvas + * + * Default if unset is false + */ + enableCanvasContextMenu?: boolean; + /** * Optionally snap graphics to nearest pixel, default is false */ @@ -745,6 +752,7 @@ export class Engine implements CanInitialize, }, canvasElementId: '', canvasElement: undefined, + enableCanvasContextMenu: false, snapToPixel: false, antialiasing: true, pixelArt: false, @@ -889,6 +897,12 @@ O|===|* >________________>\n\ this.canvas = document.createElement('canvas'); } + if (this.canvas && !options.enableCanvasContextMenu) { + this.canvas.addEventListener('contextmenu', (evt) => { + evt.preventDefault(); + }); + } + let displayMode = options.displayMode ?? DisplayMode.Fixed; if ((options.width && options.height) || options.viewport) { if (options.displayMode === undefined) { diff --git a/src/spec/EngineSpec.ts b/src/spec/EngineSpec.ts index c0596d34d..b9226e955 100644 --- a/src/spec/EngineSpec.ts +++ b/src/spec/EngineSpec.ts @@ -457,6 +457,31 @@ describe('The engine', () => { expect(fired).toHaveBeenCalled(); }); + it('should prevent the context menu from opening when enableCanvasContextMenu not set to true', () => { + const mockEvent = new Event('contextmenu', { + cancelable: true, + bubbles: true + }); + const spyPreventDefault = spyOn(mockEvent, 'preventDefault'); + engine.canvas.dispatchEvent(mockEvent); + + expect(spyPreventDefault).toHaveBeenCalled(); + }); + + it('should NOT prevent the context menu from opening when enableCanvasContextMenu set to true', () => { + engine.dispose(); + engine = null; + engine = TestUtils.engine({ width: 100, height: 100, enableCanvasContextMenu: true }); + const mockEvent = new Event('contextmenu', { + cancelable: true, + bubbles: true + }); + const spyPreventDefault = spyOn(mockEvent, 'preventDefault'); + engine.canvas.dispatchEvent(mockEvent); + + expect(spyPreventDefault).not.toHaveBeenCalled(); + }); + it('should tell engine is running', () => { const status = engine.isRunning(); expect(status).toBe(true);