QLineEdit - made mouse interactions commit preedit
Simplifying input context mouse handling rules by making the editor in charge when text gets committed and selected. This includes: - Allowing selection to start on top of preedit. Commits once a single character gets selected - Double click to commit preedit before selecting a word. - Only sending events to input context that happen on top of preedit. - Committing preedit when a mouse press happens outside of it, allowing to move cursor to click position. Change-Id: I9dab00ea3445055ffd0d7cae540a1197c5748509 Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
This commit is contained in:
parent
10dc2171cf
commit
7851568c65
@ -1388,6 +1388,9 @@ bool QLineEdit::event(QEvent * e)
|
||||
void QLineEdit::mousePressEvent(QMouseEvent* e)
|
||||
{
|
||||
Q_D(QLineEdit);
|
||||
|
||||
d->mousePressPos = e->pos();
|
||||
|
||||
if (d->sendMouseEventToInputContext(e))
|
||||
return;
|
||||
if (e->button() == Qt::RightButton)
|
||||
@ -1410,7 +1413,6 @@ void QLineEdit::mousePressEvent(QMouseEvent* e)
|
||||
#ifndef QT_NO_DRAGANDDROP
|
||||
if (!mark && d->dragEnabled && d->control->echoMode() == Normal &&
|
||||
e->button() == Qt::LeftButton && d->control->inSelection(e->pos().x())) {
|
||||
d->dndPos = e->pos();
|
||||
if (!d->dndTimer.isActive())
|
||||
d->dndTimer.start(QApplication::startDragTime(), this);
|
||||
} else
|
||||
@ -1425,20 +1427,28 @@ void QLineEdit::mousePressEvent(QMouseEvent* e)
|
||||
void QLineEdit::mouseMoveEvent(QMouseEvent * e)
|
||||
{
|
||||
Q_D(QLineEdit);
|
||||
if (d->sendMouseEventToInputContext(e))
|
||||
return;
|
||||
|
||||
if (e->buttons() & Qt::LeftButton) {
|
||||
#ifndef QT_NO_DRAGANDDROP
|
||||
if (d->dndTimer.isActive()) {
|
||||
if ((d->dndPos - e->pos()).manhattanLength() > QApplication::startDragDistance())
|
||||
if ((d->mousePressPos - e->pos()).manhattanLength() > QApplication::startDragDistance())
|
||||
d->drag();
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
d->control->moveCursor(d->xToPos(e->pos().x()), true);
|
||||
if (d->control->composeMode()) {
|
||||
int startPos = d->xToPos(d->mousePressPos.x());
|
||||
int currentPos = d->xToPos(e->pos().x());
|
||||
if (startPos != currentPos)
|
||||
d->control->setSelection(startPos, currentPos - startPos);
|
||||
|
||||
} else {
|
||||
d->control->moveCursor(d->xToPos(e->pos().x()), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
d->sendMouseEventToInputContext(e);
|
||||
}
|
||||
|
||||
/*! \reimp
|
||||
@ -1478,12 +1488,43 @@ void QLineEdit::mouseReleaseEvent(QMouseEvent* e)
|
||||
void QLineEdit::mouseDoubleClickEvent(QMouseEvent* e)
|
||||
{
|
||||
Q_D(QLineEdit);
|
||||
if (d->sendMouseEventToInputContext(e))
|
||||
return;
|
||||
|
||||
if (e->button() == Qt::LeftButton) {
|
||||
d->control->selectWordAtPos(d->xToPos(e->pos().x()));
|
||||
int position = d->xToPos(e->pos().x());
|
||||
|
||||
// exit composition mode
|
||||
if (d->control->composeMode()) {
|
||||
int preeditPos = d->control->cursor();
|
||||
int posInPreedit = position - d->control->cursor();
|
||||
int preeditLength = d->control->preeditAreaText().length();
|
||||
bool positionOnPreedit = false;
|
||||
|
||||
if (posInPreedit >= 0 && posInPreedit <= preeditLength)
|
||||
positionOnPreedit = true;
|
||||
|
||||
int textLength = d->control->end();
|
||||
d->control->commitPreedit();
|
||||
int sizeChange = d->control->end() - textLength;
|
||||
|
||||
if (positionOnPreedit) {
|
||||
if (sizeChange == 0)
|
||||
position = -1; // cancel selection, word disappeared
|
||||
else
|
||||
// ensure not selecting after preedit if event happened there
|
||||
position = qBound(preeditPos, position, preeditPos + sizeChange);
|
||||
} else if (position > preeditPos) {
|
||||
// adjust positions after former preedit by how much text changed
|
||||
position += (sizeChange - preeditLength);
|
||||
}
|
||||
}
|
||||
|
||||
if (position >= 0)
|
||||
d->control->selectWordAtPos(position);
|
||||
|
||||
d->tripleClickTimer.start(QApplication::doubleClickInterval(), this);
|
||||
d->tripleClick = e->pos();
|
||||
} else {
|
||||
d->sendMouseEventToInputContext(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,19 +259,15 @@ bool QLineEditPrivate::sendMouseEventToInputContext( QMouseEvent *e )
|
||||
if ( control->composeMode() ) {
|
||||
int tmp_cursor = xToPos(e->pos().x());
|
||||
int mousePos = tmp_cursor - control->cursor();
|
||||
if ( mousePos < 0 || mousePos > control->preeditAreaText().length() ) {
|
||||
if ( mousePos < 0 || mousePos > control->preeditAreaText().length() )
|
||||
mousePos = -1;
|
||||
// don't send move events outside the preedit area
|
||||
if ( e->type() == QEvent::MouseMove )
|
||||
return true;
|
||||
}
|
||||
|
||||
QInputContext *qic = q->inputContext();
|
||||
if ( qic )
|
||||
if (qic && mousePos >= 0) {
|
||||
// may be causing reset() in some input methods
|
||||
qic->mouseHandler(mousePos, e);
|
||||
if (!control->preeditAreaText().isEmpty())
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
Q_UNUSED(e);
|
||||
|
@ -137,8 +137,8 @@ public:
|
||||
#ifndef QT_NO_COMPLETER
|
||||
void _q_completionHighlighted(QString);
|
||||
#endif
|
||||
QPoint mousePressPos;
|
||||
#ifndef QT_NO_DRAGANDDROP
|
||||
QPoint dndPos;
|
||||
QBasicTimer dndTimer;
|
||||
void drag();
|
||||
#endif
|
||||
|
@ -164,6 +164,31 @@ void QWidgetLineControl::paste(QClipboard::Mode clipboardMode)
|
||||
|
||||
#endif // !QT_NO_CLIPBOARD
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
Exits preedit mode and commits parts marked as tentative commit
|
||||
*/
|
||||
void QWidgetLineControl::commitPreedit()
|
||||
{
|
||||
if (!composeMode())
|
||||
return;
|
||||
|
||||
qApp->inputPanel()->reset();
|
||||
|
||||
if (!m_tentativeCommit.isEmpty()) {
|
||||
internalInsert(m_tentativeCommit);
|
||||
m_tentativeCommit.clear();
|
||||
finishChange(-1, true/*not used, not documented*/, false);
|
||||
}
|
||||
|
||||
m_preeditCursor = 0;
|
||||
setPreeditArea(-1, QString());
|
||||
m_textLayout.clearAdditionalFormats();
|
||||
updateDisplayText(/*force*/ true);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
\internal
|
||||
|
||||
@ -259,6 +284,8 @@ void QWidgetLineControl::clear()
|
||||
*/
|
||||
void QWidgetLineControl::setSelection(int start, int length)
|
||||
{
|
||||
commitPreedit();
|
||||
|
||||
if(start < 0 || start > (int)m_text.length()){
|
||||
qWarning("QWidgetLineControl::setSelection: Invalid start position");
|
||||
return;
|
||||
@ -394,6 +421,8 @@ bool QWidgetLineControl::fixup() // this function assumes that validate currentl
|
||||
*/
|
||||
void QWidgetLineControl::moveCursor(int pos, bool mark)
|
||||
{
|
||||
commitPreedit();
|
||||
|
||||
if (pos != m_cursor) {
|
||||
separate();
|
||||
if (m_maskData)
|
||||
|
@ -234,6 +234,7 @@ public:
|
||||
m_tentativeCommit.clear();
|
||||
internalSetText(txt, -1, false);
|
||||
}
|
||||
void commitPreedit();
|
||||
|
||||
QString displayText() const { return m_textLayout.text(); }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user