From 331b7fa11c84107e3300b14ece5fc5991cfc35e9 Mon Sep 17 00:00:00 2001
From: Zeno Albisser <zeno.albisser@digia.com>
Date: Fri, 31 Jan 2014 17:24:40 +0100
Subject: [PATCH] Add TakeFocus in WebContentsViewQt for passing on tab focus.

Chromium calls RenderViewHostDelegate::TakeFocus when the
last focusable item within the page was reached.
We then have to move the focus on to the next/previous
QQuickItem.

Change-Id: Id0128053602ff1220c1bced1b218050b66fef659
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
---
 examples/quick/quicknanobrowser/quickwindow.qml      | 10 ++++++++++
 src/core/web_contents_adapter_client.h               |  1 +
 src/core/web_contents_view_qt.cpp                    |  5 +++++
 src/core/web_contents_view_qt.h                      |  2 ++
 src/webengine/api/qquickwebengineview.cpp            | 12 ++++++++++++
 src/webengine/api/qquickwebengineview_p_p.h          |  1 +
 .../render_widget_host_view_qt_delegate_quick.h      |  6 +++++-
 src/webenginewidgets/api/qwebenginepage_p.h          |  2 ++
 8 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/examples/quick/quicknanobrowser/quickwindow.qml b/examples/quick/quicknanobrowser/quickwindow.qml
index 63f86458e..88fc9f8a0 100644
--- a/examples/quick/quicknanobrowser/quickwindow.qml
+++ b/examples/quick/quicknanobrowser/quickwindow.qml
@@ -44,6 +44,7 @@ import QtWebEngine.experimental 1.0
 import QtQuick.Controls 1.0
 import QtQuick.Controls.Styles 1.0
 import QtQuick.Layouts 1.0
+import QtQuick.Controls.Private 1.0
 
 ApplicationWindow {
     id: browserWindow
@@ -55,6 +56,12 @@ ApplicationWindow {
     visible: true
     title: tabs.currentView && tabs.currentView.title
 
+    // Create a styleItem to determine the platform.
+    // When using style "mac", ToolButtons are not supposed to accept focus.
+    StyleItem { id: styleItem }
+    property bool platformIsMac: styleItem.style == "mac"
+
+
     Action {
         id: focus
         shortcut: "Ctrl+L"
@@ -94,17 +101,20 @@ ApplicationWindow {
                     iconSource: "icons/go-previous.png"
                     onClicked: tabs.currentView.goBack()
                     enabled: tabs.currentView && tabs.currentView.canGoBack
+                    activeFocusOnTab: !browserWindow.platformIsMac
                 }
                 ToolButton {
                     id: forwardButton
                     iconSource: "icons/go-next.png"
                     onClicked: tabs.currentView.goForward()
                     enabled: tabs.currentView && tabs.currentView.canGoForward
+                    activeFocusOnTab: !browserWindow.platformIsMac
                 }
                 ToolButton {
                     id: reloadButton
                     iconSource: tabs.currentView && tabs.currentView.loading ? "icons/process-stop.png" : "icons/view-refresh.png"
                     onClicked: tabs.currentView && tabs.currentView.loading ? tabs.currentView.stop() : tabs.currentView.reload()
+                    activeFocusOnTab: !browserWindow.platformIsMac
                 }
                 TextField {
                     id: addressBar
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 598840f1d..077e21500 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -132,6 +132,7 @@ public:
     virtual void didRunJavaScript(const QVariant& result, quint64 requestId) = 0;
     virtual void didFetchDocumentMarkup(const QString& result, quint64 requestId) = 0;
     virtual void didFetchDocumentInnerText(const QString& result, quint64 requestId) = 0;
+    virtual void passOnFocus(bool reverse) = 0;
     virtual void javaScriptConsoleMessage(int level, const QString& message, int lineNumber, const QString& sourceID) = 0;
 };
 
diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp
index 65b8e5f3a..a4cb3556e 100644
--- a/src/core/web_contents_view_qt.cpp
+++ b/src/core/web_contents_view_qt.cpp
@@ -130,3 +130,8 @@ void WebContentsViewQt::ShowContextMenu(const content::ContextMenuParams &params
     WebEngineContextMenuData contextMenuData(fromParams(params));
     m_client->contextMenuRequested(contextMenuData);
 }
+
+void WebContentsViewQt::TakeFocus(bool reverse)
+{
+    m_client->passOnFocus(reverse);
+}
diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h
index ee81ccc81..1c9da487b 100644
--- a/src/core/web_contents_view_qt.h
+++ b/src/core/web_contents_view_qt.h
@@ -112,6 +112,8 @@ public:
 
     virtual void ShowContextMenu(const content::ContextMenuParams &params) Q_DECL_OVERRIDE;
 
+    virtual void TakeFocus(bool reverse) Q_DECL_OVERRIDE;
+
 #if defined(OS_MACOSX)
     virtual void SetAllowOverlappingViews(bool overlapping) Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED }
     virtual void CloseTabAfterEventTracking() Q_DECL_OVERRIDE { QT_NOT_YET_IMPLEMENTED }
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index 049e353b6..2f5d868ea 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -180,6 +180,18 @@ void QQuickWebEngineViewPrivate::runFileChooser(FileChooserMode mode, const QStr
     ui()->showFilePicker(mode, defaultFileName, acceptedMimeTypes, adapter);
 }
 
+void QQuickWebEngineViewPrivate::passOnFocus(bool reverse)
+{
+    Q_Q(QQuickWebEngineView);
+    // In one direction we would pass forward the focus to RenderWidgetHostViewQtDelegateQuick(Painted),
+    // which in return would forward the tab key event and therefore the focus back to the QQuickWebEngineView.
+    // This is why we skip RenderWidgetHostViewQtDelegateQuick in the focus chain.
+    QQuickItem* current = QQuickItemPrivate::nextPrevItemInTabFocusChain(q, !reverse);
+    if (!qobject_cast<RenderWidgetHostViewQtDelegateQuick*>(current) && !qobject_cast<RenderWidgetHostViewQtDelegateQuickPainted*>(current))
+        current = q;
+    focusNextPrev(current, !reverse);
+}
+
 void QQuickWebEngineViewPrivate::titleChanged(const QString &title)
 {
     Q_Q(QQuickWebEngineView);
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 37ac9edf0..3de597469 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -141,6 +141,7 @@ public:
     virtual void didRunJavaScript(const QVariant&, quint64) Q_DECL_OVERRIDE { }
     virtual void didFetchDocumentMarkup(const QString&, quint64) Q_DECL_OVERRIDE { }
     virtual void didFetchDocumentInnerText(const QString&, quint64) Q_DECL_OVERRIDE { }
+    virtual void passOnFocus(bool reverse) Q_DECL_OVERRIDE;
     virtual void javaScriptConsoleMessage(int level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE;
 
     void setDevicePixelRatio(qreal);
diff --git a/src/webengine/render_widget_host_view_qt_delegate_quick.h b/src/webengine/render_widget_host_view_qt_delegate_quick.h
index 9dbe79941..8f32689d0 100644
--- a/src/webengine/render_widget_host_view_qt_delegate_quick.h
+++ b/src/webengine/render_widget_host_view_qt_delegate_quick.h
@@ -60,6 +60,10 @@ public:
         : ItemBaseT(parent)
         , m_client(client)
     {
+        this->setFocus(true);
+        this->setActiveFocusOnTab(true);
+        this->setFlag(QQuickItem::ItemIsFocusScope);
+
         this->setAcceptedMouseButtons(Qt::AllButtons);
         this->setAcceptHoverEvents(true);
     }
@@ -143,7 +147,7 @@ public:
 
     void mousePressEvent(QMouseEvent *event)
     {
-        this->setFocus(true);
+        this->forceActiveFocus();
         m_client->forwardEvent(event);
     }
 
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index 595318ffc..0a90eda07 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -83,6 +83,8 @@ public:
     virtual void didRunJavaScript(const QVariant& result, quint64 requestId) Q_DECL_OVERRIDE;
     virtual void didFetchDocumentMarkup(const QString& result, quint64 requestId) Q_DECL_OVERRIDE;
     virtual void didFetchDocumentInnerText(const QString& result, quint64 requestId) Q_DECL_OVERRIDE;
+    virtual void passOnFocus(bool reverse) Q_DECL_OVERRIDE { };
+
     virtual void javaScriptConsoleMessage(int level, const QString& message, int lineNumber, const QString& sourceID) Q_DECL_OVERRIDE;
 
     void updateAction(QWebEnginePage::WebAction) const;
-- 
GitLab