LibWeb+UI/Qt: Display 'title' tooltips only when the mouse stops moving

Now instead of sending the position in which the user entered the
tooltip area, send just the text, and let the chrome figure out how to
display it.

In the case of Qt, wait for 600 milliseconds of no mouse movement, then
display it under the mouse cursor.
This commit is contained in:
circl 2024-07-02 14:16:24 +02:00 committed by Andreas Kling
parent 6623177265
commit 0f7623dd83
Notes: sideshowbarker 2024-07-17 08:43:11 +09:00
12 changed files with 34 additions and 21 deletions

View file

@ -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;

View file

@ -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);
}

View file

@ -23,6 +23,7 @@
#include <LibWeb/HTML/ActivateTab.h>
#include <LibWebView/ViewImplementation.h>
#include <QAbstractScrollArea>
#include <QTimer>
#include <QUrl>
class QKeyEvent;
@ -103,6 +104,9 @@ private:
void finish_handling_key_event(Web::KeyEvent const&);
void update_screen_rects();
Optional<ByteString> m_tooltip_text;
QTimer m_tooltip_hover_timer;
bool m_should_show_line_box_borders { false };
Gfx::IntSize m_viewport_size;

View file

@ -567,7 +567,7 @@ bool EventHandler::handle_mousemove(CSSPixelPoint viewport_position, CSSPixelPoi
if (hovered_node_changed) {
JS::GCPtr<HTML::HTMLElement const> 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();
}

View file

@ -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() { }

View file

@ -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(position, ByteString::formatted("{}%", volume));
browsing_context().page().client().page_did_enter_tooltip_area(ByteString::formatted("{}%", volume));
}
break;

View file

@ -163,7 +163,7 @@ 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_enter_tooltip_area;
Function<void(ByteString const&)> on_enter_tooltip_area;
Function<void()> on_leave_tooltip_area;
Function<void(String const& message)> on_request_alert;
Function<void(String const& message)> on_request_confirm;

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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()

View file

@ -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;

View file

@ -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) =|