diff --git a/Kernel/TTY/VirtualConsole.cpp b/Kernel/TTY/VirtualConsole.cpp index 87e1b003e5c..fb39f196fd2 100644 --- a/Kernel/TTY/VirtualConsole.cpp +++ b/Kernel/TTY/VirtualConsole.cpp @@ -358,7 +358,12 @@ void VirtualConsole::emit(u8 const* data, size_t size) TTY::emit(data[i], true); } -void VirtualConsole::set_cursor_style(VT::CursorStyle) +void VirtualConsole::set_cursor_shape(VT::CursorShape) +{ + // Do nothing +} + +void VirtualConsole::set_cursor_blinking(bool) { // Do nothing } diff --git a/Kernel/TTY/VirtualConsole.h b/Kernel/TTY/VirtualConsole.h index 13a8add281a..ed4f307dff1 100644 --- a/Kernel/TTY/VirtualConsole.h +++ b/Kernel/TTY/VirtualConsole.h @@ -101,7 +101,8 @@ private: virtual void terminal_did_resize(u16 columns, u16 rows) override; virtual void terminal_history_changed(int) override; virtual void emit(u8 const*, size_t) override; - virtual void set_cursor_style(VT::CursorStyle) override; + virtual void set_cursor_shape(VT::CursorShape) override; + virtual void set_cursor_blinking(bool) override; // ^CharacterDevice virtual StringView class_name() const override { return "VirtualConsole"sv; } diff --git a/Userland/Libraries/LibVT/Terminal.cpp b/Userland/Libraries/LibVT/Terminal.cpp index 5eaacb682ef..26381c61919 100644 --- a/Userland/Libraries/LibVT/Terminal.cpp +++ b/Userland/Libraries/LibVT/Terminal.cpp @@ -61,32 +61,6 @@ void Terminal::alter_ansi_mode(bool should_set, Parameters params) void Terminal::alter_private_mode(bool should_set, Parameters params) { - auto steady_cursor_to_blinking = [](CursorStyle style) { - switch (style) { - case SteadyBar: - return BlinkingBar; - case SteadyBlock: - return BlinkingBlock; - case SteadyUnderline: - return BlinkingUnderline; - default: - return style; - } - }; - - auto blinking_cursor_to_steady = [](CursorStyle style) { - switch (style) { - case BlinkingBar: - return SteadyBar; - case BlinkingBlock: - return SteadyBlock; - case BlinkingUnderline: - return SteadyUnderline; - default: - return style; - } - }; - for (auto mode : params) { switch (mode) { case 1: @@ -105,23 +79,22 @@ void Terminal::alter_private_mode(bool should_set, Parameters params) case 12: if (should_set) { // Start blinking cursor - m_cursor_style = steady_cursor_to_blinking(m_cursor_style); + m_client.set_cursor_blinking(true); } else { // Stop blinking cursor - m_cursor_style = blinking_cursor_to_steady(m_cursor_style); + m_client.set_cursor_blinking(false); } - m_client.set_cursor_style(m_cursor_style); break; case 25: if (should_set) { // Show cursor - m_cursor_style = m_saved_cursor_style; - m_client.set_cursor_style(m_cursor_style); + m_cursor_shape = m_saved_cursor_shape; + m_client.set_cursor_shape(m_cursor_shape); } else { // Hide cursor - m_saved_cursor_style = m_cursor_style; - m_cursor_style = None; - m_client.set_cursor_style(None); + m_saved_cursor_shape = m_cursor_shape; + m_cursor_shape = VT::CursorShape::None; + m_client.set_cursor_shape(VT::CursorShape::None); } break; case 1047: @@ -674,22 +647,28 @@ void Terminal::DECSCUSR(Parameters params) style = params[0]; switch (style) { case 1: - m_client.set_cursor_style(BlinkingBlock); + m_client.set_cursor_shape(VT::CursorShape::Block); + m_client.set_cursor_blinking(true); break; case 2: - m_client.set_cursor_style(SteadyBlock); + m_client.set_cursor_shape(VT::CursorShape::Block); + m_client.set_cursor_blinking(false); break; case 3: - m_client.set_cursor_style(BlinkingUnderline); + m_client.set_cursor_shape(VT::CursorShape::Underline); + m_client.set_cursor_blinking(true); break; case 4: - m_client.set_cursor_style(SteadyUnderline); + m_client.set_cursor_shape(VT::CursorShape::Underline); + m_client.set_cursor_blinking(false); break; case 5: - m_client.set_cursor_style(BlinkingBar); + m_client.set_cursor_shape(VT::CursorShape::Bar); + m_client.set_cursor_blinking(true); break; case 6: - m_client.set_cursor_style(SteadyBar); + m_client.set_cursor_shape(VT::CursorShape::Bar); + m_client.set_cursor_blinking(false); break; default: dbgln("Unknown cursor style {}", style); diff --git a/Userland/Libraries/LibVT/Terminal.h b/Userland/Libraries/LibVT/Terminal.h index b3760b01064..65794d54e13 100644 --- a/Userland/Libraries/LibVT/Terminal.h +++ b/Userland/Libraries/LibVT/Terminal.h @@ -29,14 +29,11 @@ class VirtualConsole; namespace VT { -enum CursorStyle { +enum class CursorShape { None, - BlinkingBlock, - SteadyBlock, - BlinkingUnderline, - SteadyUnderline, - BlinkingBar, - SteadyBar + Block, + Underline, + Bar, }; enum CursorKeysMode { @@ -54,7 +51,8 @@ public: virtual void terminal_did_resize(u16 columns, u16 rows) = 0; virtual void terminal_history_changed(int delta) = 0; virtual void emit(u8 const*, size_t) = 0; - virtual void set_cursor_style(CursorStyle) = 0; + virtual void set_cursor_shape(CursorShape) = 0; + virtual void set_cursor_blinking(bool) = 0; }; class Terminal : public EscapeSequenceExecutor { @@ -428,8 +426,9 @@ protected: bool m_swallow_current { false }; bool m_stomp { false }; - CursorStyle m_cursor_style { BlinkingBlock }; - CursorStyle m_saved_cursor_style { BlinkingBlock }; + CursorShape m_cursor_shape { VT::CursorShape::Block }; + CursorShape m_saved_cursor_shape { VT::CursorShape::Block }; + bool m_cursor_is_blinking_set { true }; bool m_needs_bracketed_paste { false }; diff --git a/Userland/Libraries/LibVT/TerminalWidget.cpp b/Userland/Libraries/LibVT/TerminalWidget.cpp index 02fda4cb798..93faffd0226 100644 --- a/Userland/Libraries/LibVT/TerminalWidget.cpp +++ b/Userland/Libraries/LibVT/TerminalWidget.cpp @@ -170,7 +170,9 @@ void TerminalWidget::set_logical_focus(bool focus) m_has_logical_focus = focus; if (!m_has_logical_focus) { m_cursor_blink_timer->stop(); - } else { + m_cursor_blink_state = true; + } else if (m_cursor_is_blinking_set) { + m_cursor_blink_timer->stop(); m_cursor_blink_state = true; m_cursor_blink_timer->start(); } @@ -208,9 +210,11 @@ void TerminalWidget::keydown_event(GUI::KeyEvent& event) } // Reset timer so cursor doesn't blink while typing. - m_cursor_blink_timer->stop(); - m_cursor_blink_state = true; - m_cursor_blink_timer->start(); + if (m_cursor_is_blinking_set) { + m_cursor_blink_timer->stop(); + m_cursor_blink_state = true; + m_cursor_blink_timer->start(); + } if (event.key() == KeyCode::Key_PageUp && event.modifiers() == Mod_Shift) { m_scrollbar->decrease_slider_by(m_terminal.rows()); @@ -315,7 +319,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_cursor_shape == VT::CursorShape::Block && m_has_logical_focus && visual_row == row_with_cursor && column == m_terminal.cursor_column(); @@ -389,7 +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_cursor_shape == VT::CursorShape::Block && m_has_logical_focus && visual_row == row_with_cursor && column == m_terminal.cursor_column(); @@ -421,18 +425,18 @@ void TerminalWidget::paint_event(GUI::PaintEvent& event) 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)) + if (m_has_logical_focus && m_cursor_shape == VT::CursorShape::Block) return; // This has already been handled by inverting the cell colors auto cursor_color = terminal_color_to_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) { + if (m_cursor_shape == VT::CursorShape::Underline) { 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) { + } else if (m_cursor_shape == VT::CursorShape::Bar) { auto x = cell_rect.bottom_left().x(); auto y1 = cell_rect.top_left().y(); auto y2 = cell_rect.bottom_left().y(); @@ -1037,32 +1041,28 @@ void TerminalWidget::emit(u8 const* data, size_t size) } } -void TerminalWidget::set_cursor_style(CursorStyle style) +void TerminalWidget::set_cursor_blinking(bool blinking) { - switch (style) { - case None: - m_cursor_blink_timer->stop(); - m_cursor_blink_state = false; - break; - case SteadyBlock: - case SteadyUnderline: - case SteadyBar: + if (blinking) { m_cursor_blink_timer->stop(); m_cursor_blink_state = true; - break; - case BlinkingBlock: - case BlinkingUnderline: - case BlinkingBar: + m_cursor_blink_timer->start(); + m_cursor_is_blinking_set = true; + } else { + m_cursor_blink_timer->stop(); m_cursor_blink_state = true; - m_cursor_blink_timer->restart(); - break; - default: - dbgln("Cursor style not implemented"); + m_cursor_is_blinking_set = false; } - m_cursor_style = style; invalidate_cursor(); } +void TerminalWidget::set_cursor_shape(CursorShape shape) +{ + m_cursor_shape = shape; + invalidate_cursor(); + update(); +} + void TerminalWidget::context_menu_event(GUI::ContextMenuEvent& event) { if (m_hovered_href_id.is_null()) { @@ -1301,4 +1301,33 @@ void TerminalWidget::set_auto_scroll_direction(AutoScrollDirection direction) m_auto_scroll_timer->set_active(direction != AutoScrollDirection::None); } +Optional TerminalWidget::parse_cursor_shape(StringView cursor_shape_string) +{ + if (cursor_shape_string == "Block"sv) + return VT::CursorShape::Block; + + if (cursor_shape_string == "Underline"sv) + return VT::CursorShape::Underline; + + if (cursor_shape_string == "Bar"sv) + return VT::CursorShape::Bar; + + return {}; +} + +String TerminalWidget::stringify_cursor_shape(VT::CursorShape cursor_shape) +{ + switch (cursor_shape) { + case VT::CursorShape::Block: + return "Block"; + case VT::CursorShape::Underline: + return "Underline"; + case VT::CursorShape::Bar: + return "Bar"; + case VT::CursorShape::None: + return "None"; + } + VERIFY_NOT_REACHED(); +} + } diff --git a/Userland/Libraries/LibVT/TerminalWidget.h b/Userland/Libraries/LibVT/TerminalWidget.h index 99f3a852266..63de6617f60 100644 --- a/Userland/Libraries/LibVT/TerminalWidget.h +++ b/Userland/Libraries/LibVT/TerminalWidget.h @@ -96,6 +96,13 @@ public: void set_color_scheme(StringView); + VT::CursorShape cursor_shape() { return m_cursor_shape; } + virtual void set_cursor_blinking(bool) override; + virtual void set_cursor_shape(CursorShape) override; + + static Optional parse_cursor_shape(StringView); + static String stringify_cursor_shape(VT::CursorShape); + private: TerminalWidget(int ptm_fd, bool automatic_size_policy); @@ -124,7 +131,6 @@ private: virtual void terminal_did_resize(u16 columns, u16 rows) override; virtual void terminal_history_changed(int delta) override; virtual void emit(u8 const*, size_t) override; - virtual void set_cursor_style(CursorStyle) override; // ^GUI::Clipboard::ClipboardClient virtual void clipboard_content_did_change(String const&) override { update_paste_action(); } @@ -196,7 +202,8 @@ private: bool m_cursor_blink_state { true }; bool m_automatic_size_policy { false }; - VT::CursorStyle m_cursor_style { BlinkingBlock }; + VT::CursorShape m_cursor_shape { VT::CursorShape::Block }; + bool m_cursor_is_blinking_set { true }; enum class AutoScrollDirection { None,