This allows increasing and decreasing the media volume by 10% with the
up and down arrow keys, respectively. This also allows toggling the mute
state with the M key.
This allows seeking backwards and forwards by 5 seconds with the left
and right arrow keys, respectively. This also allows seeking to the
beginning and end of the media track with the home and end keys.
Mostly seen on macOS, but when we toggle playing a media element, we
need to update its layout node's display to ensure the change is
reflected on the playback button. Further, when setting the element's
display time, we need to update the display to ensure the change is
refelected on the media timeline.
There were multiple bugs in the parsing algorithm for handling text
occurring inside a `table` element:
- When there was pending non-whitespace text inside a table, we only
flushed one token instead of all pending tokens.
- Also, we didn't even flush one of the right tokens, but instead the
token that caused the flush to happen.
- Once we started flushing the right tokens, it turned out we had not
yet implemented character insertion points expressed as "before X".
- Finally, we were not exiting the "in table text" mode after flushing
pending tokens, effectively getting us stuck in that mode until EOF.
In the merging of an extremely large navigables PR, a task queue source
was added after the unique task source start value that was supposed to
remain last in the enum.
Previously, an audio loader could succeed for an HTMLVideoElement that
contains a video file, which caused the duration to be set to the bogus
duration of the audio loader instead of the correct duration from the
video container. Instead of setting the duration based on audio always,
set it to the video duration if we are creating a video element.
This is only needed because currently spec doesn't explicitly define
that navigable should have a pointer to associated container and when
this pointer should be set.
The JS::VM now owns the one Bytecode::Interpreter. We no longer have
multiple bytecode interpreters, and there is no concept of a "current"
bytecode interpreter.
If you ask for VM::bytecode_interpreter_if_exists(), it will return null
if we're not running the program in "bytecode enabled" mode.
If you ask for VM::bytecode_interpreter(), it will return a bytecode
interpreter in all modes. This is used for situations where even the AST
interpreter switches to bytecode mode (generators, etc.)
This implements the ability to drag the timeline and volume buttons on
UA-rendered media controls. The two behave a bit differently:
Volume is updated as the user drags the volume button. This isn't a very
expensive operation, so updating in real-time and hearing the volume
change feels nice.
The current time, on the other hand, is not committed until the user
releases the mouse button. Performing a seek every time we get a mouse-
move event is pretty laggy, especially for video. However, we still want
to render updates on the timeline itself (so the position of the button
and the timestamp update as you drag). To do so, we internally pause the
media and override the timestamp provided to the layout node.
In the future, we may be able to seek video periodically to provide some
visual feedback. For example, we can seek after every N seconds of
scrubbing, or when the user pauses scrubbing for a while.
The main thread in the WebContent process is often busy with layout and
running JavaScript. This can cause audio to sound jittery and crack. To
avoid this behavior, we now drive audio on a secondary thread.
Note: Browser on Serenity uses AudioServer, the connection for which is
already handled on a secondary thread within LibAudio. So this only
applies to Lagom.
Rather than using LibThreading, our hands are tied to QThread for now.
Internally, the Qt media objects use a QTimer, which is forbidden from
running on a thread that is not a QThread (the debug console is spammed
with messages pointing this out). Ideally, in the future AudioServer
will be able to run for non-Serenity platforms, and most of this can be
aligned with the Serenity implementation.
In particular:
- Don't include none submitter buttons.
- Use type_state() instead type() to avoid direct string comparisons
- Support the hidden _charset_ input
- Get form associated element's value directly instead of via the value
attribute
- Split line break normalization into a separate function so that it
can also be used by form submission.
Works for fills and strokes (using colors, gradients, or patterns),
along with images.
fill_rect() has been updated to use fill_path(), which allows it to
easily transform the rect, and already supports opacity.
Co-authored-by: MacDue <macdue@dueutil.tech>