summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorasynts <asynts@gmail.com>2020-12-02 13:41:58 +0100
committerAndreas Kling <kling@serenityos.org>2020-12-09 21:05:06 +0100
commite96faea1a232a349c4db31657624a577eaa6f7a0 (patch)
tree0c1ebef57c8c620db580365acda99ebbf9a6e59c
parent43dc47a4941d6aaa99ed847f879b4601094f6d4a (diff)
downloadserenity-e96faea1a232a349c4db31657624a577eaa6f7a0.zip
LibWeb: Support range delection accross nodes with shared parent.
-rw-r--r--Libraries/LibWeb/Page/EditEventHandler.cpp63
-rw-r--r--Libraries/LibWeb/Page/EventHandler.cpp18
2 files changed, 56 insertions, 25 deletions
diff --git a/Libraries/LibWeb/Page/EditEventHandler.cpp b/Libraries/LibWeb/Page/EditEventHandler.cpp
index de397ca220..20f8b7423c 100644
--- a/Libraries/LibWeb/Page/EditEventHandler.cpp
+++ b/Libraries/LibWeb/Page/EditEventHandler.cpp
@@ -31,6 +31,7 @@
#include <LibWeb/Page/Frame.h>
#include <LibWeb/DOM/Document.h>
+#include <LibWeb/Dump.h>
#include <LibWeb/Layout/InitialContainingBlockBox.h>
#include "EditEventHandler.h"
@@ -39,21 +40,55 @@ namespace Web {
void EditEventHandler::handle_delete(DOM::Range range)
{
- if (range.start().node() != range.end().node())
- TODO();
-
- if (is<DOM::Text>(*range.start().node())) {
- auto& node = downcast<DOM::Text>(*range.start().node());
-
- 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());
-
- m_frame.document()->layout_node()->set_selection({});
- node.invalidate_style();
+ // FIXME: Find a better way of updating the selection and cursor position.
+
+ if (range.start().node() != range.end().node()) {
+ if (range.start().node()->parent() == range.end().node()->parent()) {
+ m_frame.document()->layout_node()->set_selection({});
+ m_frame.cursor_position().set_offset(range.start().offset());
+
+ // 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;
+ }
+
+ if (!is<DOM::Text>(*range.start().node()) || !is<DOM::Text>(*range.end().node()))
+ TODO();
+
+ // 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({});
+ m_frame.cursor_position().set_offset(range.start().offset());
+
+ auto& node = downcast<DOM::Text>(*range.start().node());
+
+ 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());
+
+ 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.
+ m_frame.document()->force_layout();
}
void EditEventHandler::handle_delete(DOM::Position position)
diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp
index 4a94a54c77..e8e806d57c 100644
--- a/Libraries/LibWeb/Page/EventHandler.cpp
+++ b/Libraries/LibWeb/Page/EventHandler.cpp
@@ -353,25 +353,21 @@ bool EventHandler::handle_keydown(KeyCode key, unsigned modifiers, u32 code_poin
m_edit_event_handler->handle_delete(range);
return true;
}
+ } else {
+ m_edit_event_handler->handle_delete(range);
+ m_edit_event_handler->handle_insert(m_frame.cursor_position(), code_point);
+ return true;
}
-
- // FIXME: Check if this code point is in the printable character range.
-
- m_edit_event_handler->handle_delete(range);
- m_edit_event_handler->handle_insert(m_frame.cursor_position(), code_point);
- return true;
}
if (m_frame.cursor_position().is_valid() && m_frame.cursor_position().node()->is_editable()) {
if (key == KeyCode::Key_Backspace) {
m_edit_event_handler->handle_delete(m_frame.cursor_position());
return true;
+ } else {
+ m_edit_event_handler->handle_insert(m_frame.cursor_position(), code_point);
+ return true;
}
-
- // FIXME: Check if this code point is in the printable character range.
-
- m_edit_event_handler->handle_insert(m_frame.cursor_position(), code_point);
- return true;
}
return false;