All QWindow properties that have "window" in them have been renamed.
[profile/ivi/qtdeclarative.git] / tests / auto / quick / qquicktextedit / tst_qquicktextedit.cpp
index 9c34a7c..3966fff 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$
 #include <QMimeData>
 #include <private/qquicktextcontrol_p.h>
 #include "../../shared/util.h"
+#include "../../shared/platformquirks.h"
 #include "../../shared/platforminputcontext.h"
 #include <private/qinputmethod_p.h>
+#include <QtGui/qstylehints.h>
 
 #ifdef Q_OS_MAC
 #include <Carbon/Carbon.h>
 #endif
 
+#define SERVER_PORT 42332
+#define SERVER_ADDR "http://localhost:42332"
 
 Q_DECLARE_METATYPE(QQuickTextEdit::SelectionMode)
 Q_DECLARE_METATYPE(Qt::Key)
@@ -103,12 +107,11 @@ private slots:
     void width();
     void wrap();
     void textFormat();
-    void alignments();
-    void alignments_data();
 
     // ### these tests may be trivial
     void hAlign();
     void hAlign_RightToLeft();
+    void hAlignVisual();
     void vAlign();
     void font();
     void color();
@@ -128,27 +131,37 @@ private slots:
     void mouseSelectionMode_data();
     void mouseSelectionMode();
     void dragMouseSelection();
+    void mouseSelectionMode_accessors();
+    void selectByMouse();
+    void renderType();
     void inputMethodHints();
 
+    void positionAt_data();
     void positionAt();
 
     void linkActivated();
 
     void cursorDelegate_data();
     void cursorDelegate();
+    void remoteCursorDelegate();
     void cursorVisible();
     void delegateLoading_data();
     void delegateLoading();
     void navigation();
     void readOnly();
+#ifndef QT_NO_CLIPBOARD
     void copyAndPaste();
     void canPaste();
     void canPasteEmpty();
+    void middleClickPaste();
+#endif
     void textInput();
     void inputMethodUpdate();
     void openInputPanel();
     void geometrySignals();
+#ifndef QT_NO_CLIPBOARD
     void pastingRichText_QTBUG_14003();
+#endif
     void implicitSize_data();
     void implicitSize();
     void contentSize();
@@ -212,6 +225,8 @@ Q_DECLARE_METATYPE(IntList)
 typedef QList<Key> KeyList;
 Q_DECLARE_METATYPE(KeyList)
 
+Q_DECLARE_METATYPE(QQuickTextEdit::HAlignment)
+Q_DECLARE_METATYPE(QQuickTextEdit::VAlignment)
 Q_DECLARE_METATYPE(QQuickTextEdit::TextFormat)
 
 void tst_qquicktextedit::simulateKeys(QWindow *window, const QList<Key> &keys)
@@ -524,6 +539,28 @@ void tst_qquicktextedit::wrap()
         QVERIFY(textEditObject != 0);
         QCOMPARE(textEditObject->width(), 300.);
     }
+    {
+        QQmlComponent component(&engine);
+        component.setData("import QtQuick 2.0\n TextEdit {}", QUrl());
+        QScopedPointer<QObject> object(component.create());
+        QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(object.data());
+        QVERIFY(edit);
+
+        QSignalSpy spy(edit, SIGNAL(wrapModeChanged()));
+
+        QCOMPARE(edit->wrapMode(), QQuickTextEdit::NoWrap);
+
+        edit->setWrapMode(QQuickTextEdit::Wrap);
+        QCOMPARE(edit->wrapMode(), QQuickTextEdit::Wrap);
+        QCOMPARE(spy.count(), 1);
+
+        edit->setWrapMode(QQuickTextEdit::Wrap);
+        QCOMPARE(spy.count(), 1);
+
+        edit->setWrapMode(QQuickTextEdit::NoWrap);
+        QCOMPARE(edit->wrapMode(), QQuickTextEdit::NoWrap);
+        QCOMPARE(spy.count(), 2);
+    }
 
 }
 
@@ -545,58 +582,30 @@ void tst_qquicktextedit::textFormat()
         QVERIFY(textObject != 0);
         QVERIFY(textObject->textFormat() == QQuickTextEdit::PlainText);
     }
-}
-
-void tst_qquicktextedit::alignments_data()
-{
-    QTest::addColumn<int>("hAlign");
-    QTest::addColumn<int>("vAlign");
-    QTest::addColumn<QString>("expectfile");
-
-    QTest::newRow("LT") << int(Qt::AlignLeft) << int(Qt::AlignTop) << "alignments_lt";
-    QTest::newRow("RT") << int(Qt::AlignRight) << int(Qt::AlignTop) << "alignments_rt";
-    QTest::newRow("CT") << int(Qt::AlignHCenter) << int(Qt::AlignTop) << "alignments_ct";
-
-    QTest::newRow("LB") << int(Qt::AlignLeft) << int(Qt::AlignBottom) << "alignments_lb";
-    QTest::newRow("RB") << int(Qt::AlignRight) << int(Qt::AlignBottom) << "alignments_rb";
-    QTest::newRow("CB") << int(Qt::AlignHCenter) << int(Qt::AlignBottom) << "alignments_cb";
-
-    QTest::newRow("LC") << int(Qt::AlignLeft) << int(Qt::AlignVCenter) << "alignments_lc";
-    QTest::newRow("RC") << int(Qt::AlignRight) << int(Qt::AlignVCenter) << "alignments_rc";
-    QTest::newRow("CC") << int(Qt::AlignHCenter) << int(Qt::AlignVCenter) << "alignments_cc";
-}
-
-
-void tst_qquicktextedit::alignments()
-{
-    QSKIP("Image comparison of text is almost guaranteed to fail during development");
-
-    QFETCH(int, hAlign);
-    QFETCH(int, vAlign);
-    QFETCH(QString, expectfile);
-
-    QQuickView canvas(testFileUrl("alignments.qml"));
+    {
+        QQmlComponent component(&engine);
+        component.setData("import QtQuick 2.0\n TextEdit {}", QUrl());
+        QScopedPointer<QObject> object(component.create());
+        QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(object.data());
+        QVERIFY(edit);
 
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+        QSignalSpy spy(edit, SIGNAL(textFormatChanged(TextFormat)));
 
-    QObject *ob = canvas.rootObject();
-    QVERIFY(ob != 0);
-    ob->setProperty("horizontalAlignment",hAlign);
-    ob->setProperty("verticalAlignment",vAlign);
-    QTRY_COMPARE(ob->property("running").toBool(),false);
-    QImage actual = canvas.grabFrameBuffer();
+        QCOMPARE(edit->textFormat(), QQuickTextEdit::PlainText);
 
-    expectfile = createExpectedFileIfNotFound(expectfile, actual);
+        edit->setTextFormat(QQuickTextEdit::RichText);
+        QCOMPARE(edit->textFormat(), QQuickTextEdit::RichText);
+        QCOMPARE(spy.count(), 1);
 
-    QImage expect(expectfile);
+        edit->setTextFormat(QQuickTextEdit::RichText);
+        QCOMPARE(spy.count(), 1);
 
-    QCOMPARE(actual,expect);
+        edit->setTextFormat(QQuickTextEdit::PlainText);
+        QCOMPARE(edit->textFormat(), QQuickTextEdit::PlainText);
+        QCOMPARE(spy.count(), 2);
+    }
 }
 
-
 //the alignment tests may be trivial o.oa
 void tst_qquicktextedit::hAlign()
 {
@@ -638,26 +647,26 @@ void tst_qquicktextedit::hAlign_RightToLeft()
     QInputMethodPrivate *inputMethodPrivate = QInputMethodPrivate::get(qApp->inputMethod());
     inputMethodPrivate->testContext = &platformInputContext;
 
-    QQuickView canvas(testFileUrl("horizontalAlignment_RightToLeft.qml"));
-    QQuickTextEdit *textEdit = canvas.rootObject()->findChild<QQuickTextEdit*>("text");
+    QQuickView window(testFileUrl("horizontalAlignment_RightToLeft.qml"));
+    QQuickTextEdit *textEdit = window.rootObject()->findChild<QQuickTextEdit*>("text");
     QVERIFY(textEdit != 0);
-    canvas.show();
+    window.show();
 
     const QString rtlText = textEdit->text();
 
     // implicit alignment should follow the reading direction of text
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
-    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
 
     // explicitly left aligned
     textEdit->setHAlign(QQuickTextEdit::AlignLeft);
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
-    QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
 
     // explicitly right aligned
     textEdit->setHAlign(QQuickTextEdit::AlignRight);
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
-    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
 
     QString textString = textEdit->text();
     textEdit->setText(QString("<i>") + textString + QString("</i>"));
@@ -666,31 +675,31 @@ void tst_qquicktextedit::hAlign_RightToLeft()
     // implicitly aligned rich text should follow the reading direction of RTL text
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
     QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
-    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
 
     // explicitly left aligned rich text
     textEdit->setHAlign(QQuickTextEdit::AlignLeft);
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
     QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
-    QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
 
     // explicitly right aligned rich text
     textEdit->setHAlign(QQuickTextEdit::AlignRight);
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
     QCOMPARE(textEdit->effectiveHAlign(), textEdit->hAlign());
-    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
 
     textEdit->setText(textString);
 
     // explicitly center aligned
     textEdit->setHAlign(QQuickTextEdit::AlignHCenter);
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignHCenter);
-    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
 
     // reseted alignment should go back to following the text reading direction
     textEdit->resetHAlign();
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
-    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
 
     // mirror the text item
     QQuickItemPrivate::get(textEdit)->setLayoutMirror(true);
@@ -698,19 +707,19 @@ void tst_qquicktextedit::hAlign_RightToLeft()
     // mirrored implicit alignment should continue to follow the reading direction of the text
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
     QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
-    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
 
     // mirrored explicitly right aligned behaves as left aligned
     textEdit->setHAlign(QQuickTextEdit::AlignRight);
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
     QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignLeft);
-    QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
 
     // mirrored explicitly left aligned behaves as right aligned
     textEdit->setHAlign(QQuickTextEdit::AlignLeft);
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
     QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
-    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
 
     // disable mirroring
     QQuickItemPrivate::get(textEdit)->setLayoutMirror(false);
@@ -719,21 +728,21 @@ void tst_qquicktextedit::hAlign_RightToLeft()
     // English text should be implicitly left aligned
     textEdit->setText("Hello world!");
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
-    QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
 
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
+    QVERIFY(textEdit->hasActiveFocus());
 
     textEdit->setText(QString());
-    { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
+    { QInputMethodEvent ev(rtlText, QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(textEdit, &ev); }
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
-    { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
+    { QInputMethodEvent ev("Hello world!", QList<QInputMethodEvent::Attribute>()); QGuiApplication::sendEvent(textEdit, &ev); }
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
 
     // Clear pre-edit text.  TextEdit should maybe do this itself on setText, but that may be
     // redundant as an actual input method may take care of it.
-    { QInputMethodEvent ev; QGuiApplication::sendEvent(qGuiApp->focusObject(), &ev); }
+    { QInputMethodEvent ev; QGuiApplication::sendEvent(textEdit, &ev); }
 
     // empty text with implicit alignment follows the system locale-based
     // keyboard input direction from qApp->inputMethod()->inputDirection
@@ -741,7 +750,7 @@ void tst_qquicktextedit::hAlign_RightToLeft()
     platformInputContext.setInputDirection(Qt::LeftToRight);
     QVERIFY(qApp->inputMethod()->inputDirection() == Qt::LeftToRight);
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignLeft);
-    QVERIFY(textEdit->positionToRectangle(0).x() < canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() < window.width()/2);
 
     QSignalSpy cursorRectangleSpy(textEdit, SIGNAL(cursorRectangleChanged()));
 
@@ -749,17 +758,27 @@ void tst_qquicktextedit::hAlign_RightToLeft()
     QCOMPARE(cursorRectangleSpy.count(), 1);
     QVERIFY(qApp->inputMethod()->inputDirection() == Qt::RightToLeft);
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
-    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
+
+    // neutral text follows also input method direction
+    textEdit->resetHAlign();
+    textEdit->setText(" ()((=<>");
+    platformInputContext.setInputDirection(Qt::LeftToRight);
+    QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignLeft);
+    QVERIFY(textEdit->cursorRectangle().left() < window.width()/2);
+    platformInputContext.setInputDirection(Qt::RightToLeft);
+    QCOMPARE(textEdit->effectiveHAlign(), QQuickTextEdit::AlignRight);
+    QVERIFY(textEdit->cursorRectangle().left() > window.width()/2);
 
     // set input direction while having content
     platformInputContext.setInputDirection(Qt::LeftToRight);
     textEdit->setText("a");
     textEdit->setCursorPosition(1);
     platformInputContext.setInputDirection(Qt::RightToLeft);
-    QTest::keyClick(&canvas, Qt::Key_Backspace);
+    QTest::keyClick(&window, Qt::Key_Backspace);
     QVERIFY(textEdit->text().isEmpty());
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
-    QVERIFY(textEdit->cursorRectangle().left() > canvas.width()/2);
+    QVERIFY(textEdit->cursorRectangle().left() > window.width()/2);
 
     // input direction changed while not having focus
     platformInputContext.setInputDirection(Qt::LeftToRight);
@@ -767,11 +786,106 @@ void tst_qquicktextedit::hAlign_RightToLeft()
     platformInputContext.setInputDirection(Qt::RightToLeft);
     textEdit->setFocus(true);
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
-    QVERIFY(textEdit->cursorRectangle().left() > canvas.width()/2);
+    QVERIFY(textEdit->cursorRectangle().left() > window.width()/2);
 
     textEdit->setHAlign(QQuickTextEdit::AlignRight);
     QCOMPARE(textEdit->hAlign(), QQuickTextEdit::AlignRight);
-    QVERIFY(textEdit->positionToRectangle(0).x() > canvas.width()/2);
+    QVERIFY(textEdit->positionToRectangle(0).x() > window.width()/2);
+
+    // make sure editor doesn't rely on input for updating size
+    QQuickTextEdit *emptyEdit = window.rootObject()->findChild<QQuickTextEdit*>("emptyTextEdit");
+    QVERIFY(emptyEdit != 0);
+    platformInputContext.setInputDirection(Qt::RightToLeft);
+    emptyEdit->setFocus(true);
+    QCOMPARE(emptyEdit->hAlign(), QQuickTextEdit::AlignRight);
+    QVERIFY(emptyEdit->cursorRectangle().left() > window.width()/2);
+}
+
+
+static int numberOfNonWhitePixels(int fromX, int toX, const QImage &image)
+{
+    int pixels = 0;
+    for (int x = fromX; x < toX; ++x) {
+        for (int y = 0; y < image.height(); ++y) {
+            if (image.pixel(x, y) != qRgb(255, 255, 255))
+                pixels++;
+        }
+    }
+    return pixels;
+}
+
+void tst_qquicktextedit::hAlignVisual()
+{
+    QQuickView view(testFileUrl("hAlignVisual.qml"));
+    view.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+    QQuickText *text = view.rootObject()->findChild<QQuickText*>("textItem");
+    QVERIFY(text != 0);
+    {
+        // Left Align
+        QImage image = view.grabWindow();
+        int left = numberOfNonWhitePixels(0, image.width() / 3, image);
+        int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
+        int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
+        QVERIFY(left > mid);
+        QVERIFY(mid > right);
+    }
+    {
+        // HCenter Align
+        text->setHAlign(QQuickText::AlignHCenter);
+        QImage image = view.grabWindow();
+        int left = numberOfNonWhitePixels(0, image.width() / 3, image);
+        int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
+        int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
+        QVERIFY(left < mid);
+        QVERIFY(mid > right);
+    }
+    {
+        // Right Align
+        text->setHAlign(QQuickText::AlignRight);
+        QImage image = view.grabWindow();
+        int left = numberOfNonWhitePixels(0, image.width() / 3, image);
+        int mid = numberOfNonWhitePixels(image.width() / 3, 2 * image.width() / 3, image);
+        int right = numberOfNonWhitePixels( 2 * image.width() / 3, image.width(), image);
+        QVERIFY(left < mid);
+        QVERIFY(mid < right);
+    }
+
+    text->setWidth(200);
+
+    {
+        // Left Align
+        QImage image = view.grabWindow();
+        int x = qCeil(text->implicitWidth());
+        int left = numberOfNonWhitePixels(0, x, image);
+        int right = numberOfNonWhitePixels(x, image.width() - x, image);
+        QVERIFY(left > 0);
+        QVERIFY(right == 0);
+    }
+    {
+        // HCenter Align
+        text->setHAlign(QQuickText::AlignHCenter);
+        QImage image = view.grabWindow();
+        int x1 = qFloor(image.width() - text->implicitWidth()) / 2;
+        int x2 = image.width() - x1;
+        int left = numberOfNonWhitePixels(0, x1, image);
+        int mid = numberOfNonWhitePixels(x1, x2 - x1, image);
+        int right = numberOfNonWhitePixels(x2, image.width() - x2, image);
+        QVERIFY(left == 0);
+        QVERIFY(mid > 0);
+        QVERIFY(right == 0);
+    }
+    {
+        // Right Align
+        text->setHAlign(QQuickText::AlignRight);
+        QImage image = view.grabWindow();
+        int x = image.width() - qCeil(text->implicitWidth());
+        int left = numberOfNonWhitePixels(0, x, image);
+        int right = numberOfNonWhitePixels(x, image.width() - x, image);
+        QVERIFY(left == 0);
+        QVERIFY(right > 0);
+    }
 }
 
 void tst_qquicktextedit::vAlign()
@@ -902,13 +1016,49 @@ void tst_qquicktextedit::color()
         texteditComponent.setData(componentStr.toLatin1(), QUrl());
         QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit*>(texteditComponent.create());
 
-        QQuickTextEditPrivate *textEditPrivate = static_cast<QQuickTextEditPrivate*>(QQuickItemPrivate::get(textEditObject));
-
         QVERIFY(textEditObject);
-        QVERIFY(textEditPrivate);
-        QVERIFY(textEditPrivate->control);
-        QCOMPARE(textEditPrivate->color, QColor("black"));
+        QCOMPARE(textEditObject->color(), QColor("black"));
+        QCOMPARE(textEditObject->selectionColor(), QColor::fromRgba(0xFF000080));
+        QCOMPARE(textEditObject->selectedTextColor(), QColor("white"));
+
+        QSignalSpy colorSpy(textEditObject, SIGNAL(colorChanged(QColor)));
+        QSignalSpy selectionColorSpy(textEditObject, SIGNAL(selectionColorChanged(QColor)));
+        QSignalSpy selectedTextColorSpy(textEditObject, SIGNAL(selectedTextColorChanged(QColor)));
+
+        textEditObject->setColor(QColor("white"));
+        QCOMPARE(textEditObject->color(), QColor("white"));
+        QCOMPARE(colorSpy.count(), 1);
+
+        textEditObject->setSelectionColor(QColor("black"));
+        QCOMPARE(textEditObject->selectionColor(), QColor("black"));
+        QCOMPARE(selectionColorSpy.count(), 1);
+
+        textEditObject->setSelectedTextColor(QColor("blue"));
+        QCOMPARE(textEditObject->selectedTextColor(), QColor("blue"));
+        QCOMPARE(selectedTextColorSpy.count(), 1);
+
+        textEditObject->setColor(QColor("white"));
+        QCOMPARE(colorSpy.count(), 1);
+
+        textEditObject->setSelectionColor(QColor("black"));
+        QCOMPARE(selectionColorSpy.count(), 1);
+
+        textEditObject->setSelectedTextColor(QColor("blue"));
+        QCOMPARE(selectedTextColorSpy.count(), 1);
+
+        textEditObject->setColor(QColor("black"));
+        QCOMPARE(textEditObject->color(), QColor("black"));
+        QCOMPARE(colorSpy.count(), 2);
+
+        textEditObject->setSelectionColor(QColor("blue"));
+        QCOMPARE(textEditObject->selectionColor(), QColor("blue"));
+        QCOMPARE(selectionColorSpy.count(), 2);
+
+        textEditObject->setSelectedTextColor(QColor("white"));
+        QCOMPARE(textEditObject->selectedTextColor(), QColor("white"));
+        QCOMPARE(selectedTextColorSpy.count(), 2);
     }
+
     //test normal
     for (int i = 0; i < colorStrings.size(); i++)
     {
@@ -972,14 +1122,12 @@ void tst_qquicktextedit::textMargin()
 
 void tst_qquicktextedit::persistentSelection()
 {
-    QQuickView canvas(testFileUrl("persistentSelection.qml"));
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-    canvas.requestActivateWindow();
-
-    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+    QQuickView window(testFileUrl("persistentSelection.qml"));
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
+
+    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(window.rootObject());
     QVERIFY(edit);
     QVERIFY(edit->hasActiveFocus());
 
@@ -1041,27 +1189,26 @@ void tst_qquicktextedit::focusOnPress()
     QCOMPARE(textEditObject->focusOnPress(), true);
     QCOMPARE(activeFocusOnPressSpy.count(), 0);
 
-    QQuickCanvas canvas;
-    canvas.resize(100, 50);
-    textEditObject->setParentItem(canvas.rootItem());
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+    QQuickWindow window;
+    window.resize(100, 50);
+    textEditObject->setParentItem(window.contentItem());
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
 
     QCOMPARE(textEditObject->hasFocus(), false);
     QCOMPARE(textEditObject->hasActiveFocus(), false);
 
-    QPoint centerPoint(canvas.width()/2, canvas.height()/2);
+    QPoint centerPoint(window.width()/2, window.height()/2);
     Qt::KeyboardModifiers noModifiers = 0;
-    QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+    QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
     QGuiApplication::processEvents();
     QCOMPARE(textEditObject->hasFocus(), true);
     QCOMPARE(textEditObject->hasActiveFocus(), true);
     QCOMPARE(focusSpy.count(), 1);
     QCOMPARE(activeFocusSpy.count(), 1);
     QCOMPARE(textEditObject->selectedText(), QString());
-    QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+    QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, centerPoint);
 
     textEditObject->setFocusOnPress(false);
     QCOMPARE(textEditObject->focusOnPress(), false);
@@ -1075,13 +1222,13 @@ void tst_qquicktextedit::focusOnPress()
 
     // Wait for double click timeout to expire before clicking again.
     QTest::qWait(400);
-    QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+    QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
     QGuiApplication::processEvents();
     QCOMPARE(textEditObject->hasFocus(), false);
     QCOMPARE(textEditObject->hasActiveFocus(), false);
     QCOMPARE(focusSpy.count(), 2);
     QCOMPARE(activeFocusSpy.count(), 2);
-    QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+    QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, centerPoint);
 
     textEditObject->setFocusOnPress(true);
     QCOMPARE(textEditObject->focusOnPress(), true);
@@ -1091,14 +1238,14 @@ void tst_qquicktextedit::focusOnPress()
     textEditObject->setProperty("selectOnFocus", true);
 
     QTest::qWait(400);
-    QTest::mousePress(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+    QTest::mousePress(&window, Qt::LeftButton, noModifiers, centerPoint);
     QGuiApplication::processEvents();
     QCOMPARE(textEditObject->hasFocus(), true);
     QCOMPARE(textEditObject->hasActiveFocus(), true);
     QCOMPARE(focusSpy.count(), 3);
     QCOMPARE(activeFocusSpy.count(), 3);
     QCOMPARE(textEditObject->selectedText(), textEditObject->text());
-    QTest::mouseRelease(&canvas, Qt::LeftButton, noModifiers, centerPoint);
+    QTest::mouseRelease(&window, Qt::LeftButton, noModifiers, centerPoint);
 }
 
 void tst_qquicktextedit::selection()
@@ -1244,47 +1391,45 @@ void tst_qquicktextedit::isRightToLeft()
 
 void tst_qquicktextedit::keySelection()
 {
-    QQuickView canvas(testFileUrl("navigation.qml"));
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
-    canvas.requestActivateWindow();
+    QQuickView window(testFileUrl("navigation.qml"));
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
 
-    QVERIFY(canvas.rootObject() != 0);
+    QVERIFY(window.rootObject() != 0);
 
-    QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+    QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
 
     QVERIFY(input != 0);
-    QTRY_VERIFY(input->hasActiveFocus() == true);
+    QVERIFY(input->hasActiveFocus());
 
-    QSignalSpy spy(input, SIGNAL(selectionChanged()));
+    QSignalSpy spy(input, SIGNAL(selectedTextChanged()));
 
-    simulateKey(&canvas, Qt::Key_Right, Qt::ShiftModifier);
+    simulateKey(&window, Qt::Key_Right, Qt::ShiftModifier);
     QVERIFY(input->hasActiveFocus() == true);
     QCOMPARE(input->selectedText(), QString("a"));
     QCOMPARE(spy.count(), 1);
-    simulateKey(&canvas, Qt::Key_Right);
+    simulateKey(&window, Qt::Key_Right);
     QVERIFY(input->hasActiveFocus() == true);
     QCOMPARE(input->selectedText(), QString());
     QCOMPARE(spy.count(), 2);
-    simulateKey(&canvas, Qt::Key_Right);
+    simulateKey(&window, Qt::Key_Right);
     QVERIFY(input->hasActiveFocus() == false);
     QCOMPARE(input->selectedText(), QString());
     QCOMPARE(spy.count(), 2);
 
-    simulateKey(&canvas, Qt::Key_Left);
+    simulateKey(&window, Qt::Key_Left);
     QVERIFY(input->hasActiveFocus() == true);
     QCOMPARE(spy.count(), 2);
-    simulateKey(&canvas, Qt::Key_Left, Qt::ShiftModifier);
+    simulateKey(&window, Qt::Key_Left, Qt::ShiftModifier);
     QVERIFY(input->hasActiveFocus() == true);
     QCOMPARE(input->selectedText(), QString("a"));
     QCOMPARE(spy.count(), 3);
-    simulateKey(&canvas, Qt::Key_Left);
+    simulateKey(&window, Qt::Key_Left);
     QVERIFY(input->hasActiveFocus() == true);
     QCOMPARE(input->selectedText(), QString());
     QCOMPARE(spy.count(), 4);
-    simulateKey(&canvas, Qt::Key_Left);
+    simulateKey(&window, Qt::Key_Left);
     QVERIFY(input->hasActiveFocus() == false);
     QCOMPARE(input->selectedText(), QString());
     QCOMPARE(spy.count(), 4);
@@ -1634,39 +1779,62 @@ void tst_qquicktextedit::mouseSelection_data()
     QTest::addColumn<QString>("selectedText");
     QTest::addColumn<bool>("focus");
     QTest::addColumn<bool>("focusOnPress");
-    QTest::addColumn<bool>("doubleClick");
+    QTest::addColumn<int>("clicks");
 
     // import installed
-    QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << true << true << false;
-    QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString() << true << true << false;
-    QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString() << true << true << false;
-    QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString() << true << true << false;
-    QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << true << true << false;
-
-    QTest::newRow("on unfocused") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << false << false;
-    QTest::newRow("on word selection (4,9) unfocused") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << false << false;
-
-    QTest::newRow("on focus on press") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << true << false;
-    QTest::newRow("on word selection (4,9) focus on press") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << true << false;
-
-    QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
-    QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
-    QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
-    QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
-    QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
-    QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
-    QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
-    QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << false;
-
-    QTest::newRow("off double click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789" << true << true << true;
-    QTest::newRow("off double click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
-    QTest::newRow("off double click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
-    QTest::newRow("off double click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
-    QTest::newRow("off double click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
-    QTest::newRow("off double click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
-    QTest::newRow("off double click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
-    QTest::newRow("off double click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
-    QTest::newRow("off double click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << true;
+    QTest::newRow("on") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << true << true << 1;
+    QTest::newRow("off") << testFile("mouseselection_false.qml") << 4 << 9 << QString() << true << true << 1;
+    QTest::newRow("default") << testFile("mouseselection_default.qml") << 4 << 9 << QString() << true << true << 1;
+    QTest::newRow("off word selection") << testFile("mouseselection_false_words.qml") << 4 << 9 << QString() << true << true << 1;
+    QTest::newRow("on word selection (4,9)") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << true << true << 1;
+
+    QTest::newRow("on unfocused") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << false << 1;
+    QTest::newRow("on word selection (4,9) unfocused") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << false << 1;
+
+    QTest::newRow("on focus on press") << testFile("mouseselection_true.qml") << 4 << 9 << "45678" << false << true << 1;
+    QTest::newRow("on word selection (4,9) focus on press") << testFile("mouseselection_true_words.qml") << 4 << 9 << "0123456789" << false << true << 1;
+
+    QTest::newRow("on word selection (2,13)") << testFile("mouseselection_true_words.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+    QTest::newRow("on word selection (2,30)") << testFile("mouseselection_true_words.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+    QTest::newRow("on word selection (9,13)") << testFile("mouseselection_true_words.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+    QTest::newRow("on word selection (9,30)") << testFile("mouseselection_true_words.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+    QTest::newRow("on word selection (13,2)") << testFile("mouseselection_true_words.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+    QTest::newRow("on word selection (20,2)") << testFile("mouseselection_true_words.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+    QTest::newRow("on word selection (12,9)") << testFile("mouseselection_true_words.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+    QTest::newRow("on word selection (30,9)") << testFile("mouseselection_true_words.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 1;
+
+    QTest::newRow("on double click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789" << true << true << 2;
+    QTest::newRow("on double click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+    QTest::newRow("on double click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+    QTest::newRow("on double click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+    QTest::newRow("on double click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+    QTest::newRow("on double click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+    QTest::newRow("on double click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+    QTest::newRow("on double click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+    QTest::newRow("on double click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ" << true << true << 2;
+
+    QTest::newRow("on triple click (4,9)") << testFile("mouseselection_true.qml") << 4 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+    QTest::newRow("on triple click (2,13)") << testFile("mouseselection_true.qml") << 2 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+    QTest::newRow("on triple click (2,30)") << testFile("mouseselection_true.qml") << 2 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+    QTest::newRow("on triple click (9,13)") << testFile("mouseselection_true.qml") << 9 << 13 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+    QTest::newRow("on triple click (9,30)") << testFile("mouseselection_true.qml") << 9 << 30 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+    QTest::newRow("on triple click (13,2)") << testFile("mouseselection_true.qml") << 13 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+    QTest::newRow("on triple click (20,2)") << testFile("mouseselection_true.qml") << 20 << 2 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+    QTest::newRow("on triple click (12,9)") << testFile("mouseselection_true.qml") << 12 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+    QTest::newRow("on triple click (30,9)") << testFile("mouseselection_true.qml") << 30 << 9 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" << true << true << 3;
+
+    QTest::newRow("on triple click (2,40)") << testFile("mouseselection_true.qml") << 2 << 40 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
+    QTest::newRow("on triple click (2,50)") << testFile("mouseselection_true.qml") << 2 << 50 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+    QTest::newRow("on triple click (25,40)") << testFile("mouseselection_true.qml") << 25 << 40 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
+    QTest::newRow("on triple click (25,50)") << testFile("mouseselection_true.qml") << 25 << 50 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+    QTest::newRow("on triple click (40,25)") << testFile("mouseselection_true.qml") << 40 << 25 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n" << true << true << 3;
+    QTest::newRow("on triple click (40,50)") << testFile("mouseselection_true.qml") << 40 << 50 << "9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+    QTest::newRow("on triple click (50,25)") << testFile("mouseselection_true.qml") << 50 << 25 << "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ\n9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+    QTest::newRow("on triple click (50,40)") << testFile("mouseselection_true.qml") << 50 << 40 << "9876543210\n\nZXYWVUTSRQPON MLKJIHGFEDCBA" << true << true << 3;
+
+    QTest::newRow("on tr align") << testFile("mouseselection_align_tr.qml") << 4 << 9 << "45678" << true << true << 1;
+    QTest::newRow("on center align") << testFile("mouseselection_align_center.qml") << 4 << 9 << "45678" << true << true << 1;
+    QTest::newRow("on bl align") << testFile("mouseselection_align_bl.qml") << 4 << 9 << "45678" << true << true << 1;
 }
 
 void tst_qquicktextedit::mouseSelection()
@@ -1677,17 +1845,16 @@ void tst_qquicktextedit::mouseSelection()
     QFETCH(QString, selectedText);
     QFETCH(bool, focus);
     QFETCH(bool, focusOnPress);
-    QFETCH(bool, doubleClick);
+    QFETCH(int, clicks);
 
-    QQuickView canvas(QUrl::fromLocalFile(qmlfile));
+    QQuickView window(QUrl::fromLocalFile(qmlfile));
 
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
 
-    QVERIFY(canvas.rootObject() != 0);
-    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+    QVERIFY(window.rootObject() != 0);
+    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
     QVERIFY(textEditObject != 0);
 
     textEditObject->setFocus(focus);
@@ -1696,47 +1863,49 @@ void tst_qquicktextedit::mouseSelection()
     // press-and-drag-and-release from x1 to x2
     QPoint p1 = textEditObject->positionToRectangle(from).center().toPoint();
     QPoint p2 = textEditObject->positionToRectangle(to).center().toPoint();
-    if (doubleClick)
-        QTest::mouseClick(&canvas, Qt::LeftButton, 0, p1);
-    QTest::mousePress(&canvas, Qt::LeftButton, 0, p1);
-    QTest::mouseMove(&canvas, p2);
-    QTest::mouseRelease(&canvas, Qt::LeftButton, 0, p2);
-    QTest::qWait(50);
+    if (clicks == 2)
+        QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
+    else if (clicks == 3)
+        QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
+    QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, p1);
+    QTest::mouseMove(&window, p2);
+    QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, p2);
     QTRY_COMPARE(textEditObject->selectedText(), selectedText);
 
     // Clicking and shift to clicking between the same points should select the same text.
     textEditObject->setCursorPosition(0);
-    if (doubleClick)
-        QTest::mouseDClick(&canvas, Qt::LeftButton, 0, p1);
-    else
-        QTest::mouseClick(&canvas, Qt::LeftButton, Qt::NoModifier, p1);
-    QTest::mouseClick(&canvas, Qt::LeftButton, Qt::ShiftModifier, p2);
-    QTest::qWait(50);
+    if (clicks > 1)
+        QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
+    if (clicks != 2)
+        QTest::mouseClick(&window, Qt::LeftButton, Qt::NoModifier, p1);
+    QTest::mouseClick(&window, Qt::LeftButton, Qt::ShiftModifier, p2);
     QTRY_COMPARE(textEditObject->selectedText(), selectedText);
+
+    // ### This is to prevent double click detection from carrying over to the next test.
+    QTest::qWait(QGuiApplication::styleHints()->mouseDoubleClickInterval() + 10);
 }
 
 void tst_qquicktextedit::dragMouseSelection()
 {
     QString qmlfile = testFile("mouseselection_true.qml");
 
-    QQuickView canvas(QUrl::fromLocalFile(qmlfile));
+    QQuickView window(QUrl::fromLocalFile(qmlfile));
 
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
 
-    QVERIFY(canvas.rootObject() != 0);
-    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+    QVERIFY(window.rootObject() != 0);
+    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
     QVERIFY(textEditObject != 0);
 
     // press-and-drag-and-release from x1 to x2
     int x1 = 10;
     int x2 = 70;
-    int y = textEditObject->height()/2;
-    QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
-    QTest::mouseMove(&canvas, QPoint(x2, y));
-    QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+    int y = QFontMetrics(textEditObject->font()).height() / 2;
+    QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+    QTest::mouseMove(&window, QPoint(x2, y));
+    QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
     QTest::qWait(300);
     QString str1;
     QTRY_VERIFY((str1 = textEditObject->selectedText()).length() > 3);
@@ -1744,14 +1913,15 @@ void tst_qquicktextedit::dragMouseSelection()
     // press and drag the current selection.
     x1 = 40;
     x2 = 100;
-    QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
-    QTest::mouseMove(&canvas, QPoint(x2, y));
-    QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+    QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+    QTest::mouseMove(&window, QPoint(x2, y));
+    QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
     QTest::qWait(300);
     QString str2;
     QTRY_VERIFY((str2 = textEditObject->selectedText()).length() > 3);
 
     QVERIFY(str1 != str2); // Verify the second press and drag is a new selection and not the first moved.
+
 }
 
 void tst_qquicktextedit::mouseSelectionMode_data()
@@ -1772,27 +1942,23 @@ void tst_qquicktextedit::mouseSelectionMode()
 
     QString text = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 
-    QQuickView canvas(QUrl::fromLocalFile(qmlfile));
+    QQuickView window(QUrl::fromLocalFile(qmlfile));
 
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(&canvas, qGuiApp->focusWindow());
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
 
-    QVERIFY(canvas.rootObject() != 0);
-    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+    QVERIFY(window.rootObject() != 0);
+    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
     QVERIFY(textEditObject != 0);
 
     // press-and-drag-and-release from x1 to x2
     int x1 = 10;
     int x2 = 70;
     int y = textEditObject->height()/2;
-    QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(x1,y));
-    QTest::mouseMove(&canvas, QPoint(x2, y));
-    //QTest::mouseMove(canvas, QPoint(x2,y)); // doesn't work
-//    QMouseEvent mv(QEvent::MouseMove, QPoint(x2,y), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
-//    QGuiApplication::sendEvent(&canvas, &mv);
-    QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(x2,y));
+    QTest::mousePress(&window, Qt::LeftButton, 0, QPoint(x1,y));
+    QTest::mouseMove(&window, QPoint(x2, y));
+    QTest::mouseRelease(&window, Qt::LeftButton, 0, QPoint(x2,y));
     QString str = textEditObject->selectedText();
     if (selectWords) {
         QTRY_COMPARE(textEditObject->selectedText(), text);
@@ -1802,14 +1968,88 @@ void tst_qquicktextedit::mouseSelectionMode()
     }
 }
 
+void tst_qquicktextedit::mouseSelectionMode_accessors()
+{
+    QQmlComponent component(&engine);
+    component.setData("import QtQuick 2.0\n TextEdit {}", QUrl());
+    QScopedPointer<QObject> object(component.create());
+    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(object.data());
+    QVERIFY(edit);
+
+    QSignalSpy spy(edit, SIGNAL(mouseSelectionModeChanged(SelectionMode)));
+
+    QCOMPARE(edit->mouseSelectionMode(), QQuickTextEdit::SelectCharacters);
+
+    edit->setMouseSelectionMode(QQuickTextEdit::SelectWords);
+    QCOMPARE(edit->mouseSelectionMode(), QQuickTextEdit::SelectWords);
+    QCOMPARE(spy.count(), 1);
+
+    edit->setMouseSelectionMode(QQuickTextEdit::SelectWords);
+    QCOMPARE(spy.count(), 1);
+
+    edit->setMouseSelectionMode(QQuickTextEdit::SelectCharacters);
+    QCOMPARE(edit->mouseSelectionMode(), QQuickTextEdit::SelectCharacters);
+    QCOMPARE(spy.count(), 2);
+}
+
+void tst_qquicktextedit::selectByMouse()
+{
+    QQmlComponent component(&engine);
+    component.setData("import QtQuick 2.0\n TextEdit {}", QUrl());
+    QScopedPointer<QObject> object(component.create());
+    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(object.data());
+    QVERIFY(edit);
+
+    QSignalSpy spy(edit, SIGNAL(selectByMouseChanged(bool)));
+
+    QCOMPARE(edit->selectByMouse(), false);
+
+    edit->setSelectByMouse(true);
+    QCOMPARE(edit->selectByMouse(), true);
+    QCOMPARE(spy.count(), 1);
+    QCOMPARE(spy.at(0).at(0).toBool(), true);
+
+    edit->setSelectByMouse(true);
+    QCOMPARE(spy.count(), 1);
+
+    edit->setSelectByMouse(false);
+    QCOMPARE(edit->selectByMouse(), false);
+    QCOMPARE(spy.count(), 2);
+    QCOMPARE(spy.at(1).at(0).toBool(), false);
+}
+
+void tst_qquicktextedit::renderType()
+{
+    QQmlComponent component(&engine);
+    component.setData("import QtQuick 2.0\n TextEdit {}", QUrl());
+    QScopedPointer<QObject> object(component.create());
+    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(object.data());
+    QVERIFY(edit);
+
+    QSignalSpy spy(edit, SIGNAL(renderTypeChanged()));
+
+    QCOMPARE(edit->renderType(), QQuickTextEdit::QtRendering);
+
+    edit->setRenderType(QQuickTextEdit::NativeRendering);
+    QCOMPARE(edit->renderType(), QQuickTextEdit::NativeRendering);
+    QCOMPARE(spy.count(), 1);
+
+    edit->setRenderType(QQuickTextEdit::NativeRendering);
+    QCOMPARE(spy.count(), 1);
+
+    edit->setRenderType(QQuickTextEdit::QtRendering);
+    QCOMPARE(edit->renderType(), QQuickTextEdit::QtRendering);
+    QCOMPARE(spy.count(), 2);
+}
+
 void tst_qquicktextedit::inputMethodHints()
 {
-    QQuickView canvas(testFileUrl("inputmethodhints.qml"));
-    canvas.show();
-    canvas.requestActivateWindow();
+    QQuickView window(testFileUrl("inputmethodhints.qml"));
+    window.show();
+    window.requestActivate();
 
-    QVERIFY(canvas.rootObject() != 0);
-    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+    QVERIFY(window.rootObject() != 0);
+    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
     QVERIFY(textEditObject != 0);
     QVERIFY(textEditObject->inputMethodHints() & Qt::ImhNoPredictiveText);
     QSignalSpy inputMethodHintSpy(textEditObject, SIGNAL(inputMethodHintsChanged()));
@@ -1823,19 +2063,38 @@ void tst_qquicktextedit::inputMethodHints()
     QCOMPARE(plainTextEdit.inputMethodHints(), Qt::ImhNone);
 }
 
+void tst_qquicktextedit::positionAt_data()
+{
+    QTest::addColumn<QQuickTextEdit::HAlignment>("horizontalAlignment");
+    QTest::addColumn<QQuickTextEdit::VAlignment>("verticalAlignment");
+
+    QTest::newRow("top-left") << QQuickTextEdit::AlignLeft << QQuickTextEdit::AlignTop;
+    QTest::newRow("bottom-left") << QQuickTextEdit::AlignLeft << QQuickTextEdit::AlignBottom;
+    QTest::newRow("center-left") << QQuickTextEdit::AlignLeft << QQuickTextEdit::AlignVCenter;
+
+    QTest::newRow("top-right") << QQuickTextEdit::AlignRight << QQuickTextEdit::AlignTop;
+    QTest::newRow("top-center") << QQuickTextEdit::AlignHCenter << QQuickTextEdit::AlignTop;
+
+    QTest::newRow("center") << QQuickTextEdit::AlignHCenter << QQuickTextEdit::AlignVCenter;
+}
+
 void tst_qquicktextedit::positionAt()
 {
-    QQuickView canvas(testFileUrl("positionAt.qml"));
-    QVERIFY(canvas.rootObject() != 0);
-    canvas.show();
-    canvas.requestActivateWindow();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-
-    QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+    QFETCH(QQuickTextEdit::HAlignment, horizontalAlignment);
+    QFETCH(QQuickTextEdit::VAlignment, verticalAlignment);
+
+    QQuickView window(testFileUrl("positionAt.qml"));
+    QVERIFY(window.rootObject() != 0);
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
+
+    QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
     QVERIFY(texteditObject != 0);
+    texteditObject->setHAlign(horizontalAlignment);
+    texteditObject->setVAlign(verticalAlignment);
 
-    QTextLayout layout(texteditObject->text());
+    QTextLayout layout(texteditObject->text().replace(QLatin1Char('\n'), QChar::LineSeparator));
     layout.setFont(texteditObject->font());
 
     if (!qmlDisableDistanceField()) {
@@ -1846,15 +2105,45 @@ void tst_qquicktextedit::positionAt()
 
     layout.beginLayout();
     QTextLine line = layout.createLine();
+    line.setLineWidth(texteditObject->width());
+    QTextLine secondLine = layout.createLine();
+    secondLine.setLineWidth(texteditObject->width());
     layout.endLayout();
 
-    const int y0 = line.height() / 2;
-    const int y1 = line.height() * 3 / 2;
+    qreal y0;
+    qreal y1;
+
+    switch (verticalAlignment) {
+    case QQuickTextEdit::AlignTop:
+        y0 = line.height() / 2;
+        y1 = line.height() * 3 / 2;
+        break;
+    case QQuickTextEdit::AlignVCenter:
+        y0 = (texteditObject->height() - line.height()) / 2;
+        y1 = (texteditObject->height() + line.height()) / 2;
+        break;
+    case QQuickTextEdit::AlignBottom:
+        y0 = texteditObject->height() - line.height() * 3 / 2;
+        y1 = texteditObject->height() - line.height() / 2;
+        break;
+    }
 
+    qreal xoff;
+    switch (horizontalAlignment) {
+    case QQuickTextEdit::AlignLeft:
+        xoff = 0;
+        break;
+    case QQuickTextEdit::AlignHCenter:
+        xoff = (texteditObject->width() - secondLine.naturalTextWidth()) / 2;
+        break;
+    case QQuickTextEdit::AlignRight:
+        xoff = texteditObject->width() - secondLine.naturalTextWidth();
+        break;
+    }
     int pos = texteditObject->positionAt(texteditObject->width()/2, y0);
 
-    int widthBegin = floor(line.cursorToX(pos - 1));
-    int widthEnd = ceil(line.cursorToX(pos + 1));
+    int widthBegin = floor(xoff + line.cursorToX(pos - 1));
+    int widthEnd = ceil(xoff + line.cursorToX(pos + 1));
 
     QVERIFY(widthBegin <= texteditObject->width() / 2);
     QVERIFY(widthEnd >= texteditObject->width() / 2);
@@ -1867,7 +2156,7 @@ void tst_qquicktextedit::positionAt()
     texteditObject->setCursorPosition(0);
 
     QInputMethodEvent inputEvent(preeditText, QList<QInputMethodEvent::Attribute>());
-    QGuiApplication::sendEvent(qGuiApp->focusObject(), &inputEvent);
+    QGuiApplication::sendEvent(texteditObject, &inputEvent);
 
     // Check all points within the preedit text return the same position.
     QCOMPARE(texteditObject->positionAt(0, y0), 0);
@@ -1883,13 +2172,13 @@ void tst_qquicktextedit::positionAt()
 
 void tst_qquicktextedit::linkActivated()
 {
-    QQuickView canvas(testFileUrl("linkActivated.qml"));
-    QVERIFY(canvas.rootObject() != 0);
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
+    QQuickView window(testFileUrl("linkActivated.qml"));
+    QVERIFY(window.rootObject() != 0);
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
 
-    QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(canvas.rootObject());
+    QQuickTextEdit *texteditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
     QVERIFY(texteditObject != 0);
 
     QSignalSpy spy(texteditObject, SIGNAL(linkActivated(QString)));
@@ -1899,21 +2188,21 @@ void tst_qquicktextedit::linkActivated()
     const QPointF linkPos = texteditObject->positionToRectangle(7).center();
     const QPointF textPos = texteditObject->positionToRectangle(2).center();
 
-    QTest::mouseClick(&canvas, Qt::LeftButton, 0, linkPos.toPoint());
+    QTest::mouseClick(&window, Qt::LeftButton, 0, linkPos.toPoint());
     QTRY_COMPARE(spy.count(), 1);
     QCOMPARE(spy.last()[0].toString(), link);
 
-    QTest::mouseClick(&canvas, Qt::LeftButton, 0, textPos.toPoint());
+    QTest::mouseClick(&window, Qt::LeftButton, 0, textPos.toPoint());
     QTest::qWait(50);
     QCOMPARE(spy.count(), 1);
 
     texteditObject->setReadOnly(true);
 
-    QTest::mouseClick(&canvas, Qt::LeftButton, 0, linkPos.toPoint());
+    QTest::mouseClick(&window, Qt::LeftButton, 0, linkPos.toPoint());
     QTRY_COMPARE(spy.count(), 2);
     QCOMPARE(spy.last()[0].toString(), link);
 
-    QTest::mouseClick(&canvas, Qt::LeftButton, 0, textPos.toPoint());
+    QTest::mouseClick(&window, Qt::LeftButton, 0, textPos.toPoint());
     QTest::qWait(50);
     QCOMPARE(spy.count(), 2);
 }
@@ -1931,12 +2220,15 @@ void tst_qquicktextedit::cursorDelegate()
     QFETCH(QUrl, source);
     QQuickView view(source);
     view.show();
-    view.requestActivateWindow();
+    view.requestActivate();
     QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
     QVERIFY(textEditObject != 0);
-    QVERIFY(textEditObject->findChild<QQuickItem*>("cursorInstance"));
+    // Delegate creation is deferred until focus in or cursor visibility is forced.
+    QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
+    QVERIFY(!textEditObject->isCursorVisible());
     //Test Delegate gets created
     textEditObject->setFocus(true);
+    QVERIFY(textEditObject->isCursorVisible());
     QQuickItem* delegateObject = textEditObject->findChild<QQuickItem*>("cursorInstance");
     QVERIFY(delegateObject);
     QCOMPARE(delegateObject->property("localProperty").toString(), QString("Hello"));
@@ -1991,6 +2283,8 @@ void tst_qquicktextedit::cursorDelegate()
     QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
     QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
 
+    textEditObject->setReadOnly(false);
+
     // Delegate moved when text is entered
     textEditObject->setText(QString());
     for (int i = 0; i < 20; ++i) {
@@ -2004,7 +2298,22 @@ void tst_qquicktextedit::cursorDelegate()
     for (int i = 0; i < 20; ++i) {
         QInputMethodEvent event;
         event.setCommitString("a");
-        QGuiApplication::sendEvent(&view, &event);
+        QGuiApplication::sendEvent(textEditObject, &event);
+        QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
+        QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
+    }
+    // Delegate moved when text is removed by im.
+    for (int i = 19; i > 1; --i) {
+        QInputMethodEvent event;
+        event.setCommitString(QString(), -1, 1);
+        QGuiApplication::sendEvent(textEditObject, &event);
+        QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
+        QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
+    }
+    {   // Delegate moved the text is changed in place by im.
+        QInputMethodEvent event;
+        event.setCommitString("i", -1, 1);
+        QGuiApplication::sendEvent(textEditObject, &event);
         QCOMPARE(textEditObject->cursorRectangle().x(), delegateObject->x());
         QCOMPARE(textEditObject->cursorRectangle().y(), delegateObject->y());
     }
@@ -2014,6 +2323,38 @@ void tst_qquicktextedit::cursorDelegate()
     QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
 }
 
+void tst_qquicktextedit::remoteCursorDelegate()
+{
+    TestHTTPServer server(SERVER_PORT);
+    server.serveDirectory(dataDirectory());
+
+    QQuickView view;
+
+    QQmlComponent component(view.engine(), QUrl(SERVER_ADDR "/RemoteCursor.qml"));
+
+    view.rootContext()->setContextProperty("contextDelegate", &component);
+    view.setSource(testFileUrl("cursorTestRemote.qml"));
+    view.show();
+    view.requestActivate();
+    QQuickTextEdit *textEditObject = view.rootObject()->findChild<QQuickTextEdit*>("textEditObject");
+    QVERIFY(textEditObject != 0);
+
+    // Delegate is created on demand, and so won't be available immediately.  Focus in or
+    // setCursorVisible(true) will trigger creation.
+    QTRY_VERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
+    QVERIFY(!textEditObject->isCursorVisible());
+
+    textEditObject->setFocus(true);
+    QVERIFY(textEditObject->isCursorVisible());
+
+    QCOMPARE(component.status(), QQmlComponent::Loading);
+    QVERIFY(!textEditObject->findChild<QQuickItem*>("cursorInstance"));
+
+    // Wait for component to load.
+    QTRY_COMPARE(component.status(), QQmlComponent::Ready);
+    QVERIFY(textEditObject->findChild<QQuickItem*>("cursorInstance"));
+}
+
 void tst_qquicktextedit::cursorVisible()
 {
     QQuickTextEdit edit;
@@ -2022,9 +2363,9 @@ void tst_qquicktextedit::cursorVisible()
 
     QQuickView view(testFileUrl("cursorVisible.qml"));
     view.show();
-    view.requestActivateWindow();
-    QTest::qWaitForWindowShown(&view);
-    QTRY_COMPARE(&view, qGuiApp->focusWindow());
+    view.requestActivate();
+    QTest::qWaitForWindowActive(&view);
+    QCOMPARE(&view, qGuiApp->focusWindow());
 
     QCOMPARE(edit.isCursorVisible(), false);
 
@@ -2054,14 +2395,14 @@ void tst_qquicktextedit::cursorVisible()
 
     QWindow alternateView;
     alternateView.show();
-    alternateView.requestActivateWindow();
-    QTest::qWaitForWindowShown(&alternateView);
+    alternateView.requestActivate();
+    QTest::qWaitForWindowActive(&alternateView);
 
     QCOMPARE(edit.isCursorVisible(), false);
     QCOMPARE(spy.count(), 6);
 
-    view.requestActivateWindow();
-    QTest::qWaitForWindowShown(&view);
+    view.requestActivate();
+    QTest::qWaitForWindowActive(&view);
     QCOMPARE(edit.isCursorVisible(), true);
     QCOMPARE(spy.count(), 7);
 
@@ -2120,20 +2461,17 @@ void tst_qquicktextedit::delegateLoading_data()
 
 void tst_qquicktextedit::delegateLoading()
 {
-#ifdef Q_OS_MAC
-    QSKIP("Test crashes during canvas tear down. QTBUG-23010");
-#endif
     QFETCH(QString, qmlfile);
     QFETCH(QString, error);
 
-    TestHTTPServer server(42332);
+    TestHTTPServer server(SERVER_PORT);
     server.serveDirectory(testFile("httpfail"), TestHTTPServer::Disconnect);
     server.serveDirectory(testFile("httpslow"), TestHTTPServer::Delay);
     server.serveDirectory(testFile("http"));
 
-    QQuickView view(QUrl(QLatin1String("http://localhost:42332/") + qmlfile));
+    QQuickView view(QUrl(QLatin1String(SERVER_ADDR "/") + qmlfile));
     view.show();
-    view.requestActivateWindow();
+    view.requestActivate();
 
     if (!error.isEmpty()) {
         QTest::ignoreMessage(QtWarningMsg, error.toUtf8());
@@ -2168,51 +2506,43 @@ the extent of the text, then they should ignore the keys.
 */
 void tst_qquicktextedit::navigation()
 {
-    QQuickView canvas(testFileUrl("navigation.qml"));
-    canvas.show();
-    canvas.requestActivateWindow();
+    QQuickView window(testFileUrl("navigation.qml"));
+    window.show();
+    window.requestActivate();
 
-    QVERIFY(canvas.rootObject() != 0);
+    QVERIFY(window.rootObject() != 0);
 
-    QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+    QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
 
     QVERIFY(input != 0);
     QTRY_VERIFY(input->hasActiveFocus() == true);
-    simulateKey(&canvas, Qt::Key_Left);
+    simulateKey(&window, Qt::Key_Left);
     QVERIFY(input->hasActiveFocus() == false);
-    simulateKey(&canvas, Qt::Key_Right);
+    simulateKey(&window, Qt::Key_Right);
     QVERIFY(input->hasActiveFocus() == true);
-    simulateKey(&canvas, Qt::Key_Right);
+    simulateKey(&window, Qt::Key_Right);
     QVERIFY(input->hasActiveFocus() == true);
-    simulateKey(&canvas, Qt::Key_Right);
+    simulateKey(&window, Qt::Key_Right);
     QVERIFY(input->hasActiveFocus() == false);
-    simulateKey(&canvas, Qt::Key_Left);
+    simulateKey(&window, Qt::Key_Left);
     QVERIFY(input->hasActiveFocus() == true);
 
     // Test left and right navigation works if the TextEdit is empty (QTBUG-25447).
     input->setText(QString());
     QCOMPARE(input->cursorPosition(), 0);
-    simulateKey(&canvas, Qt::Key_Right);
+    simulateKey(&window, Qt::Key_Right);
     QCOMPARE(input->hasActiveFocus(), false);
-    simulateKey(&canvas, Qt::Key_Left);
+    simulateKey(&window, Qt::Key_Left);
     QCOMPARE(input->hasActiveFocus(), true);
-    simulateKey(&canvas, Qt::Key_Left);
+    simulateKey(&window, Qt::Key_Left);
     QCOMPARE(input->hasActiveFocus(), false);
 }
 
-void tst_qquicktextedit::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_qquicktextedit::copyAndPaste()
+{
+    if (!PlatformQuirks::isClipboardAvailable())
+        QSKIP("This machine doesn't support the clipboard");
 
     QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
     QQmlComponent textEditComponent(&engine);
@@ -2236,6 +2566,9 @@ void tst_qquicktextedit::copyAndPaste() {
     QVERIFY(textEdit->canPaste());
     textEdit->setReadOnly(true);
     QVERIFY(!textEdit->canPaste());
+    textEdit->paste();
+    QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
+    QCOMPARE(textEdit->text().length(), 24);
     textEdit->setReadOnly(false);
     QVERIFY(textEdit->canPaste());
 
@@ -2245,11 +2578,21 @@ void tst_qquicktextedit::copyAndPaste() {
     QQuickTextEditPrivate *editPrivate = static_cast<QQuickTextEditPrivate*>(pri);
     QCOMPARE(textEdit->text(), editPrivate->text);
 
+    // cut: no selection
+    textEdit->cut();
+    QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
+
     // select word
     textEdit->setCursorPosition(0);
     textEdit->selectWord();
     QCOMPARE(textEdit->selectedText(), QString("Hello"));
 
+    // cut: read only.
+    textEdit->setReadOnly(true);
+    textEdit->cut();
+    QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
+    textEdit->setReadOnly(false);
+
     // select all and cut
     textEdit->selectAll();
     textEdit->cut();
@@ -2257,12 +2600,24 @@ void tst_qquicktextedit::copyAndPaste() {
     textEdit->paste();
     QCOMPARE(textEdit->text(), QString("Hello world!Hello world!"));
     QCOMPARE(textEdit->text().length(), 24);
-#endif
+
+    // Copy first word.
+    textEdit->setCursorPosition(0);
+    textEdit->selectWord();
+    textEdit->copy();
+    // copy: no selection, previous copy retained;
+    textEdit->setCursorPosition(0);
+    QCOMPARE(textEdit->selectedText(), QString());
+    textEdit->copy();
+    textEdit->setText(QString());
+    textEdit->paste();
+    QCOMPARE(textEdit->text(), QString("Hello"));
 }
+#endif
 
-void tst_qquicktextedit::canPaste() {
 #ifndef QT_NO_CLIPBOARD
-
+void tst_qquicktextedit::canPaste()
+{
     QGuiApplication::clipboard()->setText("Some text");
 
     QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
@@ -2272,15 +2627,15 @@ void tst_qquicktextedit::canPaste() {
     QVERIFY(textEdit != 0);
 
     // check initial value - QTBUG-17765
-    QQuickTextControl tc(0);
+    QTextDocument document;
+    QQuickTextControl tc(&document);
     QCOMPARE(textEdit->canPaste(), tc.canPaste());
-
-#endif
 }
+#endif
 
-void tst_qquicktextedit::canPasteEmpty() {
 #ifndef QT_NO_CLIPBOARD
-
+void tst_qquicktextedit::canPasteEmpty()
+{
     QGuiApplication::clipboard()->clear();
 
     QString componentStr = "import QtQuick 2.0\nTextEdit { text: \"Hello world!\" }";
@@ -2290,31 +2645,74 @@ void tst_qquicktextedit::canPasteEmpty() {
     QVERIFY(textEdit != 0);
 
     // check initial value - QTBUG-17765
-    QQuickTextControl tc(0);
+    QTextDocument document;
+    QQuickTextControl tc(&document);
     QCOMPARE(textEdit->canPaste(), tc.canPaste());
-
+}
 #endif
+
+#ifndef QT_NO_CLIPBOARD
+void tst_qquicktextedit::middleClickPaste()
+{
+    if (!PlatformQuirks::isClipboardAvailable())
+        QSKIP("This machine doesn't support the clipboard");
+
+    QQuickView window(testFileUrl("mouseselection_true.qml"));
+
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
+
+    QVERIFY(window.rootObject() != 0);
+    QQuickTextEdit *textEditObject = qobject_cast<QQuickTextEdit *>(window.rootObject());
+    QVERIFY(textEditObject != 0);
+
+    textEditObject->setFocus(true);
+
+    QString originalText = textEditObject->text();
+    QString selectedText = "234567";
+
+    // press-and-drag-and-release from x1 to x2
+    const QPoint p1 = textEditObject->positionToRectangle(2).center().toPoint();
+    const QPoint p2 = textEditObject->positionToRectangle(8).center().toPoint();
+    const QPoint p3 = textEditObject->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(textEditObject->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(textEditObject->text().mid(1, selectedText.length()), selectedText);
+    else
+        QCOMPARE(textEditObject->text(), originalText);
 }
+#endif
 
 void tst_qquicktextedit::readOnly()
 {
-    QQuickView canvas(testFileUrl("readOnly.qml"));
-    canvas.show();
-    canvas.requestActivateWindow();
+    QQuickView window(testFileUrl("readOnly.qml"));
+    window.show();
+    window.requestActivate();
 
-    QVERIFY(canvas.rootObject() != 0);
+    QVERIFY(window.rootObject() != 0);
 
-    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("myInput")));
+    QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("myInput")));
 
     QVERIFY(edit != 0);
     QTRY_VERIFY(edit->hasActiveFocus() == true);
     QVERIFY(edit->isReadOnly() == true);
     QString initial = edit->text();
     for (int k=Qt::Key_0; k<=Qt::Key_Z; k++)
-        simulateKey(&canvas, k);
-    simulateKey(&canvas, Qt::Key_Return);
-    simulateKey(&canvas, Qt::Key_Space);
-    simulateKey(&canvas, Qt::Key_Escape);
+        simulateKey(&window, k);
+    simulateKey(&window, Qt::Key_Return);
+    simulateKey(&window, Qt::Key_Space);
+    simulateKey(&window, Qt::Key_Escape);
     QCOMPARE(edit->text(), initial);
 
     edit->setCursorPosition(3);
@@ -2336,9 +2734,8 @@ void tst_qquicktextedit::textInput()
 {
     QQuickView view(testFileUrl("inputMethodEvent.qml"));
     view.show();
-    view.requestActivateWindow();
-    QTest::qWaitForWindowShown(&view);
-    QTRY_COMPARE(&view, qGuiApp->focusWindow());
+    view.requestActivate();
+    QTest::qWaitForWindowActive(&view);
     QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
     QVERIFY(edit);
     QVERIFY(edit->hasActiveFocus() == true);
@@ -2347,7 +2744,7 @@ void tst_qquicktextedit::textInput()
     QSignalSpy spy(edit, SIGNAL(textChanged()));
     QInputMethodEvent event;
     event.setCommitString( "Hello world!", 0, 0);
-    QGuiApplication::sendEvent(qGuiApp->focusObject(), &event);
+    QGuiApplication::sendEvent(edit, &event);
     QCOMPARE(edit->text(), QString("Hello world!"));
     QCOMPARE(spy.count(), 1);
 
@@ -2357,7 +2754,7 @@ void tst_qquicktextedit::textInput()
     QCOMPARE(editPrivate->text, QString("Hello world!"));
 
     QInputMethodQueryEvent queryEvent(Qt::ImEnabled);
-    QGuiApplication::sendEvent(qGuiApp->focusObject(), &queryEvent);
+    QGuiApplication::sendEvent(edit, &queryEvent);
     QCOMPARE(queryEvent.value(Qt::ImEnabled).toBool(), true);
 
     edit->setReadOnly(true);
@@ -2373,9 +2770,8 @@ void tst_qquicktextedit::inputMethodUpdate()
 
     QQuickView view(testFileUrl("inputMethodEvent.qml"));
     view.show();
-    view.requestActivateWindow();
-    QTest::qWaitForWindowShown(&view);
-    QTRY_COMPARE(&view, qGuiApp->focusWindow());
+    view.requestActivate();
+    QTest::qWaitForWindowActive(&view);
     QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
     QVERIFY(edit);
     QVERIFY(edit->hasActiveFocus() == true);
@@ -2464,9 +2860,8 @@ void tst_qquicktextedit::openInputPanel()
 
     QQuickView view(testFileUrl("openInputPanel.qml"));
     view.show();
-    view.requestActivateWindow();
-    QTest::qWaitForWindowShown(&view);
-    QTRY_COMPARE(&view, qGuiApp->focusWindow());
+    view.requestActivate();
+    QTest::qWaitForWindowActive(&view);
 
     QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
     QVERIFY(edit);
@@ -2474,7 +2869,6 @@ void tst_qquicktextedit::openInputPanel()
     // check default values
     QVERIFY(edit->focusOnPress());
     QVERIFY(!edit->hasActiveFocus());
-    qDebug() << &edit << qApp->focusObject();
     QVERIFY(qApp->focusObject() != edit);
 
     QCOMPARE(qApp->inputMethod()->isVisible(), false);
@@ -2509,7 +2903,7 @@ void tst_qquicktextedit::openInputPanel()
 
     anotherEdit.setFocus(false);
     QVERIFY(qApp->focusObject() != &anotherEdit);
-    QCOMPARE(view.activeFocusItem(), view.rootItem());
+    QCOMPARE(view.activeFocusItem(), view.contentItem());
     anotherEdit.setFocus(true);
 
     qApp->inputMethod()->hide();
@@ -2532,14 +2926,6 @@ void tst_qquicktextedit::openInputPanel()
     QTest::mouseRelease(&view, Qt::LeftButton, noModifiers, centerPoint);
     QCOMPARE(qApp->inputMethod()->isVisible(), false);
 
-    // input panel should open when openSoftwareInputPanel is called
-    edit->openSoftwareInputPanel();
-    QCOMPARE(qApp->inputMethod()->isVisible(), true);
-
-    // input panel should close when closeSoftwareInputPanel is called
-    edit->closeSoftwareInputPanel();
-    QCOMPARE(qApp->inputMethod()->isVisible(), false);
-
     inputMethodPrivate->testContext = 0;
 }
 
@@ -2553,9 +2939,9 @@ void tst_qquicktextedit::geometrySignals()
     delete o;
 }
 
+#ifndef QT_NO_CLIPBOARD
 void tst_qquicktextedit::pastingRichText_QTBUG_14003()
 {
-#ifndef QT_NO_CLIPBOARD
     QString componentStr = "import QtQuick 2.0\nTextEdit { textFormat: TextEdit.PlainText }";
     QQmlComponent component(&engine);
     component.setData(componentStr.toLatin1(), QUrl::fromLocalFile(""));
@@ -2571,8 +2957,8 @@ void tst_qquicktextedit::pastingRichText_QTBUG_14003()
     obj->paste();
     QTRY_VERIFY(obj->text() == "");
     QTRY_VERIFY(obj->textFormat() == QQuickTextEdit::PlainText);
-#endif
 }
+#endif
 
 void tst_qquicktextedit::implicitSize_data()
 {
@@ -2698,6 +3084,7 @@ void tst_qquicktextedit::clipRect()
     cursorComponent.setData("import QtQuick 2.0\nRectangle { height: 20; width: 8 }", QUrl());
 
     edit->setCursorDelegate(&cursorComponent);
+    edit->setCursorVisible(true);
 
     // If a cursor delegate is used it's size should determine the excess width.
     QCOMPARE(edit->clipRect().x(), qreal(0));
@@ -2779,6 +3166,7 @@ void tst_qquicktextedit::boundingRect()
     cursorComponent.setData("import QtQuick 2.0\nRectangle { height: 20; width: 8 }", QUrl());
 
     edit->setCursorDelegate(&cursorComponent);
+    edit->setCursorVisible(true);
 
     // Don't include the size of a cursor delegate as it has its own bounding rect.
     QCOMPARE(edit->boundingRect().x(), qreal(0));
@@ -2811,10 +3199,9 @@ void tst_qquicktextedit::preeditCursorRectangle()
 
     QQuickView view(testFileUrl("inputMethodEvent.qml"));
     view.show();
-    view.requestActivateWindow();
-    QTest::qWaitForWindowShown(&view);
+    view.requestActivate();
+    QTest::qWaitForWindowActive(&view);
 
-    QTRY_COMPARE(&view, qGuiApp->focusWindow());
     QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
     QVERIFY(edit);
 
@@ -2826,30 +3213,31 @@ void tst_qquicktextedit::preeditCursorRectangle()
 
     QRectF currentRect;
 
+    QCOMPARE(QGuiApplication::focusObject(), static_cast<QObject *>(edit));
     QInputMethodQueryEvent query(Qt::ImCursorRectangle);
-    QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
+    QCoreApplication::sendEvent(edit, &query);
     QRectF previousRect = query.value(Qt::ImCursorRectangle).toRectF();
 
     // Verify that the micro focus rect is positioned the same for position 0 as
     // it would be if there was no preedit text.
     QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>()
             << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 0, preeditText.length(), QVariant()));
-    QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
-    QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
+    QCoreApplication::sendEvent(edit, &imEvent);
+    QCoreApplication::sendEvent(edit, &query);
     currentRect = query.value(Qt::ImCursorRectangle).toRectF();
     QCOMPARE(edit->cursorRectangle(), currentRect);
     QCOMPARE(cursor->pos(), currentRect.topLeft());
     QCOMPARE(currentRect, previousRect);
-    QCOMPARE(editSpy.count(), 0); editSpy.clear();
-    QCOMPARE(panelSpy.count(), 0); panelSpy.clear();
 
     // Verify that the micro focus rect moves to the left as the cursor position
     // is incremented.
+    editSpy.clear();
+    panelSpy.clear();
     for (int i = 1; i <= 5; ++i) {
         QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>()
                 << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, i, preeditText.length(), QVariant()));
-        QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
-        QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
+        QCoreApplication::sendEvent(edit, &imEvent);
+        QCoreApplication::sendEvent(edit, &query);
         currentRect = query.value(Qt::ImCursorRectangle).toRectF();
         QCOMPARE(edit->cursorRectangle(), currentRect);
         QCOMPARE(cursor->pos(), currentRect.topLeft());
@@ -2859,14 +3247,27 @@ void tst_qquicktextedit::preeditCursorRectangle()
         previousRect = currentRect;
     }
 
+    // Verify that if the cursor rectangle is updated if the pre-edit text changes
+    // but the (non-zero) cursor position is the same.
+    editSpy.clear();
+    panelSpy.clear();
+    {   QInputMethodEvent imEvent("wwwww", QList<QInputMethodEvent::Attribute>()
+                << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, 5, 1, QVariant()));
+        QCoreApplication::sendEvent(edit, &imEvent); }
+    QCoreApplication::sendEvent(edit, &query);
+    currentRect = query.value(Qt::ImCursorRectangle).toRectF();
+    QCOMPARE(edit->cursorRectangle(), currentRect);
+    QCOMPARE(cursor->pos(), currentRect.topLeft());
+    QCOMPARE(editSpy.count(), 1);
+    QCOMPARE(panelSpy.count(), 1);
+
     // Verify that if there is no preedit cursor then the micro focus rect is the
     // same as it would be if it were positioned at the end of the preedit text.
-    QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent);
     editSpy.clear();
     panelSpy.clear();
     {   QInputMethodEvent imEvent(preeditText, QList<QInputMethodEvent::Attribute>());
-        QCoreApplication::sendEvent(qGuiApp->focusObject(), &imEvent); }
-    QCoreApplication::sendEvent(qGuiApp->focusObject(), &query);
+        QCoreApplication::sendEvent(edit, &imEvent); }
+    QCoreApplication::sendEvent(edit, &query);
     currentRect = query.value(Qt::ImCursorRectangle).toRectF();
     QCOMPARE(edit->cursorRectangle(), currentRect);
     QCOMPARE(cursor->pos(), currentRect.topLeft());
@@ -2881,11 +3282,13 @@ void tst_qquicktextedit::inputMethodComposing()
 
     QQuickView view(testFileUrl("inputContext.qml"));
     view.show();
-    view.requestActivateWindow();
-    QTest::qWaitForWindowShown(&view);
-    QTRY_COMPARE(&view, qGuiApp->focusWindow());
+    view.requestActivate();
+    QTest::qWaitForWindowActive(&view);
+
     QQuickTextEdit *edit = qobject_cast<QQuickTextEdit *>(view.rootObject());
     QVERIFY(edit);
+    QCOMPARE(QGuiApplication::focusObject(), static_cast<QObject *>(edit));
+
     QSignalSpy spy(edit, SIGNAL(inputMethodComposingChanged()));
     edit->setCursorPosition(12);
 
@@ -2983,9 +3386,9 @@ void tst_qquicktextedit::inputMethodComposing()
 
 void tst_qquicktextedit::cursorRectangleSize()
 {
-    QQuickView *canvas = new QQuickView(testFileUrl("positionAt.qml"));
-    QVERIFY(canvas->rootObject() != 0);
-    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(canvas->rootObject());
+    QQuickView *window = new QQuickView(testFileUrl("positionAt.qml"));
+    QVERIFY(window->rootObject() != 0);
+    QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit *>(window->rootObject());
 
     // make sure cursor rectangle is not at (0,0)
     textEdit->setX(10);
@@ -2993,12 +3396,12 @@ void tst_qquicktextedit::cursorRectangleSize()
     textEdit->setCursorPosition(3);
     QVERIFY(textEdit != 0);
     textEdit->setFocus(true);
-    canvas->show();
-    canvas->requestActivateWindow();
-    QTest::qWaitForWindowShown(canvas);
+    window->show();
+    window->requestActivate();
+    QTest::qWaitForWindowActive(window);
 
     QInputMethodQueryEvent event(Qt::ImCursorRectangle);
-    qApp->sendEvent(qApp->focusObject(), &event);
+    qApp->sendEvent(textEdit, &event);
     QRectF cursorRectFromQuery = event.value(Qt::ImCursorRectangle).toRectF();
 
     QRectF cursorRectFromItem = textEdit->cursorRectangle();
@@ -3010,14 +3413,14 @@ void tst_qquicktextedit::cursorRectangleSize()
     // item cursor rectangle and positionToRectangle calculations match
     QCOMPARE(cursorRectFromItem, cursorRectFromPositionToRectangle);
 
-    // item-canvas transform and input item transform match
-    QCOMPARE(QQuickItemPrivate::get(textEdit)->itemToCanvasTransform(), qApp->inputMethod()->inputItemTransform());
+    // item-window transform and input item transform match
+    QCOMPARE(QQuickItemPrivate::get(textEdit)->itemToWindowTransform(), qApp->inputMethod()->inputItemTransform());
 
     // input panel cursorRectangle property and tranformed item cursor rectangle match
-    QRectF sceneCursorRect = QQuickItemPrivate::get(textEdit)->itemToCanvasTransform().mapRect(cursorRectFromItem);
+    QRectF sceneCursorRect = QQuickItemPrivate::get(textEdit)->itemToWindowTransform().mapRect(cursorRectFromItem);
     QCOMPARE(sceneCursorRect, qApp->inputMethod()->cursorRectangle());
 
-    delete canvas;
+    delete window;
 }
 
 void tst_qquicktextedit::getText_data()
@@ -3029,6 +3432,8 @@ void tst_qquicktextedit::getText_data()
 
     const QString richBoldText = QStringLiteral("This is some <b>bold</b> text");
     const QString plainBoldText = QStringLiteral("This is some bold text");
+    const QString richBoldTextLB = QStringLiteral("This is some<br/><b>bold</b> text");
+    const QString plainBoldTextLB = QString(QStringLiteral("This is some\nbold text")).replace(QLatin1Char('\n'), QChar(QChar::LineSeparator));
 
     QTest::newRow("all plain text")
             << standard.at(0)
@@ -3069,6 +3474,47 @@ void tst_qquicktextedit::getText_data()
             << richBoldText
             << 14 << 21
             << plainBoldText.mid(14, 7);
+
+    // Line break.
+    QTest::newRow("all plain text (line break)")
+            << standard.at(1)
+            << 0 << standard.at(1).length()
+            << standard.at(1);
+
+    QTest::newRow("plain text sub string (line break)")
+            << standard.at(1)
+            << 0 << 12
+            << standard.at(1).mid(0, 12);
+
+    QTest::newRow("plain text sub string reversed (line break)")
+            << standard.at(1)
+            << 12 << 0
+            << standard.at(1).mid(0, 12);
+
+    QTest::newRow("plain text cropped beginning (line break)")
+            << standard.at(1)
+            << -3 << 4
+            << standard.at(1).mid(0, 4);
+
+    QTest::newRow("plain text cropped end (line break)")
+            << standard.at(1)
+            << 23 << standard.at(1).length() + 8
+            << standard.at(1).mid(23);
+
+    QTest::newRow("plain text cropped beginning and end (line break)")
+            << standard.at(1)
+            << -9 << standard.at(1).length() + 4
+            << standard.at(1);
+
+    QTest::newRow("all rich text (line break)")
+            << richBoldTextLB
+            << 0 << plainBoldTextLB.length()
+            << plainBoldTextLB;
+
+    QTest::newRow("rich text sub string (line break)")
+            << richBoldTextLB
+            << 14 << 21
+            << plainBoldTextLB.mid(14, 7);
 }
 
 void tst_qquicktextedit::getText()
@@ -3380,7 +3826,7 @@ void tst_qquicktextedit::insert()
     textEdit->setTextFormat(textFormat);
     textEdit->select(selectionStart, selectionEnd);
 
-    QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged()));
+    QSignalSpy selectionSpy(textEdit, SIGNAL(selectedTextChanged()));
     QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged()));
     QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged()));
     QSignalSpy textSpy(textEdit, SIGNAL(textChanged()));
@@ -3404,8 +3850,8 @@ void tst_qquicktextedit::insert()
     if (selectionStart > selectionEnd)
         qSwap(selectionStart, selectionEnd);
 
-    QEXPECT_FAIL("into selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
-    QEXPECT_FAIL("into reversed selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
+    QEXPECT_FAIL("into selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
+    QEXPECT_FAIL("into reversed selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
     QCOMPARE(selectionSpy.count() > 0, selectionChanged);
     QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
     QEXPECT_FAIL("into reversed selection", "selectionEndChanged signal not emitted", Continue);
@@ -3625,7 +4071,7 @@ void tst_qquicktextedit::remove()
     textEdit->setTextFormat(textFormat);
     textEdit->select(selectionStart, selectionEnd);
 
-    QSignalSpy selectionSpy(textEdit, SIGNAL(selectionChanged()));
+    QSignalSpy selectionSpy(textEdit, SIGNAL(selectedTextChanged()));
     QSignalSpy selectionStartSpy(textEdit, SIGNAL(selectionStartChanged()));
     QSignalSpy selectionEndSpy(textEdit, SIGNAL(selectionEndChanged()));
     QSignalSpy textSpy(textEdit, SIGNAL(textChanged()));
@@ -3648,8 +4094,8 @@ void tst_qquicktextedit::remove()
     QCOMPARE(textEdit->selectionEnd(), expectedSelectionEnd);
     QCOMPARE(textEdit->cursorPosition(), expectedCursorPosition);
 
-    QEXPECT_FAIL("from selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
-    QEXPECT_FAIL("from reversed selection", "selectionChanged signal isn't emitted on edits within selection", Continue);
+    QEXPECT_FAIL("from selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
+    QEXPECT_FAIL("from reversed selection", "selectedTextChanged signal isn't emitted on edits within selection", Continue);
     QCOMPARE(selectionSpy.count() > 0, selectionChanged);
     QCOMPARE(selectionStartSpy.count() > 0, selectionStart != expectedSelectionStart);
     QEXPECT_FAIL("from reversed selection", "selectionEndChanged signal not emitted", Continue);
@@ -3806,18 +4252,19 @@ void tst_qquicktextedit::keySequence()
     QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
     QVERIFY(textEdit != 0);
 
-    QQuickCanvas canvas;
-    textEdit->setParentItem(canvas.rootItem());
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+    QQuickWindow window;
+    textEdit->setParentItem(window.contentItem());
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
+
+    QVERIFY(textEdit->hasActiveFocus());
 
-    simulateKey(&canvas, layoutDirection);
+    simulateKey(&window, layoutDirection);
 
     textEdit->select(selectionStart, selectionEnd);
 
-    simulateKeys(&canvas, sequence);
+    simulateKeys(&window, sequence);
 
     QCOMPARE(textEdit->cursorPosition(), cursorPosition);
     QCOMPARE(textEdit->text(), expectedText);
@@ -3968,13 +4415,13 @@ void tst_qquicktextedit::undo()
     QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
     QVERIFY(textEdit != 0);
 
-    QQuickCanvas canvas;
-    textEdit->setParentItem(canvas.rootItem());
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+    QQuickWindow window;
+    textEdit->setParentItem(window.contentItem());
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
 
+    QVERIFY(textEdit->hasActiveFocus());
     QVERIFY(!textEdit->canUndo());
 
     QSignalSpy spy(textEdit, SIGNAL(canUndoChanged()));
@@ -3995,7 +4442,7 @@ void tst_qquicktextedit::undo()
         }
 
         for (int j = 0; j < insertString.at(i).length(); j++)
-            QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
+            QTest::keyClick(&window, insertString.at(i).at(j).toLatin1());
     }
 
     QCOMPARE(spy.count(), 1);
@@ -4054,12 +4501,12 @@ void tst_qquicktextedit::redo()
     QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
     QVERIFY(textEdit != 0);
 
-    QQuickCanvas canvas;
-    textEdit->setParentItem(canvas.rootItem());
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+    QQuickWindow window;
+    textEdit->setParentItem(window.contentItem());
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
+    QVERIFY(textEdit->hasActiveFocus());
 
     QVERIFY(!textEdit->canUndo());
     QVERIFY(!textEdit->canRedo());
@@ -4072,7 +4519,7 @@ void tst_qquicktextedit::redo()
         if (insertIndex[i] > -1)
             textEdit->setCursorPosition(insertIndex[i]);
         for (int j = 0; j < insertString.at(i).length(); j++)
-            QTest::keyClick(&canvas, insertString.at(i).at(j).toLatin1());
+            QTest::keyClick(&window, insertString.at(i).at(j).toLatin1());
         QVERIFY(textEdit->canUndo());
         QVERIFY(!textEdit->canRedo());
     }
@@ -4234,6 +4681,37 @@ void tst_qquicktextedit::undo_keypressevents_data()
 
         QTest::newRow("Inserts,moving,selection and overwriting") << 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"
+                << ""
+                << "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"
+                << "A"
+                << "123";
+        QTest::newRow("Copy,paste") << keys << expectedString;
+    }
 }
 
 void tst_qquicktextedit::undo_keypressevents()
@@ -4247,14 +4725,14 @@ void tst_qquicktextedit::undo_keypressevents()
     QQuickTextEdit *textEdit = qobject_cast<QQuickTextEdit*>(textEditComponent.create());
     QVERIFY(textEdit != 0);
 
-    QQuickCanvas canvas;
-    textEdit->setParentItem(canvas.rootItem());
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QTRY_COMPARE(QGuiApplication::activeWindow(), &canvas);
+    QQuickWindow window;
+    textEdit->setParentItem(window.contentItem());
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
+    QVERIFY(textEdit->hasActiveFocus());
 
-    simulateKeys(&canvas, keys);
+    simulateKeys(&window, keys);
 
     for (int i = 0; i < expectedString.size(); ++i) {
         QCOMPARE(textEdit->text() , expectedString[i]);
@@ -4308,7 +4786,7 @@ void tst_qquicktextedit::embeddedImages()
     QFETCH(QUrl, qmlfile);
     QFETCH(QString, error);
 
-    TestHTTPServer server(42332);
+    TestHTTPServer server(SERVER_PORT);
     server.serveDirectory(testFile("http"));
 
     if (!error.isEmpty())
@@ -4335,13 +4813,13 @@ void tst_qquicktextedit::embeddedImages()
 
 void tst_qquicktextedit::emptytags_QTBUG_22058()
 {
-    QQuickView canvas(testFileUrl("qtbug-22058.qml"));
-    QVERIFY(canvas.rootObject() != 0);
+    QQuickView window(testFileUrl("qtbug-22058.qml"));
+    QVERIFY(window.rootObject() != 0);
 
-    canvas.show();
-    canvas.requestActivateWindow();
-    QTest::qWaitForWindowShown(&canvas);
-    QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(canvas.rootObject()->property("inputField")));
+    window.show();
+    window.requestActivate();
+    QTest::qWaitForWindowActive(&window);
+    QQuickTextEdit *input = qobject_cast<QQuickTextEdit *>(qvariant_cast<QObject *>(window.rootObject()->property("inputField")));
     QVERIFY(input->hasActiveFocus());
 
     QInputMethodEvent event("", QList<QInputMethodEvent::Attribute>());