LibWeb: Notify ImageStyleValue::Clients on animation
Previously image animations driven by `ImageStyleValueResource` invalidated clients using `on_animate`, this was only implemented by the `background` presentational attribute of `HTMLBodyElement`. It now uses `notify_clients_did_update` which is implemented by all clients.
This commit is contained in:
parent
ce7a963344
commit
11ab66c752
6 changed files with 53 additions and 20 deletions
|
|
@ -97,18 +97,22 @@ void ImageStyleValueResource::add_callbacks_if_needed(DOM::Document& document)
|
|||
[weak_document = GC::Weak(document), url = m_url] {
|
||||
if (auto document = weak_document.ptr()) {
|
||||
if (auto* resource = document->css_image_resource(url))
|
||||
resource->notify_image_style_values_did_update(*document);
|
||||
resource->on_decoded_image_data_loaded(*document);
|
||||
}
|
||||
},
|
||||
nullptr);
|
||||
}
|
||||
|
||||
void ImageStyleValueResource::notify_image_style_values_did_update(DOM::Document& document)
|
||||
void ImageStyleValueResource::on_decoded_image_data_loaded(DOM::Document& document)
|
||||
{
|
||||
notify_image_style_values_did_update();
|
||||
start_animation_timer_if_needed(document);
|
||||
}
|
||||
|
||||
void ImageStyleValueResource::notify_image_style_values_did_update()
|
||||
{
|
||||
for (auto const* image_style_value : m_image_style_values)
|
||||
image_style_value->notify_clients_did_update();
|
||||
|
||||
start_animation_timer_if_needed(document);
|
||||
}
|
||||
|
||||
void ImageStyleValueResource::start_animation_timer_if_needed(DOM::Document& document)
|
||||
|
|
@ -183,8 +187,7 @@ void ImageStyleValueResource::animate(DOM::Document&)
|
|||
stop_animation_timer();
|
||||
}
|
||||
|
||||
for (auto const* image_style_value : m_image_style_values)
|
||||
image_style_value->notify_did_animate();
|
||||
notify_image_style_values_did_update();
|
||||
}
|
||||
|
||||
ValueComparingNonnullRefPtr<ImageStyleValue const> ImageStyleValue::create(URL const& url)
|
||||
|
|
@ -439,12 +442,6 @@ void ImageStyleValue::notify_clients_did_update() const
|
|||
client->image_style_value_did_update(const_cast<ImageStyleValue&>(*this));
|
||||
}
|
||||
|
||||
void ImageStyleValue::notify_did_animate() const
|
||||
{
|
||||
if (on_animate)
|
||||
on_animate();
|
||||
}
|
||||
|
||||
Optional<::URL::URL> ImageStyleValue::resolved_url(DOM::Document const& document) const
|
||||
{
|
||||
if (m_url.url().is_empty())
|
||||
|
|
|
|||
|
|
@ -45,7 +45,8 @@ public:
|
|||
|
||||
private:
|
||||
void add_callbacks_if_needed(DOM::Document&);
|
||||
void notify_image_style_values_did_update(DOM::Document&);
|
||||
void on_decoded_image_data_loaded(DOM::Document&);
|
||||
void notify_image_style_values_did_update();
|
||||
void start_animation_timer_if_needed(DOM::Document&);
|
||||
void stop_animation_timer();
|
||||
bool is_animatable() const;
|
||||
|
|
@ -109,8 +110,6 @@ public:
|
|||
Optional<Gfx::DecodedImageFrame> current_frame(DOM::Document const&, DevicePixelRect const& dest_rect) const;
|
||||
size_t current_frame_index(DOM::Document const&) const;
|
||||
|
||||
mutable Function<void()> on_animate;
|
||||
|
||||
GC::Ptr<HTML::DecodedImageData> image_data(DOM::Document const&) const;
|
||||
|
||||
private:
|
||||
|
|
@ -122,7 +121,6 @@ private:
|
|||
void register_client(Client&) const;
|
||||
void unregister_client(Client&) const;
|
||||
void notify_clients_did_update() const;
|
||||
void notify_did_animate() const;
|
||||
void update_style_sheet_resource_context(CSSStyleSheet const&);
|
||||
Optional<::URL::URL> resolved_url(DOM::Document const&) const;
|
||||
::URL::URL style_resource_base_url(DOM::Document const&) const;
|
||||
|
|
|
|||
|
|
@ -137,10 +137,6 @@ void HTMLBodyElement::attribute_changed(FlyString const& name, Optional<String>
|
|||
m_background_style_value = nullptr;
|
||||
if (auto maybe_background_url = document().encoding_parse_url(value.value_or(String {})); maybe_background_url.has_value()) {
|
||||
m_background_style_value = CSS::ImageStyleValue::create(maybe_background_url.value());
|
||||
m_background_style_value->on_animate = [this] {
|
||||
if (paintable())
|
||||
paintable()->set_needs_repaint();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
BIN
Tests/LibWeb/Screenshot/data/red-then-green.gif
Normal file
BIN
Tests/LibWeb/Screenshot/data/red-then-green.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 241 B |
Binary file not shown.
|
After Width: | Height: | Size: 316 B |
|
|
@ -0,0 +1,42 @@
|
|||
<!doctype html>
|
||||
<html class="reftest-wait">
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 50px;
|
||||
/* red-then-green.gif is 100x50: frame 0 is solid red for 500ms, frame 1 is solid green for 100s, it does not loop */
|
||||
background: url("../data/red-then-green.gif") no-repeat;
|
||||
}
|
||||
</style>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
const waitForAnimationToStart = () =>
|
||||
new Promise(resolve => {
|
||||
const wait = () => {
|
||||
if (internals.activeImageStyleValueAnimationCount() > 0) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
requestAnimationFrame(wait);
|
||||
};
|
||||
|
||||
wait();
|
||||
});
|
||||
|
||||
(async () => {
|
||||
// Wait for the animation to start
|
||||
await waitForAnimationToStart();
|
||||
|
||||
// Wait until the next frame
|
||||
await new Promise(resolve => setTimeout(resolve, 600));
|
||||
|
||||
// Take a screenshot - the image should have been invalidated and repainted.
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
})();
|
||||
</script>
|
||||
</html>
|
||||
Loading…
Reference in a new issue