Fix QQuickTextInput::moveCursorSelection()
[profile/ivi/qtdeclarative.git] / tests / auto / quick / qquicktextinput / tst_qquicktextinput.cpp
index 3bdaf2e..249755b 100644 (file)
@@ -1,38 +1,38 @@
 /****************************************************************************
 **
-** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
 **
 ** This file is part of the test suite of the Qt Toolkit.
 **
 ** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.  For licensing terms and
+** conditions see http://qt.digia.com/licensing.  For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
 ** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 **
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
+** In addition, as a special exception, Digia gives you certain additional
+** rights.  These rights are described in the Digia Qt LGPL Exception
 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 **
 ** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
 **
 **
 ** $QT_END_LICENSE$
@@ -61,6 +61,7 @@
 #endif
 
 #include "qplatformdefs.h"
+#include "../../shared/platformquirks.h"
 #include "../../shared/platforminputcontext.h"
 
 #define SERVER_PORT 14460
@@ -126,10 +127,11 @@ private slots:
     void dragMouseSelection();
     void mouseSelectionMode_data();
     void mouseSelectionMode();
+    void mouseSelectionMode_accessors();
+    void selectByMouse();
+    void renderType();
     void tripleClickSelectsAll();
 
-    void horizontalAlignment_data();
-    void horizontalAlignment();
     void horizontalAlignment_RightToLeft();
     void verticalAlignment();
 
@@ -152,10 +154,13 @@ private slots:
     void cursorRectangle();
     void navigation();
     void navigation_RTL();
+#ifndef QT_NO_CLIPBOARD
     void copyAndPaste();
     void copyAndPasteKeySequence();
     void canPasteEmpty();
     void canPaste();
+    void middleClickPaste();
+#endif
     void readOnly();
     void focusOnPress();
 
@@ -468,6 +473,57 @@ void tst_qquicktextinput::font()
 
 void tst_qquicktextinput::color()
 {
+    //test initial color
+    {
+        QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello World\" }";
+        QQmlComponent texteditComponent(&engine);
+        texteditComponent.setData(componentStr.toLatin1(), QUrl());
+        QScopedPointer<QObject> object(texteditComponent.create());
+        QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput*>(object.data());
+
+        QVERIFY(textInputObject);
+        QCOMPARE(textInputObject->color(), QColor("black"));
+        QCOMPARE(textInputObject->selectionColor(), QColor::fromRgba(0xFF000080));
+        QCOMPARE(textInputObject->selectedTextColor(), QColor("white"));
+
+        QSignalSpy colorSpy(textInputObject, SIGNAL(colorChanged()));
+        QSignalSpy selectionColorSpy(textInputObject, SIGNAL(selectionColorChanged()));
+        QSignalSpy selectedTextColorSpy(textInputObject, SIGNAL(selectedTextColorChanged()));
+
+        textInputObject->setColor(QColor("white"));
+        QCOMPARE(textInputObject->color(), QColor("white"));
+        QCOMPARE(colorSpy.count(), 1);
+
+        textInputObject->setSelectionColor(QColor("black"));
+        QCOMPARE(textInputObject->selectionColor(), QColor("black"));
+        QCOMPARE(selectionColorSpy.count(), 1);
+
+        textInputObject->setSelectedTextColor(QColor("blue"));
+        QCOMPARE(textInputObject->selectedTextColor(), QColor("blue"));
+        QCOMPARE(selectedTextColorSpy.count(), 1);
+
+        textInputObject->setColor(QColor("white"));
+        QCOMPARE(colorSpy.count(), 1);
+
+        textInputObject->setSelectionColor(QColor("black"));
+        QCOMPARE(selectionColorSpy.count(), 1);
+
+        textInputObject->setSelectedTextColor(QColor("blue"));
+        QCOMPARE(selectedTextColorSpy.count(), 1);
+
+        textInputObject->setColor(QColor("black"));
+        QCOMPARE(textInputObject->color(), QColor("black"));
+        QCOMPARE(colorSpy.count(), 2);
+
+        textInputObject->setSelectionColor(QColor("blue"));
+        QCOMPARE(textInputObject->selectionColor(), QColor("blue"));
+        QCOMPARE(selectionColorSpy.count(), 2);
+
+        textInputObject->setSelectedTextColor(QColor("white"));
+        QCOMPARE(textInputObject->selectedTextColor(), QColor("white"));
+        QCOMPARE(selectedTextColorSpy.count(), 2);
+    }
+
     //test color
     for (int i = 0; i < colorStrings.size(); i++)
     {
@@ -557,6 +613,29 @@ void tst_qquicktextinput::wrap()
 
         delete textObject;
     }
+
+    {
+        QQmlComponent component(&engine);
+        component.setData("import QtQuick 2.0\n TextInput {}", QUrl());
+        QScopedPointer<QObject> object(component.create());
+        QQuickTextInput *input = qobject_cast<QQuickTextInput *>(object.data());
+        QVERIFY(input);
+
+        QSignalSpy spy(input, SIGNAL(wrapModeChanged()));
+
+        QCOMPARE(input->wrapMode(), QQuickTextInput::NoWrap);
+
+        input->setWrapMode(QQuickTextInput::Wrap);
+        QCOMPARE(input->wrapMode(), QQuickTextInput::Wrap);
+        QCOMPARE(spy.count(), 1);
+
+        input->setWrapMode(QQuickTextInput::Wrap);
+        QCOMPARE(spy.count(), 1);
+
+        input->setWrapMode(QQuickTextInput::NoWrap);
+        QCOMPARE(input->wrapMode(), QQuickTextInput::NoWrap);
+        QCOMPARE(spy.count(), 2);
+    }
 }
 
 void tst_qquicktextinput::selection()
@@ -832,10 +911,12 @@ void tst_qquicktextinput::moveCursorSelection_data()
     QTest::newRow("jum<()>ped|words")
             << standard[0] << 23 << 23 << QQuickTextInput::SelectWords << 23 << 23 << true;
 
-    QTest::newRow("Hello<(,)> |words")
-            << standard[2] << 5 << 6 << QQuickTextInput::SelectWords << 5 << 6 << true;
-    QTest::newRow("Hello<(, )>world|words,ltr")
-            << standard[2] << 5 << 7 << QQuickTextInput::SelectWords << 5 << 7 << false;
+    QTest::newRow("<Hello(,)> |words,ltr")
+            << standard[2] << 5 << 6 << QQuickTextInput::SelectWords << 0 << 6 << false;
+    QTest::newRow("Hello<(,)> |words,rtl")
+            << standard[2] << 6 << 5 << QQuickTextInput::SelectWords << 5 << 6 << false;
+    QTest::newRow("<Hello(, )>world|words,ltr")
+            << standard[2] << 5 << 7 << QQuickTextInput::SelectWords << 0 << 7 << false;
     QTest::newRow("Hello<(, )world>|words,rtl")
             << standard[2] << 7 << 5 << QQuickTextInput::SelectWords << 5 << 12 << false;
     QTest::newRow("<Hel(lo, )>world|words,ltr")
@@ -848,35 +929,35 @@ void tst_qquicktextinput::moveCursorSelection_data()
             << standard[2] << 5 << 5 << QQuickTextInput::SelectWords << 5 << 5 << true;
     QTest::newRow("Hello,<()>|words")
             << standard[2] << 6 << 6 << QQuickTextInput::SelectWords << 6 << 6 << true;
-    QTest::newRow("Hello<,( )>world|words,ltr")
-            << standard[2] << 6 << 7 << QQuickTextInput::SelectWords << 5 << 7 << false;
+    QTest::newRow("Hello,<( )>world|words,ltr")
+            << standard[2] << 6 << 7 << QQuickTextInput::SelectWords << 6 << 7 << false;
     QTest::newRow("Hello,<( )world>|words,rtl")
             << standard[2] << 7 << 6 << QQuickTextInput::SelectWords << 6 << 12 << false;
-    QTest::newRow("Hello<,( world)>|words,ltr")
-            << standard[2] << 6 << 12 << QQuickTextInput::SelectWords << 5 << 12 << false;
-    QTest::newRow("Hello,<( world)>|words,rtl")
-            << standard[2] << 12 << 6 << QQuickTextInput::SelectWords << 6 << 12 << false;
-    QTest::newRow("Hello<,( world!)>|words,ltr")
-            << standard[2] << 6 << 13 << QQuickTextInput::SelectWords << 5 << 13 << false;
-    QTest::newRow("Hello,<( world!)>|words,rtl")
-            << standard[2] << 13 << 6 << QQuickTextInput::SelectWords << 6 << 13 << false;
-    QTest::newRow("Hello<(, world!)>|words")
-            << standard[2] << 5 << 13 << QQuickTextInput::SelectWords << 5 << 13 << true;
-    // Fails due to an issue with QTextBoundaryFinder and punctuation at the end of strings.
-    // QTBUG-11365
-    // QTest::newRow("world<(!)>|words")
-    //         << standard[2] << 12 << 13 << QQuickTextInput::SelectWords << 12 << 13 << true;
+    QTest::newRow("Hello,<( world)>|words")
+            << standard[2] << 6 << 12 << QQuickTextInput::SelectWords << 6 << 12 << true;
+    QTest::newRow("Hello,<( world!)>|words")
+            << standard[2] << 6 << 13 << QQuickTextInput::SelectWords << 6 << 13 << true;
+    QTest::newRow("<Hello(, world!)>|words,ltr")
+            << standard[2] << 5 << 13 << QQuickTextInput::SelectWords << 0 << 13 << false;
+    QTest::newRow("Hello<(, world!)>|words,rtl")
+            << standard[2] << 13 << 5 << QQuickTextInput::SelectWords << 5 << 13 << false;
+    QTest::newRow("<world(!)>|words,ltr")
+            << standard[2] << 12 << 13 << QQuickTextInput::SelectWords << 7 << 13 << false;
+    QTest::newRow("world<(!)>|words,rtl")
+            << standard[2] << 13 << 12 << QQuickTextInput::SelectWords << 12 << 13 << false;
     QTest::newRow("world!<()>)|words")
             << standard[2] << 13 << 13 << QQuickTextInput::SelectWords << 13 << 13 << true;
     QTest::newRow("world<()>!)|words")
             << standard[2] << 12 << 12 << QQuickTextInput::SelectWords << 12 << 12 << true;
 
-    QTest::newRow("<(,)>olleH |words")
-            << standard[3] << 7 << 8 << QQuickTextInput::SelectWords << 7 << 8 << true;
+    QTest::newRow("<(,)>olleH |words,ltr")
+            << standard[3] << 7 << 8 << QQuickTextInput::SelectWords << 7 << 8 << false;
+    QTest::newRow("<(,)olleH> |words,rtl")
+            << standard[3] << 8 << 7 << QQuickTextInput::SelectWords << 7 << 13 << false;
     QTest::newRow("<dlrow( ,)>olleH|words,ltr")
             << standard[3] << 6 << 8 << QQuickTextInput::SelectWords << 1 << 8 << false;
-    QTest::newRow("dlrow<( ,)>olleH|words,rtl")
-            << standard[3] << 8 << 6 << QQuickTextInput::SelectWords << 6 << 8 << false;
+    QTest::newRow("dlrow<( ,)olleH>|words,rtl")
+            << standard[3] << 8 << 6 << QQuickTextInput::SelectWords << 6 << 13 << false;
     QTest::newRow("<dlrow( ,ol)leH>|words,ltr")
             << standard[3] << 6 << 10 << QQuickTextInput::SelectWords << 1 << 13 << false;
     QTest::newRow("dlrow<( ,ol)leH>|words,rtl")
@@ -889,20 +970,20 @@ void tst_qquicktextinput::moveCursorSelection_data()
             << standard[3] << 7 << 7 << QQuickTextInput::SelectWords << 7 << 7 << true;
     QTest::newRow("<dlrow( )>,olleH|words,ltr")
             << standard[3] << 6 << 7 << QQuickTextInput::SelectWords << 1 << 7 << false;
-    QTest::newRow("dlrow<( ),>olleH|words,rtl")
-            << standard[3] << 7 << 6 << QQuickTextInput::SelectWords << 6 << 8 << false;
-    QTest::newRow("<(dlrow )>,olleH|words,ltr")
-            << standard[3] << 1 << 7 << QQuickTextInput::SelectWords << 1 << 7 << false;
-    QTest::newRow("<(dlrow ),>olleH|words,rtl")
-            << standard[3] << 7 << 1 << QQuickTextInput::SelectWords << 1 << 8 << false;
-    QTest::newRow("<(!dlrow )>,olleH|words,ltr")
-            << standard[3] << 0 << 7 << QQuickTextInput::SelectWords << 0 << 7 << false;
-    QTest::newRow("<(!dlrow ),>olleH|words,rtl")
-            << standard[3] << 7 << 0 << QQuickTextInput::SelectWords << 0 << 8 << false;
-    QTest::newRow("(!dlrow ,)olleH|words")
-            << standard[3] << 0 << 8 << QQuickTextInput::SelectWords << 0 << 8 << true;
-    QTest::newRow("<(!)>dlrow|words")
-            << standard[3] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 1 << true;
+    QTest::newRow("dlrow<( )>,olleH|words,rtl")
+            << standard[3] << 7 << 6 << QQuickTextInput::SelectWords << 6 << 7 << false;
+    QTest::newRow("<(dlrow )>,olleH|words")
+            << standard[3] << 1 << 7 << QQuickTextInput::SelectWords << 1 << 7 << true;
+    QTest::newRow("<(!dlrow )>,olleH|words")
+            << standard[3] << 0 << 7 << QQuickTextInput::SelectWords << 0 << 7 << true;
+    QTest::newRow("<(!dlrow ,)>olleH|words,ltr")
+            << standard[3] << 0 << 8 << QQuickTextInput::SelectWords << 0 << 8 << false;
+    QTest::newRow("<(!dlrow ,)olleH>|words,rtl")
+            << standard[3] << 8 << 0 << QQuickTextInput::SelectWords << 0 << 13 << false;
+    QTest::newRow("<(!)>dlrow|words,ltr")
+            << standard[3] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 1 << false;
+    QTest::newRow("<(!)dlrow|words,rtl")
+            << standard[3] << 1 << 0 << QQuickTextInput::SelectWords << 0 << 6 << false;
     QTest::newRow("<()>!dlrow|words")
             << standard[3] << 0 << 0 << QQuickTextInput::SelectWords << 0 << 0 << true;
     QTest::newRow("!<()>dlrow|words")
@@ -911,16 +992,15 @@ void tst_qquicktextinput::moveCursorSelection_data()
     QTest::newRow(" <s(pac)ey>   text |words")
             << standard[4] << 1 << 4 << QQuickTextInput::SelectWords << 1 << 7 << true;
     QTest::newRow(" spacey   <t(ex)t> |words")
-            << standard[4] << 11 << 13 << QQuickTextInput::SelectWords << 10 << 14 << false; // Should be reversible. QTBUG-11365
+            << standard[4] << 11 << 13 << QQuickTextInput::SelectWords << 10 << 14 << true;
     QTest::newRow("<( )>spacey   text |words|ltr")
             << standard[4] << 0 << 1 << QQuickTextInput::SelectWords << 0 << 1 << false;
     QTest::newRow("<( )spacey>   text |words|rtl")
             << standard[4] << 1 << 0 << QQuickTextInput::SelectWords << 0 << 7 << false;
     QTest::newRow("spacey   <text( )>|words|ltr")
             << standard[4] << 14 << 15 << QQuickTextInput::SelectWords << 10 << 15 << false;
-//    QTBUG-11365
-//    QTest::newRow("spacey   text<( )>|words|rtl")
-//            << standard[4] << 15 << 14 << QQuickTextInput::SelectWords << 14 << 15 << false;
+    QTest::newRow("spacey   text<( )>|words|rtl")
+            << standard[4] << 15 << 14 << QQuickTextInput::SelectWords << 14 << 15 << false;
     QTest::newRow("<()> spacey   text |words")
             << standard[4] << 0 << 0 << QQuickTextInput::SelectWords << 0 << 0 << false;
     QTest::newRow(" spacey   text <()>|words")
@@ -1262,38 +1342,78 @@ void tst_qquicktextinput::mouseSelectionMode()
     }
 }
 
-void tst_qquicktextinput::horizontalAlignment_data()
+void tst_qquicktextinput::mouseSelectionMode_accessors()
 {
-    QTest::addColumn<int>("hAlign");
-    QTest::addColumn<QString>("expectfile");
+    QQmlComponent component(&engine);
+    component.setData("import QtQuick 2.0\n TextInput {}", QUrl());
+    QScopedPointer<QObject> object(component.create());
+    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(object.data());
+    QVERIFY(input);
+
+    QSignalSpy spy(input, SIGNAL(mouseSelectionModeChanged(SelectionMode)));
 
-    QTest::newRow("L") << int(Qt::AlignLeft) << "halign_left";
-    QTest::newRow("R") << int(Qt::AlignRight) << "halign_right";
-    QTest::newRow("C") << int(Qt::AlignHCenter) << "halign_center";
+    QCOMPARE(input->mouseSelectionMode(), QQuickTextInput::SelectCharacters);
+
+    input->setMouseSelectionMode(QQuickTextInput::SelectWords);
+    QCOMPARE(input->mouseSelectionMode(), QQuickTextInput::SelectWords);
+    QCOMPARE(spy.count(), 1);
+
+    input->setMouseSelectionMode(QQuickTextInput::SelectWords);
+    QCOMPARE(spy.count(), 1);
+
+    input->setMouseSelectionMode(QQuickTextInput::SelectCharacters);
+    QCOMPARE(input->mouseSelectionMode(), QQuickTextInput::SelectCharacters);
+    QCOMPARE(spy.count(), 2);
 }
 
-void tst_qquicktextinput::horizontalAlignment()
+void tst_qquicktextinput::selectByMouse()
 {
-    QSKIP("Image comparison of text is almost guaranteed to fail during development");
+    QQmlComponent component(&engine);
+    component.setData("import QtQuick 2.0\n TextInput {}", QUrl());
+    QScopedPointer<QObject> object(component.create());
+    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(object.data());
+    QVERIFY(input);
 
-    QFETCH(int, hAlign);
-    QFETCH(QString, expectfile);
+    QSignalSpy spy(input, SIGNAL(selectByMouseChanged(bool)));
 
-    QQuickView window(testFileUrl("horizontalAlignment.qml"));
+    QCOMPARE(input->selectByMouse(), false);
 
-    window.show();
-    QVERIFY(QTest::qWaitForWindowExposed(&window));
+    input->setSelectByMouse(true);
+    QCOMPARE(input->selectByMouse(), true);
+    QCOMPARE(spy.count(), 1);
+    QCOMPARE(spy.at(0).at(0).toBool(), true);
 
-    QObject *ob = window.rootObject();
-    QVERIFY(ob != 0);
-    ob->setProperty("horizontalAlignment",hAlign);
-    QImage actual = window.grabWindow();
+    input->setSelectByMouse(true);
+    QCOMPARE(spy.count(), 1);
 
-    expectfile = createExpectedFileIfNotFound(expectfile, actual);
+    input->setSelectByMouse(false);
+    QCOMPARE(input->selectByMouse(), false);
+    QCOMPARE(spy.count(), 2);
+    QCOMPARE(spy.at(1).at(0).toBool(), false);
+}
+
+void tst_qquicktextinput::renderType()
+{
+    QQmlComponent component(&engine);
+    component.setData("import QtQuick 2.0\n TextInput {}", QUrl());
+    QScopedPointer<QObject> object(component.create());
+    QQuickTextInput *input = qobject_cast<QQuickTextInput *>(object.data());
+    QVERIFY(input);
+
+    QSignalSpy spy(input, SIGNAL(renderTypeChanged()));
 
-    QImage expect(expectfile);
+    QCOMPARE(input->renderType(), QQuickTextInput::QtRendering);
 
-    QCOMPARE(actual,expect);
+    input->setRenderType(QQuickTextInput::NativeRendering);
+    QCOMPARE(input->renderType(), QQuickTextInput::NativeRendering);
+    QCOMPARE(spy.count(), 1);
+
+    input->setRenderType(QQuickTextInput::NativeRendering);
+    QCOMPARE(spy.count(), 1);
+
+    input->setRenderType(QQuickTextInput::QtRendering);
+    QCOMPARE(input->renderType(), QQuickTextInput::QtRendering);
+    QCOMPARE(spy.count(), 2);
 }
 
 void tst_qquicktextinput::horizontalAlignment_RightToLeft()
@@ -1381,7 +1501,7 @@ void tst_qquicktextinput::horizontalAlignment_RightToLeft()
     QTest::qWaitForWindowActive(&window);
     QVERIFY(textInput->hasActiveFocus());
 
-    // If there is no commited text, the preedit text should determine the alignment.
+    // If there is no committed text, the preedit text should determine the alignment.
     textInput->setText(QString());
     { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(textInput, &ev); }
     QCOMPARE(textInput->hAlign(), QQuickTextInput::AlignRight);
@@ -2272,19 +2392,11 @@ void tst_qquicktextinput::navigation_RTL()
     QVERIFY(input->hasActiveFocus() == true);
 }
 
-void tst_qquicktextinput::copyAndPaste() {
 #ifndef QT_NO_CLIPBOARD
-
-#ifdef Q_OS_MAC
-    {
-        PasteboardRef pasteboard;
-        OSStatus status = PasteboardCreate(0, &pasteboard);
-        if (status == noErr)
-            CFRelease(pasteboard);
-        else
-            QSKIP("This machine doesn't support the clipboard");
-    }
-#endif
+void tst_qquicktextinput::copyAndPaste()
+{
+    if (!PlatformQuirks::isClipboardAvailable())
+        QSKIP("This machine doesn't support the clipboard");
 
     QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
     QQmlComponent textInputComponent(&engine);
@@ -2308,14 +2420,27 @@ void tst_qquicktextinput::copyAndPaste() {
     QVERIFY(textInput->canPaste());
     textInput->setReadOnly(true);
     QVERIFY(!textInput->canPaste());
+    textInput->paste();
+    QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
+    QCOMPARE(textInput->text().length(), 24);
     textInput->setReadOnly(false);
     QVERIFY(textInput->canPaste());
 
+    // cut: no selection
+    textInput->cut();
+    QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
+
     // select word
     textInput->setCursorPosition(0);
     textInput->selectWord();
     QCOMPARE(textInput->selectedText(), QString("Hello"));
 
+    // cut: read only.
+    textInput->setReadOnly(true);
+    textInput->cut();
+    QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
+    textInput->setReadOnly(false);
+
     // select all and cut
     textInput->selectAll();
     textInput->cut();
@@ -2324,6 +2449,18 @@ void tst_qquicktextinput::copyAndPaste() {
     QCOMPARE(textInput->text(), QString("Hello world!Hello world!"));
     QCOMPARE(textInput->text().length(), 24);
 
+    // Copy first word.
+    textInput->setCursorPosition(0);
+    textInput->selectWord();
+    textInput->copy();
+    // copy: no selection, previous copy retained;
+    textInput->setCursorPosition(0);
+    QCOMPARE(textInput->selectedText(), QString());
+    textInput->copy();
+    textInput->setText(QString());
+    textInput->paste();
+    QCOMPARE(textInput->text(), QString("Hello"));
+
     // clear copy buffer
     QClipboard *clipboard = QGuiApplication::clipboard();
     QVERIFY(clipboard);
@@ -2350,22 +2487,14 @@ void tst_qquicktextinput::copyAndPaste() {
     }
 
     delete textInput;
-#endif
 }
+#endif
 
-void tst_qquicktextinput::copyAndPasteKeySequence() {
 #ifndef QT_NO_CLIPBOARD
-
-#ifdef Q_OS_MAC
-    {
-        PasteboardRef pasteboard;
-        OSStatus status = PasteboardCreate(0, &pasteboard);
-        if (status == noErr)
-            CFRelease(pasteboard);
-        else
-            QSKIP("This machine doesn't support the clipboard");
-    }
-#endif
+void tst_qquicktextinput::copyAndPasteKeySequence()
+{
+    if (!PlatformQuirks::isClipboardAvailable())
+        QSKIP("This machine doesn't support the clipboard");
 
     QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\"; focus: true }";
     QQmlComponent textInputComponent(&engine);
@@ -2374,7 +2503,7 @@ void tst_qquicktextinput::copyAndPasteKeySequence() {
     QVERIFY(textInput != 0);
 
     QQuickWindow window;
-    textInput->setParentItem(window.rootItem());
+    textInput->setParentItem(window.contentItem());
     window.show();
     window.requestActivateWindow();
     QTest::qWaitForWindowActive(&window);
@@ -2426,12 +2555,12 @@ void tst_qquicktextinput::copyAndPasteKeySequence() {
     }
 
     delete textInput;
-#endif
 }
+#endif
 
-void tst_qquicktextinput::canPasteEmpty() {
 #ifndef QT_NO_CLIPBOARD
-
+void tst_qquicktextinput::canPasteEmpty()
+{
     QGuiApplication::clipboard()->clear();
 
     QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
@@ -2442,13 +2571,12 @@ void tst_qquicktextinput::canPasteEmpty() {
 
     bool cp = !textInput->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
     QCOMPARE(textInput->canPaste(), cp);
-
-#endif
 }
+#endif
 
-void tst_qquicktextinput::canPaste() {
 #ifndef QT_NO_CLIPBOARD
-
+void tst_qquicktextinput::canPaste()
+{
     QGuiApplication::clipboard()->setText("Some text");
 
     QString componentStr = "import QtQuick 2.0\nTextInput { text: \"Hello world!\" }";
@@ -2459,9 +2587,51 @@ void tst_qquicktextinput::canPaste() {
 
     bool cp = !textInput->isReadOnly() && QGuiApplication::clipboard()->text().length() != 0;
     QCOMPARE(textInput->canPaste(), cp);
-
+}
 #endif
+
+#ifndef QT_NO_CLIPBOARD
+void tst_qquicktextinput::middleClickPaste()
+{
+    if (!PlatformQuirks::isClipboardAvailable())
+        QSKIP("This machine doesn't support the clipboard");
+
+    QQuickView window(testFileUrl("mouseselection_true.qml"));
+
+    window.show();
+    window.requestActivateWindow();
+    QTest::qWaitForWindowActive(&window);
+
+    QVERIFY(window.rootObject() != 0);
+    QQuickTextInput *textInputObject = qobject_cast<QQuickTextInput *>(window.rootObject());
+    QVERIFY(textInputObject != 0);
+
+    textInputObject->setFocus(true);
+
+    QString originalText = textInputObject->text();
+    QString selectedText = "234567";
+
+    // press-and-drag-and-release from x1 to x2
+    const QPoint p1 = textInputObject->positionToRectangle(2).center().toPoint();
+    const QPoint p2 = textInputObject->positionToRectangle(8).center().toPoint();
+    const QPoint p3 = textInputObject->positionToRectangle(1).center().toPoint();
+    QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p1);
+    QTest::mouseMove(&window, p2);
+    QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p2);
+    QTRY_COMPARE(textInputObject->selectedText(), selectedText);
+
+    // Middle click pastes the selected text, assuming the platform supports it.
+    QTest::mouseClick(&window, Qt::MiddleButton, Qt::NoModifier, p3);
+
+    // ### This is to prevent double click detection from carrying over to the next test.
+    QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 10);
+
+    if (QGuiApplication::clipboard()->supportsSelection())
+        QCOMPARE(textInputObject->text().mid(1, selectedText.length()), selectedText);
+    else
+        QCOMPARE(textInputObject->text(), originalText);
 }
+#endif
 
 void tst_qquicktextinput::passwordCharacter()
 {
@@ -2670,7 +2840,7 @@ void tst_qquicktextinput::cursorVisible()
     QCOMPARE(input.isCursorVisible(), true);
     QCOMPARE(spy.count(), 5);
 
-    QWindow alternateView;
+    QQuickView alternateView;
     alternateView.show();
     alternateView.requestActivateWindow();
     QTest::qWaitForWindowActive(&alternateView);
@@ -3128,7 +3298,7 @@ void tst_qquicktextinput::focusOnPress()
 
     QQuickWindow window;
     window.resize(100, 50);
-    textInputObject->setParentItem(window.rootItem());
+    textInputObject->setParentItem(window.contentItem());
     window.show();
     window.requestActivateWindow();
     QTest::qWaitForWindowActive(&window);
@@ -3236,7 +3406,7 @@ void tst_qquicktextinput::openInputPanel()
 
     anotherInput.setFocus(false);
     QVERIFY(qApp->focusObject() != &anotherInput);
-    QCOMPARE(view.activeFocusItem(), view.rootItem());
+    QCOMPARE(view.activeFocusItem(), view.contentItem());
     anotherInput.setFocus(true);
 
     qApp->inputMethod()->hide();
@@ -3280,7 +3450,7 @@ void tst_qquicktextinput::setHAlignClearCache()
     QQuickView view;
     MyTextInput input;
     input.setText("Hello world");
-    input.setParentItem(view.rootItem());
+    input.setParentItem(view.contentItem());
     view.show();
     view.requestActivateWindow();
     QTest::qWaitForWindowActive(&view);
@@ -3300,8 +3470,8 @@ void tst_qquicktextinput::focusOutClearSelection()
     QQuickTextInput input2;
     input.setText(QLatin1String("Hello world"));
     input.setFocus(true);
-    input2.setParentItem(view.rootItem());
-    input.setParentItem(view.rootItem());
+    input2.setParentItem(view.contentItem());
+    input.setParentItem(view.contentItem());
     input.componentComplete();
     input2.componentComplete();
     view.show();
@@ -4798,7 +4968,7 @@ void tst_qquicktextinput::keySequence()
     textInput->setEchoMode(echoMode);
 
     QQuickWindow window;
-    textInput->setParentItem(window.rootItem());
+    textInput->setParentItem(window.contentItem());
     window.show();
     window.requestActivateWindow();
     QTest::qWaitForWindowActive(&window);
@@ -4959,7 +5129,7 @@ void tst_qquicktextinput::undo()
     QVERIFY(textInput != 0);
 
     QQuickWindow window;
-    textInput->setParentItem(window.rootItem());
+    textInput->setParentItem(window.contentItem());
     window.show();
     window.requestActivateWindow();
     QTest::qWaitForWindowActive(&window);
@@ -5045,7 +5215,7 @@ void tst_qquicktextinput::redo()
     QVERIFY(textInput != 0);
 
     QQuickWindow window;
-    textInput->setParentItem(window.rootItem());
+    textInput->setParentItem(window.contentItem());
     window.show();
     window.requestActivateWindow();
     QTest::qWaitForWindowActive(&window);
@@ -5332,6 +5502,37 @@ void tst_qquicktextinput::undo_keypressevents_data()
 
         QTest::newRow("Insert,move,select,delete next word,undo,insert") << keys << expectedString;
     }
+
+    bool canCopyPaste = PlatformQuirks::isClipboardAvailable();
+
+    if (canCopyPaste) {
+        KeyList keys;
+        keys    << "123"
+                << QKeySequence(QKeySequence::SelectStartOfLine)
+                << QKeySequence(QKeySequence::Cut)
+                << "ABC"
+                << QKeySequence(QKeySequence::Paste);
+        QStringList expectedString = QStringList()
+                << "ABC123"
+                << "ABC"
+                // TextEdit: ""
+                << "123";
+        QTest::newRow("Cut,paste") << keys << expectedString;
+    }
+    if (canCopyPaste) {
+        KeyList keys;
+        keys    << "123"
+                << QKeySequence(QKeySequence::SelectStartOfLine)
+                << QKeySequence(QKeySequence::Copy)
+                << "ABC"
+                << QKeySequence(QKeySequence::Paste);
+        QStringList expectedString = QStringList()
+                << "ABC123"
+                << "ABC"
+                // TextEdit: "A"
+                << "123";
+        QTest::newRow("Copy,paste") << keys << expectedString;
+    }
 }
 
 void tst_qquicktextinput::undo_keypressevents()
@@ -5346,7 +5547,7 @@ void tst_qquicktextinput::undo_keypressevents()
     QVERIFY(textInput != 0);
 
     QQuickWindow window;
-    textInput->setParentItem(window.rootItem());
+    textInput->setParentItem(window.contentItem());
     window.show();
     window.requestActivateWindow();
     QTest::qWaitForWindowActive(&window);
@@ -5379,8 +5580,8 @@ void tst_qquicktextinput::backspaceSurrogatePairs()
     textInput->setParentItem(window.contentItem());
     window.show();
     window.requestActivateWindow();
-    QTest::qWaitForWindowShown(&window);
-    QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
+    QVERIFY(QTest::qWaitForWindowActive(&window));
+    QCOMPARE(QGuiApplication::focusWindow(), &window);
 
     for (int i = text.length(); i >= 0; i -= 2) {
         QCOMPARE(textInput->text(), text.mid(0, i));
@@ -5753,7 +5954,7 @@ void tst_qquicktextinput::setInputMask()
         textInput->insert(0, input);
     } else {
         QQuickWindow window;
-        textInput->setParentItem(window.rootItem());
+        textInput->setParentItem(window.contentItem());
         window.show();
         window.requestActivateWindow();
         QTest::qWaitForWindowActive(&window);
@@ -5816,7 +6017,7 @@ void tst_qquicktextinput::clearInputMask()
     QQuickTextInput *textInput = qobject_cast<QQuickTextInput*>(textInputComponent.create());
     QVERIFY(textInput != 0);
 
-    QVERIFY(textInput->inputMask() != QString());
+    QVERIFY(!textInput->inputMask().isEmpty());
     textInput->setInputMask(QString());
     QCOMPARE(textInput->inputMask(), QString());
 }
@@ -5883,7 +6084,7 @@ void tst_qquicktextinput::keypress_inputMask()
     QVERIFY(textInput != 0);
 
     QQuickWindow window;
-    textInput->setParentItem(window.rootItem());
+    textInput->setParentItem(window.contentItem());
     window.show();
     window.requestActivateWindow();
     QTest::qWaitForWindowActive(&window);