LibWeb+UI: Add tooltip overriding and use it for <video> tags

This call is used to inform the chrome that it should display a tooltip
now and avoid any hovering timers. This is used by <video> tags to
display the volume percentage when it is changed.
This commit is contained in:
circl 2024-07-02 16:48:57 +02:00 committed by Andreas Kling
parent 0f7623dd83
commit ceb9c3b797
Notes: sideshowbarker 2024-07-17 01:55:29 +09:00
11 changed files with 79 additions and 5 deletions

View File

@ -532,6 +532,22 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_
[self reload];
};
m_web_view_bridge->on_request_tooltip_override = [weak_self](auto, auto const& tooltip) {
LadybirdWebView* self = weak_self;
if (self == nil) {
return;
}
self.toolTip = Ladybird::string_to_ns_string(tooltip);
};
m_web_view_bridge->on_stop_tooltip_override = [weak_self]() {
LadybirdWebView* self = weak_self;
if (self == nil) {
return;
}
self.toolTip = nil;
};
m_web_view_bridge->on_enter_tooltip_area = [weak_self](auto const& tooltip) {
LadybirdWebView* self = weak_self;
if (self == nil) {

View File

@ -99,6 +99,24 @@ WebContentView::WebContentView(QWidget* window, WebContentOptions const& web_con
update_cursor(cursor);
};
on_request_tooltip_override = [this](auto position, auto const& tooltip) {
m_tooltip_override = true;
if (m_tooltip_hover_timer.isActive())
m_tooltip_hover_timer.stop();
auto tooltip_without_carriage_return = tooltip.contains("\r"sv)
? tooltip.replace("\r\n"sv, "\n"sv, ReplaceMode::All).replace("\r"sv, "\n"sv, ReplaceMode::All)
: tooltip;
QToolTip::showText(
mapToGlobal(QPoint(position.x(), position.y())),
qstring_from_ak_string(tooltip_without_carriage_return),
this);
};
on_stop_tooltip_override = [this]() {
m_tooltip_override = false;
};
on_enter_tooltip_area = [this](auto const& tooltip) {
m_tooltip_text = tooltip.contains("\r"sv)
? tooltip.replace("\r\n"sv, "\n"sv, ReplaceMode::All).replace("\r"sv, "\n"sv, ReplaceMode::All)
@ -332,9 +350,11 @@ void WebContentView::keyReleaseEvent(QKeyEvent* event)
void WebContentView::mouseMoveEvent(QMouseEvent* event)
{
if (QToolTip::isVisible())
QToolTip::hideText();
m_tooltip_hover_timer.start(600);
if (!m_tooltip_override) {
if (QToolTip::isVisible())
QToolTip::hideText();
m_tooltip_hover_timer.start(600);
}
enqueue_native_event(Web::MouseEvent::Type::MouseMove, *event);
}

View File

@ -104,6 +104,7 @@ private:
void finish_handling_key_event(Web::KeyEvent const&);
void update_screen_rects();
bool m_tooltip_override { false };
Optional<ByteString> m_tooltip_text;
QTimer m_tooltip_hover_timer;

View File

@ -328,6 +328,8 @@ public:
virtual void page_did_request_image_context_menu(CSSPixelPoint, URL::URL const&, [[maybe_unused]] ByteString const& target, [[maybe_unused]] unsigned modifiers, Gfx::Bitmap const*) { }
virtual void page_did_request_media_context_menu(CSSPixelPoint, [[maybe_unused]] ByteString const& target, [[maybe_unused]] unsigned modifiers, Page::MediaContextMenu) { }
virtual void page_did_middle_click_link(URL::URL const&, [[maybe_unused]] ByteString const& target, [[maybe_unused]] unsigned modifiers) { }
virtual void page_did_request_tooltip_override(CSSPixelPoint, ByteString const&) { }
virtual void page_did_stop_tooltip_override() { }
virtual void page_did_enter_tooltip_area(ByteString const&) { }
virtual void page_did_leave_tooltip_area() { }
virtual void page_did_hover_link(URL::URL const&) { }

View File

@ -302,7 +302,7 @@ MediaPaintable::DispatchEventOfSameName MediaPaintable::handle_mouseup(Badge<Eve
break;
case HTML::HTMLMediaElement::MouseTrackingComponent::Volume:
browsing_context().page().client().page_did_leave_tooltip_area();
browsing_context().page().client().page_did_stop_tooltip_override();
break;
}
@ -351,7 +351,7 @@ MediaPaintable::DispatchEventOfSameName MediaPaintable::handle_mousemove(Badge<E
set_volume(media_element, *cached_layout_boxes.volume_scrub_rect, position);
auto volume = static_cast<u8>(media_element.volume() * 100.0);
browsing_context().page().client().page_did_enter_tooltip_area(ByteString::formatted("{}%", volume));
browsing_context().page().client().page_did_request_tooltip_override({ position.x(), cached_layout_boxes.volume_scrub_rect->y() }, ByteString::formatted("{}%", volume));
}
break;

View File

@ -163,6 +163,8 @@ public:
Function<void()> on_refresh;
Function<void(Gfx::Bitmap const&)> on_favicon_change;
Function<void(Gfx::StandardCursor)> on_cursor_change;
Function<void(Gfx::IntPoint, ByteString const&)> on_request_tooltip_override;
Function<void()> on_stop_tooltip_override;
Function<void(ByteString const&)> on_enter_tooltip_area;
Function<void()> on_leave_tooltip_area;
Function<void(String const& message)> on_request_alert;

View File

@ -170,6 +170,22 @@ void WebContentClient::did_change_url(u64 page_id, URL::URL const& url)
}
}
void WebContentClient::did_request_tooltip_override(u64 page_id, Gfx::IntPoint position, ByteString const& title)
{
if (auto view = view_for_page_id(page_id); view.has_value()) {
if (view->on_request_tooltip_override)
view->on_request_tooltip_override(view->to_widget_position(position), title);
}
}
void WebContentClient::did_stop_tooltip_override(u64 page_id)
{
if (auto view = view_for_page_id(page_id); view.has_value()) {
if (view->on_stop_tooltip_override)
view->on_stop_tooltip_override();
}
}
void WebContentClient::did_enter_tooltip_area(u64 page_id, ByteString const& title)
{
if (auto view = view_for_page_id(page_id); view.has_value()) {

View File

@ -55,6 +55,8 @@ private:
virtual void did_layout(u64 page_id, Gfx::IntSize) override;
virtual void did_change_title(u64 page_id, ByteString const&) override;
virtual void did_change_url(u64 page_id, URL::URL const&) override;
virtual void did_request_tooltip_override(u64 page_id, Gfx::IntPoint, ByteString const&) override;
virtual void did_stop_tooltip_override(u64 page_id) override;
virtual void did_enter_tooltip_area(u64 page_id, ByteString const&) override;
virtual void did_leave_tooltip_area(u64 page_id) override;
virtual void did_hover_link(u64 page_id, URL::URL const&) override;

View File

@ -318,6 +318,17 @@ Gfx::IntRect PageClient::page_did_request_fullscreen_window()
return client().did_request_fullscreen_window(m_id);
}
void PageClient::page_did_request_tooltip_override(Web::CSSPixelPoint position, ByteString const& title)
{
auto device_position = page().css_to_device_point(position);
client().async_did_request_tooltip_override(m_id, { device_position.x(), device_position.y() }, title);
}
void PageClient::page_did_stop_tooltip_override()
{
client().async_did_leave_tooltip_area(m_id);
}
void PageClient::page_did_enter_tooltip_area(ByteString const& title)
{
client().async_did_enter_tooltip_area(m_id, title);

View File

@ -119,6 +119,8 @@ private:
virtual Gfx::IntRect page_did_request_maximize_window() override;
virtual Gfx::IntRect page_did_request_minimize_window() override;
virtual Gfx::IntRect page_did_request_fullscreen_window() override;
virtual void page_did_request_tooltip_override(Web::CSSPixelPoint, ByteString const&) override;
virtual void page_did_stop_tooltip_override() override;
virtual void page_did_enter_tooltip_area(ByteString const&) override;
virtual void page_did_leave_tooltip_area() override;
virtual void page_did_hover_link(URL::URL const&) override;

View File

@ -27,6 +27,8 @@ endpoint WebContentClient
did_layout(u64 page_id, Gfx::IntSize content_size) =|
did_change_title(u64 page_id, ByteString title) =|
did_change_url(u64 page_id, URL::URL url) =|
did_request_tooltip_override(u64 page_id, Gfx::IntPoint position, ByteString title) =|
did_stop_tooltip_override(u64 page_id) =|
did_enter_tooltip_area(u64 page_id, ByteString title) =|
did_leave_tooltip_area(u64 page_id) =|
did_hover_link(u64 page_id, URL::URL url) =|