Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Fixed

- Fixed issue where window resize events were handled twice when using window-based display modes (FitScreen, FitScreenAndFill, FitScreenAndZoom, FillScreen), causing double resolution/viewport computation and double canvas size writes
- Fixed issue where `scaleTo({…})` and `scaleBy({…})` actions would cause entities to keep scaling indefinitely after the action completed, due to a copy-paste bug that zeroed `angularVelocity` instead of `scaleFactor`
- Fixed issue where `scaleTo({…})` and `scaleBy({…})` actions used a live reference to the entity's scale vector as the interpolation start point, causing the easing curve to be corrupted if the entity's scale changed during the action
- Fixed issue where the first action in a sequence would not execute after calling `clearActions()` mid-execution. All action types now properly reset their initialization state when stopped, resolving issue #3468
Expand Down
6 changes: 4 additions & 2 deletions src/engine/screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,9 @@ export class Screen {
if (this._resizeObserver) {
this._resizeObserver.disconnect();
}
this.parent.removeEventListener('resize', this._resizeHandler);
if (!(this.parent instanceof Window)) {
this.parent.removeEventListener('resize', this._resizeHandler);
}
// Safari <=13.1 workaround
if (this._mediaQueryList.removeEventListener) {
this._mediaQueryList.removeEventListener('change', this._pixelRatioChangeHandler);
Expand Down Expand Up @@ -1171,8 +1173,8 @@ export class Screen {
this._resizeHandler();
});
this._resizeObserver.observe(this.parent);
this.parent.addEventListener('resize', this._resizeHandler);
}
this.parent.addEventListener('resize', this._resizeHandler);
}

/**
Expand Down
15 changes: 14 additions & 1 deletion src/spec/vitest/loader-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,25 @@

const oldPos = [loader.playButtonRootElement.style.left, loader.playButtonRootElement.style.top];

engine.screen.viewport = { width: 100, height: 100 };
const originalGetBoundingClientRect = engine.canvas.getBoundingClientRect;
engine.canvas.getBoundingClientRect = () => ({
x: 0,
y: 0,
width: 500,
height: 500,
top: 0,
left: 0,
right: 500,
bottom: 500,
toJSON: () => {}

Check failure on line 299 in src/spec/vitest/loader-spec.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected empty method 'toJSON'
});

engine.browser.window.nativeComponent.dispatchEvent(new Event('resize'));

const newPos = [loader.playButtonRootElement.style.left, loader.playButtonRootElement.style.top];

engine.canvas.getBoundingClientRect = originalGetBoundingClientRect;

expect(oldPos).not.toEqual(newPos);
});

Expand Down
17 changes: 17 additions & 0 deletions src/spec/vitest/screen-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -996,4 +996,21 @@ describe('A Screen', () => {
' (read more here https://excaliburjs.com/docs/screens#understanding-viewport--resolution).'
]);
});

it('should only register window resize listener once for Window parent (not twice)', () => {
const addEventListenerSpy = vi.spyOn(window, 'addEventListener');

const sut = new ex.Screen({
canvas,
context,
browser,
displayMode: ex.DisplayMode.FitScreen,
viewport: { width: 800, height: 600 }
});

const resizeListenerCalls = addEventListenerSpy.mock.calls.filter((call) => call[0] === 'resize');
expect(resizeListenerCalls.length).toBe(1);

addEventListenerSpy.mockRestore();
});
});
Loading