From 39286a50c32321981adb82ea47c93b7398b257d8 Mon Sep 17 00:00:00 2001
From: Simon Hausmann <simon.hausmann@digia.com>
Date: Mon, 25 Aug 2014 11:06:58 +0200
Subject: [PATCH] Fix cursor blinking for TextInput and TextEdit

Before commit fb339b21b8a24b835cea7a057c47b7c5ad80dd72 relied on the simple
transparent rectangle node to remain invisible. After that commit we used the
regular rectangle node, which doesn't seem to like toggling the color between
transparent and solid black and therefore the cursor was always visible.

As advised by Gunnar this patch implements a much simpler logic: When the
cursor is supposed to be invisible, we just don't create a scene graph node for
it anymore.

Change-Id: I7b0e173f6d37997559ee0911f37903efdb14847f
Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@digia.com>
Reviewed-by: Gunnar Sletta <gunnar@sletta.org>
---
 src/quick/items/qquicktextedit.cpp    | 14 +++++----
 src/quick/items/qquicktextinput.cpp   | 44 +++++----------------------
 src/quick/items/qquicktextinput_p_p.h |  2 --
 src/quick/items/qquicktextnode.cpp    |  8 +++++
 src/quick/items/qquicktextnode_p.h    |  1 +
 5 files changed, 25 insertions(+), 44 deletions(-)

diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index e8c2199076..aca7150ca2 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -153,8 +153,10 @@ namespace {
                 removeChildNode(cursorNode);
             delete cursorNode;
             cursorNode = newNode;
-            appendChildNode(cursorNode);
-            cursorNode->setFlag(QSGNode::OwnedByParent);
+            if (cursorNode) {
+                appendChildNode(cursorNode);
+                cursorNode->setFlag(QSGNode::OwnedByParent);
+            }
         }
 
         QSGRectangleNode *cursorNode;
@@ -1903,10 +1905,10 @@ QSGNode *QQuickTextEdit::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *
     }
 
     if (d->cursorComponent == 0 && !isReadOnly()) {
-        QColor color = (!d->cursorVisible || !d->control->cursorOn())
-                ? QColor(0, 0, 0, 0)
-                : d->color;
-        rootNode->resetCursorNode(d->sceneGraphContext()->createRectangleNode(cursorRectangle(), color));
+        QSGRectangleNode* cursor = 0;
+        if (d->cursorVisible && d->control->cursorOn())
+            cursor = d->sceneGraphContext()->createRectangleNode(cursorRectangle(), d->color);
+        rootNode->resetCursorNode(cursor);
     }
 
     return rootNode;
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index d3d4bde36b..c91b79dd34 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -1852,17 +1852,13 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
         node = new QQuickTextNode(this);
     d->textNode = node;
 
-    if (!d->textLayoutDirty && oldNode != 0) {
-        QSGRectangleNode *cursorNode = node->cursorNode();
-        if (cursorNode != 0 && !isReadOnly()) {
-            cursorNode->setRect(cursorRectangle());
+    const bool showCursor = !isReadOnly() && d->cursorItem == 0 && d->cursorVisible && (d->m_blinkStatus || d->m_blinkPeriod == 0);
 
-            if (!d->cursorVisible || d->cursorItem || (!d->m_blinkStatus && d->m_blinkPeriod > 0)) {
-                d->hideCursor();
-            } else {
-                d->showCursor();
-            }
-        }
+    if (!d->textLayoutDirty && oldNode != 0) {
+        if (showCursor)
+            node->setCursor(cursorRectangle(), d->color);
+        else
+            node->clearCursor();
     } else {
         node->setUseNativeRenderer(d->renderType == NativeRendering);
         node->deleteContent();
@@ -1890,14 +1886,8 @@ QSGNode *QQuickTextInput::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData
                                                                  // selection
         }
 
-        if (!isReadOnly() && d->cursorItem == 0) {
-            node->setCursor(cursorRectangle(), d->color);
-            if (!d->cursorVisible || (!d->m_blinkStatus && d->m_blinkPeriod > 0)) {
-                d->hideCursor();
-            } else {
-                d->showCursor();
-            }
-        }
+        if (showCursor)
+                node->setCursor(cursorRectangle(), d->color);
 
         d->textLayoutDirty = false;
     }
@@ -2696,24 +2686,6 @@ void QQuickTextInput::selectionChanged()
     }
 }
 
-void QQuickTextInputPrivate::showCursor()
-{
-    if (textNode != 0 && textNode->cursorNode() != 0) {
-        QSGRectangleNode *cursor = textNode->cursorNode();
-        cursor->setColor(color);
-        cursor->update();
-    }
-}
-
-void QQuickTextInputPrivate::hideCursor()
-{
-    if (textNode != 0 && textNode->cursorNode() != 0) {
-        QSGRectangleNode *cursor = textNode->cursorNode();
-        cursor->setColor(QColor(0, 0, 0, 0));
-        cursor->update();
-    }
-}
-
 QRectF QQuickTextInput::boundingRect() const
 {
     Q_D(const QQuickTextInput);
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 2caca45bce..7d9f3ff9ce 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -150,8 +150,6 @@ public:
 #ifndef QT_NO_IM
     Qt::InputMethodHints effectiveInputMethodHints() const;
 #endif
-    void hideCursor();
-    void showCursor();
     void handleFocusEvent(QFocusEvent *event);
 
     struct MaskInputData {
diff --git a/src/quick/items/qquicktextnode.cpp b/src/quick/items/qquicktextnode.cpp
index 964dd0d4a5..5f246682ec 100644
--- a/src/quick/items/qquicktextnode.cpp
+++ b/src/quick/items/qquicktextnode.cpp
@@ -179,6 +179,14 @@ void QQuickTextNode::setCursor(const QRectF &rect, const QColor &color)
     appendChildNode(m_cursorNode);
 }
 
+void QQuickTextNode::clearCursor()
+{
+    if (m_cursorNode)
+        removeChildNode(m_cursorNode);
+    delete m_cursorNode;
+    m_cursorNode = 0;
+}
+
 void QQuickTextNode::initEngine(const QColor& textColor, const QColor& selectedTextColor, const QColor& selectionColor, const QColor& anchorColor, const QPointF &position)
 {
     m_engine.reset(new QQuickTextNodeEngine);
diff --git a/src/quick/items/qquicktextnode_p.h b/src/quick/items/qquicktextnode_p.h
index fef17ae8e8..7f9cd77152 100644
--- a/src/quick/items/qquicktextnode_p.h
+++ b/src/quick/items/qquicktextnode_p.h
@@ -88,6 +88,7 @@ public:
                          int selectionStart = -1, int selectionEnd = -1);
 
     void setCursor(const QRectF &rect, const QColor &color);
+    void clearCursor();
     QSGRectangleNode *cursorNode() const { return m_cursorNode; }
 
     QSGGlyphNode *addGlyphs(const QPointF &position, const QGlyphRun &glyphs, const QColor &color,
-- 
GitLab