diff options
author | Daniel Bertalan <dani@danielbertalan.dev> | 2021-05-24 09:36:41 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-05-24 11:27:58 +0200 |
commit | 875a2cbb7150b036af343364a8bf2d07a97dd03d (patch) | |
tree | d87934aaf9c68fcb188b5bdd541ab3cf4ef8ccf5 /Userland/Libraries/LibVT/TerminalWidget.cpp | |
parent | 7dfc804d7d749203974fde1687b9c9c4d6442cea (diff) | |
download | serenity-875a2cbb7150b036af343364a8bf2d07a97dd03d.zip |
LibVT+Kernel: Add support for setting cursor styles
This commit introduces support for 3 new escape sequences:
1. Stop blinking cursor mode
2. `DECTCEM` mode (enable/disable cursor)
3. `DECSCUSR` (set cursor style)
`TerminalWidget` now supports the following cursor types: block,
underline and vertical bar. Each of these can blink or be steady.
`VirtualConsole` ignores these (just as we were doing before).
Diffstat (limited to 'Userland/Libraries/LibVT/TerminalWidget.cpp')
-rw-r--r-- | Userland/Libraries/LibVT/TerminalWidget.cpp | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/Userland/Libraries/LibVT/TerminalWidget.cpp b/Userland/Libraries/LibVT/TerminalWidget.cpp index dc3cc504a4..432ff28df2 100644 --- a/Userland/Libraries/LibVT/TerminalWidget.cpp +++ b/Userland/Libraries/LibVT/TerminalWidget.cpp @@ -326,6 +326,7 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event) for (size_t column = 0; column < line.length(); ++column) { bool should_reverse_fill_for_cursor_or_selection = m_cursor_blink_state + && (m_cursor_style == VT::CursorStyle::SteadyBlock || m_cursor_style == VT::CursorStyle::BlinkingBlock) && m_has_logical_focus && visual_row == row_with_cursor && column == m_terminal.cursor_column(); @@ -392,6 +393,7 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event) for (size_t column = 0; column < line.length(); ++column) { auto attribute = line.attribute_at(column); bool should_reverse_fill_for_cursor_or_selection = m_cursor_blink_state + && (m_cursor_style == VT::CursorStyle::SteadyBlock || m_cursor_style == VT::CursorStyle::BlinkingBlock) && m_has_logical_focus && visual_row == row_with_cursor && column == m_terminal.cursor_column(); @@ -417,11 +419,31 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event) } // Draw cursor. - if (!m_has_logical_focus && row_with_cursor < m_terminal.rows()) { + if (m_cursor_blink_state && row_with_cursor < m_terminal.rows()) { auto& cursor_line = m_terminal.line(first_row_from_history + row_with_cursor); - if (m_terminal.cursor_row() < (m_terminal.rows() - rows_from_history)) { - auto cell_rect = glyph_rect(row_with_cursor, m_terminal.cursor_column()).inflated(0, m_line_spacing); - painter.draw_rect(cell_rect, color_from_rgb(cursor_line.attribute_at(m_terminal.cursor_column()).effective_foreground_color())); + if (m_terminal.cursor_row() >= (m_terminal.rows() - rows_from_history)) + return; + + if (m_has_logical_focus && (m_cursor_style == VT::CursorStyle::BlinkingBlock || m_cursor_style == VT::CursorStyle::SteadyBlock)) + return; // This has already been handled by inverting the cell colors + + auto cursor_color = color_from_rgb(cursor_line.attribute_at(m_terminal.cursor_column()).effective_foreground_color()); + auto cell_rect = glyph_rect(row_with_cursor, m_terminal.cursor_column()).inflated(0, m_line_spacing); + if (m_cursor_style == VT::CursorStyle::BlinkingUnderline || m_cursor_style == VT::CursorStyle::SteadyUnderline) { + auto x1 = cell_rect.bottom_left().x(); + auto x2 = cell_rect.bottom_right().x(); + auto y = cell_rect.bottom_left().y(); + for (auto x = x1; x <= x2; ++x) + painter.set_pixel({ x, y }, cursor_color); + } else if (m_cursor_style == VT::CursorStyle::BlinkingBar || m_cursor_style == VT::CursorStyle::SteadyBar) { + auto x = cell_rect.bottom_left().x(); + auto y1 = cell_rect.top_left().y(); + auto y2 = cell_rect.bottom_left().y(); + for (auto y = y1; y <= y2; ++y) + painter.set_pixel({ x, y }, cursor_color); + } else { + // We fall back to a block if we don't support the selected cursor type. + painter.draw_rect(cell_rect, cursor_color); } } } @@ -986,6 +1008,32 @@ void TerminalWidget::emit(const u8* data, size_t size) } } +void TerminalWidget::set_cursor_style(CursorStyle style) +{ + switch (style) { + case None: + m_cursor_blink_timer->stop(); + m_cursor_blink_state = false; + break; + case SteadyBlock: + case SteadyUnderline: + case SteadyBar: + m_cursor_blink_timer->stop(); + m_cursor_blink_state = true; + break; + case BlinkingBlock: + case BlinkingUnderline: + case BlinkingBar: + m_cursor_blink_state = true; + m_cursor_blink_timer->restart(); + break; + default: + dbgln("Cursor style not implemented"); + } + m_cursor_style = style; + invalidate_cursor(); +} + void TerminalWidget::context_menu_event(GUI::ContextMenuEvent& event) { if (m_hovered_href_id.is_null()) { @@ -1107,5 +1155,4 @@ void TerminalWidget::set_font_and_resize_to_fit(const Gfx::Font& font) set_font(font); resize(widget_size_for_font(font)); } - } |