summaryrefslogtreecommitdiff
path: root/Libraries/LibWeb
diff options
context:
space:
mode:
authorasynts <asynts@gmail.com>2020-12-03 18:46:56 +0100
committerAndreas Kling <kling@serenityos.org>2020-12-09 21:05:06 +0100
commita94a1d9f9eb9e75e9d1fc5365e7f27cc3172871d (patch)
tree67d27f170cb5bcf5326d8a78df58fe6712605321 /Libraries/LibWeb
parentb3d7c5bfbca5b68246ff3459817872322d18951f (diff)
downloadserenity-a94a1d9f9eb9e75e9d1fc5365e7f27cc3172871d.zip
LibWeb: Implement deletion of more complex selections.
Diffstat (limited to 'Libraries/LibWeb')
-rw-r--r--Libraries/LibWeb/Page/EditEventHandler.cpp78
-rw-r--r--Libraries/LibWeb/Page/EventHandler.cpp1
2 files changed, 42 insertions, 37 deletions
diff --git a/Libraries/LibWeb/Page/EditEventHandler.cpp b/Libraries/LibWeb/Page/EditEventHandler.cpp
index 12a0e4cf4d..8a33ec6df2 100644
--- a/Libraries/LibWeb/Page/EditEventHandler.cpp
+++ b/Libraries/LibWeb/Page/EditEventHandler.cpp
@@ -40,45 +40,49 @@ namespace Web {
void EditEventHandler::handle_delete(DOM::Range range)
{
- if (range.start().node() != range.end().node()) {
- if (range.start().node()->parent() == range.end().node()->parent()) {
- // Remove all intermediate nodes.
- auto* current = range.start().node()->next_sibling();
- while (current != range.end().node()) {
- auto* next = current->next_sibling();
- current->parent()->remove_child(*current);
- current = next;
- }
-
- // Join remaining text together.
- StringBuilder builder;
- builder.append(downcast<DOM::Text>(range.start().node())->data().substring_view(0, range.start().offset()));
- builder.append(downcast<DOM::Text>(range.end().node())->data().substring_view(range.end().offset()));
-
- range.start().node()->parent()->remove_child(*range.end().node());
- downcast<DOM::Text>(range.start().node())->set_data(builder.to_string());
-
- range.start().node()->invalidate_style();
- } else {
- TODO();
- }
- } else {
- if (is<DOM::Text>(*range.start().node())) {
- m_frame.document()->layout_node()->set_selection({});
+ auto* start = downcast<DOM::Text>(range.start().node());
+ auto* end = downcast<DOM::Text>(range.end().node());
+
+ // Remove all the nodes that are fully enclosed in the range.
+ HashTable<DOM::Node*> queued_for_deletion;
+ for (auto* node = start->next_in_pre_order(); node; node = node->next_in_pre_order()) {
+ if (node == end)
+ break;
+
+ queued_for_deletion.set(node);
+ }
+ for (auto* parent = start->parent(); parent; parent = parent->parent())
+ queued_for_deletion.remove(parent);
+ for (auto* parent = end->parent(); parent; parent = parent->parent())
+ queued_for_deletion.remove(parent);
+ for (auto* node : queued_for_deletion)
+ node->parent()->remove_child(*node);
+
+ if (start == end || start->next_sibling() == end) {
+ // If the start and end text nodes are now immediate siblings, merge the remainders into one.
- auto& node = downcast<DOM::Text>(*range.start().node());
+ StringBuilder builder;
+ builder.append(start->data().substring_view(0, range.start().offset()));
+ builder.append(end->data().substring_view(range.end().offset()));
+
+ start->set_data(builder.to_string());
+ start->invalidate_style();
- StringBuilder builder;
- builder.append(node.data().substring_view(0, range.start().offset()));
- builder.append(node.data().substring_view(range.end().offset()));
- node.set_data(builder.to_string());
+ if (start != end)
+ start->parent()->remove_child(*end);
+ } else {
+ // Otherwise, remove parts from both nodes.
- node.invalidate_style();
- }
+ start->set_data(start->data().substring_view(0, range.start().offset()));
+ start->invalidate_style();
+
+ end->set_data(end->data().substring_view(range.end().offset()));
+ end->invalidate_style();
}
- // FIXME: We need to remove stale layout nodes when nodes are removed from the DOM. Currently,
- // this is the only way to get these to disappear.
+ // FIXME: When nodes are removed from the DOM, the associated layout nodes become stale and still
+ // remain in the layout tree. This has to be fixed, this just causes everything to be recomputed
+ // which really hurts performance.
m_frame.document()->force_layout();
}
@@ -96,9 +100,9 @@ void EditEventHandler::handle_insert(DOM::Position position, u32 code_point)
node.invalidate_style();
}
- // FIXME: We need to remove stale layout nodes when nodes are removed from the DOM. Currently,
- // this is the only way to get these to disappear.
+ // FIXME: When nodes are removed from the DOM, the associated layout nodes become stale and still
+ // remain in the layout tree. This has to be fixed, this just causes everything to be recomputed
+ // which really hurts performance.
m_frame.document()->force_layout();
}
-
}
diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp
index 48fbb68454..9f3f80b697 100644
--- a/Libraries/LibWeb/Page/EventHandler.cpp
+++ b/Libraries/LibWeb/Page/EventHandler.cpp
@@ -422,4 +422,5 @@ void EventHandler::set_mouse_event_tracking_layout_node(Layout::Node* layout_nod
else
m_mouse_event_tracking_layout_node = nullptr;
}
+
}