We use 'wasm-bindgen-futures' as our futures executor on web, which
in turn uses 'queueMicroTask'. This can result in the browser executing
one of our futures while we're still inside our `requestAnimationFrame`
callback (in particular, while we still have the `Player` mutex locked).
We now detect this condition by attempting the lock the Player mutex
inside of our `spawn_local` future. If this fails, we `await`
a `setTimeout`-based promise, which ensures that our code runs in
a new top-level `setTimeout` javascript 'task' (outside of our
`requestAnimationFrame` callback).
Turns out that an object isn't 'instanceof Object' in Firefox, if it was made from another window/process/tab/whatever. In this case, that meant that Ruffle always thought it was null because wasm-bindgen relies on 'instanceof Object'
This patch changes how the player focus is managed.
Before this patch, `instance.has_focus` was unrelated
to the current focus managed by the browser.
When the user clicked anywhere on the window, it was set to `false`,
and when the user clicked on the player, it was set to `true`.
This had two major issues.
1. When the user clicked on the player, `has_focus` was set to `false`,
and then again to `true`. That was problematic when listening
to focus change events.
2. Not using browser's focus makes it harder to integrate with Ruffle,
i.e. tab out of Ruffle.
This patch uses browser's focus management to detect focus
and listen to focus events:
1. on `focusin` – FocusGained event is fired,
2. on `focusout` – FocusLost event is fired, and
3. on `pointerdown` – focus is manually set to the canvas.
The canvas has `tabindex` set to -1 in order to be focusable.
If System#useCodepage has been set to true, the form loader now uses the
encoding specified in the HTTP response content type field, if existing,
to decode remote text files. chardetng is now (only) used if the HTTP
response doesn't specify any encoding or if the file is local.
Ruffle does not have direct clipboard access on web, so the current
paste implementation from the context menu does not work.
This patch intercepts the paste context menu callback,
and uses the Clipboard API to ask the browser for the clipboard
and update it before calling the callback.
When the Clipboard API is not available or the user denies
clipboard permission, a modal informing the user about
cut, copy, paste shortcuts is displayed.
This modal informs the user that they can use shortcuts
for copy, cut, and paste instead of using the context menu.
This modal is meant to be displayed when the browser
does not support reading the clipboard,
or the user denies permission to the clipboard.
This patch adds support for saving files on web using FileReference.
When writing data, a download is triggered with the default file name.
Currently, there's no dialog that lets the user select save destination.
This patch also ensures that all implementations of FileDialogResult
behave the same way: desktop, web, and tests.
The methods `write` and `refresh` have been merged into one:
`write_and_refresh`, which allows the tests and web implementations
behave the same way as desktop.
This patch ensures that sockets are closed properly.
Without it, when the application-end of the socket was closed,
the other end was left intact, and the socket was not closed.
This has several advantages:
1. it allows using async variants of send and recv,
2. it adds consistency as until now Receiver was async,
and Sender was not.