LibWeb: Move the navigable's cursor position to be owned by the document

Navigables are re-used for navigations within the same tab. Its current
ownership of the cursor position is a bit ad-hoc, so nothing in the spec
indicates when to reset the cursor, nor do we manually do so. So when a
cursor update happens on one page, that cursor is retained on the next
page.

Instead, let's have the document own the cursor. Each navigation results
in a new document, thus we don't need to worry about resetting cursors.

This also makes many of the callsites feel nicer. We were previously
often going from the node, to the document, to the navigable, to the
cursor. This patch removes the navigable hop.
This commit is contained in:
Timothy Flynn 2024-08-02 07:31:40 -04:00 committed by Andreas Kling
commit faebbbc281
Notes: github-actions[bot] 2024-08-02 16:41:32 +00:00
15 changed files with 155 additions and 159 deletions

View file

@ -108,21 +108,6 @@ Navigable::Navigable(JS::NonnullGCPtr<Page> page)
, m_event_handler({}, *this)
{
all_navigables().set(this);
m_cursor_blink_timer = Core::Timer::create_repeating(500, [this] {
if (!is_focused())
return;
if (!m_cursor_position)
return;
auto node = m_cursor_position->node();
if (!node)
return;
node->document().update_layout();
if (node->paintable()) {
m_cursor_blink_state = !m_cursor_blink_state;
node->paintable()->set_needs_display();
}
});
}
Navigable::~Navigable()
@ -138,7 +123,6 @@ void Navigable::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_current_session_history_entry);
visitor.visit(m_active_session_history_entry);
visitor.visit(m_container);
visitor.visit(m_cursor_position);
m_event_handler.visit_edges(visitor);
}
@ -2162,46 +2146,11 @@ UserNavigationInvolvement user_navigation_involvement(DOM::Event const& event)
return event.is_trusted() ? UserNavigationInvolvement::Activation : UserNavigationInvolvement::None;
}
void Navigable::did_edit(Badge<EditEventHandler>)
{
reset_cursor_blink_cycle();
if (m_cursor_position && is<DOM::Text>(*m_cursor_position->node())) {
auto& text_node = static_cast<DOM::Text&>(*m_cursor_position->node());
if (auto text_node_owner = text_node.editable_text_node_owner())
text_node_owner->did_edit_text_node({});
}
}
void Navigable::reset_cursor_blink_cycle()
{
m_cursor_blink_state = true;
m_cursor_blink_timer->restart();
if (m_cursor_position && m_cursor_position->node()->paintable())
m_cursor_position->node()->paintable()->set_needs_display();
}
bool Navigable::is_focused() const
{
return &m_page->focused_navigable() == this;
}
void Navigable::set_cursor_position(JS::NonnullGCPtr<DOM::Position> position)
{
if (m_cursor_position && m_cursor_position->equals(position))
return;
if (m_cursor_position && m_cursor_position->node()->paintable())
m_cursor_position->node()->paintable()->set_needs_display();
m_cursor_position = position;
if (m_cursor_position && m_cursor_position->node()->paintable())
m_cursor_position->node()->paintable()->set_needs_display();
reset_cursor_blink_cycle();
}
static String visible_text_in_range(DOM::Range const& range)
{
// NOTE: This is an adaption of Range stringification, but we skip over DOM nodes that don't have a corresponding layout node.
@ -2262,20 +2211,4 @@ void Navigable::paste(String const& text)
m_event_handler.handle_paste(text);
}
bool Navigable::increment_cursor_position_offset()
{
if (!m_cursor_position->increment_offset())
return false;
reset_cursor_blink_cycle();
return true;
}
bool Navigable::decrement_cursor_position_offset()
{
if (!m_cursor_position->decrement_offset())
return false;
reset_cursor_blink_cycle();
return true;
}
}