1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 02:47:35 +00:00

LibWeb: Improve Unicode compatibility of HTML contenteditable

This patch updates the Page::keydown_event event handler to implement
crude Unicode support. It implements new method in EditEventHandler to
more easily handle deleting a single character after the cursor.
Furthermore, it makes use of the previously implemented methods to
increment and decrement the cursor position, which take into account
that Unicode codepoint may be multiple bytes wide.

This means it is now possible to mostly edit Unicode in editable DOM
nodes without any crashes. :^)
This commit is contained in:
Max Wipfli 2021-05-18 22:09:15 +02:00 committed by Andreas Kling
parent 7181cb3a9c
commit 9440a3c280
3 changed files with 32 additions and 45 deletions

View file

@ -1,21 +1,41 @@
/*
* Copyright (c) 2020, the SerenityOS developers.
* Copyright (c) 2020-2021, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "EditEventHandler.h"
#include <AK/StringBuilder.h>
#include <AK/Utf8View.h>
#include <LibWeb/DOM/Document.h>
#include <LibWeb/DOM/Position.h>
#include <LibWeb/DOM/Range.h>
#include <LibWeb/DOM/Text.h>
#include <LibWeb/Layout/InitialContainingBlockBox.h>
#include <LibWeb/Layout/LayoutPosition.h>
#include <LibWeb/Page/EditEventHandler.h>
#include <LibWeb/Page/Frame.h>
namespace Web {
void EditEventHandler::handle_delete_character_after(const DOM::Position& cursor_position)
{
if (cursor_position.offset_is_at_end_of_node()) {
// FIXME: Move to the next node and delete the first character there.
return;
}
auto& node = *static_cast<DOM::Text*>(const_cast<DOM::Node*>(cursor_position.node()));
auto& text = node.data();
auto codepoint_length = Utf8View(text).iterator_at_byte_offset(cursor_position.offset()).code_point_length_in_bytes();
StringBuilder builder;
builder.append(text.substring_view(0, cursor_position.offset()));
builder.append(text.substring_view(cursor_position.offset() + codepoint_length));
node.set_data(builder.to_string());
m_frame.did_edit({});
}
// This method is quite convoluted but this is necessary to make editing feel intuitive.
void EditEventHandler::handle_delete(DOM::Range& range)
{