aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den-exter@nokia.com>2012-03-29 16:34:09 +1000
committerQt by Nokia <qt-info@nokia.com>2012-04-02 10:45:55 +0200
commit368a3a736c8dbe945cd820b78523191522351494 (patch)
tree76299394a65073e52920b0d8114d8574b51ae249 /src/quick
parent9cddbbff9da88ba9c889ae1f306e837c3a66377e (diff)
Set cursorVisible to false when im cursor length is 0.
If the length of the QInputMethodEvent::Cursor attribute is 0 the cursor is supposed to be hidden. To ensure this and any other IM state is reverted when the input method is reset send a empty event to the editor when preedit is cancelled or removed and count formatting or cursor changes when determining if the input method is composing (i.e has state that needs to be reset). Change-Id: Ifca69aa0c18776b1aef355ed6ae9aecc40b9d475 Reviewed-by: Yann Bodson <yann.bodson@nokia.com>
Diffstat (limited to 'src/quick')
-rw-r--r--src/quick/items/qquicktextcontrol.cpp74
-rw-r--r--src/quick/items/qquicktextcontrol_p.h4
-rw-r--r--src/quick/items/qquicktextcontrol_p_p.h4
-rw-r--r--src/quick/items/qquicktextedit.cpp12
-rw-r--r--src/quick/items/qquicktextinput.cpp51
-rw-r--r--src/quick/items/qquicktextinput_p_p.h5
6 files changed, 112 insertions, 38 deletions
diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp
index eefe938467..739b5f859b 100644
--- a/src/quick/items/qquicktextcontrol.cpp
+++ b/src/quick/items/qquicktextcontrol.cpp
@@ -44,6 +44,7 @@
#ifndef QT_NO_TEXTCONTROL
+#include <qcoreapplication.h>
#include <qfont.h>
#include <qpainter.h>
#include <qevent.h>
@@ -107,11 +108,12 @@ QQuickTextControlPrivate::QQuickTextControlPrivate()
ignoreAutomaticScrollbarAdjustement(false),
overwriteMode(false),
acceptRichText(true),
- hideCursor(false),
+ cursorVisible(false),
hasFocus(false),
isEnabled(true),
hadSelectionOnMousePress(false),
- wordSelectionEnabled(false)
+ wordSelectionEnabled(false),
+ hasImState(false)
{}
bool QQuickTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e)
@@ -292,6 +294,8 @@ void QQuickTextControlPrivate::setContent(Qt::TextFormat format, const QString &
{
Q_Q(QQuickTextControl);
+ cancelPreedit();
+
// for use when called from setPlainText. we may want to re-use the currently
// set char format then.
const QTextCharFormat charFormatForInsertion = cursor.charFormat();
@@ -1441,13 +1445,16 @@ void QQuickTextControlPrivate::inputMethodEvent(QInputMethodEvent *e)
QList<QTextLayout::FormatRange> overrides;
const int oldPreeditCursor = preeditCursor;
preeditCursor = e->preeditString().length();
- hideCursor = false;
+ hasImState = !e->preeditString().isEmpty();
+ cursorVisible = true;
for (int i = 0; i < e->attributes().size(); ++i) {
const QInputMethodEvent::Attribute &a = e->attributes().at(i);
if (a.type == QInputMethodEvent::Cursor) {
+ hasImState = true;
preeditCursor = a.start;
- hideCursor = !a.length;
+ cursorVisible = a.length != 0;
} else if (a.type == QInputMethodEvent::TextFormat) {
+ hasImState = true;
QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
if (f.isValid()) {
QTextLayout::FormatRange o;
@@ -1514,6 +1521,37 @@ void QQuickTextControlPrivate::focusEvent(QFocusEvent *e)
}
}
+bool QQuickTextControl::hasImState() const
+{
+ Q_D(const QQuickTextControl);
+ return d->hasImState;
+}
+
+bool QQuickTextControl::cursorVisible() const
+{
+ Q_D(const QQuickTextControl);
+ return d->cursorVisible;
+}
+
+void QQuickTextControl::setCursorVisible(bool visible)
+{
+ Q_D(QQuickTextControl);
+ d->cursorVisible = visible;
+ d->setBlinkingCursorEnabled(d->cursorVisible
+ && (d->interactionFlags & (Qt::TextEditable | Qt::TextSelectableByKeyboard)));
+}
+
+QTextCursor QQuickTextControl::cursorForPosition(const QPointF &pos) const
+{
+ Q_D(const QQuickTextControl);
+ int cursorPos = hitTest(pos, Qt::FuzzyHit);
+ if (cursorPos == -1)
+ cursorPos = 0;
+ QTextCursor c(d->doc);
+ c.setPosition(cursorPos);
+ return c;
+}
+
QRectF QQuickTextControl::cursorRect(const QTextCursor &cursor) const
{
Q_D(const QQuickTextControl);
@@ -1727,21 +1765,31 @@ bool QQuickTextControlPrivate::isPreediting() const
void QQuickTextControlPrivate::commitPreedit()
{
- if (!isPreediting())
+ Q_Q(QQuickTextControl);
+
+ if (!hasImState)
return;
qApp->inputMethod()->commit();
- if (!isPreediting())
+ if (!hasImState)
return;
- cursor.beginEditBlock();
- preeditCursor = 0;
- QTextBlock block = cursor.block();
- QTextLayout *layout = block.layout();
- layout->setPreeditArea(-1, QString());
- layout->clearAdditionalFormats();
- cursor.endEditBlock();
+ QInputMethodEvent event;
+ QCoreApplication::sendEvent(q->parent(), &event);
+}
+
+void QQuickTextControlPrivate::cancelPreedit()
+{
+ Q_Q(QQuickTextControl);
+
+ if (!hasImState)
+ return;
+
+ qApp->inputMethod()->reset();
+
+ QInputMethodEvent event;
+ QCoreApplication::sendEvent(q->parent(), &event);
}
void QQuickTextControl::setTextInteractionFlags(Qt::TextInteractionFlags flags)
diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h
index 9e3fc90eb1..be3f7f7ccf 100644
--- a/src/quick/items/qquicktextcontrol_p.h
+++ b/src/quick/items/qquicktextcontrol_p.h
@@ -98,6 +98,10 @@ public:
QString toHtml() const;
#endif
+ bool hasImState() const;
+ bool cursorVisible() const;
+ void setCursorVisible(bool visible);
+ QTextCursor cursorForPosition(const QPointF &pos) const;
QRectF cursorRect(const QTextCursor &cursor) const;
QRectF cursorRect() const;
QRectF selectionRect(const QTextCursor &cursor) const;
diff --git a/src/quick/items/qquicktextcontrol_p_p.h b/src/quick/items/qquicktextcontrol_p_p.h
index c5a39cc759..3a10f007be 100644
--- a/src/quick/items/qquicktextcontrol_p_p.h
+++ b/src/quick/items/qquicktextcontrol_p_p.h
@@ -127,6 +127,7 @@ public:
bool isPreediting() const;
void commitPreedit();
+ void cancelPreedit();
QPointF trippleClickPoint;
QPointF mousePressPos;
@@ -155,11 +156,12 @@ public:
bool ignoreAutomaticScrollbarAdjustement : 1;
bool overwriteMode : 1;
bool acceptRichText : 1;
- bool hideCursor : 1; // used to hide the cursor in the preedit area
+ bool cursorVisible : 1; // used to hide the cursor in the preedit area
bool hasFocus : 1;
bool isEnabled : 1;
bool hadSelectionOnMousePress : 1;
bool wordSelectionEnabled : 1;
+ bool hasImState : 1;
void _q_copyLink();
void _q_updateBlock(const QTextBlock &);
diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp
index 4fa5233b9a..f727c54322 100644
--- a/src/quick/items/qquicktextedit.cpp
+++ b/src/quick/items/qquicktextedit.cpp
@@ -871,10 +871,9 @@ void QQuickTextEdit::setCursorVisible(bool on)
if (d->cursorVisible == on)
return;
d->cursorVisible = on;
- QFocusEvent focusEvent(on ? QEvent::FocusIn : QEvent::FocusOut);
if (!on && !d->persistentSelection)
d->control->setCursorIsFocusIndicator(true);
- d->control->processEvent(&focusEvent, QPointF(0, -d->yoff));
+ d->control->setCursorVisible(on);
emit cursorVisibleChanged(d->cursorVisible);
}
@@ -1536,15 +1535,18 @@ void QQuickTextEdit::inputMethodEvent(QInputMethodEvent *event)
Q_D(QQuickTextEdit);
const bool wasComposing = isInputMethodComposing();
d->control->processEvent(event, QPointF(0, -d->yoff));
+ setCursorVisible(d->control->cursorVisible());
if (wasComposing != isInputMethodComposing())
emit inputMethodComposingChanged();
}
void QQuickTextEdit::itemChange(ItemChange change, const ItemChangeData &value)
{
+ Q_D(QQuickTextEdit);
if (change == ItemActiveFocusHasChanged) {
setCursorVisible(value.boolValue); // ### refactor: focus handling && d->canvas && d->canvas->hasFocus());
-
+ QFocusEvent focusEvent(value.boolValue ? QEvent::FocusIn : QEvent::FocusOut);
+ d->control->processEvent(&focusEvent, QPointF(0, -d->yoff));
if (value.boolValue) {
q_updateAlignment();
connect(qApp->inputMethod(), SIGNAL(inputDirectionChanged(Qt::LayoutDirection)),
@@ -1729,9 +1731,7 @@ bool QQuickTextEdit::canRedo() const
bool QQuickTextEdit::isInputMethodComposing() const
{
Q_D(const QQuickTextEdit);
- if (QTextLayout *layout = d->control->textCursor().block().layout())
- return layout->preeditAreaText().length() > 0;
- return false;
+ return d->control->hasImState();
}
void QQuickTextEditPrivate::init()
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index ccd7ff1673..5aa01d27f3 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -45,6 +45,7 @@
#include <private/qqmlglobal_p.h>
+#include <QtCore/qcoreapplication.h>
#include <QtQml/qqmlinfo.h>
#include <QtGui/qevent.h>
#include <QTextBoundaryFinder>
@@ -124,8 +125,8 @@ void QQuickTextInput::setText(const QString &s)
Q_D(QQuickTextInput);
if (s == text())
return;
- if (d->composeMode())
- qApp->inputMethod()->reset();
+
+ d->cancelPreedit();
d->internalSetText(s, -1, false);
}
@@ -674,9 +675,7 @@ QRectF QQuickTextInput::cursorRectangle() const
{
Q_D(const QQuickTextInput);
- int c = d->m_cursor;
- if (d->m_preeditCursor != -1)
- c += d->m_preeditCursor;
+ int c = d->m_cursor + d->m_preeditCursor;
if (d->m_echoMode == NoEcho)
c = 0;
QTextLine l = d->m_textLayout.lineForTextPosition(c);
@@ -1398,7 +1397,7 @@ void QQuickTextInput::keyPressEvent(QKeyEvent* ev)
void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev)
{
Q_D(QQuickTextInput);
- const bool wasComposing = d->preeditAreaText().length() > 0;
+ const bool wasComposing = d->hasImState;
if (d->m_readOnly) {
ev->ignore();
} else {
@@ -1407,7 +1406,7 @@ void QQuickTextInput::inputMethodEvent(QInputMethodEvent *ev)
if (!ev->isAccepted())
QQuickImplicitSizeItem::inputMethodEvent(ev);
- if (wasComposing != (d->m_textLayout.preeditAreaText().length() > 0))
+ if (wasComposing != d->hasImState)
emit inputMethodComposingChanged();
}
@@ -2513,7 +2512,7 @@ void QQuickTextInput::itemChange(ItemChange change, const ItemChangeData &value)
bool QQuickTextInput::isInputMethodComposing() const
{
Q_D(const QQuickTextInput);
- return d->preeditAreaText().length() > 0;
+ return d->hasImState;
}
void QQuickTextInputPrivate::init()
@@ -2820,18 +2819,31 @@ void QQuickTextInputPrivate::paste(QClipboard::Mode clipboardMode)
*/
void QQuickTextInputPrivate::commitPreedit()
{
- if (!composeMode())
+ Q_Q(QQuickTextInput);
+
+ if (!hasImState)
return;
qApp->inputMethod()->commit();
- if (!composeMode())
+ if (!hasImState)
+ return;
+
+ QInputMethodEvent ev;
+ QCoreApplication::sendEvent(q, &ev);
+}
+
+void QQuickTextInputPrivate::cancelPreedit()
+{
+ Q_Q(QQuickTextInput);
+
+ if (!hasImState)
return;
- m_preeditCursor = 0;
- m_textLayout.setPreeditArea(-1, QString());
- m_textLayout.clearAdditionalFormats();
- updateLayout();
+ qApp->inputMethod()->reset();
+
+ QInputMethodEvent ev;
+ QCoreApplication::sendEvent(q, &ev);
}
/*!
@@ -3113,15 +3125,19 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
m_textLayout.setPreeditArea(m_cursor, event->preeditString());
#endif //QT_NO_IM
const int oldPreeditCursor = m_preeditCursor;
+ const bool oldCursorVisible = cursorVisible;
m_preeditCursor = event->preeditString().length();
- m_hideCursor = false;
+ hasImState = !event->preeditString().isEmpty();
+ cursorVisible = true;
QList<QTextLayout::FormatRange> formats;
for (int i = 0; i < event->attributes().size(); ++i) {
const QInputMethodEvent::Attribute &a = event->attributes().at(i);
if (a.type == QInputMethodEvent::Cursor) {
+ hasImState = true;
m_preeditCursor = a.start;
- m_hideCursor = !a.length;
+ cursorVisible = a.length != 0;
} else if (a.type == QInputMethodEvent::TextFormat) {
+ hasImState = true;
QTextCharFormat f = qvariant_cast<QTextFormat>(a.value).toCharFormat();
if (f.isValid()) {
QTextLayout::FormatRange o;
@@ -3144,6 +3160,9 @@ void QQuickTextInputPrivate::processInputMethodEvent(QInputMethodEvent *event)
if (isGettingInput)
finishChange(priorState);
+ if (cursorVisible != oldCursorVisible)
+ emit q->cursorVisibleChanged(cursorVisible);
+
if (selectionChange) {
emit q->selectionChanged();
q->updateInputMethod(Qt::ImCursorRectangle | Qt::ImAnchorPosition
diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h
index 74efdcf469..1bc2cf548b 100644
--- a/src/quick/items/qquicktextinput_p_p.h
+++ b/src/quick/items/qquicktextinput_p_p.h
@@ -115,7 +115,7 @@ public:
, selectPressed(false)
, textLayoutDirty(true)
, persistentSelection(false)
- , m_hideCursor(false)
+ , hasImState(false)
, m_separator(0)
, m_readOnly(0)
, m_textDirty(0)
@@ -245,7 +245,7 @@ public:
bool selectPressed:1;
bool textLayoutDirty:1;
bool persistentSelection:1;
- bool m_hideCursor : 1; // used to hide the m_cursor inside preedit areas
+ bool hasImState : 1;
bool m_separator : 1;
bool m_readOnly : 1;
bool m_textDirty : 1;
@@ -319,6 +319,7 @@ public:
#endif
void commitPreedit();
+ void cancelPreedit();
Qt::CursorMoveStyle cursorMoveStyle() const { return m_textLayout.cursorMoveStyle(); }
void setCursorMoveStyle(Qt::CursorMoveStyle style) { m_textLayout.setCursorMoveStyle(style); }