summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorten Johan Sørvig <morten.sorvig@digia.com>2014-08-25 12:29:56 +0200
committerMorten Johan Sørvig <morten.sorvig@theqtcompany.com>2015-02-12 06:31:20 +0000
commit529214523d3bd79b749fef0c49cd8a3c2933c19c (patch)
treef9c037181829744c2403a392dc486cc6df99de52
parent083323c8b7c37092fedcec4fd34f568c4a674c03 (diff)
OS X Implementation.
Adds implementation for the native WebView on OS X and removes the QtWebEngine as the fallback. The current implementation requires QT_MAC_WANTS_LAYER=1 QSG_RENDER_LOOP=basic [ChangeLog][WebView][OS X] Added OS X implementation. Change-Id: I2807a082c8aa519b8c3afe332996d3d454ff2383 Reviewed-by: Christian Stromme <christian.stromme@theqtcompany.com>
-rw-r--r--examples/webview/minibrowser/main.cpp8
-rw-r--r--examples/webview/minibrowser/minibrowser.pro2
-rw-r--r--src/imports/imports.pro2
-rw-r--r--src/webview/qquickwebview.h6
-rw-r--r--src/webview/qwebview_osx.mm241
-rw-r--r--src/webview/qwebview_osx_p.h97
-rw-r--r--src/webview/webview-lib.pri10
7 files changed, 361 insertions, 5 deletions
diff --git a/examples/webview/minibrowser/main.cpp b/examples/webview/minibrowser/main.cpp
index 1db0bc0..bc10a69 100644
--- a/examples/webview/minibrowser/main.cpp
+++ b/examples/webview/minibrowser/main.cpp
@@ -74,6 +74,14 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv);
QGuiApplication::setApplicationDisplayName(QCoreApplication::translate("main",
"QtWebView Example"));
+#ifdef Q_OS_OSX
+ // On OS X, correct WebView / QtQuick compositing and stacking requires running
+ // Qt in layer-backed mode, which again resuires rendering on the Gui thread.
+ qWarning("Setting QT_MAC_WANTS_LAYER=1 and QSG_RENDER_LOOP=basic");
+ qputenv("QT_MAC_WANTS_LAYER", "1");
+ qputenv("QSG_RENDER_LOOP", "basic");
+#endif
+
#ifdef QT_WEBVIEW_WEBENGINE_BACKEND
QtWebEngine::initialize();
#endif // QT_WEBVIEW_WEBENGINE_BACKEND
diff --git a/examples/webview/minibrowser/minibrowser.pro b/examples/webview/minibrowser/minibrowser.pro
index e02757c..a95b6d4 100644
--- a/examples/webview/minibrowser/minibrowser.pro
+++ b/examples/webview/minibrowser/minibrowser.pro
@@ -2,7 +2,7 @@ TEMPLATE = app
QT += qml quick
-qtHaveModule(webengine) {
+!osx:qtHaveModule(webengine) {
QT += webengine
DEFINES += QT_WEBVIEW_WEBENGINE_BACKEND
}
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index 88e4c3b..92bfc97 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -7,7 +7,7 @@ QT += qml quick webview webview-private
SOURCES += \
$$PWD/webview.cpp
-!android: qtHaveModule(webengine) {
+!android:!osx: qtHaveModule(webengine) {
QT += webengine webengine-private
DEFINES += QT_WEBVIEW_WEBENGINE_BACKEND
}
diff --git a/src/webview/qquickwebview.h b/src/webview/qquickwebview.h
index 004fe10..936971b 100644
--- a/src/webview/qquickwebview.h
+++ b/src/webview/qquickwebview.h
@@ -48,12 +48,12 @@
// We mean it.
//
-#include "qwebviewinterface_p.h"
+#include <QtWebView/private/qwebviewinterface_p.h>
#if !defined(QT_WEBVIEW_WEBENGINE_BACKEND)
-#include "qwebview_p.h"
-#include "qquickviewcontroller_p.h"
+#include <QtWebView/private/qwebview_p.h>
+#include <QtWebView/private/qquickviewcontroller_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/webview/qwebview_osx.mm b/src/webview/qwebview_osx.mm
new file mode 100644
index 0000000..ee95f9f
--- /dev/null
+++ b/src/webview/qwebview_osx.mm
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebView module 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 The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwebview_p.h"
+#include "qwebview_osx_p.h"
+#include "qwebviewloadrequest_p.h"
+
+
+#include <QtCore/qstring.h>
+#include <QtCore/qvariant.h>
+
+#import <CoreFoundation/CoreFoundation.h>
+#import <Webkit/WebKit.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOsxWebViewPrivate;
+
+@interface QtFrameLoadDelegate : NSObject {
+ QOsxWebViewPrivate *qtWebViewPrivate;
+}
+- (QtFrameLoadDelegate *)initWithQWebViewPrivate:(QOsxWebViewPrivate *)webViewPrivate;
+- (void)pageDone;
+
+// protocol:
+- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame;
+- (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame;
+- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame;
+- (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame;
+@end
+
+@implementation QtFrameLoadDelegate
+
+- (QtFrameLoadDelegate *)initWithQWebViewPrivate:(QOsxWebViewPrivate *)webViewPrivate
+{
+ qtWebViewPrivate = webViewPrivate;
+ return self;
+}
+
+- (void)pageDone
+{
+ Q_EMIT qtWebViewPrivate->titleChanged();
+ Q_EMIT qtWebViewPrivate->loadProgressChanged();
+}
+
+- (void)webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame
+{
+ Q_UNUSED(sender);
+ Q_UNUSED(frame);
+
+ // WebView gives us per-frame notifications while the QWebView API
+ // should provide per-page notifications. Keep track of started frame loads
+ // and emit notifications when the final frame completes.
+ if (++qtWebViewPrivate->requestFrameCount == 1) {
+ Q_EMIT qtWebViewPrivate->loadingChanged(QWebViewLoadRequestPrivate(qtWebViewPrivate->url(),
+ QWebView::LoadStartedStatus,
+ QString()));
+ }
+}
+
+- (void)webView:(WebView *)sender didCommitLoadForFrame:(WebFrame *)frame
+{
+ Q_UNUSED(sender);
+ Q_UNUSED(frame);
+}
+
+- (void)webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame
+{
+ Q_UNUSED(sender);
+ Q_UNUSED(frame);
+ if (--qtWebViewPrivate->requestFrameCount == 0) {
+ [self pageDone];
+ Q_EMIT qtWebViewPrivate->loadingChanged(QWebViewLoadRequestPrivate(qtWebViewPrivate->url(),
+ QWebView::LoadSucceededStatus,
+ QString()));
+ }
+}
+
+- (void)webView:(WebView *)sender didFailLoadWithError:(NSError *)error forFrame:(WebFrame *)frame
+{
+ Q_UNUSED(sender);
+ Q_UNUSED(error);
+ Q_UNUSED(frame);
+ if (--qtWebViewPrivate->requestFrameCount == 0) {
+ [self pageDone];
+ NSString *errorString = [error localizedFailureReason];
+ Q_EMIT qtWebViewPrivate->loadingChanged(QWebViewLoadRequestPrivate(qtWebViewPrivate->url(),
+ QWebView::LoadFailedStatus,
+ QString::fromNSString(errorString)));
+ }
+}
+
+@end
+
+QWebViewPrivate *QWebViewPrivate::create(QWebView *q)
+{
+ return new QOsxWebViewPrivate(q);
+}
+
+QOsxWebViewPrivate::QOsxWebViewPrivate(QWebView *q)
+ : QWebViewPrivate(q)
+{
+ NSRect frame = NSMakeRect(0.0, 0.0, 400, 400);
+ webView = [[WebView alloc] initWithFrame:frame frameName:@"Qt Frame" groupName:nil];
+ [webView setFrameLoadDelegate:[[QtFrameLoadDelegate alloc] initWithQWebViewPrivate:this]];
+ m_window = QWindow::fromWinId(reinterpret_cast<WId>(webView));
+}
+
+QOsxWebViewPrivate::~QOsxWebViewPrivate()
+{
+ [webView.frameLoadDelegate release];
+ [webView release];
+}
+
+QUrl QOsxWebViewPrivate::url() const
+{
+ NSString *currentURL = [webView stringByEvaluatingJavaScriptFromString:@"window.location.href"];
+ return QString::fromNSString(currentURL);
+}
+
+void QOsxWebViewPrivate::setUrl(const QUrl &url)
+{
+ requestFrameCount = 0;
+ [[webView mainFrame] loadRequest:[NSURLRequest requestWithURL:url.toNSURL()]];
+}
+
+bool QOsxWebViewPrivate::canGoBack() const
+{
+ return webView.canGoBack;
+}
+
+void QOsxWebViewPrivate::goBack()
+{
+ [webView goBack];
+}
+
+bool QOsxWebViewPrivate::canGoForward() const
+{
+ return webView.canGoForward;
+}
+
+void QOsxWebViewPrivate::goForward()
+{
+ [webView goForward];
+}
+
+void QOsxWebViewPrivate::reload()
+{
+ [[webView mainFrame] reload];
+}
+
+QString QOsxWebViewPrivate::title() const
+{
+ NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
+ return QString::fromNSString(title);
+}
+
+int QOsxWebViewPrivate::loadProgress() const
+{
+ // TODO:
+ return isLoading() ? 100 : 0;
+}
+
+bool QOsxWebViewPrivate::isLoading() const
+{
+ return webView.isLoading;
+}
+
+void QOsxWebViewPrivate::runJavaScriptPrivate(const QString& script, int callbackId)
+{
+ // ### TODO needs more async
+ NSString *result = [webView stringByEvaluatingJavaScriptFromString:script.toNSString()];
+ if (callbackId != -1)
+ Q_EMIT javaScriptResult(callbackId, QVariant::fromValue(QString::fromNSString(result)));
+}
+
+void QOsxWebViewPrivate::setParentView(QObject *view)
+{
+ m_window->setParent(qobject_cast<QWindow *>(view));
+}
+
+void QOsxWebViewPrivate::setGeometry(const QRect &geometry)
+{
+ m_window->setGeometry(geometry);
+}
+
+void QOsxWebViewPrivate::setVisibility(QWindow::Visibility visibility)
+{
+ m_window->setVisibility(visibility);
+}
+
+void QOsxWebViewPrivate::setVisible(bool visible)
+{
+ m_window->setVisible(visible);
+}
+
+void QOsxWebViewPrivate::stop()
+{
+ [webView stopLoading:webView];
+}
+
+void QOsxWebViewPrivate::loadHtml(const QString &html, const QUrl &baseUrl)
+{
+ Q_UNUSED(html);
+ Q_UNUSED(baseUrl);
+}
+
+QT_END_NAMESPACE
diff --git a/src/webview/qwebview_osx_p.h b/src/webview/qwebview_osx_p.h
new file mode 100644
index 0000000..b7da068
--- /dev/null
+++ b/src/webview/qwebview_osx_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWebView module 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 The Qt Company. For licensing terms and
+** conditions see http://www.qt.io/terms-conditions. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWEBVIEW_IOS_P_H
+#define QWEBVIEW_IOS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+#include <QtCore/qurl.h>
+#include <QtGui/qwindow.h>
+
+#include "qwebview_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+Q_FORWARD_DECLARE_OBJC_CLASS(WebView);
+
+class QOsxWebViewPrivate : public QWebViewPrivate
+{
+ Q_OBJECT
+public:
+ QOsxWebViewPrivate(QWebView *q);
+ ~QOsxWebViewPrivate();
+
+ QUrl url() const;
+ void setUrl(const QUrl &url);
+ bool canGoBack() const;
+ bool canGoForward() const;
+ QString title() const;
+ int loadProgress() const;
+ bool isLoading() const;
+ void runJavaScriptPrivate(const QString& script, int callbackId);
+
+ void setParentView(QObject *view) Q_DECL_OVERRIDE;
+ void setGeometry(const QRect &geometry) Q_DECL_OVERRIDE;
+ void setVisibility(QWindow::Visibility visibility) Q_DECL_OVERRIDE;
+ void setVisible(bool visible) Q_DECL_OVERRIDE;
+
+public Q_SLOTS:
+ void goBack();
+ void goForward();
+ void reload();
+ void stop();
+ void loadHtml(const QString &html, const QUrl &baseUrl = QUrl()) Q_DECL_OVERRIDE;
+
+public:
+ QWindow *m_window;
+ WebView *webView;
+ int requestFrameCount;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWEBVIEW_IOS_P_H
diff --git a/src/webview/webview-lib.pri b/src/webview/webview-lib.pri
index 64753cd..fbae4cc 100644
--- a/src/webview/webview-lib.pri
+++ b/src/webview/webview-lib.pri
@@ -44,6 +44,16 @@ android {
$$COMMON_HEADERS \
qwebview_ios_p.h
+} else:osx {
+ LIBS_PRIVATE += -framework Cocoa -framework WebKit
+ SOURCES += \
+ $$COMMON_SOURCES
+ OBJECTIVE_SOURCES += \
+ qwebview_osx.mm
+ PRIVATE_HEADERS += \
+ $$COMMON_HEADERS \
+ qwebview_osx_p.h
+
} else {
qtHaveModule(webengine) {
QT += webengine webengine-private