See PR #276
So, I’ve done a bit of bug-hunting (and in the process submitted a pull request for an unrelated issue #274) and found the bug-causing sequence:
- User presses Ok on
DlgFromDict - This fires
psychoJS.window.adjustScreenSize()which requests a fullscreen transition from the browser - At the same time,
experimentInit()sets up the Slider, and at some point, calls_estimateBoundingBox() - In
_estimateBoundingBox(),this._tickPositions_pxis set usingtickPositions.map() tickPositions.map()usesto_px()with athis._winargument- BUG OCCURS HERE:
to_px()usesthis._win.sizeto converttickPositionsfrom PsychoPy dimension units to browser pixel units - Finally, the initial label positions,
this._labelPositions_px, are set fromthis._tickPositions_px
The problem at Step 6 is that this._win.size represents the current window size. At this point, this._win.size may still be the pre-fullscreen window size, so the labels are placed in the correct positions for the pre-fullscreen window. However, once post-fullscreen, the labels will be in the wrong positions.
The main issue is that Step 2 is async, so it cannot be guaranteed which state the window is in.
You can easily reproduce the bug by:
-
Option 1: Make your window very small before pressing Ok on
DlgFromDict. Once fullscreen, the labels will be grouped in the center of the window. This is becausethis._win.sizeis small. -
Option 2: Wait until fullscreen is achieved, and then fire
experimentInit()again. This re-initializes the Sliders, and the labels will be in the correct positions. -
Option 3: Manually fullscreen the window before pressing Ok on
DlgFromDict. The labels will be in the correct positions because the window size has not changed
Possible fix:
- Add a timeout between closing
DlgFromDictand triggeringScheduler.Event.NEXT. InDlgFromDict>close: function() ...:
Replace (line 288 on GitHub):
self._dialogComponent.status = PsychoJS.Status.FINISHED;
With:
if (self._psychoJS._window.fullscr) {
setTimeout(() => self._dialogComponent.status = PsychoJS.Status.FINISHED, 2000);
} else {
self._dialogComponent.status = PsychoJS.Status.FINISHED;
}
This sets a timeout for 2000ms before continuing. In my quick testing, a minimum of around 500ms seemed to work too, but 2000ms hopefully gives some buffer space without making the experiment appear to be frozen.
(I tried a fix that listened for the fullscreenchange event, but at least in my quick testing, it still required a delay to guarantee the resize was complete)