Revision control
++ // Copyright (C) 2021 The Qt Company Ltd.
++ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
++
++ #include "qvideowidget.h"
++ #include "qvideowidget_p.h"
++
++ #include <QtMultimedia/private/qtmultimediaglobal_p.h>
++ #include <QtMultimedia/qtmultimediaglobal.h>
++ #include <QtMultimedia/qvideoframeformat.h>
++ #include <QtMultimedia/qvideosink.h>
++ #include <QtMultimedia/private/qvideowindow_p.h>
++
++ #include <QtGui/qevent.h>
++ #include <QtGui/qguiapplication.h>
++ #include <QtCore/qobject.h>
++
++ QT_BEGIN_NAMESPACE
++
++ using namespace Qt::Literals;
++
++ /*!
++ \class QVideoWidget
++
++
++ \brief The QVideoWidget class provides a widget which presents video
++ produced by a media object.
++ \ingroup multimedia
++ \ingroup multimedia_video
++ \inmodule QtMultimediaWidgets
++
++ Attaching a QVideoWidget to a QMediaPlayer or QCamera allows it to display the
++ video or image output of that object.
++
++ \snippet multimedia-snippets/video.cpp Video widget
++
++ \b {Note}: Only a single display output can be attached to a media
++ object at one time.
++
++ \warning QVideoWidget is not supported on the \c eglfs platform plugin.
++
++ \sa QCamera, QMediaPlayer, QGraphicsVideoItem
++ */
++ /*!
++ \variable QVideoWidget::d_ptr
++ \internal
++ */
++ /*!
++ Constructs a new video widget.
++
++ The \a parent is passed to QWidget.
++ */
++ QVideoWidget::QVideoWidget(QWidget *parent)
++ : QWidget(parent, {})
++ , d_ptr(new QVideoWidgetPrivate)
++ {
++ d_ptr->q_ptr = this;
++ d_ptr->isEglfs = QGuiApplication::platformName().startsWith("eglfs"_L1, Qt::CaseInsensitive);
++
++ if (d_ptr->isEglfs) {
++ qWarning("QVideoWidget is not supported on eglfs");
++ d_ptr->fakeVideoSink = new QVideoSink(this);
++ } else {
++ d_ptr->videoWindow = new QVideoWindow;
++ d_ptr->videoWindow->setFlag(Qt::WindowTransparentForInput, true);
++ d_ptr->windowContainer = QWidget::createWindowContainer(d_ptr->videoWindow, this, Qt::WindowTransparentForInput);
++ d_ptr->windowContainer->move(0, 0);
++ d_ptr->windowContainer->resize(size());
++ connect(d_ptr->videoWindow, &QVideoWindow::aspectRatioModeChanged, this,
++ &QVideoWidget::aspectRatioModeChanged);
++ }
++ }
++
++ /*!
++ Destroys a video widget.
++ */
++ QVideoWidget::~QVideoWidget()
++ {
++ delete d_ptr->videoWindow;
++ delete d_ptr;
++ }
++
++ /*!
++ Returns the QVideoSink instance.
++ */
++ QVideoSink *QVideoWidget::videoSink() const
++ {
++ return d_ptr->videoWindow ? d_ptr->videoWindow->videoSink() : d_ptr->fakeVideoSink;
++ }
++
++ /*!
++ \property QVideoWidget::aspectRatioMode
++ \brief how video is scaled with respect to its aspect ratio.
++ */
++
++ Qt::AspectRatioMode QVideoWidget::aspectRatioMode() const
++ {
++ return d_ptr->videoWindow ? d_ptr->videoWindow->aspectRatioMode() : Qt::KeepAspectRatio;
++ }
++
++ void QVideoWidget::setAspectRatioMode(Qt::AspectRatioMode mode)
++ {
++ if (d_ptr->videoWindow)
++ d_ptr->videoWindow->setAspectRatioMode(mode);
++ }
++
++ /*!
++ \property QVideoWidget::fullScreen
++ \brief whether video display is confined to a window or is fullScreen.
++ */
++
++ void QVideoWidget::setFullScreen(bool fullScreen)
++ {
++ Q_D(QVideoWidget);
++ if (isFullScreen() == fullScreen)
++ return;
++
++ if (d_ptr->isEglfs)
++ return;
++
++ Qt::WindowFlags flags = windowFlags();
++
++ if (fullScreen) {
++ // get the position of the widget in global coordinates
++ QPoint position = mapToGlobal(QPoint(0,0));
++ d->nonFullScreenFlags = flags & (Qt::Window | Qt::SubWindow);
++ d_ptr->nonFullscreenPos = pos();
++ flags |= Qt::Window;
++ flags &= ~Qt::SubWindow;
++ setWindowFlags(flags);
++ // move the widget to the position it had on screen, so that showFullScreen() will
++ // place it on the correct screen
++ move(position);
++
++ showFullScreen();
++ } else {
++ flags &= ~(Qt::Window | Qt::SubWindow); //clear the flags...
++ flags |= d->nonFullScreenFlags; //then we reset the flags (window and subwindow)
++ setWindowFlags(flags);
++
++ showNormal();
++ move(d_ptr->nonFullscreenPos);
++ d_ptr->nonFullscreenPos = {};
++ }
++ }
++
++ /*!
++ Returns the size hint for the current back end,
++ if there is one, or else the size hint from QWidget.
++ */
++ QSize QVideoWidget::sizeHint() const
++ {
++ auto size = videoSink()->videoSize();
++ if (size.isValid())
++ return size;
++
++ return QWidget::sizeHint();
++ }
++
++ /*!
++ \reimp
++ Current event \a event.
++ Returns the value of the base class QWidget::event(QEvent *event) function.
++ */
++ bool QVideoWidget::event(QEvent *event)
++ {
++ Q_D(QVideoWidget);
++
++ if (event->type() == QEvent::WindowStateChange) {
++ bool fullScreen = bool(windowState() & Qt::WindowFullScreen);
++ if (fullScreen != d->wasFullScreen) {
++ Q_EMIT fullScreenChanged(fullScreen);
++ d->wasFullScreen = fullScreen;
++ }
++ }
++
++ return QWidget::event(event);
++ }
++
++ /*!
++ \reimp
++ Handles the show \a event.
++ */
++ void QVideoWidget::showEvent(QShowEvent *event)
++ {
++ QWidget::showEvent(event);
++ }
++
++ /*!
++ \reimp
++ Handles the hide \a event.
++ */
++ void QVideoWidget::hideEvent(QHideEvent *event)
++ {
++ QWidget::hideEvent(event);
++ }
++
++ /*!
++ \reimp
++ Handles the resize \a event.
++ */
++ void QVideoWidget::resizeEvent(QResizeEvent *event)
++ {
++ if (!d_ptr->isEglfs)
++ d_ptr->windowContainer->resize(event->size());
++ QWidget::resizeEvent(event);
++ }
++
++ /*!
++ \reimp
++ Handles the move \a event.
++ */
++ void QVideoWidget::moveEvent(QMoveEvent *event)
++ {
++ if (!d_ptr->isEglfs)
++ QWidget::moveEvent(event);
++ }
++
++ QT_END_NAMESPACE
++
++ #include "moc_qvideowidget.cpp"