From a44bd2c94fcbba1797d2ee0d0d5f23c815db27e9 Mon Sep 17 00:00:00 2001 From: JavaZeroo <71128095+JavaZeroo@users.noreply.github.com> Date: Fri, 30 Oct 2026 12:15:15 +0800 Subject: [PATCH] fix(qt): measure the preedit, clear it on focus loss and keep rejected commits refs #155 The preview now uses the font advance instead of the QChar count, losing focus drops the composition, and a commit rejected by the bounded queue keeps its preview visible. --- src/qt/terminal_widget.hpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/qt/terminal_widget.hpp b/src/qt/terminal_widget.hpp index 875c5319..5d83e0c2 100644 --- a/src/qt/terminal_widget.hpp +++ b/src/qt/terminal_widget.hpp @@ -71,8 +71,12 @@ class TerminalWidget final : public QWidget { QWidget::closeEvent(event); } bool event(QEvent* event) override { - if (event->type() == QEvent::FocusOut || event->type() == QEvent::Hide) + if (event->type() == QEvent::FocusOut || event->type() == QEvent::Hide) { keyboard_.reset(); + // Losing focus ends any composition: the input context drops it, and + // keeping a stale preview would draw text the session never receives. + if (!preedit_.isEmpty()) { preedit_.clear(); update(); } + } // QWidget normally consumes Tab for focus traversal before keyPressEvent. if (event->type() == QEvent::KeyPress && static_cast(event)->key() == Qt::Key_Tab) { keyPressEvent(static_cast(event)); return event->isAccepted(); @@ -180,8 +184,9 @@ class TerminalWidget final : public QWidget { const QString commit = event->commitString(); if (!commit.isEmpty()) { ime_log("commit", commit); - model_.send(commit.toUtf8()); - preedit_.clear(); + // Keep the preview when the bounded input queue rejected the commit: + // the text stays visible instead of silently disappearing. + if (model_.send(commit.toUtf8())) preedit_.clear(); update(); } event->accept(); @@ -218,8 +223,11 @@ class TerminalWidget final : public QWidget { if (!preedit_.isEmpty()) { // Compose in place at the caret; the committed text is what reaches // the session, this preview is presentation only. + // Measure the preview instead of counting characters: a wide or + // combining preedit is not "one cell per QChar". + const QFontMetricsF compose_metrics(base_font); const QRectF area(margin + screen.column * cell_width_, margin + screen.row * cell_height_, - static_cast(cell_width_) * static_cast(preedit_.size()), + compose_metrics.horizontalAdvance(preedit_), static_cast(cell_height_)); auto compose_font = base_font; compose_font.setUnderline(true); painter.setFont(compose_font);