void QQuickTextInput::mouseDoubleClickEvent(QMouseEvent *event)
{
Q_D(QQuickTextInput);
- if (d->sendMouseEventToInputContext(event))
- return;
- if (d->selectByMouse) {
+
+ if (d->selectByMouse && event->button() == Qt::LeftButton) {
+ d->control->commitPreedit();
int cursor = d->xToPos(event->localPos().x());
d->control->selectWordAtPos(cursor);
event->setAccepted(true);
d->tripleClickTimer.start();
}
} else {
+ if (d->sendMouseEventToInputContext(event))
+ return;
QQuickImplicitSizeItem::mouseDoubleClickEvent(event);
}
}
void QQuickTextInput::mousePressEvent(QMouseEvent *event)
{
Q_D(QQuickTextInput);
- if (d->sendMouseEventToInputContext(event))
- return;
+
+ d->pressPos = event->localPos();
+
if (d->focusOnPress) {
bool hadActiveFocus = hasActiveFocus();
forceActiveFocus();
if (d->selectByMouse) {
setKeepMouseGrab(false);
d->selectPressed = true;
- d->pressPos = event->localPos();
QPoint distanceVector = d->pressPos.toPoint() - d->tripleClickStartPoint;
if (d->hasPendingTripleClick()
&& distanceVector.manhattanLength() < qApp->styleHints()->startDragDistance()) {
return;
}
}
+
+ if (d->sendMouseEventToInputContext(event))
+ return;
+
bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
int cursor = d->xToPos(event->localPos().x());
d->control->moveCursor(cursor, mark);
void QQuickTextInput::mouseMoveEvent(QMouseEvent *event)
{
Q_D(QQuickTextInput);
- if (d->sendMouseEventToInputContext(event))
- return;
+
if (d->selectPressed) {
if (qAbs(int(event->localPos().x() - d->pressPos.x())) > qApp->styleHints()->startDragDistance())
setKeepMouseGrab(true);
- moveCursorSelection(d->xToPos(event->localPos().x()), d->mouseSelectionMode);
+
+ if (d->control->composeMode()) {
+ // start selection
+ int startPos = d->xToPos(d->pressPos.x());
+ int currentPos = d->xToPos(event->localPos().x());
+ if (startPos != currentPos)
+ d->control->setSelection(startPos, currentPos - startPos);
+ } else {
+ moveCursorSelection(d->xToPos(event->localPos().x()), d->mouseSelectionMode);
+ }
event->setAccepted(true);
} else {
QQuickImplicitSizeItem::mouseMoveEvent(event);
bool QQuickTextInputPrivate::sendMouseEventToInputContext(QMouseEvent *event)
{
#if !defined QT_NO_IM
- if (control->composeMode() && event->type() == QEvent::MouseButtonRelease) {
+ if (control->composeMode()) {
int tmp_cursor = xToPos(event->localPos().x());
int mousePos = tmp_cursor - control->cursor();
- // may be causing reset() in some input methods
- qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
- if (!control->preeditAreaText().isEmpty())
+ if (mousePos >= 0 && mousePos <= control->preeditAreaText().length()) {
+ if (event->type() == QEvent::MouseButtonRelease) {
+ qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
+ }
return true;
+ }
}
#else
Q_UNUSED(event);
void QDeclarative1TextInput::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QDeclarative1TextInput);
- if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick))
- return;
- if (d->selectByMouse) {
+ if (d->selectByMouse && event->button() == Qt::LeftButton) {
int cursor = d->xToPos(event->pos().x());
d->control->selectWordAtPos(cursor);
event->setAccepted(true);
} else {
+ if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonDblClick))
+ return;
QDeclarative1PaintedItem::mouseDoubleClickEvent(event);
}
}
void QDeclarative1TextInput::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QDeclarative1TextInput);
- if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress))
- return;
+
+ d->pressPos = event->pos();
+
if(d->focusOnPress){
bool hadActiveFocus = hasActiveFocus();
forceActiveFocus();
if (d->selectByMouse) {
setKeepMouseGrab(false);
d->selectPressed = true;
- d->pressPos = event->pos();
}
+ if (d->sendMouseEventToInputContext(event, QEvent::MouseButtonPress))
+ return;
+
bool mark = (event->modifiers() & Qt::ShiftModifier) && d->selectByMouse;
int cursor = d->xToPos(event->pos().x());
d->control->moveCursor(cursor, mark);
void QDeclarative1TextInput::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QDeclarative1TextInput);
- if (d->sendMouseEventToInputContext(event, QEvent::MouseMove))
- return;
+
if (d->selectPressed) {
if (qAbs(int(event->pos().x() - d->pressPos.x())) > QApplication::startDragDistance())
setKeepMouseGrab(true);
- moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
+
+ if (d->control->composeMode()) {
+ // start selection
+ int startPos = d->xToPos(d->pressPos.x());
+ int currentPos = d->xToPos(event->pos().x());
+ if (startPos != currentPos)
+ d->control->setSelection(startPos, currentPos - startPos);
+ } else {
+ moveCursorSelection(d->xToPos(event->pos().x()), d->mouseSelectionMode);
+ }
event->setAccepted(true);
} else {
QDeclarative1PaintedItem::mouseMoveEvent(event);
if (event->widget() && control->composeMode()) {
int tmp_cursor = xToPos(event->pos().x());
int mousePos = tmp_cursor - control->cursor();
- if (mousePos < 0 || mousePos > control->preeditAreaText().length()) {
- mousePos = -1;
- // don't send move events outside the preedit area
- if (eventType == QEvent::MouseMove)
- return true;
- }
-
- QInputContext *qic = event->widget()->inputContext();
- if (qic) {
- QMouseEvent mouseEvent(
- eventType,
- event->widget()->mapFromGlobal(event->screenPos()),
- event->screenPos(),
- event->button(),
- event->buttons(),
- event->modifiers());
- // may be causing reset() in some input methods
- qic->mouseHandler(mousePos, &mouseEvent);
- event->setAccepted(mouseEvent.isAccepted());
- }
- if (!control->preeditAreaText().isEmpty())
+ if (mousePos >= 0 && mousePos <= control->preeditAreaText().length()) {
+ if (eventType == QEvent::MouseButtonRelease) {
+ qApp->inputPanel()->invokeAction(QInputPanel::Click, mousePos);
+ }
return true;
+ }
}
#else
Q_UNUSED(event);
#include <qtest.h>
#include <QtTest/QSignalSpy>
#include "../shared/util.h"
+#include <private/qinputpanel_p.h>
#include <QtDeclarative/qdeclarativeengine.h>
#include <QFile>
#include <QtDeclarative/qquickview.h>
private slots:
void initTestCase();
void cleanupTestCase();
+ void cleanup();
void text();
void width();
void font();
void preeditAutoScroll();
void preeditCursorRectangle();
+ void inputContextMouseHandler();
void inputMethodComposing();
void cursorRectangleSize();
QList<Key> &operator <<(QList<Key> &keys, const QKeySequence &sequence)
{
- for (int i = 0; i < sequence.count(); ++i)
+ for (uint i = 0; i < sequence.count(); ++i)
keys << Key(sequence[i], QChar());
return keys;
}
void tst_qquicktextinput::cleanupTestCase()
{
+}
+void tst_qquicktextinput::cleanup()
+{
+ // ensure not even skipped tests with custom input context leave it dangling
+ QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
+ inputPanelPrivate->testContext = 0;
}
+
tst_qquicktextinput::tst_qquicktextinput()
{
standard << "the quick brown fox jumped over the lazy dog"
class PlatformInputContext : public QPlatformInputContext
{
public:
- PlatformInputContext() : m_visible(false) {}
+ PlatformInputContext()
+ : m_visible(false), m_action(QInputPanel::Click), m_cursorPosition(0),
+ m_invokeActionCallCount(0)
+ {
+ }
virtual void showInputPanel()
{
{
return m_visible;
}
+ virtual void invokeAction(QInputPanel::Action action, int cursorPosition)
+ {
+ m_invokeActionCallCount++;
+ m_action = action;
+ m_cursorPosition = cursorPosition;
+ }
bool m_visible;
+ QInputPanel::Action m_action;
+ int m_cursorPosition;
+ int m_invokeActionCallCount;
};
void tst_qquicktextinput::openInputPanel()
// input panel should close when closeSoftwareInputPanel is called
input->closeSoftwareInputPanel();
QCOMPARE(qApp->inputPanel()->visible(), false);
-
- inputPanelPrivate->testContext = 0;
}
class MyTextInput : public QQuickTextInput
QVERIFY(panelSpy.count() > 0);
}
+void tst_qquicktextinput::inputContextMouseHandler()
+{
+ PlatformInputContext platformInputContext;
+ QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
+ inputPanelPrivate->testContext = &platformInputContext;
+
+ QString text = "supercalifragisiticexpialidocious!";
+ QQuickView view(QUrl::fromLocalFile(TESTDATA("inputContext.qml")));
+ QQuickTextInput *input = qobject_cast<QQuickTextInput *>(view.rootObject());
+ QVERIFY(input);
+
+ input->setFocus(true);
+ input->setText("");
+
+ view.show();
+ view.requestActivateWindow();
+ QTest::qWaitForWindowShown(&view);
+ QTRY_COMPARE(&view, qGuiApp->focusWindow());
+
+ QFontMetricsF fm(input->font());
+ const qreal y = fm.height() / 2;
+ QPoint position = QPointF(fm.width(text.mid(0, 2)), y).toPoint();
+
+ QInputMethodEvent inputEvent(text.mid(0, 5), QList<QInputMethodEvent::Attribute>());
+ QApplication::sendEvent(input, &inputEvent);
+
+ QTest::mousePress(&view, Qt::LeftButton, Qt::NoModifier, position);
+ QTest::mouseRelease(&view, Qt::LeftButton, Qt::NoModifier, position);
+ QGuiApplication::processEvents();
+
+ QCOMPARE(platformInputContext.m_action, QInputPanel::Click);
+ QCOMPARE(platformInputContext.m_invokeActionCallCount, 1);
+ QCOMPARE(platformInputContext.m_cursorPosition, 2);
+}
+
void tst_qquicktextinput::inputMethodComposing()
{
QString text = "supercalifragisiticexpialidocious!";
#include <QDir>
#include <QStyle>
#include <QInputContext>
-#include <QtWidgets/5.0.0/QtWidgets/private/qapplication_p.h>
+#include <private/qapplication_p.h>
+#include <private/qinputpanel_p.h>
#include "qplatformdefs.h"
return expectfile;
}
+class PlatformInputContext : public QPlatformInputContext
+{
+public:
+ PlatformInputContext()
+ : m_visible(false), m_action(QInputPanel::Click), m_cursorPosition(0),
+ m_invokeActionCallCount(0)
+ {
+ }
+
+ virtual void showInputPanel()
+ {
+ m_visible = true;
+ }
+ virtual void hideInputPanel()
+ {
+ m_visible = false;
+ }
+ virtual bool isInputPanelVisible() const
+ {
+ return m_visible;
+ }
+ virtual void invokeAction(QInputPanel::Action action, int cursorPosition)
+ {
+ m_invokeActionCallCount++;
+ m_action = action;
+ m_cursorPosition = cursorPosition;
+ }
+
+ bool m_visible;
+ QInputPanel::Action m_action;
+ int m_cursorPosition;
+ int m_invokeActionCallCount;
+};
+
+
class tst_qdeclarativetextinput : public QObject
{
tst_qdeclarativetextinput();
private slots:
+ void cleanup();
void text();
void width();
QStringList colorStrings;
};
+
tst_qdeclarativetextinput::tst_qdeclarativetextinput()
{
standard << "the quick brown fox jumped over the lazy dog"
<< "#2AC05F";
}
+void tst_qdeclarativetextinput::cleanup()
+{
+ // ensure not even skipped tests with custom input context leave it dangling
+ QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
+ inputPanelPrivate->testContext = 0;
+}
+
void tst_qdeclarativetextinput::text()
{
{
void tst_qdeclarativetextinput::inputContextMouseHandler()
{
+ PlatformInputContext platformInputContext;
+ QInputPanelPrivate *inputPanelPrivate = QInputPanelPrivate::get(qApp->inputPanel());
+ inputPanelPrivate->testContext = &platformInputContext;
+
QString text = "supercalifragisiticexpialidocious!";
QGraphicsScene scene;
QGraphicsView view(&scene);
- MyInputContext *ic = new MyInputContext;
- qApp->setInputContext(ic);
+
QDeclarative1TextInput input;
input.setWidth(200);
- input.setText(text.mid(0, 12));
input.setCursorPosition(12);
input.setPos(0, 0);
input.setFocus(true);
const qreal y = fm.height() / 2;
QPoint position2 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 2)), y)));
- QPoint position8 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 8)), y)));
- QPoint position20 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 20)), y)));
- QPoint position27 = view.mapFromScene(input.mapToScene(QPointF(fm.width(text.mid(0, 27)), y)));
- QPoint globalPosition2 = view.viewport()->mapToGlobal(position2);
- QPoint globalposition8 = view.viewport()->mapToGlobal(position8);
- QPoint globalposition20 = view.viewport()->mapToGlobal(position20);
- QPoint globalposition27 = view.viewport()->mapToGlobal(position27);
- ic->sendEvent(QInputMethodEvent(text.mid(12), QList<QInputMethodEvent::Attribute>()));
-
- QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
- QCOMPARE(ic->eventType, QEvent::MouseButtonDblClick);
- QCOMPARE(ic->eventPosition, position2);
- QCOMPARE(ic->eventGlobalPosition, globalPosition2);
- QCOMPARE(ic->eventButton, Qt::LeftButton);
- QCOMPARE(ic->eventModifiers, Qt::NoModifier);
- QVERIFY(ic->cursor < 0);
- ic->eventType = QEvent::None;
+ QInputMethodEvent inputEvent(text.mid(0, 5), QList<QInputMethodEvent::Attribute>());
+ QApplication::sendEvent(&view, &inputEvent);
QTest::mousePress(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
- QCOMPARE(ic->eventType, QEvent::MouseButtonPress);
- QCOMPARE(ic->eventPosition, position2);
- QCOMPARE(ic->eventGlobalPosition, globalPosition2);
- QCOMPARE(ic->eventButton, Qt::LeftButton);
- QCOMPARE(ic->eventModifiers, Qt::NoModifier);
- QVERIFY(ic->cursor < 0);
- ic->eventType = QEvent::None;
-
- { QMouseEvent mv(QEvent::MouseMove, position8, globalposition8, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QApplication::sendEvent(view.viewport(), &mv); }
- QCOMPARE(ic->eventType, QEvent::None);
-
- { QMouseEvent mv(QEvent::MouseMove, position27, globalposition27, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QApplication::sendEvent(view.viewport(), &mv); }
- QCOMPARE(ic->eventType, QEvent::MouseMove);
- QCOMPARE(ic->eventPosition, position27);
- QCOMPARE(ic->eventGlobalPosition, globalposition27);
- QCOMPARE(ic->eventButton, Qt::LeftButton);
- QCOMPARE(ic->eventModifiers, Qt::NoModifier);
- QVERIFY(ic->cursor >= 14 && ic->cursor <= 16); // 15 is expected but some platforms may be off by one.
- ic->eventType = QEvent::None;
-
- QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position27);
- QCOMPARE(ic->eventType, QEvent::MouseButtonRelease);
- QCOMPARE(ic->eventPosition, position27);
- QCOMPARE(ic->eventGlobalPosition, globalposition27);
- QCOMPARE(ic->eventButton, Qt::LeftButton);
- QCOMPARE(ic->eventModifiers, Qt::NoModifier);
- QVERIFY(ic->cursor >= 14 && ic->cursor <= 16);
- ic->eventType = QEvent::None;
-
- // And in the other direction.
- QTest::mouseDClick(view.viewport(), Qt::LeftButton, Qt::ControlModifier, position27);
- QCOMPARE(ic->eventType, QEvent::MouseButtonDblClick);
- QCOMPARE(ic->eventPosition, position27);
- QCOMPARE(ic->eventGlobalPosition, globalposition27);
- QCOMPARE(ic->eventButton, Qt::LeftButton);
- QCOMPARE(ic->eventModifiers, Qt::ControlModifier);
- QVERIFY(ic->cursor >= 14 && ic->cursor <= 16);
- ic->eventType = QEvent::None;
-
- QTest::mousePress(view.viewport(), Qt::RightButton, Qt::ControlModifier, position27);
- QCOMPARE(ic->eventType, QEvent::MouseButtonPress);
- QCOMPARE(ic->eventPosition, position27);
- QCOMPARE(ic->eventGlobalPosition, globalposition27);
- QCOMPARE(ic->eventButton, Qt::RightButton);
- QCOMPARE(ic->eventModifiers, Qt::ControlModifier);
- QVERIFY(ic->cursor >= 14 && ic->cursor <= 16);
- ic->eventType = QEvent::None;
-
- { QMouseEvent mv(QEvent::MouseMove, position20, globalposition20, Qt::RightButton, Qt::RightButton,Qt::ControlModifier);
- QApplication::sendEvent(view.viewport(), &mv); }
- QCOMPARE(ic->eventType, QEvent::MouseMove);
- QCOMPARE(ic->eventPosition, position20);
- QCOMPARE(ic->eventGlobalPosition, globalposition20);
- QCOMPARE(ic->eventButton, Qt::RightButton);
- QCOMPARE(ic->eventModifiers, Qt::ControlModifier);
- QVERIFY(ic->cursor >= 7 && ic->cursor <= 9);
- ic->eventType = QEvent::None;
-
- { QMouseEvent mv(QEvent::MouseMove, position2, globalPosition2, Qt::RightButton, Qt::RightButton,Qt::ControlModifier);
- QApplication::sendEvent(view.viewport(), &mv); }
- QCOMPARE(ic->eventType, QEvent::None);
-
- QTest::mouseRelease(view.viewport(), Qt::RightButton, Qt::ControlModifier, position2);
- QCOMPARE(ic->eventType, QEvent::MouseButtonRelease);
- QCOMPARE(ic->eventPosition, position2);
- QCOMPARE(ic->eventGlobalPosition, globalPosition2);
- QCOMPARE(ic->eventButton, Qt::RightButton);
- QCOMPARE(ic->eventModifiers, Qt::ControlModifier);
- QVERIFY(ic->cursor < 0);
- ic->eventType = QEvent::None;
+ QTest::mouseRelease(view.viewport(), Qt::LeftButton, Qt::NoModifier, position2);
+ QApplication::processEvents();
+
+ QCOMPARE(platformInputContext.m_action, QInputPanel::Click);
+ QCOMPARE(platformInputContext.m_invokeActionCallCount, 1);
+ QCOMPARE(platformInputContext.m_cursorPosition, 2);
}
void tst_qdeclarativetextinput::inputMethodComposing()