[LyX/2.5.x] Respond correctly to Qt::ImCursorRectangles when there exist no preedits

Koji Yokota <[email protected]> Sat, 04 Jul 2026 04:31:07 +0000
Newsgroups gmane.editors.lyx.cvs
Message-ID <[email protected]>
commit 9e567b589335159b24296dd71173f9092f9a4b62
Author: Koji Yokota <[email protected]>
Date:   Mon May 11 19:38:52 2026 +0900

    Respond correctly to Qt::ImCursorRectangles when there exist no preedits
    
    The input method query Qt::ImCursorRectangles can come in even when
    nothing is typed.
    
    Backports afa18782. Previous commit 1a09c517 is backporting 2a40e52
    by dependency.
---
 src/frontends/qt/GuiInputMethod.cpp | 53 +++++++++++++++++++++++++++----------
 1 file changed, 39 insertions(+), 14 deletions(-)

diff --git a/src/frontends/qt/GuiInputMethod.cpp b/src/frontends/qt/GuiInputMethod.cpp
index 27da8d6841..50e119b93a 100644
--- a/src/frontends/qt/GuiInputMethod.cpp
+++ b/src/frontends/qt/GuiInputMethod.cpp
@@ -15,6 +15,8 @@
 #include "GuiInputMethod.h"
 
 #include "Buffer.h"
+#include "BufferView.h"
+#include "CaretGeometry.h"
 #include "ColorCache.h"
 #include "Cursor.h"
 #include "CutAndPaste.h"
@@ -286,6 +288,11 @@ void GuiInputMethod::processPreedit(QInputMethodEvent* ev)
 	// if preedit string is not empty, we are still working on it
 	d->im_state_.preediting_ = d->preedit_str_.empty() ? false : true;
 
+	if (!d->im_state_.preediting_) {
+		d->im_state_.anchor_rect_ = QRectF();
+		d->im_state_.cursor_rect_ = QRectF();
+	}
+
 	// notify the completion to both im and app itself
 	Q_EMIT inputMethodStateChanged(Qt::ImQueryInput);
 	Q_EMIT preeditProcessed(ev);
@@ -930,21 +937,39 @@ QVariant GuiInputMethod::inputMethodQuery(Qt::InputMethodQuery query)
 	// this is the CJK-specific composition window position and
 	// the context menu position when the menu key is pressed.
 	case Qt::ImCursorRectangle: {
-		QRectF * rect;
-		if (d->im_state_.composing_mode_) {
-			// in the editing mode, cursor_rect_ follows the position of the
-			// virtual caret, but the drop down of predicted candidates wants
-			// the starting point of the preedit, so respond with anchor_rect_
-			// that points the starting point during the editing mode
-			rect = &d->im_state_.anchor_rect_;
-			LYXERR(Debug::DEBUG,
-			       "     (Composing mode: use anchor_rect_ for ImCursorRectangle)");
-		} else
-			rect = &d->im_state_.cursor_rect_;
+		if (d->im_state_.anchor_rect_.isNull()) {
+			// This is the case when the query came in before we have any
+			// preedit strings
+			QRectF rect;
+			CaretGeometry const & cg = d->buffer_view_->caretGeometry();
+			rect.setRect(cg.left, cg.top, cg.width(), cg.height());
+
+			LYXERR(Debug::KEY, msg << " x:" << rect.x() << " y:" << rect.y()
+				   << " w:" << rect.width() << " h:" << rect.height());
 
-		LYXERR(Debug::DEBUG, msg << " x:" << rect->x() << " y:" << rect->y()
-		       << " w:" << rect->width() << " h:" << rect->height());
-		return *rect;
+			return rect;
+		} else {
+			QRectF * rect_ptr;
+			if (d->im_state_.composing_mode_) {
+				// in the editing mode, cursor_rect_ follows the position of
+				// the virtual caret, but the drop down of predicted candidates
+				// wants the starting point of the preedit, so respond with
+				// anchor_rect_ that points the starting point during the
+				// editing mode
+				rect_ptr = &d->im_state_.anchor_rect_;
+			} else
+				rect_ptr = &d->im_state_.cursor_rect_;
+
+			LYXERR(Debug::KEY, msg << " x:" << rect_ptr->x() <<
+			       " y:" << rect_ptr->y() <<
+			       " w:" << rect_ptr->width() <<
+			       " h:" << rect_ptr->height());
+			if (d->im_state_.composing_mode_)
+				LYXERR(Debug::KEY, "     (Composing mode: use anchor_rect_"
+				       " for ImCursorRectangle)");
+
+			return *rect_ptr;
+		}
 		break;
 	}
 	case Qt::ImCurrentSelection: {
-- 
lyx-cvs mailing list
[email protected]
https://lists.lyx.org/mailman/listinfo/lyx-cvs