From b24a6419869c14e32e87cb97e529cc25c246b5e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCri=20Valdmann?= <juri.valdmann@qt.io> Date: Wed, 5 Apr 2017 17:14:16 +0200 Subject: [PATCH] Create example for full screen feature in WebEngine Adds an example ('videoplayer') showing how to enable the Fullscreen API[1] in QWebEngineView. This is one of the missing examples blocking the removal of demobrowser. [1]: https://fullscreen.spec.whatwg.org Task-number: QTBUG-59820 Change-Id: Ib02a1556515d87e595ca54c2bce18c9144030fbc Reviewed-by: Kai Koehne <kai.koehne@qt.io> Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io> Reviewed-by: Michal Klocek <michal.klocek@qt.io> --- .../videoplayer/data/index.html | 23 +++ .../videoplayer/data/videoplayer.qrc | 5 + .../doc/images/videoplayer-example.png | Bin 0 -> 34140 bytes .../videoplayer/doc/src/videoplayer.qdoc | 186 ++++++++++++++++++ .../videoplayer/fullscreennotification.cpp | 87 ++++++++ .../videoplayer/fullscreennotification.h | 61 ++++++ .../videoplayer/fullscreenwindow.cpp | 88 +++++++++ .../videoplayer/fullscreenwindow.h | 68 +++++++ .../webenginewidgets/videoplayer/main.cpp | 53 +++++ .../videoplayer/mainwindow.cpp | 72 +++++++ .../webenginewidgets/videoplayer/mainwindow.h | 64 ++++++ .../videoplayer/videoplayer.pro | 19 ++ .../webenginewidgets/webenginewidgets.pro | 3 +- src/webengine/doc/qtwebengine.qdocconf | 2 +- 14 files changed, 729 insertions(+), 2 deletions(-) create mode 100644 examples/webenginewidgets/videoplayer/data/index.html create mode 100644 examples/webenginewidgets/videoplayer/data/videoplayer.qrc create mode 100644 examples/webenginewidgets/videoplayer/doc/images/videoplayer-example.png create mode 100644 examples/webenginewidgets/videoplayer/doc/src/videoplayer.qdoc create mode 100644 examples/webenginewidgets/videoplayer/fullscreennotification.cpp create mode 100644 examples/webenginewidgets/videoplayer/fullscreennotification.h create mode 100644 examples/webenginewidgets/videoplayer/fullscreenwindow.cpp create mode 100644 examples/webenginewidgets/videoplayer/fullscreenwindow.h create mode 100644 examples/webenginewidgets/videoplayer/main.cpp create mode 100644 examples/webenginewidgets/videoplayer/mainwindow.cpp create mode 100644 examples/webenginewidgets/videoplayer/mainwindow.h create mode 100644 examples/webenginewidgets/videoplayer/videoplayer.pro diff --git a/examples/webenginewidgets/videoplayer/data/index.html b/examples/webenginewidgets/videoplayer/data/index.html new file mode 100644 index 000000000..4a1bdc33e --- /dev/null +++ b/examples/webenginewidgets/videoplayer/data/index.html @@ -0,0 +1,23 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <style type="text/css"> + #ytplayer { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + } + </style> + </head> + <body> + <iframe + id="ytplayer" + src="https://www.youtube.com/embed/CjyjEUFn_FI" + frameborder="0" + allowfullscreen> + </iframe> + </body> +</html> diff --git a/examples/webenginewidgets/videoplayer/data/videoplayer.qrc b/examples/webenginewidgets/videoplayer/data/videoplayer.qrc new file mode 100644 index 000000000..c3322b454 --- /dev/null +++ b/examples/webenginewidgets/videoplayer/data/videoplayer.qrc @@ -0,0 +1,5 @@ +<RCC> + <qresource prefix="/"> + <file>index.html</file> + </qresource> +</RCC> diff --git a/examples/webenginewidgets/videoplayer/doc/images/videoplayer-example.png b/examples/webenginewidgets/videoplayer/doc/images/videoplayer-example.png new file mode 100644 index 0000000000000000000000000000000000000000..9cf51d84aaa00f8136df365c5edf3c514780c6e9 GIT binary patch literal 34140 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%0Daas&6krzUG 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 literal 0 HcmV?d00001 diff --git a/examples/webenginewidgets/videoplayer/doc/src/videoplayer.qdoc b/examples/webenginewidgets/videoplayer/doc/src/videoplayer.qdoc new file mode 100644 index 000000000..599e13e6c --- /dev/null +++ b/examples/webenginewidgets/videoplayer/doc/src/videoplayer.qdoc @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:FDL$ +** 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 Free Documentation License Usage +** Alternatively, this file may be used under the terms of the GNU Free +** Documentation License version 1.3 as published by the Free Software +** Foundation and appearing in the file included in the packaging of +** this file. Please review the following information to ensure +** the GNU Free Documentation License version 1.3 requirements +** will be met: http://www.gnu.org/copyleft/fdl.html. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example webenginewidgets/videoplayer + \title WebEngine Widgets Video Player Example + \ingroup webengine-widgetexamples + \brief Displays full screen video using \l QWebEngineView + + \image videoplayer-example.png + + \e {Video Player} demonstrates how to support full screen playback of HTML5 + video using \l QWebEngineView. + + \l {https://fullscreen.spec.whatwg.org/}{The Fullscreen API} is a + cross-browser Javascript API that enables a web page to request that one of + its HTML elements be made to occupy the user's entire screen. It is + commonly used for full screen video playback via the \c <video> element, but + can in principle be used to display any HTML content in full screen mode. Qt + WebEngine supports this API, however it is disabled by default. This example + shows the steps needed to switch it on, including: + + \list + \li Enabling it in \l QWebEngineSettings. + \li Handling the \l QWebEnginePage::fullScreenRequested signal by creating + a new full screen window. + \li Displaying a notification popup to ensure that the user is aware + that something is being displayed full screen. + \endlist + + \include examples-run.qdocinc + + \section1 Overview + + Once started, the example program will create a normal (non-fullscreen) + window with a \l QWebEngineView showing an embedded YouTube video player. + You can then click on the full screen toggle button (bottom-right corner) to + enter full screen mode. This should also display a centered notification + overlay informing you that you can exit full screen mode by pressing the + escape key. + + Implementation-wise entering full screen mode entails creating a new full + screen window with a separate \l QWebEngineView instance and migrating the + \l QWebEnginePage from the normal window's \l QWebEngineView to this new \l + QWebEngineView. Exiting full screen mode reverses this migration. + + The example code is divided between three classes, \c MainWindow, \c + FullScreenWindow, and \c FullScreenNotification. The classes \c MainWindow + and \c FullScreenWindow are each responsible for managing one top-level + window, while \c FullScreenNotification is responsible for styling and + animating the notification box. A \c MainWindow is created on startup and + lives for the entire program runtime, while a new \c FullScreenWindow is + created every time full screen mode is entered. + + \section1 MainWindow Class Declaration + + A \c MainWindow is a \l QMainWindow with a \l QWebEngineView as the central + widget: + + \quotefromfile webenginewidgets/videoplayer/mainwindow.h + \skipto #include + \printuntil /^\}/ + + \section1 MainWindow Class Definition + + In the constructor we start by setting up the \l QWebEngineView as the + central widget: + + \quotefromfile webenginewidgets/videoplayer/mainwindow.cpp + \skipto MainWindow::MainWindow + \printuntil setCentralWidget + + We then configure Qt WebEngine to advertise support for the Fullscreen API: + + \printline QWebEngineSettings + + Without this line the full screen toggle button would be disabled (grayed + out) as the Javascript running on the page can detect that our browser + does not support full screen mode. + + Next we connect the \c fullScreenRequested signal to our slot: + + \printuntil &MainWindow::fullScreenRequested + + This signal is emitted whenever the Javascript on the page wants to enter or + exit full screen mode. Without handling this signal (but still keeping the + \c FullScreenSupportEnabled attribute as \c true) the toggle button will be + enabled but clicking on it will have no effect as Javascript's full screen + request will be denied. + + Finally, we load some HTML (see + \l{webenginewidgets/videoplayer/data/index.html}{index.html} included with + the example) into our \l QWebEngineView: + + \printline load + + The second part of \c MainWindow is handling the full screen requests: + + \skipto MainWindow::fullScreenRequested + \printuntil /^\}/ + + We create a new \c FullScreenWindow when entering full screen mode, and + delete it when exiting. + + \section1 FullScreenWindow Class Declaration + + A \c FullScreenWindow is a \l QWidget containing a \l QWebEngineView and a + \c FullScreenNotification. + + \quotefromfile webenginewidgets/videoplayer/fullscreenwindow.h + \skipto #include + \printuntil /^\}/ + + \section1 FullScreenWindow Class Definition + + The constructor is responsible for hiding the normal window (while saving + its geometry) and showing the new \c FullScreenWindow instead: + + \quotefromfile webenginewidgets/videoplayer/fullscreenwindow.cpp + \skipto FullScreenWindow::FullScreenWindow + \printuntil /^\}/ + + The call to \l QWebEngineView::setPage will move the web page from the \c + MainWindow's view to \c FullScreenWindow's view. + + In the destructor we use the same method to move the page back, after which + we restore the main window's geometry and visibility: + + \skipto FullScreenWindow::~FullScreenWindow + \printuntil /^\}/ + + We override \l QWidget::resizeEvent to do manual layout, keeping the \l + QWebEngineView maximized, and the \c FullScreenNotification centered within + the window: + + \skipto FullScreenWindow::resizeEvent + \printuntil /^\}/ + + \section1 FullScreenNotification Class Declaration + + A \c FullScreenNotification is just a \l QLabel with some styling and + animation: + + \quotefromfile webenginewidgets/videoplayer/fullscreennotification.h + \skipto #include + \printuntil /^\}/ + + \section1 FullScreenWindow Class Definition + + In the constructor we configure the QLabel and set up a delayed fade-out + animation using \l {The Animation Framework}: + + \quotefromfile webenginewidgets/videoplayer/fullscreennotification.cpp + \skipto FullScreenNotification::FullScreenNotification + \printuntil /^\}/ + + The custom signal \c shown, which we use to trigger the animation, is + emitted from the \c showEvent method: + + \skipto FullScreenNotification::showEvent + \printuntil /^\}/ +*/ diff --git a/examples/webenginewidgets/videoplayer/fullscreennotification.cpp b/examples/webenginewidgets/videoplayer/fullscreennotification.cpp new file mode 100644 index 000000000..e65e2cbad --- /dev/null +++ b/examples/webenginewidgets/videoplayer/fullscreennotification.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "fullscreennotification.h" + +#include <QGraphicsOpacityEffect> +#include <QPropertyAnimation> +#include <QSequentialAnimationGroup> + +FullScreenNotification::FullScreenNotification(QWidget *parent) + : QLabel(parent) + , m_previouslyVisible(false) +{ + setText(tr("You are now in full screen mode. Press ESC to quit!")); + setStyleSheet( + "font-size: 24px;" + "color: white;" + "background-color: black;" + "border-color: white;" + "border-width: 2px;" + "border-style: solid;" + "padding: 100px"); + setAttribute(Qt::WA_TransparentForMouseEvents); + + auto effect = new QGraphicsOpacityEffect; + effect->setOpacity(1); + setGraphicsEffect(effect); + + auto animations = new QSequentialAnimationGroup(this); + animations->addPause(3000); + auto opacityAnimation = new QPropertyAnimation(effect, "opacity", animations); + opacityAnimation->setDuration(2000); + opacityAnimation->setStartValue(1.0); + opacityAnimation->setEndValue(0.0); + opacityAnimation->setEasingCurve(QEasingCurve::OutQuad); + animations->addAnimation(opacityAnimation); + + connect(this, &FullScreenNotification::shown, + [animations](){ animations->start(); }); + + connect(animations, &QAbstractAnimation::finished, + [this](){ this->hide(); }); +} + +void FullScreenNotification::showEvent(QShowEvent *event) +{ + QLabel::showEvent(event); + if (!m_previouslyVisible && isVisible()) + emit shown(); + m_previouslyVisible = isVisible(); +} diff --git a/examples/webenginewidgets/videoplayer/fullscreennotification.h b/examples/webenginewidgets/videoplayer/fullscreennotification.h new file mode 100644 index 000000000..9f1befb9f --- /dev/null +++ b/examples/webenginewidgets/videoplayer/fullscreennotification.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef FULLSCREENNOTIFICATION_H +#define FULLSCREENNOTIFICATION_H + +#include <QLabel> + +class FullScreenNotification : public QLabel +{ + Q_OBJECT +public: + FullScreenNotification(QWidget *parent = nullptr); + +protected: + void showEvent(QShowEvent *event) override; + +signals: + void shown(); + +private: + bool m_previouslyVisible; +}; + +#endif // FULLSCREENNOTIFICATION_H diff --git a/examples/webenginewidgets/videoplayer/fullscreenwindow.cpp b/examples/webenginewidgets/videoplayer/fullscreenwindow.cpp new file mode 100644 index 000000000..df28839a2 --- /dev/null +++ b/examples/webenginewidgets/videoplayer/fullscreenwindow.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "fullscreenwindow.h" + +#include "fullscreennotification.h" + +#include <QAction> +#include <QLabel> +#include <QWebEngineView> + +FullScreenWindow::FullScreenWindow(QWebEngineView *oldView, QWidget *parent) + : QWidget(parent) + , m_view(new QWebEngineView(this)) + , m_notification(new FullScreenNotification(this)) + , m_oldView(oldView) + , m_oldGeometry(oldView->window()->geometry()) +{ + m_view->stackUnder(m_notification); + + auto exitAction = new QAction(this); + exitAction->setShortcut(Qt::Key_Escape); + connect(exitAction, &QAction::triggered, [this]() { + m_view->triggerPageAction(QWebEnginePage::ExitFullScreen); + }); + addAction(exitAction); + + m_view->setPage(m_oldView->page()); + setGeometry(m_oldGeometry); + showFullScreen(); + m_oldView->window()->hide(); +} + +FullScreenWindow::~FullScreenWindow() +{ + m_oldView->setPage(m_view->page()); + m_oldView->window()->setGeometry(m_oldGeometry); + m_oldView->window()->show(); + hide(); +} + +void FullScreenWindow::resizeEvent(QResizeEvent *event) +{ + QRect viewGeometry(QPoint(0, 0), size()); + m_view->setGeometry(viewGeometry); + + QRect notificationGeometry(QPoint(0, 0), m_notification->sizeHint()); + notificationGeometry.moveCenter(viewGeometry.center()); + m_notification->setGeometry(notificationGeometry); + + QWidget::resizeEvent(event); +} diff --git a/examples/webenginewidgets/videoplayer/fullscreenwindow.h b/examples/webenginewidgets/videoplayer/fullscreenwindow.h new file mode 100644 index 000000000..dda0a9885 --- /dev/null +++ b/examples/webenginewidgets/videoplayer/fullscreenwindow.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef FULLSCREENWINDOW_H +#define FULLSCREENWINDOW_H + +#include <QWidget> + +QT_BEGIN_NAMESPACE +class QWebEngineView; +QT_END_NAMESPACE + +class FullScreenNotification; + +class FullScreenWindow : public QWidget +{ + Q_OBJECT +public: + explicit FullScreenWindow(QWebEngineView *oldView, QWidget *parent = nullptr); + ~FullScreenWindow(); + +protected: + void resizeEvent(QResizeEvent *event) override; + +private: + QWebEngineView *m_view; + FullScreenNotification *m_notification; + QWebEngineView *m_oldView; + QRect m_oldGeometry; +}; + +#endif // FULLSCREENWINDOW_H diff --git a/examples/webenginewidgets/videoplayer/main.cpp b/examples/webenginewidgets/videoplayer/main.cpp new file mode 100644 index 000000000..fcddd988e --- /dev/null +++ b/examples/webenginewidgets/videoplayer/main.cpp @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mainwindow.h" +#include <QApplication> + +int main(int argc, char *argv[]) +{ + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QApplication app(argc, argv); + + MainWindow mainWindow; + mainWindow.show(); + + return app.exec(); +} diff --git a/examples/webenginewidgets/videoplayer/mainwindow.cpp b/examples/webenginewidgets/videoplayer/mainwindow.cpp new file mode 100644 index 000000000..55885e0c5 --- /dev/null +++ b/examples/webenginewidgets/videoplayer/mainwindow.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "mainwindow.h" + +#include <QWebEngineView> +#include <QWebEngineSettings> +#include <QWebEngineFullScreenRequest> + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , m_view(new QWebEngineView(this)) +{ + setCentralWidget(m_view); + m_view->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true); + connect(m_view->page(), + &QWebEnginePage::fullScreenRequested, + this, + &MainWindow::fullScreenRequested); + m_view->load(QUrl(QStringLiteral("qrc:/index.html"))); +} + +void MainWindow::fullScreenRequested(QWebEngineFullScreenRequest request) +{ + if (request.toggleOn()) { + if (m_fullScreenWindow) + return; + request.accept(); + m_fullScreenWindow.reset(new FullScreenWindow(m_view)); + } else { + if (!m_fullScreenWindow) + return; + request.accept(); + m_fullScreenWindow.reset(); + } +} diff --git a/examples/webenginewidgets/videoplayer/mainwindow.h b/examples/webenginewidgets/videoplayer/mainwindow.h new file mode 100644 index 000000000..a270c6295 --- /dev/null +++ b/examples/webenginewidgets/videoplayer/mainwindow.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include "fullscreenwindow.h" + +#include <QMainWindow> +#include <QWebEngineView> +#include <QWebEngineFullScreenRequest> + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + +private slots: + void fullScreenRequested(QWebEngineFullScreenRequest request); + +private: + QWebEngineView *m_view; + QScopedPointer<FullScreenWindow> m_fullScreenWindow; +}; + +#endif // MAINWINDOW_H diff --git a/examples/webenginewidgets/videoplayer/videoplayer.pro b/examples/webenginewidgets/videoplayer/videoplayer.pro new file mode 100644 index 000000000..ab55992e0 --- /dev/null +++ b/examples/webenginewidgets/videoplayer/videoplayer.pro @@ -0,0 +1,19 @@ +TEMPLATE = app + +QT += webenginewidgets + +HEADERS += \ + mainwindow.h \ + fullscreenwindow.h \ + fullscreennotification.h + +SOURCES += main.cpp \ + mainwindow.cpp \ + fullscreenwindow.cpp \ + fullscreennotification.cpp + +RESOURCES += \ + data/videoplayer.qrc + +target.path = $$[QT_INSTALL_EXAMPLES]/webenginewidgets/videoplayer +INSTALLS += target diff --git a/examples/webenginewidgets/webenginewidgets.pro b/examples/webenginewidgets/webenginewidgets.pro index 353104d6a..41582bbf7 100644 --- a/examples/webenginewidgets/webenginewidgets.pro +++ b/examples/webenginewidgets/webenginewidgets.pro @@ -6,7 +6,8 @@ SUBDIRS += \ cookiebrowser \ demobrowser \ markdowneditor \ - simplebrowser + simplebrowser \ + videoplayer contains(WEBENGINE_CONFIG, use_spellchecker):!cross_compile { !contains(WEBENGINE_CONFIG, use_native_spellchecker) { diff --git a/src/webengine/doc/qtwebengine.qdocconf b/src/webengine/doc/qtwebengine.qdocconf index fe83b082f..bc63addbe 100644 --- a/src/webengine/doc/qtwebengine.qdocconf +++ b/src/webengine/doc/qtwebengine.qdocconf @@ -67,7 +67,7 @@ exampledirs += . \ ../../core/doc/snippets \ ../../webenginewidgets/doc/snippets -examples.fileextensions += *.aff *.dic +examples.fileextensions += *.aff *.dic *.html imagedirs += images -- GitLab