diff options
-rw-r--r-- | Libraries/LibWeb/Layout/LayoutText.cpp | 23 | ||||
-rw-r--r-- | Libraries/LibWeb/Layout/LayoutText.h | 1 | ||||
-rw-r--r-- | Libraries/LibWeb/Page/EventHandler.cpp | 1 | ||||
-rw-r--r-- | Libraries/LibWeb/Page/Frame.cpp | 28 | ||||
-rw-r--r-- | Libraries/LibWeb/Page/Frame.h | 13 |
5 files changed, 66 insertions, 0 deletions
diff --git a/Libraries/LibWeb/Layout/LayoutText.cpp b/Libraries/LibWeb/Layout/LayoutText.cpp index 7a4cc81885..55696b5531 100644 --- a/Libraries/LibWeb/Layout/LayoutText.cpp +++ b/Libraries/LibWeb/Layout/LayoutText.cpp @@ -32,6 +32,7 @@ #include <LibWeb/DOM/Document.h> #include <LibWeb/Layout/LayoutBlock.h> #include <LibWeb/Layout/LayoutText.h> +#include <LibWeb/Page/Frame.h> #include <ctype.h> namespace Web { @@ -101,6 +102,28 @@ void LayoutText::paint_fragment(PaintContext& context, const LineBoxFragment& fr painter.add_clip_rect(enclosing_int_rect(selection_rect)); painter.draw_text(enclosing_int_rect(fragment.absolute_rect()), text.substring_view(fragment.start(), fragment.length()), Gfx::TextAlignment::TopLeft, context.palette().selection_text()); } + + paint_cursor_if_needed(context, fragment); +} + +void LayoutText::paint_cursor_if_needed(PaintContext& context, const LineBoxFragment& fragment) const +{ + if (!frame().cursor_blink_state()) + return; + + if (frame().cursor_position().node() != &node()) + return; + + if (!(frame().cursor_position().offset() >= (unsigned)fragment.start() && frame().cursor_position().offset() < (unsigned)(fragment.start() + fragment.length()))) + return; + + auto fragment_rect = fragment.absolute_rect(); + + float cursor_x = fragment_rect.x() + specified_style().font().width(fragment.text().substring_view(0, frame().cursor_position().offset() - fragment.start())); + float cursor_top = fragment_rect.top(); + float cursor_height = fragment_rect.height(); + Gfx::IntRect cursor_rect(cursor_x, cursor_top, 1, cursor_height); + context.painter().draw_rect(cursor_rect, context.palette().text_cursor()); } template<typename Callback> diff --git a/Libraries/LibWeb/Layout/LayoutText.h b/Libraries/LibWeb/Layout/LayoutText.h index 66b3bf0cad..155694c25a 100644 --- a/Libraries/LibWeb/Layout/LayoutText.h +++ b/Libraries/LibWeb/Layout/LayoutText.h @@ -54,6 +54,7 @@ public: private: void split_into_lines_by_rules(LayoutBlock& container, LayoutMode, bool do_collapse, bool do_wrap_lines, bool do_wrap_breaks); + void paint_cursor_if_needed(PaintContext&, const LineBoxFragment&) const; template<typename Callback> void for_each_chunk(Callback, LayoutMode, bool do_wrap_lines, bool do_wrap_breaks) const; diff --git a/Libraries/LibWeb/Page/EventHandler.cpp b/Libraries/LibWeb/Page/EventHandler.cpp index 0bb63b83b4..b9e6e618b2 100644 --- a/Libraries/LibWeb/Page/EventHandler.cpp +++ b/Libraries/LibWeb/Page/EventHandler.cpp @@ -150,6 +150,7 @@ bool EventHandler::handle_mousedown(const Gfx::IntPoint& position, unsigned butt } } else { if (button == GUI::MouseButton::Left) { + m_frame.set_cursor_position(DOM::Position(*node, result.index_in_node)); layout_root()->selection().set({ result.layout_node, result.index_in_node }, {}); dump_selection("MouseDown"); m_in_mouse_selection = true; diff --git a/Libraries/LibWeb/Page/Frame.cpp b/Libraries/LibWeb/Page/Frame.cpp index 5262c8bd36..e81e9722b6 100644 --- a/Libraries/LibWeb/Page/Frame.cpp +++ b/Libraries/LibWeb/Page/Frame.cpp @@ -40,6 +40,7 @@ Frame::Frame(DOM::Element& host_element, Frame& main_frame) , m_event_handler({}, *this) , m_host_element(host_element.make_weak_ptr()) { + setup(); } Frame::Frame(Page& page) @@ -48,12 +49,23 @@ Frame::Frame(Page& page) , m_loader(*this) , m_event_handler({}, *this) { + setup(); } Frame::~Frame() { } +void Frame::setup() +{ + m_cursor_blink_timer = Core::Timer::construct(500, [this] { + if (m_cursor_position.node() && m_cursor_position.node()->layout_node()) { + m_cursor_blink_state = !m_cursor_blink_state; + m_cursor_position.node()->layout_node()->set_needs_display(); + } + }); +} + void Frame::set_document(DOM::Document* document) { if (m_document == document) @@ -168,4 +180,20 @@ Gfx::IntPoint Frame::to_main_frame_position(const Gfx::IntPoint& a_position) return position; } +void Frame::set_cursor_position(const DOM::Position & position) +{ + if (m_cursor_position == position) + return; + + if (m_cursor_position.node() && m_cursor_position.node()->layout_node()) + m_cursor_position.node()->layout_node()->set_needs_display(); + + m_cursor_position = position; + + if (m_cursor_position.node() && m_cursor_position.node()->layout_node()) + m_cursor_position.node()->layout_node()->set_needs_display(); + + dbg() << "Cursor position: " << m_cursor_position; +} + } diff --git a/Libraries/LibWeb/Page/Frame.h b/Libraries/LibWeb/Page/Frame.h index 07d2bf8a1a..74a88f2c18 100644 --- a/Libraries/LibWeb/Page/Frame.h +++ b/Libraries/LibWeb/Page/Frame.h @@ -30,9 +30,11 @@ #include <AK/Noncopyable.h> #include <AK/RefPtr.h> #include <AK/WeakPtr.h> +#include <LibCore/Timer.h> #include <LibGfx/Bitmap.h> #include <LibGfx/Rect.h> #include <LibGfx/Size.h> +#include <LibWeb/DOM/Position.h> #include <LibWeb/Loader/FrameLoader.h> #include <LibWeb/Page/EventHandler.h> #include <LibWeb/TreeNode.h> @@ -83,10 +85,17 @@ public: Gfx::IntPoint to_main_frame_position(const Gfx::IntPoint&); Gfx::IntRect to_main_frame_rect(const Gfx::IntRect&); + const DOM::Position& cursor_position() const { return m_cursor_position; } + void set_cursor_position(const DOM::Position&); + + bool cursor_blink_state() const { return m_cursor_blink_state; } + private: explicit Frame(DOM::Element& host_element, Frame& main_frame); explicit Frame(Page&); + void setup(); + Page& m_page; Frame& m_main_frame; @@ -97,6 +106,10 @@ private: RefPtr<DOM::Document> m_document; Gfx::IntSize m_size; Gfx::IntRect m_viewport_rect; + + DOM::Position m_cursor_position; + RefPtr<Core::Timer> m_cursor_blink_timer; + bool m_cursor_blink_state { false }; }; } |