diff --git a/src/gui/shell.cpp b/src/gui/shell.cpp index ee82a3291..adbe436fc 100644 --- a/src/gui/shell.cpp +++ b/src/gui/shell.cpp @@ -625,27 +625,6 @@ void Shell::handleModeChange(const QVariantList& opargs) const QString mode{ m_nvim->decode(opargs.at(0).toByteArray()) }; const uint64_t modeIndex{ opargs.at(1).toULongLong() }; - if (!m_cursor.IsStyleEnabled()) { - if (mode == "insert") { - m_cursor.SetColor({}); - m_cursor.SetStyle(Cursor::Shape::Vertical, 25); - m_cursor.SetTimer(0, 0, 0); - } - else if (mode == "replace") { - m_cursor.SetColor({}); - m_cursor.SetStyle(Cursor::Shape::Horizontal, 20); - m_cursor.SetTimer(0, 0, 0); - } - else { - m_cursor.SetColor({}); - m_cursor.SetStyle(Cursor::Shape::Block, 100); - m_cursor.SetTimer(0, 0, 0); - } - - update(neovimCursorRect()); - return; - } - const uint32_t sizeModeInfo{ static_cast(m_modeInfo.size()) }; if (modeIndex >= sizeModeInfo) { return; @@ -705,7 +684,19 @@ void Shell::handleModeChange(const QVariantList& opargs) m_cursor.SetStyle(cursorShape, cellPercentage); m_cursor.SetTimer(blinkWaitTime, blinkOnTime, blinkOffTime); - update(neovimCursorRect()); + auto old = m_insertMode; + + // TODO: Implement visual aids for other modes + if (mode == "insert") { + m_insertMode = true; + } else { + m_insertMode = false; + } + + // redraw the cursor + if (old != m_insertMode) { + update(neovimCursorRect()); + } } void Shell::handleModeInfoSet(const QVariantList& opargs) @@ -728,7 +719,7 @@ void Shell::handleModeInfoSet(const QVariantList& opargs) return; } - m_cursor.SetIsStyleEnabled(cursor_style_enabled); + m_cursor.SetIsEnabled(cursor_style_enabled); m_modeInfo = mode_info.at(0).toList(); } @@ -1105,7 +1096,36 @@ void Shell::paintEvent(QPaintEvent *ev) return; } + // Option guicursor can be disabled with `:set guicursor=`. + if (m_cursor.IsEnabled()) + { + ShellWidget::paintEvent(ev); + return; + } + ShellWidget::paintEvent(ev); + + // paint cursor - we are not actually using Neovim colors yet, + // just invert the shell colors by painting white with XoR + if (!m_neovimBusy && ev->region().contains(neovimCursorTopLeft())) { + bool wide = contents().constValue(m_cursor_pos.y(), + m_cursor_pos.x()).IsDoubleWidth(); + QRect cursorRect(neovimCursorTopLeft(), cellSize()); + + if (m_insertMode) { + cursorRect.setWidth(2); + } else if (wide) { + cursorRect.setWidth(cursorRect.width()*2); + } + QPainter painter(this); + painter.setPen(m_cursor_color); + painter.setCompositionMode(QPainter::RasterOp_SourceXorDestination); + if (hasFocus()) { + painter.fillRect(cursorRect, m_cursor_color); + } else { + painter.drawRect(cursorRect); + } + } } void Shell::keyPressEvent(QKeyEvent *ev) diff --git a/src/gui/shell.h b/src/gui/shell.h index 259dabef2..b01ba8cbd 100644 --- a/src/gui/shell.h +++ b/src/gui/shell.h @@ -175,6 +175,7 @@ private slots: QColor m_hg_foreground{ Qt::black }; QColor m_hg_background{ Qt:: white }; QColor m_hg_special; + QColor m_cursor_color{ Qt::white }; /// Modern 'ext_linegrid' highlight definition map QMap m_highlightMap; @@ -182,6 +183,7 @@ private slots: /// Neovim mode descriptions from "mode_change", used by guicursor QVariantList m_modeInfo; + bool m_insertMode{ false }; bool m_resizing{ false }; QSize m_resize_neovim_pending; QLabel* m_tooltip{ nullptr }; diff --git a/src/gui/shellwidget/cursor.h b/src/gui/shellwidget/cursor.h index abdaee7d9..a68fb9f20 100644 --- a/src/gui/shellwidget/cursor.h +++ b/src/gui/shellwidget/cursor.h @@ -41,7 +41,7 @@ class Cursor : public QObject m_percentage = cellPercentage; } - void SetIsStyleEnabled(bool isStyleEnabled) noexcept + void SetIsEnabled(bool isStyleEnabled) noexcept { m_styleEnabled = isStyleEnabled; } @@ -51,14 +51,14 @@ class Cursor : public QObject m_isBusy = isBusy; } - bool IsStyleEnabled() const noexcept + bool IsEnabled() const noexcept { return m_styleEnabled && !m_isBusy; } bool IsVisible() const noexcept { - return !m_isBusy && m_blinkState != BlinkState::Off; + return IsEnabled() && (m_blinkState != BlinkState::Off); } QColor GetBackgroundColor() const noexcept