diff options
-rw-r--r-- | examples/webview/minibrowser/main.cpp | 8 | ||||
-rw-r--r-- | examples/webview/minibrowser/minibrowser.pro | 2 | ||||
-rw-r--r-- | src/imports/imports.pro | 2 | ||||
-rw-r--r-- | src/webview/qquickwebview.h | 6 | ||||
-rw-r--r-- | src/webview/qwebview_osx.mm | 241 | ||||
-rw-r--r-- | src/webview/qwebview_osx_p.h | 97 | ||||
-rw-r--r-- | src/webview/webview-lib.pri | 10 |
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 |