From 8417ade5529b9536c22f16181210a5b78ddc455c Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Tue, 22 Apr 2025 13:06:45 -0400 Subject: [PATCH] LibWeb: Update the media display when the hovered component changes This allows the media paintable to be redrawn when the media element is paused. We change the color of some components on hover, but if the media was paused, that would not be rendered. This wasn't an issue while the media is playing because the update to the timeline would take care of redrawing the paintable. --- Libraries/LibWeb/HTML/HTMLMediaElement.h | 15 +++++--- Libraries/LibWeb/Painting/MediaPaintable.cpp | 36 +++++++++++++++----- Libraries/LibWeb/Painting/MediaPaintable.h | 2 +- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/Libraries/LibWeb/HTML/HTMLMediaElement.h b/Libraries/LibWeb/HTML/HTMLMediaElement.h index 38dc0c444af..20ce380c825 100644 --- a/Libraries/LibWeb/HTML/HTMLMediaElement.h +++ b/Libraries/LibWeb/HTML/HTMLMediaElement.h @@ -132,12 +132,18 @@ public: WebIDL::ExceptionOr handle_keydown(Badge, UIEvents::KeyCode, u32 modifiers); - enum class MouseTrackingComponent { + enum class MediaComponent { + PlaybackButton, + SpeakerButton, Timeline, Volume, }; - void set_layout_mouse_tracking_component(Badge, Optional mouse_tracking_component) { m_mouse_tracking_component = move(mouse_tracking_component); } - Optional const& layout_mouse_tracking_component(Badge) const { return m_mouse_tracking_component; } + + void set_layout_mouse_tracking_component(Badge, Optional mouse_tracking_component) { m_mouse_tracking_component = move(mouse_tracking_component); } + Optional const& layout_mouse_tracking_component(Badge) const { return m_mouse_tracking_component; } + + void set_layout_hovered_component(Badge, Optional hovered_component) { m_hovered_component = hovered_component; } + Optional const& layout_hovered_component(Badge) const { return m_hovered_component; } void set_layout_mouse_position(Badge, Optional mouse_position) { m_mouse_position = move(mouse_position); } Optional const& layout_mouse_position(Badge) const { return m_mouse_position; } @@ -318,7 +324,8 @@ private: bool m_seek_in_progress = false; // Cached state for layout. - Optional m_mouse_tracking_component; + Optional m_mouse_tracking_component; + Optional m_hovered_component; bool m_tracking_mouse_position_while_playing { false }; Optional m_mouse_position; Optional m_display_time; diff --git a/Libraries/LibWeb/Painting/MediaPaintable.cpp b/Libraries/LibWeb/Painting/MediaPaintable.cpp index a7daf63f58f..3b0bdec0f2a 100644 --- a/Libraries/LibWeb/Painting/MediaPaintable.cpp +++ b/Libraries/LibWeb/Painting/MediaPaintable.cpp @@ -272,7 +272,7 @@ void MediaPaintable::paint_control_bar_volume(PaintContext& context, HTML::HTMLM volume_button_rect.shrink(components.volume_scrub_rect.width() - components.volume_button_size, components.volume_scrub_rect.height() - components.volume_button_size); volume_button_rect.set_x(components.volume_scrub_rect.x() + volume_button_offset_x - components.volume_button_size / 2); - auto volume_is_hovered = rect_is_hovered(media_element, components.volume_rect, mouse_position, HTML::HTMLMediaElement::MouseTrackingComponent::Volume); + auto volume_is_hovered = rect_is_hovered(media_element, components.volume_rect, mouse_position, HTML::HTMLMediaElement::MediaComponent::Volume); auto volume_color = control_button_color(volume_is_hovered); context.display_list_recorder().fill_ellipse(volume_button_rect.to_type(), volume_color); } @@ -289,10 +289,10 @@ MediaPaintable::DispatchEventOfSameName MediaPaintable::handle_mousedown(Badgecontains(position_adjusted_by_scroll_offset)) { - media_element.set_layout_mouse_tracking_component({}, HTML::HTMLMediaElement::MouseTrackingComponent::Timeline); + media_element.set_layout_mouse_tracking_component({}, HTML::HTMLMediaElement::MediaComponent::Timeline); set_current_time(media_element, *cached_layout_boxes.timeline_rect, position_adjusted_by_scroll_offset, Temporary::Yes); } else if (cached_layout_boxes.volume_rect.has_value() && cached_layout_boxes.volume_rect->contains(position_adjusted_by_scroll_offset)) { - media_element.set_layout_mouse_tracking_component({}, HTML::HTMLMediaElement::MouseTrackingComponent::Volume); + media_element.set_layout_mouse_tracking_component({}, HTML::HTMLMediaElement::MediaComponent::Volume); set_volume(media_element, *cached_layout_boxes.volume_scrub_rect, position_adjusted_by_scroll_offset); } @@ -312,14 +312,17 @@ MediaPaintable::DispatchEventOfSameName MediaPaintable::handle_mouseup(Badge(*navigable()).event_handler().set_mouse_event_tracking_paintable(nullptr); @@ -361,12 +364,12 @@ MediaPaintable::DispatchEventOfSameName MediaPaintable::handle_mousemove(Badgecontains(position_adjusted_by_scroll_offset)) + media_element.set_layout_hovered_component({}, HTML::HTMLMediaElement::MediaComponent::PlaybackButton); + else if (cached_layout_boxes.speaker_button_rect.has_value() && cached_layout_boxes.speaker_button_rect->contains(position_adjusted_by_scroll_offset)) + media_element.set_layout_hovered_component({}, HTML::HTMLMediaElement::MediaComponent::SpeakerButton); + else if (cached_layout_boxes.volume_rect.has_value() && cached_layout_boxes.volume_rect->contains(position_adjusted_by_scroll_offset)) + media_element.set_layout_hovered_component({}, HTML::HTMLMediaElement::MediaComponent::Volume); + else + media_element.set_layout_hovered_component({}, {}); + + if (previous_hovered_component != media_element.layout_hovered_component({})) + set_needs_display(); + if (absolute_rect().contains(position_adjusted_by_scroll_offset)) { media_element.set_layout_mouse_position({}, position_adjusted_by_scroll_offset); return DispatchEventOfSameName::Yes; @@ -416,7 +436,7 @@ void MediaPaintable::set_volume(HTML::HTMLMediaElement& media_element, CSSPixelR media_element.set_volume(volume).release_value_but_fixme_should_propagate_errors(); } -bool MediaPaintable::rect_is_hovered(HTML::HTMLMediaElement const& media_element, Optional const& rect, Optional const& mouse_position, Optional const& allowed_mouse_tracking_component) +bool MediaPaintable::rect_is_hovered(HTML::HTMLMediaElement const& media_element, Optional const& rect, Optional const& mouse_position, Optional const& allowed_mouse_tracking_component) { if (auto const& mouse_tracking_component = media_element.layout_mouse_tracking_component({}); mouse_tracking_component.has_value()) return mouse_tracking_component == allowed_mouse_tracking_component; diff --git a/Libraries/LibWeb/Painting/MediaPaintable.h b/Libraries/LibWeb/Painting/MediaPaintable.h index 6cbcae75afa..6d9b8f850f0 100644 --- a/Libraries/LibWeb/Painting/MediaPaintable.h +++ b/Libraries/LibWeb/Painting/MediaPaintable.h @@ -61,7 +61,7 @@ private: static void set_current_time(HTML::HTMLMediaElement& media_element, CSSPixelRect timeline_rect, CSSPixelPoint mouse_position, Temporary); static void set_volume(HTML::HTMLMediaElement& media_element, CSSPixelRect volume_rect, CSSPixelPoint mouse_position); - static bool rect_is_hovered(HTML::HTMLMediaElement const& media_element, Optional const& rect, Optional const& mouse_position, Optional const& allowed_mouse_tracking_component = {}); + static bool rect_is_hovered(HTML::HTMLMediaElement const& media_element, Optional const& rect, Optional const& mouse_position, Optional const& allowed_mouse_tracking_component = {}); }; }