diff --git a/Ladybird/AppKit/UI/LadybirdWebView.mm b/Ladybird/AppKit/UI/LadybirdWebView.mm index 538230c95fa..1f698759768 100644 --- a/Ladybird/AppKit/UI/LadybirdWebView.mm +++ b/Ladybird/AppKit/UI/LadybirdWebView.mm @@ -532,7 +532,7 @@ static void copy_data_to_clipboard(StringView data, NSPasteboardType pasteboard_ [self reload]; }; - m_web_view_bridge->on_enter_tooltip_area = [weak_self](auto, auto const& tooltip) { + m_web_view_bridge->on_enter_tooltip_area = [weak_self](auto const& tooltip) { LadybirdWebView* self = weak_self; if (self == nil) { return; diff --git a/Ladybird/Qt/WebContentView.cpp b/Ladybird/Qt/WebContentView.cpp index 739f4450053..17b22c4338e 100644 --- a/Ladybird/Qt/WebContentView.cpp +++ b/Ladybird/Qt/WebContentView.cpp @@ -79,6 +79,16 @@ WebContentView::WebContentView(QWidget* window, WebContentOptions const& web_con update_screen_rects(); }); + m_tooltip_hover_timer.setSingleShot(true); + + QObject::connect(&m_tooltip_hover_timer, &QTimer::timeout, [this] { + if (m_tooltip_text.has_value()) + QToolTip::showText( + QCursor::pos(), + qstring_from_ak_string(m_tooltip_text.value()), + this); + }); + initialize_client((parent_client == nullptr) ? CreateNewClient::Yes : CreateNewClient::No); on_ready_to_paint = [this]() { @@ -89,18 +99,14 @@ WebContentView::WebContentView(QWidget* window, WebContentOptions const& web_con update_cursor(cursor); }; - on_enter_tooltip_area = [this](auto position, auto const& tooltip) { - auto tooltip_without_carriage_return = tooltip.contains("\r"sv) + 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) : tooltip; - QToolTip::showText( - mapToGlobal(QPoint(position.x(), position.y())), - qstring_from_ak_string(tooltip_without_carriage_return), - this); }; - on_leave_tooltip_area = []() { - QToolTip::hideText(); + on_leave_tooltip_area = [this]() { + m_tooltip_text.clear(); }; on_finish_handling_key_event = [this](auto const& event) { @@ -326,6 +332,10 @@ void WebContentView::keyReleaseEvent(QKeyEvent* event) void WebContentView::mouseMoveEvent(QMouseEvent* event) { + if (QToolTip::isVisible()) + QToolTip::hideText(); + m_tooltip_hover_timer.start(600); + enqueue_native_event(Web::MouseEvent::Type::MouseMove, *event); } diff --git a/Ladybird/Qt/WebContentView.h b/Ladybird/Qt/WebContentView.h index cca4732f5d0..29757fdf8a5 100644 --- a/Ladybird/Qt/WebContentView.h +++ b/Ladybird/Qt/WebContentView.h @@ -23,6 +23,7 @@ #include #include #include +#include #include class QKeyEvent; @@ -103,6 +104,9 @@ private: void finish_handling_key_event(Web::KeyEvent const&); void update_screen_rects(); + Optional m_tooltip_text; + QTimer m_tooltip_hover_timer; + bool m_should_show_line_box_borders { false }; Gfx::IntSize m_viewport_size; diff --git a/Userland/Libraries/LibWeb/Page/EventHandler.cpp b/Userland/Libraries/LibWeb/Page/EventHandler.cpp index 1c342163ba2..cad5ecdaff7 100644 --- a/Userland/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Userland/Libraries/LibWeb/Page/EventHandler.cpp @@ -567,7 +567,7 @@ bool EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSPixelPoi if (hovered_node_changed) { JS::GCPtr hovered_html_element = document.hovered_node() ? document.hovered_node()->enclosing_html_element_with_attribute(HTML::AttributeNames::title) : nullptr; if (hovered_html_element && hovered_html_element->title().has_value()) { - page.client().page_did_enter_tooltip_area(viewport_position, hovered_html_element->title()->to_byte_string()); + page.client().page_did_enter_tooltip_area(hovered_html_element->title()->to_byte_string()); } else { page.client().page_did_leave_tooltip_area(); } diff --git a/Userland/Libraries/LibWeb/Page/Page.h b/Userland/Libraries/LibWeb/Page/Page.h index ff5d98ac042..89b61bb0c25 100644 --- a/Userland/Libraries/LibWeb/Page/Page.h +++ b/Userland/Libraries/LibWeb/Page/Page.h @@ -328,7 +328,7 @@ 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_enter_tooltip_area(CSSPixelPoint, ByteString const&) { } + 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&) { } virtual void page_did_unhover_link() { } diff --git a/Userland/Libraries/LibWeb/Painting/MediaPaintable.cpp b/Userland/Libraries/LibWeb/Painting/MediaPaintable.cpp index 422bb0d7d69..d40168326af 100644 --- a/Userland/Libraries/LibWeb/Painting/MediaPaintable.cpp +++ b/Userland/Libraries/LibWeb/Painting/MediaPaintable.cpp @@ -351,7 +351,7 @@ MediaPaintable::DispatchEventOfSameName MediaPaintable::handle_mousemove(Badge(media_element.volume() * 100.0); - browsing_context().page().client().page_did_enter_tooltip_area(position, ByteString::formatted("{}%", volume)); + browsing_context().page().client().page_did_enter_tooltip_area(ByteString::formatted("{}%", volume)); } break; diff --git a/Userland/Libraries/LibWebView/ViewImplementation.h b/Userland/Libraries/LibWebView/ViewImplementation.h index aa1fe6367bf..cf733a54973 100644 --- a/Userland/Libraries/LibWebView/ViewImplementation.h +++ b/Userland/Libraries/LibWebView/ViewImplementation.h @@ -163,7 +163,7 @@ public: Function on_refresh; Function on_favicon_change; Function on_cursor_change; - Function on_enter_tooltip_area; + Function on_enter_tooltip_area; Function on_leave_tooltip_area; Function on_request_alert; Function on_request_confirm; diff --git a/Userland/Libraries/LibWebView/WebContentClient.cpp b/Userland/Libraries/LibWebView/WebContentClient.cpp index fc11d0c5f04..dc9251911f2 100644 --- a/Userland/Libraries/LibWebView/WebContentClient.cpp +++ b/Userland/Libraries/LibWebView/WebContentClient.cpp @@ -170,11 +170,11 @@ void WebContentClient::did_change_url(u64 page_id, URL::URL const& url) } } -void WebContentClient::did_enter_tooltip_area(u64 page_id, Gfx::IntPoint content_position, ByteString const& title) +void WebContentClient::did_enter_tooltip_area(u64 page_id, ByteString const& title) { if (auto view = view_for_page_id(page_id); view.has_value()) { if (view->on_enter_tooltip_area) - view->on_enter_tooltip_area(view->to_widget_position(content_position), title); + view->on_enter_tooltip_area(title); } } diff --git a/Userland/Libraries/LibWebView/WebContentClient.h b/Userland/Libraries/LibWebView/WebContentClient.h index 3a21c5b75ad..fa204d4cb2b 100644 --- a/Userland/Libraries/LibWebView/WebContentClient.h +++ b/Userland/Libraries/LibWebView/WebContentClient.h @@ -55,7 +55,7 @@ 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_enter_tooltip_area(u64 page_id, Gfx::IntPoint, ByteString const&) 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; virtual void did_unhover_link(u64 page_id) override; diff --git a/Userland/Services/WebContent/PageClient.cpp b/Userland/Services/WebContent/PageClient.cpp index a171f8cdc83..6bb2b4e42cb 100644 --- a/Userland/Services/WebContent/PageClient.cpp +++ b/Userland/Services/WebContent/PageClient.cpp @@ -318,10 +318,9 @@ Gfx::IntRect PageClient::page_did_request_fullscreen_window() return client().did_request_fullscreen_window(m_id); } -void PageClient::page_did_enter_tooltip_area(Web::CSSPixelPoint content_position, ByteString const& title) +void PageClient::page_did_enter_tooltip_area(ByteString const& title) { - auto device_position = page().css_to_device_point(content_position); - client().async_did_enter_tooltip_area(m_id, { device_position.x(), device_position.y() }, title); + client().async_did_enter_tooltip_area(m_id, title); } void PageClient::page_did_leave_tooltip_area() diff --git a/Userland/Services/WebContent/PageClient.h b/Userland/Services/WebContent/PageClient.h index 141f1e23f43..7e40b083d55 100644 --- a/Userland/Services/WebContent/PageClient.h +++ b/Userland/Services/WebContent/PageClient.h @@ -119,7 +119,7 @@ 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_enter_tooltip_area(Web::CSSPixelPoint, ByteString const&) 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; virtual void page_did_unhover_link() override; diff --git a/Userland/Services/WebContent/WebContentClient.ipc b/Userland/Services/WebContent/WebContentClient.ipc index 3ec9d8ef7b5..b1948d84cef 100644 --- a/Userland/Services/WebContent/WebContentClient.ipc +++ b/Userland/Services/WebContent/WebContentClient.ipc @@ -27,7 +27,7 @@ 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_enter_tooltip_area(u64 page_id, Gfx::IntPoint content_position, ByteString title) =| + 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) =| did_unhover_link(u64 page_id) =|