diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index f96329139d52876943ef45e7e5851b07668cfef4..619577d93fa3bcd3642097056c8839c533e3a620 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -54,9 +54,10 @@
 #include "base/command_line.h"
 #include "cc/output/direct_renderer.h"
 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
-#include "content/browser/renderer_host/text_input_manager.h"
 #include "content/common/cursors/webcursor.h"
+#include "content/common/input_messages.h"
 #include "content/public/browser/browser_accessibility_state.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_switches.h"
@@ -92,6 +93,13 @@
 
 namespace QtWebEngineCore {
 
+enum ImStateFlags {
+    TextInputStateUpdated = 1 << 0,
+    TextSelectionUpdated = 1 << 1,
+    TextSelectionBoundsUpdated = 1 << 2,
+    AllFlags = TextInputStateUpdated | TextSelectionUpdated | TextSelectionBoundsUpdated
+};
+
 static inline ui::LatencyInfo CreateLatencyInfo(const blink::WebInputEvent& event) {
   ui::LatencyInfo latency_info;
   // The latency number should only be added if the timestamp is valid.
@@ -238,13 +246,17 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget
     , m_needsDelegatedFrameAck(false)
     , m_loadVisuallyCommittedState(NotCommitted)
     , m_adapterClient(0)
-    , m_currentInputType(ui::TEXT_INPUT_TYPE_NONE)
     , m_imeInProgress(false)
     , m_receivedEmptyImeText(false)
     , m_initPending(false)
     , m_beginFrameSource(nullptr)
     , m_needsBeginFrames(false)
     , m_addedFrameObserver(false)
+    , m_imState(0)
+    , m_anchorPositionWithinSelection(0)
+    , m_cursorPositionWithinSelection(0)
+    , m_cursorPosition(0)
+    , m_emptyPreviousSelection(true)
 {
     m_host->SetView(this);
 #ifndef QT_NO_ACCESSIBILITY
@@ -255,6 +267,9 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost* widget
     auto* task_runner = base::ThreadTaskRunnerHandle::Get().get();
     m_beginFrameSource.reset(new cc::DelayBasedBeginFrameSource(
             base::MakeUnique<cc::DelayBasedTimeSource>(task_runner)));
+
+    if (GetTextInputManager())
+        GetTextInputManager()->AddObserver(this);
 }
 
 RenderWidgetHostViewQt::~RenderWidgetHostViewQt()
@@ -263,6 +278,9 @@ RenderWidgetHostViewQt::~RenderWidgetHostViewQt()
 #ifndef QT_NO_ACCESSIBILITY
     QAccessible::removeActivationObserver(this);
 #endif // QT_NO_ACCESSIBILITY
+
+    if (text_input_manager_)
+        text_input_manager_->RemoveObserver(this);
 }
 
 void RenderWidgetHostViewQt::setDelegate(RenderWidgetHostViewQtDelegate* delegate)
@@ -576,15 +594,6 @@ void RenderWidgetHostViewQt::SetIsLoading(bool)
     // We use WebContentsDelegateQt::LoadingStateChanged to notify about loading state.
 }
 
-void RenderWidgetHostViewQt::TextInputStateChanged(const content::TextInputState &params)
-{
-    m_currentInputType = params.type;
-    m_delegate->inputMethodStateChanged(params.type != ui::TEXT_INPUT_TYPE_NONE);
-    m_delegate->setInputMethodHints(toQtInputMethodHints(params.type));
-
-    m_surroundingText = QString::fromStdString(params.value);
-}
-
 void RenderWidgetHostViewQt::ImeCancelComposition()
 {
     qApp->inputMethod()->reset();
@@ -707,16 +716,114 @@ void RenderWidgetHostViewQt::ClearCompositorFrame()
 {
 }
 
-void RenderWidgetHostViewQt::SelectionChanged(const base::string16 &text, size_t offset, const gfx::Range &range)
+void RenderWidgetHostViewQt::OnUpdateTextInputStateCalled(content::TextInputManager *text_input_manager, RenderWidgetHostViewBase *updated_view, bool did_update_state)
 {
-    content::RenderWidgetHostViewBase::SelectionChanged(text, offset, range);
-    m_adapterClient->selectionChanged();
+    Q_UNUSED(text_input_manager);
+    Q_UNUSED(updated_view);
+    Q_UNUSED(did_update_state);
+
+    ui::TextInputType type = getTextInputType();
+    m_delegate->inputMethodStateChanged(type != ui::TEXT_INPUT_TYPE_NONE);
+    m_delegate->setInputMethodHints(toQtInputMethodHints(type));
+
+    const content::TextInputState *state = text_input_manager_->GetTextInputState();
+    if (!state)
+        return;
+
+    if (GetSelectedText().empty())
+        m_cursorPosition = state->selection_start;
+
+    m_surroundingText = QString::fromStdString(state->value);
+
+    // Remove IME composition text from the surrounding text
+    if (state->composition_start != -1 && state->composition_end != -1)
+        m_surroundingText.remove(state->composition_start, state->composition_end - state->composition_start);
+
+    if (m_imState & ImStateFlags::TextInputStateUpdated) {
+        m_imState = ImStateFlags::TextInputStateUpdated;
+        return;
+    }
+
+    // Ignore selection change triggered by ime composition unless it clears an actual text selection
+    if (state->composition_start != -1 && m_emptyPreviousSelection) {
+        m_imState = 0;
+        return;
+    }
+
+    m_imState |= ImStateFlags::TextInputStateUpdated;
+    if (m_imState == ImStateFlags::AllFlags)
+        selectionChanged();
+}
+
+void RenderWidgetHostViewQt::OnSelectionBoundsChanged(content::TextInputManager *text_input_manager, RenderWidgetHostViewBase *updated_view)
+{
+    Q_UNUSED(text_input_manager);
+    Q_UNUSED(updated_view);
+
+    m_imState |= ImStateFlags::TextSelectionBoundsUpdated;
+    if (m_imState == ImStateFlags::AllFlags)
+        selectionChanged();
+}
+
+void RenderWidgetHostViewQt::OnTextSelectionChanged(content::TextInputManager *text_input_manager, RenderWidgetHostViewBase *updated_view)
+{
+    Q_UNUSED(text_input_manager);
+    Q_UNUSED(updated_view);
 
 #if defined(USE_X11)
-    // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
-    ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION);
-    clipboard_writer.WriteText(text);
-#endif
+    if (!GetSelectedText().empty()) {
+        // Set the CLIPBOARD_TYPE_SELECTION to the ui::Clipboard.
+        ui::ScopedClipboardWriter clipboard_writer(ui::CLIPBOARD_TYPE_SELECTION);
+        clipboard_writer.WriteText(GetSelectedText());
+    }
+#endif // defined(USE_X11)
+
+    m_imState |= ImStateFlags::TextSelectionUpdated;
+    if (m_imState == ImStateFlags::AllFlags)
+        selectionChanged();
+}
+
+void RenderWidgetHostViewQt::selectionChanged()
+{
+    // Reset input manager state
+    m_imState = 0;
+
+    const content::TextInputManager::TextSelection *selection = text_input_manager_->GetTextSelection();
+    if (!selection)
+        return;
+
+    if (!selection->range.IsValid())
+        return;
+
+    // Avoid duplicate empty selectionChanged() signals
+    if (GetSelectedText().empty() && m_emptyPreviousSelection) {
+        m_anchorPositionWithinSelection = m_cursorPosition;
+        m_cursorPositionWithinSelection = m_cursorPosition;
+        return;
+    }
+
+    uint newAnchorPositionWithinSelection = 0;
+    uint newCursorPositionWithinSelection = 0;
+
+    if (text_input_manager_->GetSelectionRegion()->anchor.type() == gfx::SelectionBound::RIGHT) {
+        newAnchorPositionWithinSelection = selection->range.GetMax() - selection->offset;
+        newCursorPositionWithinSelection = selection->range.GetMin() - selection->offset;
+    } else {
+        newAnchorPositionWithinSelection = selection->range.GetMin() - selection->offset;
+        newCursorPositionWithinSelection = selection->range.GetMax() - selection->offset;
+    }
+
+    if (m_anchorPositionWithinSelection == newAnchorPositionWithinSelection && m_cursorPositionWithinSelection == newCursorPositionWithinSelection)
+        return;
+
+    m_anchorPositionWithinSelection = newAnchorPositionWithinSelection;
+    m_cursorPositionWithinSelection = newCursorPositionWithinSelection;
+
+    if (!GetSelectedText().empty())
+        m_cursorPosition = newCursorPositionWithinSelection;
+
+    m_emptyPreviousSelection = GetSelectedText().empty();
+    m_adapterClient->selectionChanged();
 }
 
 void RenderWidgetHostViewQt::OnGestureEvent(const ui::GestureEventData& gesture)
@@ -820,34 +927,27 @@ QVariant RenderWidgetHostViewQt::inputMethodQuery(Qt::InputMethodQuery query)
 {
     switch (query) {
     case Qt::ImEnabled:
-        return QVariant(m_currentInputType != ui::TEXT_INPUT_TYPE_NONE);
+        return QVariant(getTextInputType() != ui::TEXT_INPUT_TYPE_NONE);
     case Qt::ImFont:
+        // TODO: Implement this
         return QVariant();
     case Qt::ImCursorRectangle:
-        // QIBusPlatformInputContext might query ImCursorRectangle before the
-        // RenderWidgetHostView is created. Without an available view GetSelectionRange()
-        // returns nullptr.
-        if (!GetTextInputManager()->GetSelectionRegion())
+        if (!text_input_manager_ || !text_input_manager_->GetActiveWidget())
             return QVariant();
-        return toQt(GetTextInputManager()->GetSelectionRegion()->caret_rect);
+        return toQt(text_input_manager_->GetSelectionRegion()->caret_rect);
     case Qt::ImCursorPosition:
-        Q_ASSERT(GetTextInputManager()->GetSelectionRegion());
-        return toQt(GetTextInputManager()->GetSelectionRegion()->focus.edge_top_rounded().x());
+        return m_cursorPosition;
     case Qt::ImAnchorPosition:
-        Q_ASSERT(GetTextInputManager()->GetSelectionRegion());
-        return toQt(GetTextInputManager()->GetSelectionRegion()->anchor.edge_top_rounded().x());
+        return GetSelectedText().empty() ? m_cursorPosition : m_anchorPositionWithinSelection;
     case Qt::ImSurroundingText:
         return m_surroundingText;
-    case Qt::ImCurrentSelection: {
-        Q_ASSERT(GetTextInputManager()->GetTextSelection());
-        base::string16 text;
-        GetTextInputManager()->GetTextSelection()->GetSelectedText(&text);
-        return toQt(text);
-    }
+    case Qt::ImCurrentSelection:
+        return toQt(GetSelectedText());
     case Qt::ImMaximumTextLength:
+        // TODO: Implement this
         return QVariant(); // No limit.
     case Qt::ImHints:
-        return int(toQtInputMethodHints(m_currentInputType));
+        return int(toQtInputMethodHints(getTextInputType()));
     default:
         return QVariant();
     }
@@ -1005,6 +1105,9 @@ void RenderWidgetHostViewQt::handleKeyEvent(QKeyEvent *ev)
 
 void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
 {
+    // Reset input manager state
+    m_imState = 0;
+
     if (!m_host)
         return;
 
@@ -1016,19 +1119,9 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
 
     const QList<QInputMethodEvent::Attribute> &attributes = ev->attributes();
     std::vector<blink::WebCompositionUnderline> underlines;
-    auto ensureValidSelectionRange = [&]() {
-        if (!selectionRange.IsValid()) {
-            // We did not receive a valid selection range, hence the range is going to mark the
-            // cursor position.
-            int newCursorPosition =
-                    (cursorPositionInPreeditString < 0) ? preeditString.length()
-                                                        : cursorPositionInPreeditString;
-            selectionRange.set_start(newCursorPosition);
-            selectionRange.set_end(newCursorPosition);
-        }
-    };
+    bool hasSelection = false;
 
-    Q_FOREACH (const QInputMethodEvent::Attribute &attribute, attributes) {
+    for (const auto &attribute : attributes) {
         switch (attribute.type) {
         case QInputMethodEvent::TextFormat: {
             if (preeditString.isEmpty())
@@ -1065,6 +1158,15 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
             cursorPositionInPreeditString = attribute.start;
             break;
         case QInputMethodEvent::Selection:
+            hasSelection = true;
+
+            // Cancel IME composition
+            if (preeditString.isEmpty() && attribute.start + attribute.length == 0) {
+                selectionRange.set_start(0);
+                selectionRange.set_end(0);
+                break;
+            }
+
             selectionRange.set_start(qMin(attribute.start, (attribute.start + attribute.length)));
             selectionRange.set_end(qMax(attribute.start, (attribute.start + attribute.length)));
             break;
@@ -1073,6 +1175,22 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
         }
     }
 
+    if (!selectionRange.IsValid()) {
+        // We did not receive a valid selection range, hence the range is going to mark the
+        // cursor position.
+        int newCursorPosition =
+                (cursorPositionInPreeditString < 0) ? preeditString.length()
+                                                    : cursorPositionInPreeditString;
+        selectionRange.set_start(newCursorPosition);
+        selectionRange.set_end(newCursorPosition);
+    }
+
+    if (hasSelection) {
+        content::RenderFrameHost *frameHost = getFocusedFrameHost();
+        if (frameHost)
+            frameHost->Send(new InputMsg_SetEditableSelectionOffsets(frameHost->GetRoutingID(), selectionRange.start(), selectionRange.end()));
+    }
+
     int replacementLength = ev->replacementLength();
     gfx::Range replacementRange = gfx::Range::InvalidRange();
 
@@ -1089,7 +1207,6 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
     }
 
     auto setCompositionString = [&](const QString &compositionString){
-        ensureValidSelectionRange();
         m_host->ImeSetComposition(toString16(compositionString),
                                   underlines,
                                   replacementRange,
@@ -1126,7 +1243,7 @@ void RenderWidgetHostViewQt::handleInputMethodEvent(QInputMethodEvent *ev)
         // flickering in the textarea (or any other element).
         // Instead we postpone the processing of the empty QInputMethodEvent by posting it
         // to the same focused object, and cancelling the composition on the next event loop tick.
-        if (!m_receivedEmptyImeText && m_imeInProgress) {
+        if (!m_receivedEmptyImeText && m_imeInProgress && !hasSelection) {
             m_receivedEmptyImeText = true;
             m_imeInProgress = false;
             QInputMethodEvent *eventCopy = new QInputMethodEvent(*ev);
@@ -1304,4 +1421,26 @@ void RenderWidgetHostViewQt::OnBeginFrameSourcePausedChanged(bool paused)
     // begin frames.
 }
 
+content::RenderFrameHost *RenderWidgetHostViewQt::getFocusedFrameHost()
+{
+    content::RenderViewHostImpl *viewHost = content::RenderViewHostImpl::From(m_host);
+    if (!viewHost)
+        return nullptr;
+
+    content::FrameTreeNode *focusedFrame = viewHost->GetDelegate()->GetFrameTree()->GetFocusedFrame();
+    if (!focusedFrame)
+        return nullptr;
+
+    return focusedFrame->current_frame_host();
+}
+
+ui::TextInputType RenderWidgetHostViewQt::getTextInputType() const
+{
+    if (text_input_manager_ && text_input_manager_->GetTextInputState())
+        return text_input_manager_->GetTextInputState()->type;
+
+    return ui::TEXT_INPUT_TYPE_NONE;
+}
+
+
 } // namespace QtWebEngineCore
diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
index 1dae96a537374800dfacf14bca76473d7781b6ea..78b946a605e74aaf0e53abb7be20ff9eb40e1cd4 100644
--- a/src/core/render_widget_host_view_qt.h
+++ b/src/core/render_widget_host_view_qt.h
@@ -47,6 +47,7 @@
 #include "cc/resources/transferable_resource.h"
 #include "content/browser/accessibility/browser_accessibility_manager.h"
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/renderer_host/text_input_manager.h"
 #include "content/common/view_messages.h"
 #include "gpu/ipc/common/gpu_messages.h"
 #include "ui/events/gesture_detection/filtered_gesture_provider.h"
@@ -74,6 +75,7 @@ QT_END_NAMESPACE
 class WebContentsAdapterClient;
 
 namespace content {
+class RenderFrameHost;
 class RenderWidgetHostImpl;
 }
 
@@ -104,6 +106,7 @@ class RenderWidgetHostViewQt
 #ifndef QT_NO_ACCESSIBILITY
     , public QAccessible::ActivationObserver
 #endif // QT_NO_ACCESSIBILITY
+    , public content::TextInputManager::Observer
 {
 public:
     enum LoadVisuallyCommittedState {
@@ -140,7 +143,6 @@ public:
     virtual void UnlockMouse() Q_DECL_OVERRIDE;
     virtual void UpdateCursor(const content::WebCursor&) Q_DECL_OVERRIDE;
     virtual void SetIsLoading(bool) Q_DECL_OVERRIDE;
-    virtual void TextInputStateChanged(const content::TextInputState& params) Q_DECL_OVERRIDE;
     virtual void ImeCancelComposition() Q_DECL_OVERRIDE;
     virtual void ImeCompositionRangeChanged(const gfx::Range&, const std::vector<gfx::Rect>&) Q_DECL_OVERRIDE;
     virtual void RenderProcessGone(base::TerminationStatus, int) Q_DECL_OVERRIDE;
@@ -161,9 +163,6 @@ public:
     virtual void UnlockCompositingSurface() Q_DECL_OVERRIDE;
     virtual void SetNeedsBeginFrames(bool needs_begin_frames) Q_DECL_OVERRIDE;
 
-    // Overridden from RenderWidgetHostViewBase.
-    virtual void SelectionChanged(const base::string16 &text, size_t offset, const gfx::Range &range) Q_DECL_OVERRIDE;
-
     // Overridden from ui::GestureProviderClient.
     virtual void OnGestureEvent(const ui::GestureEventData& gesture) Q_DECL_OVERRIDE;
 
@@ -177,6 +176,11 @@ public:
     virtual bool forwardEvent(QEvent *) Q_DECL_OVERRIDE;
     virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) Q_DECL_OVERRIDE;
 
+    // Overridden from content::TextInputManager::Observer
+    virtual void OnUpdateTextInputStateCalled(content::TextInputManager *text_input_manager, RenderWidgetHostViewBase *updated_view, bool did_update_state) Q_DECL_OVERRIDE;
+    virtual void OnSelectionBoundsChanged(content::TextInputManager *text_input_manager, RenderWidgetHostViewBase *updated_view) Q_DECL_OVERRIDE;
+    virtual void OnTextSelectionChanged(content::TextInputManager *text_input_manager, RenderWidgetHostViewBase *updated_view) Q_DECL_OVERRIDE;
+
     // cc::BeginFrameObserverBase implementation.
     bool OnBeginFrameDerivedImpl(const cc::BeginFrameArgs& args) override;
     void OnBeginFrameSourcePausedChanged(bool paused) override;
@@ -220,6 +224,10 @@ private:
 
     bool IsPopup() const;
 
+    void selectionChanged();
+    content::RenderFrameHost *getFocusedFrameHost();
+    ui::TextInputType getTextInputType() const;
+
     content::RenderWidgetHostImpl *m_host;
     ui::FilteredGestureProvider m_gestureProvider;
     base::TimeDelta m_eventsToNowDelta;
@@ -239,7 +247,6 @@ private:
     WebContentsAdapterClient *m_adapterClient;
     MultipleMouseClickHelper m_clickHelper;
 
-    ui::TextInputType m_currentInputType;
     bool m_imeInProgress;
     bool m_receivedEmptyImeText;
     QPoint m_previousMousePosition;
@@ -253,6 +260,11 @@ private:
     gfx::Vector2dF m_lastScrollOffset;
     gfx::SizeF m_lastContentsSize;
 
+    uint m_imState;
+    uint m_anchorPositionWithinSelection;
+    uint m_cursorPositionWithinSelection;
+    uint m_cursorPosition;
+    bool m_emptyPreviousSelection;
     QString m_surroundingText;
 };
 
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index 4d073e94c63469912d13c9626cc91a8870404c0b..b03418aeab913dc538e036aebca57e73989cf2b7 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -120,8 +120,6 @@ private Q_SLOTS:
     void testLocalStorageVisibility();
     void testEnablePersistentStorage();
     void consoleOutput();
-    void inputMethods_data();
-    void inputMethods();
     void errorPageExtension();
     void errorPageExtensionLoadFinished();
     void userAgentNewlineStripping();
@@ -1631,569 +1629,6 @@ void tst_QWebEnginePage::backActionUpdate()
     QVERIFY(action->isEnabled());
 }
 
-void tst_QWebEnginePage::inputMethods_data()
-{
-    QTest::addColumn<QString>("viewType");
-    QTest::newRow("QWebEngineView") << "QWebEngineView";
-    QTest::newRow("QGraphicsWebView") << "QGraphicsWebView";
-}
-
-#if defined(QWEBENGINEPAGE_INPUTMETHODQUERY)
-static void clickOnPage(QWebEnginePage* page, const QPoint& position)
-{
-    QMouseEvent evpres(QEvent::MouseButtonPress, position, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
-    page->event(&evpres);
-    QMouseEvent evrel(QEvent::MouseButtonRelease, position, Qt::LeftButton, Qt::NoButton, Qt::NoModifier);
-    page->event(&evrel);
-}
-#endif
-
-void tst_QWebEnginePage::inputMethods()
-{
-#if !defined(QWEBENGINEPAGE_INPUTMETHODQUERY)
-    QSKIP("QWEBENGINEPAGE_INPUTMETHODQUERY");
-#else
-    QFETCH(QString, viewType);
-    QWebEnginePage* page = new QWebEnginePage;
-    QObject* view = 0;
-    QScopedPointer<QObject> container(0);
-    if (viewType == "QWebEngineView") {
-        QWebEngineView* wv = new QWebEngineView;
-        wv->setPage(page);
-        view = wv;
-        container.reset(view);
-    } else if (viewType == "QGraphicsWebView") {
-        QGraphicsWebView* wv = new QGraphicsWebView;
-        wv->setPage(page);
-        view = wv;
-
-        QGraphicsView* gv = new QGraphicsView;
-        QGraphicsScene* scene = new QGraphicsScene(gv);
-        gv->setScene(scene);
-        scene->addItem(wv);
-        wv->setGeometry(QRect(0, 0, 500, 500));
-
-        container.reset(gv);
-    } else
-        QVERIFY2(false, "Unknown view type");
-
-    page->settings()->setFontFamily(QWebEngineSettings::SerifFont, page->settings()->fontFamily(QWebEngineSettings::FixedFont));
-    page->setHtml("<html><body>" \
-                                            "<input type='text' id='input1' style='font-family: serif' value='' maxlength='20'/><br>" \
-                                            "<input type='password'/>" \
-                                            "</body></html>");
-    page->mainFrame()->setFocus();
-
-    TestInputContext testContext;
-
-    QWebEngineElementCollection inputs = page->mainFrame()->documentElement().findAll("input");
-    QPoint textInputCenter = inputs.at(0).geometry().center();
-
-    clickOnPage(page, textInputCenter);
-
-    //ImMicroFocus
-    QVariant variant = page->inputMethodQuery(Qt::ImMicroFocus);
-    QVERIFY(inputs.at(0).geometry().contains(variant.toRect().topLeft()));
-
-    // We assigned the serif font famility to be the same as the fixef font family.
-    // Then test ImFont on a serif styled element, we should get our fixef font family.
-    variant = page->inputMethodQuery(Qt::ImFont);
-    QFont font = variant.value<QFont>();
-    QCOMPARE(page->settings()->fontFamily(QWebEngineSettings::FixedFont), font.family());
-
-    QList<QInputMethodEvent::Attribute> inputAttributes;
-
-    //Insert text.
-    {
-        QInputMethodEvent eventText("QtWebEngine", inputAttributes);
-        QSignalSpy signalSpy(page, SIGNAL(microFocusChanged()));
-        page->event(&eventText);
-        QCOMPARE(signalSpy.count(), 0);
-    }
-
-    {
-        QInputMethodEvent eventText("", inputAttributes);
-        eventText.setCommitString(QString("QtWebEngine"), 0, 0);
-        page->event(&eventText);
-    }
-
-    //ImMaximumTextLength
-    variant = page->inputMethodQuery(Qt::ImMaximumTextLength);
-    QCOMPARE(20, variant.toInt());
-
-    //Set selection
-    inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 3, 2, QVariant());
-    QInputMethodEvent eventSelection("",inputAttributes);
-    page->event(&eventSelection);
-
-    //ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    int anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 3);
-
-    //ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    int cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 5);
-
-    //ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    QString selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString("eb"));
-
-    //Set selection with negative length
-    inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 6, -5, QVariant());
-    QInputMethodEvent eventSelection3("",inputAttributes);
-    page->event(&eventSelection3);
-
-    //ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 1);
-
-    //ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 6);
-
-    //ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString("tWebK"));
-
-    //ImSurroundingText
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    QString value = variant.value<QString>();
-    QCOMPARE(value, QString("QtWebEngine"));
-
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        // Clear the selection, so the next test does not clear any contents.
-        QInputMethodEvent::Attribute newSelection(QInputMethodEvent::Selection, 0, 0, QVariant());
-        attributes.append(newSelection);
-        QInputMethodEvent event("composition", attributes);
-        page->event(&event);
-    }
-
-    // A ongoing composition should not change the surrounding text before it is committed.
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    value = variant.value<QString>();
-    QCOMPARE(value, QString("QtWebEngine"));
-
-    // Cancel current composition first
-    inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 0, QVariant());
-    QInputMethodEvent eventSelection4("", inputAttributes);
-    page->event(&eventSelection4);
-
-    // START - Tests for Selection when the Editor is NOT in Composition mode
-
-    // LEFT to RIGHT selection
-    // Deselect the selection by sending MouseButtonPress events
-    // This moves the current cursor to the end of the text
-    clickOnPage(page, textInputCenter);
-
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        QInputMethodEvent event(QString(), attributes);
-        event.setCommitString("XXX", 0, 0);
-        page->event(&event);
-        event.setCommitString(QString(), -2, 2); // Erase two characters.
-        page->event(&event);
-        event.setCommitString(QString(), -1, 1); // Erase one character.
-        page->event(&event);
-        variant = page->inputMethodQuery(Qt::ImSurroundingText);
-        value = variant.value<QString>();
-        QCOMPARE(value, QString("QtWebEngine"));
-    }
-
-    //Move to the start of the line
-    page->triggerAction(QWebEnginePage::MoveToStartOfLine);
-
-    QKeyEvent keyRightEventPress(QEvent::KeyPress, Qt::Key_Right, Qt::NoModifier);
-    QKeyEvent keyRightEventRelease(QEvent::KeyRelease, Qt::Key_Right, Qt::NoModifier);
-
-    //Move 2 characters RIGHT
-    for (int j = 0; j < 2; ++j) {
-        page->event(&keyRightEventPress);
-        page->event(&keyRightEventRelease);
-    }
-
-    //Select to the end of the line
-    page->triggerAction(QWebEnginePage::SelectEndOfLine);
-
-    //ImAnchorPosition QtWebEngine
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 2);
-
-    //ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 8);
-
-    //ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString("WebKit"));
-
-    //RIGHT to LEFT selection
-    //Deselect the selection (this moves the current cursor to the end of the text)
-    clickOnPage(page, textInputCenter);
-
-    //ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 8);
-
-    //ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 8);
-
-    //ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString(""));
-
-    QKeyEvent keyLeftEventPress(QEvent::KeyPress, Qt::Key_Left, Qt::NoModifier);
-    QKeyEvent keyLeftEventRelease(QEvent::KeyRelease, Qt::Key_Left, Qt::NoModifier);
-
-    //Move 2 characters LEFT
-    for (int i = 0; i < 2; ++i) {
-        page->event(&keyLeftEventPress);
-        page->event(&keyLeftEventRelease);
-    }
-
-    //Select to the start of the line
-    page->triggerAction(QWebEnginePage::SelectStartOfLine);
-
-    //ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 6);
-
-    //ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 0);
-
-    //ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString("QtWebK"));
-
-    //END - Tests for Selection when the Editor is not in Composition mode
-
-    page->setHtml("<html><body>" \
-                                            "<input type='text' id='input4' value='QtWebEngine inputMethod'/>" \
-                                            "</body></html>");
-    evaluateJavaScriptSync(page, "var inputEle = document.getElementById('input4'); inputEle.focus(); inputEle.select();");
-
-    // Clear the selection, also cancel the ongoing composition if there is one.
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        QInputMethodEvent::Attribute newSelection(QInputMethodEvent::Selection, 0, 0, QVariant());
-        attributes.append(newSelection);
-        QInputMethodEvent event("", attributes);
-        page->event(&event);
-    }
-
-    // ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString(""));
-
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    QString surroundingValue = variant.value<QString>();
-    QCOMPARE(surroundingValue, QString("QtWebEngine inputMethod"));
-
-    // ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 0);
-
-    // ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 0);
-
-    // 1. Insert a character to the beginning of the line.
-    // Send temporary text, which makes the editor has composition 'm'.
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        QInputMethodEvent event("m", attributes);
-        page->event(&event);
-    }
-
-    // ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString(""));
-
-    // ImSurroundingText
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    surroundingValue = variant.value<QString>();
-    QCOMPARE(surroundingValue, QString("QtWebEngine inputMethod"));
-
-    // ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 0);
-
-    // ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 0);
-
-    // Send temporary text, which makes the editor has composition 'n'.
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        QInputMethodEvent event("n", attributes);
-        page->event(&event);
-    }
-
-    // ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString(""));
-
-    // ImSurroundingText
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    surroundingValue = variant.value<QString>();
-    QCOMPARE(surroundingValue, QString("QtWebEngine inputMethod"));
-
-    // ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 0);
-
-    // ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 0);
-
-    // Send commit text, which makes the editor conforms composition.
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        QInputMethodEvent event("", attributes);
-        event.setCommitString("o");
-        page->event(&event);
-    }
-
-    // ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString(""));
-
-    // ImSurroundingText
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    surroundingValue = variant.value<QString>();
-    QCOMPARE(surroundingValue, QString("oQtWebEngine inputMethod"));
-
-    // ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 1);
-
-    // ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 1);
-
-    // 2. insert a character to the middle of the line.
-    // Send temporary text, which makes the editor has composition 'd'.
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        QInputMethodEvent event("d", attributes);
-        page->event(&event);
-    }
-
-    // ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString(""));
-
-    // ImSurroundingText
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    surroundingValue = variant.value<QString>();
-    QCOMPARE(surroundingValue, QString("oQtWebEngine inputMethod"));
-
-    // ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 1);
-
-    // ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 1);
-
-    // Send commit text, which makes the editor conforms composition.
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        QInputMethodEvent event("", attributes);
-        event.setCommitString("e");
-        page->event(&event);
-    }
-
-    // ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString(""));
-
-    // ImSurroundingText
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    surroundingValue = variant.value<QString>();
-    QCOMPARE(surroundingValue, QString("oeQtWebEngine inputMethod"));
-
-    // ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 2);
-
-    // ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 2);
-
-    // 3. Insert a character to the end of the line.
-    page->triggerAction(QWebEnginePage::MoveToEndOfLine);
-
-    // Send temporary text, which makes the editor has composition 't'.
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        QInputMethodEvent event("t", attributes);
-        page->event(&event);
-    }
-
-    // ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString(""));
-
-    // ImSurroundingText
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    surroundingValue = variant.value<QString>();
-    QCOMPARE(surroundingValue, QString("oeQtWebEngine inputMethod"));
-
-    // ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 22);
-
-    // ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 22);
-
-    // Send commit text, which makes the editor conforms composition.
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        QInputMethodEvent event("", attributes);
-        event.setCommitString("t");
-        page->event(&event);
-    }
-
-    // ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString(""));
-
-    // ImSurroundingText
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    surroundingValue = variant.value<QString>();
-    QCOMPARE(surroundingValue, QString("oeQtWebEngine inputMethodt"));
-
-    // ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 23);
-
-    // ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 23);
-
-    // 4. Replace the selection.
-    page->triggerAction(QWebEnginePage::SelectPreviousWord);
-
-    // ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString("inputMethodt"));
-
-    // ImSurroundingText
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    surroundingValue = variant.value<QString>();
-    QCOMPARE(surroundingValue, QString("oeQtWebEngine inputMethodt"));
-
-    // ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 11);
-
-    // ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 23);
-
-    // Send temporary text, which makes the editor has composition 'w'.
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        QInputMethodEvent event("w", attributes);
-        page->event(&event);
-    }
-
-    // ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString(""));
-
-    // ImSurroundingText
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    surroundingValue = variant.value<QString>();
-    QCOMPARE(surroundingValue, QString("oeQtWebEngine "));
-
-    // ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 11);
-
-    // ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 11);
-
-    // Send commit text, which makes the editor conforms composition.
-    {
-        QList<QInputMethodEvent::Attribute> attributes;
-        QInputMethodEvent event("", attributes);
-        event.setCommitString("2");
-        page->event(&event);
-    }
-
-    // ImCurrentSelection
-    variant = page->inputMethodQuery(Qt::ImCurrentSelection);
-    selectionValue = variant.value<QString>();
-    QCOMPARE(selectionValue, QString(""));
-
-    // ImSurroundingText
-    variant = page->inputMethodQuery(Qt::ImSurroundingText);
-    surroundingValue = variant.value<QString>();
-    QCOMPARE(surroundingValue, QString("oeQtWebEngine 2"));
-
-    // ImCursorPosition
-    variant = page->inputMethodQuery(Qt::ImCursorPosition);
-    cursorPosition =  variant.toInt();
-    QCOMPARE(cursorPosition, 12);
-
-    // ImAnchorPosition
-    variant = page->inputMethodQuery(Qt::ImAnchorPosition);
-    anchorPosition =  variant.toInt();
-    QCOMPARE(anchorPosition, 12);
-#endif
-}
-
 void tst_QWebEnginePage::protectBindingsRuntimeObjectsFromCollector()
 {
 #if !defined(QWEBENGINEPAGE_CREATEPLUGIN)
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index a6138c59de5d9e92ecd0d7357b03d17d29308d17..82e50409d6f602dbd32648554cda2b5340d8c41e 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -97,8 +97,11 @@ private Q_SLOTS:
     void postData();
 
     void softwareInputPanel();
+    void inputMethods();
+    void textSelection();
     void hiddenText();
     void emptyInputMethodEvent();
+    void imeComposition();
     void newlineInTextarea();
 };
 
@@ -1341,6 +1344,24 @@ static QPoint elementCenter(QWebEnginePage *page, const QString &id)
     return QPoint(rectList.at(0).toInt(), rectList.at(1).toInt());
 }
 
+static QRect elementGeometry(QWebEnginePage *page, const QString &id)
+{
+    const QString jsCode(
+                "(function() {"
+                "   var elem = document.getElementById('" + id + "');"
+                "   var rect = elem.getBoundingClientRect();"
+                "   return [rect.left, rect.top, rect.right, rect.bottom];"
+                "})()");
+    QVariantList coords = evaluateJavaScriptSync(page, jsCode).toList();
+
+    if (coords.count() != 4) {
+        qWarning("elementGeometry faield.");
+        return QRect();
+    }
+
+    return QRect(coords[0].toInt(), coords[1].toInt(), coords[2].toInt(), coords[3].toInt());
+}
+
 void tst_QWebEngineView::softwareInputPanel()
 {
     TestInputContext testContext;
@@ -1398,6 +1419,183 @@ void tst_QWebEngineView::softwareInputPanel()
     QVERIFY(!testContext.isInputPanelVisible());
 }
 
+void tst_QWebEngineView::inputMethods()
+{
+    QWebEngineView view;
+    view.show();
+
+    QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
+    QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
+    view.settings()->setFontFamily(QWebEngineSettings::SerifFont, view.settings()->fontFamily(QWebEngineSettings::FixedFont));
+    view.setHtml("<html><body>"
+                 "  <input type='text' id='input1' style='font-family: serif' value='' maxlength='20' size='50'/>"
+                 "</body></html>");
+    QVERIFY(loadFinishedSpy.wait());
+
+    QPoint textInputCenter = elementCenter(view.page(), "input1");
+    QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, textInputCenter);
+    QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input1"));
+
+    // ImCursorRectangle
+    QVariant variant = view.focusProxy()->inputMethodQuery(Qt::ImCursorRectangle);
+    QVERIFY(elementGeometry(view.page(), "input1").contains(variant.toRect().topLeft()));
+
+    // We assigned the serif font family to be the same as the fixed font family.
+    // Then test ImFont on a serif styled element, we should get our fixed font family.
+    variant = view.focusProxy()->inputMethodQuery(Qt::ImFont);
+    QFont font = variant.value<QFont>();
+    QEXPECT_FAIL("", "UNIMPLEMENTED: RenderWidgetHostViewQt::inputMethodQuery(Qt::ImFont)", Continue);
+    QCOMPARE(view.settings()->fontFamily(QWebEngineSettings::FixedFont), font.family());
+
+    QList<QInputMethodEvent::Attribute> inputAttributes;
+
+    // Insert text
+    {
+        QString text = QStringLiteral("QtWebEngine");
+        QInputMethodEvent eventText(text, inputAttributes);
+        QApplication::sendEvent(view.focusProxy(), &eventText);
+        QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), text);
+        QCOMPARE(selectionChangedSpy.count(), 0);
+    }
+
+    {
+        QString text = QStringLiteral("QtWebEngine");
+        QInputMethodEvent eventText("", inputAttributes);
+        eventText.setCommitString(text, 0, 0);
+        QApplication::sendEvent(view.focusProxy(), &eventText);
+        QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), text);
+        QCOMPARE(selectionChangedSpy.count(), 0);
+    }
+
+    // ImMaximumTextLength
+    QEXPECT_FAIL("", "UNIMPLEMENTED: RenderWidgetHostViewQt::inputMethodQuery(Qt::ImMaximumTextLength)", Continue);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImMaximumTextLength).toInt(), 20);
+
+    // Set selection
+    inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 3, 2, QVariant());
+    QInputMethodEvent eventSelection1("", inputAttributes);
+
+    QApplication::sendEvent(view.focusProxy(), &eventSelection1);
+    QVERIFY(selectionChangedSpy.wait());
+    QCOMPARE(selectionChangedSpy.count(), 1);
+
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 3);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 5);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString("eb"));
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine"));
+
+    // Set selection with negative length
+    inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 6, -5, QVariant());
+    QInputMethodEvent eventSelection2("", inputAttributes);
+    QApplication::sendEvent(view.focusProxy(), &eventSelection2);
+    QVERIFY(selectionChangedSpy.wait());
+    QCOMPARE(selectionChangedSpy.count(), 2);
+
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 1);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 6);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString("tWebE"));
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine"));
+
+    QList<QInputMethodEvent::Attribute> attributes;
+    // Clear the selection, so the next test does not clear any contents.
+    QInputMethodEvent::Attribute newSelection(QInputMethodEvent::Selection, 0, 0, QVariant());
+    attributes.append(newSelection);
+    QInputMethodEvent eventComposition("composition", attributes);
+    QApplication::sendEvent(view.focusProxy(), &eventComposition);
+    QVERIFY(selectionChangedSpy.wait());
+    QCOMPARE(selectionChangedSpy.count(), 3);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+
+    // An ongoing composition should not change the surrounding text before it is committed.
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine"));
+
+    // Cancel current composition first
+    inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 0, 0, QVariant());
+    QInputMethodEvent eventSelection3("", inputAttributes);
+    QApplication::sendEvent(view.focusProxy(), &eventSelection3);
+
+    // Cancelling composition should not clear the surrounding text
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine"));
+}
+
+void tst_QWebEngineView::textSelection()
+{
+    QWebEngineView view;
+    view.show();
+
+    QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
+    QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
+    view.setHtml("<html><body>"
+                 "  <input type='text' id='input1' value='QtWebEngine' size='50'/>"
+                 "</body></html>");
+    QVERIFY(loadFinishedSpy.wait());
+
+    // Tests for Selection when the Editor is NOT in Composition mode
+
+    // LEFT to RIGHT selection
+    // Mouse click event moves the current cursor to the end of the text
+    QPoint textInputCenter = elementCenter(view.page(), "input1");
+    QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, textInputCenter);
+    QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input1"));
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 11);
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 11);
+    // There was no selection to be changed by the click
+    QCOMPARE(selectionChangedSpy.count(), 0);
+
+    QList<QInputMethodEvent::Attribute> attributes;
+    QInputMethodEvent event(QString(), attributes);
+    event.setCommitString("XXX", 0, 0);
+    QApplication::sendEvent(view.focusProxy(), &event);
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngineXXX"));
+
+    event.setCommitString(QString(), -2, 2); // Erase two characters.
+    QApplication::sendEvent(view.focusProxy(), &event);
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngineX"));
+
+    event.setCommitString(QString(), -1, 1); // Erase one character.
+    QApplication::sendEvent(view.focusProxy(), &event);
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine"));
+
+    // Move to the start of the line
+    QTest::keyClick(view.focusProxy(), Qt::Key_Home);
+
+    // Move 2 characters RIGHT
+    for (int j = 0; j < 2; ++j)
+        QTest::keyClick(view.focusProxy(), Qt::Key_Right);
+
+    // Select to the end of the line
+    QTest::keyClick(view.focusProxy(), Qt::Key_End, Qt::ShiftModifier);
+    QVERIFY(selectionChangedSpy.wait());
+    QCOMPARE(selectionChangedSpy.count(), 1);
+
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 2);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 11);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString("WebEngine"));
+
+    // RIGHT to LEFT selection
+    // Deselect the selection (this moves the current cursor to the end of the text)
+    QTest::mouseClick(view.focusProxy(), Qt::LeftButton, 0, textInputCenter);
+    QVERIFY(selectionChangedSpy.wait());
+    QCOMPARE(selectionChangedSpy.count(), 2);
+
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 11);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 11);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+
+    // Move 2 characters LEFT
+    for (int i = 0; i < 2; ++i)
+        QTest::keyClick(view.focusProxy(), Qt::Key_Left);
+
+    // Select to the start of the line
+    QTest::keyClick(view.focusProxy(), Qt::Key_Home, Qt::ShiftModifier);
+    QVERIFY(selectionChangedSpy.wait());
+    QCOMPARE(selectionChangedSpy.count(), 3);
+
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 9);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 0);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString("QtWebEngi"));
+}
+
 void tst_QWebEngineView::hiddenText()
 {
     QWebEngineView view;
@@ -1451,6 +1649,193 @@ void tst_QWebEngineView::emptyInputMethodEvent()
     QCOMPARE(inputValue, QString("QtWebEngine"));
 }
 
+void tst_QWebEngineView::imeComposition()
+{
+    QWebEngineView view;
+    view.show();
+
+    QSignalSpy selectionChangedSpy(&view, SIGNAL(selectionChanged()));
+    QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
+    view.setHtml("<html><body>"
+                 "  <input type='text' id='input1' value='QtWebEngine inputMethod'/>"
+                 "</body></html>");
+    QVERIFY(loadFinishedSpy.wait());
+
+    evaluateJavaScriptSync(view.page(), "var inputEle = document.getElementById('input1'); inputEle.focus(); inputEle.select();");
+    QTRY_VERIFY(!evaluateJavaScriptSync(view.page(), "window.getSelection().toString()").toString().isEmpty());
+
+    QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue);
+    QVERIFY(selectionChangedSpy.wait(100));
+    QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue);
+    QCOMPARE(selectionChangedSpy.count(), 1);
+
+    // Clear the selection, also cancel the ongoing composition if there is one.
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent::Attribute newSelection(QInputMethodEvent::Selection, 0, 0, QVariant());
+        attributes.append(newSelection);
+        QInputMethodEvent event("", attributes);
+        QApplication::sendEvent(view.focusProxy(), &event);
+        QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "window.getSelection().toString()").toString().isEmpty());
+
+        QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue);
+        QVERIFY(selectionChangedSpy.wait(100));
+        QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue);
+        QCOMPARE(selectionChangedSpy.count(), 2);
+    }
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine inputMethod"));
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 0);
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 0);
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+
+    selectionChangedSpy.clear();
+
+
+    // 1. Insert a character to the beginning of the line.
+    // Send temporary text, which makes the editor has composition 'm'.
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent event("m", attributes);
+        QApplication::sendEvent(view.focusProxy(), &event);
+    }
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine inputMethod"));
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 0);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 0);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+    QCOMPARE(selectionChangedSpy.count(), 0);
+
+    // Send temporary text, which makes the editor has composition 'n'.
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent event("n", attributes);
+        QApplication::sendEvent(view.focusProxy(), &event);
+    }
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("QtWebEngine inputMethod"));
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 0);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 0);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+    QCOMPARE(selectionChangedSpy.count(), 0);
+
+    // Send commit text, which makes the editor conforms composition.
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent event("", attributes);
+        event.setCommitString("o");
+        QApplication::sendEvent(view.focusProxy(), &event);
+    }
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("oQtWebEngine inputMethod"));
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 1);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 1);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+    QCOMPARE(selectionChangedSpy.count(), 0);
+
+
+    // 2. insert a character to the middle of the line.
+    // Send temporary text, which makes the editor has composition 'd'.
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent event("d", attributes);
+        QApplication::sendEvent(view.focusProxy(), &event);
+    }
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("oQtWebEngine inputMethod"));
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 1);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 1);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+    QCOMPARE(selectionChangedSpy.count(), 0);
+
+    // Send commit text, which makes the editor conforms composition.
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent event("", attributes);
+        event.setCommitString("e");
+        QApplication::sendEvent(view.focusProxy(), &event);
+    }
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("oeQtWebEngine inputMethod"));
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 2);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 2);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+    QCOMPARE(selectionChangedSpy.count(), 0);
+
+
+    // 3. Insert a character to the end of the line.
+    QTest::keyClick(view.focusProxy(), Qt::Key_End);
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 25);
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 25);
+
+    // Send temporary text, which makes the editor has composition 't'.
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent event("t", attributes);
+        QApplication::sendEvent(view.focusProxy(), &event);
+    }
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("oeQtWebEngine inputMethod"));
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 25);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 25);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+    QCOMPARE(selectionChangedSpy.count(), 0);
+
+    // Send commit text, which makes the editor conforms composition.
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent event("", attributes);
+        event.setCommitString("t");
+        QApplication::sendEvent(view.focusProxy(), &event);
+    }
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("oeQtWebEngine inputMethodt"));
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 26);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 26);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+    QCOMPARE(selectionChangedSpy.count(), 0);
+
+
+    // 4. Replace the selection.
+#ifndef Q_OS_MACOS
+    QTest::keyClick(view.focusProxy(), Qt::Key_Left, Qt::ShiftModifier | Qt::ControlModifier);
+#else
+    QTest::keyClick(view.focusProxy(), Qt::Key_Left, Qt::ShiftModifier | Qt::AltModifier);
+#endif
+    QVERIFY(selectionChangedSpy.wait());
+    QCOMPARE(selectionChangedSpy.count(), 1);
+
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("oeQtWebEngine inputMethodt"));
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 14);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 26);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString("inputMethodt"));
+
+    // Send temporary text, which makes the editor has composition 'w'.
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent event("w", attributes);
+        QApplication::sendEvent(view.focusProxy(), &event);
+        QTRY_VERIFY(evaluateJavaScriptSync(view.page(), "window.getSelection().toString()").toString().isEmpty());
+        QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), QString("oeQtWebEngine w"));
+
+        QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue);
+        QVERIFY(selectionChangedSpy.wait(100));
+        QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue);
+        QCOMPARE(selectionChangedSpy.count(), 2);
+    }
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("oeQtWebEngine "));
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 14);
+    QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 14);
+    QEXPECT_FAIL("", "https://bugreports.qt.io/browse/QTBUG-53134", Continue);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+
+    // Send commit text, which makes the editor conforms composition.
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent event("", attributes);
+        event.setCommitString("2");
+        QApplication::sendEvent(view.focusProxy(), &event);
+    }
+    // There is no text selection to be changed at this point thus we can't wait for selectionChanged signal.
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("oeQtWebEngine 2"));
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 15);
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 15);
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
+}
+
 void tst_QWebEngineView::newlineInTextarea()
 {
     QWebEngineView view;