/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qvideowidget_p.h"
#include "qpaintervideosurface_p.h"

#include <qmediaobject.h>
#include <qmediaservice.h>
#include <qvideowindowcontrol.h>
#include <qvideowidgetcontrol.h>

#include <qvideorenderercontrol.h>
#include <qvideosurfaceformat.h>
#include <qpainter.h>

#include <qapplication.h>
#include <qevent.h>
#include <qboxlayout.h>
#include <qnamespace.h>

#include <qwindow.h>
#include <private/qhighdpiscaling_p.h>

#ifdef Q_OS_WIN
#include <QtCore/qt_windows.h>
#endif

using namespace Qt;

QT_BEGIN_NAMESPACE

QVideoWidgetControlBackend::QVideoWidgetControlBackend(
        QMediaService *service, QVideoWidgetControl *control, QWidget *widget)
    : m_service(service)
    , m_widgetControl(control)
{
    connect(control, SIGNAL(brightnessChanged(int)), widget, SLOT(_q_brightnessChanged(int)));
    connect(control, SIGNAL(contrastChanged(int)), widget, SLOT(_q_contrastChanged(int)));
    connect(control, SIGNAL(hueChanged(int)), widget, SLOT(_q_hueChanged(int)));
    connect(control, SIGNAL(saturationChanged(int)), widget, SLOT(_q_saturationChanged(int)));
    connect(control, SIGNAL(fullScreenChanged(bool)), widget, SLOT(_q_fullScreenChanged(bool)));

    QBoxLayout *layout = new QVBoxLayout;
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);

    QWidget *videoWidget = control->videoWidget();
    videoWidget->setMouseTracking(widget->hasMouseTracking());
    layout->addWidget(videoWidget);

    widget->setLayout(layout);
}

void QVideoWidgetControlBackend::releaseControl()
{
    m_service->releaseControl(m_widgetControl);
}

void QVideoWidgetControlBackend::setBrightness(int brightness)
{
    m_widgetControl->setBrightness(brightness);
}

void QVideoWidgetControlBackend::setContrast(int contrast)
{
    m_widgetControl->setContrast(contrast);
}

void QVideoWidgetControlBackend::setHue(int hue)
{
    m_widgetControl->setHue(hue);
}

void QVideoWidgetControlBackend::setSaturation(int saturation)
{
    m_widgetControl->setSaturation(saturation);
}

void QVideoWidgetControlBackend::setFullScreen(bool fullScreen)
{
    m_widgetControl->setFullScreen(fullScreen);
}


Qt::AspectRatioMode QVideoWidgetControlBackend::aspectRatioMode() const
{
    return m_widgetControl->aspectRatioMode();
}

void QVideoWidgetControlBackend::setAspectRatioMode(Qt::AspectRatioMode mode)
{
    m_widgetControl->setAspectRatioMode(mode);
}

QRendererVideoWidgetBackend::QRendererVideoWidgetBackend(
        QMediaService *service, QVideoRendererControl *control, QWidget *widget)
    : m_service(service)
    , m_rendererControl(control)
    , m_widget(widget)
    , m_surface(new QPainterVideoSurface)
    , m_aspectRatioMode(Qt::KeepAspectRatio)
    , m_updatePaintDevice(true)
{
    connect(this, SIGNAL(brightnessChanged(int)), m_widget, SLOT(_q_brightnessChanged(int)));
    connect(this, SIGNAL(contrastChanged(int)), m_widget, SLOT(_q_contrastChanged(int)));
    connect(this, SIGNAL(hueChanged(int)), m_widget, SLOT(_q_hueChanged(int)));
    connect(this, SIGNAL(saturationChanged(int)), m_widget, SLOT(_q_saturationChanged(int)));
    connect(m_surface, SIGNAL(frameChanged()), this, SLOT(frameChanged()));
    connect(m_surface, SIGNAL(surfaceFormatChanged(QVideoSurfaceFormat)),
            this, SLOT(formatChanged(QVideoSurfaceFormat)));

    if (m_rendererControl)
        m_rendererControl->setSurface(m_surface);
}

QRendererVideoWidgetBackend::~QRendererVideoWidgetBackend()
{
    delete m_surface;
}

QAbstractVideoSurface *QRendererVideoWidgetBackend::videoSurface() const
{
    return m_surface;
}

void QRendererVideoWidgetBackend::releaseControl()
{
    if (m_service && m_rendererControl)
        m_service->releaseControl(m_rendererControl);
}

void QRendererVideoWidgetBackend::clearSurface()
{
    if (m_rendererControl)
        m_rendererControl->setSurface(0);
}

void QRendererVideoWidgetBackend::setBrightness(int brightness)
{
    m_surface->setBrightness(brightness);

    emit brightnessChanged(brightness);
}

void QRendererVideoWidgetBackend::setContrast(int contrast)
{
    m_surface->setContrast(contrast);

    emit contrastChanged(contrast);
}

void QRendererVideoWidgetBackend::setHue(int hue)
{
    m_surface->setHue(hue);

    emit hueChanged(hue);
}

void QRendererVideoWidgetBackend::setSaturation(int saturation)
{
    m_surface->setSaturation(saturation);

    emit saturationChanged(saturation);
}

Qt::AspectRatioMode QRendererVideoWidgetBackend::aspectRatioMode() const
{
    return m_aspectRatioMode;
}

void QRendererVideoWidgetBackend::setAspectRatioMode(Qt::AspectRatioMode mode)
{
    m_aspectRatioMode = mode;

    m_widget->updateGeometry();
}

void QRendererVideoWidgetBackend::setFullScreen(bool)
{
}

QSize QRendererVideoWidgetBackend::sizeHint() const
{
    return m_surface->surfaceFormat().sizeHint();
}

void QRendererVideoWidgetBackend::showEvent()
{
}

void QRendererVideoWidgetBackend::hideEvent(QHideEvent *)
{
#if QT_CONFIG(opengl)
    m_updatePaintDevice = true;
#endif
}

void QRendererVideoWidgetBackend::resizeEvent(QResizeEvent *)
{
    updateRects();
}

void QRendererVideoWidgetBackend::moveEvent(QMoveEvent *)
{
}

void QRendererVideoWidgetBackend::paintEvent(QPaintEvent *event)
{
    QPainter painter(m_widget);

    if (m_widget->testAttribute(Qt::WA_OpaquePaintEvent)) {
        QRegion borderRegion = event->region();
        borderRegion = borderRegion.subtracted(m_boundingRect);

        QBrush brush = m_widget->palette().window();

        for (const QRect &r : borderRegion)
            painter.fillRect(r, brush);
    }

    if (m_surface->isActive() && m_boundingRect.intersects(event->rect())) {
        m_surface->paint(&painter, m_boundingRect, m_sourceRect);

        m_surface->setReady(true);
    } else {
#if QT_CONFIG(opengl)
        if (m_updatePaintDevice && (painter.paintEngine()->type() == QPaintEngine::OpenGL
                || painter.paintEngine()->type() == QPaintEngine::OpenGL2)) {
            m_updatePaintDevice = false;

            m_surface->updateGLContext();
            if (m_surface->supportedShaderTypes() & QPainterVideoSurface::GlslShader) {
                m_surface->setShaderType(QPainterVideoSurface::GlslShader);
            } else {
                m_surface->setShaderType(QPainterVideoSurface::FragmentProgramShader);
            }
        }
#endif
    }

}

void QRendererVideoWidgetBackend::formatChanged(const QVideoSurfaceFormat &format)
{
    m_nativeSize = format.sizeHint();

    updateRects();

    m_widget->updateGeometry();
    m_widget->update();
}

void QRendererVideoWidgetBackend::frameChanged()
{
    m_widget->update(m_boundingRect);
}

void QRendererVideoWidgetBackend::updateRects()
{
    QRect rect = m_widget->rect();

    if (m_nativeSize.isEmpty()) {
        m_boundingRect = QRect();
    } else if (m_aspectRatioMode == Qt::IgnoreAspectRatio) {
        m_boundingRect = rect;
        m_sourceRect = QRectF(0, 0, 1, 1);
    } else if (m_aspectRatioMode == Qt::KeepAspectRatio) {
        QSize size = m_nativeSize;
        size.scale(rect.size(), Qt::KeepAspectRatio);

        m_boundingRect = QRect(0, 0, size.width(), size.height());
        m_boundingRect.moveCenter(rect.center());

        m_sourceRect = QRectF(0, 0, 1, 1);
    } else if (m_aspectRatioMode == Qt::KeepAspectRatioByExpanding) {
        m_boundingRect = rect;

        QSizeF size = rect.size();
        size.scale(m_nativeSize, Qt::KeepAspectRatio);

        m_sourceRect = QRectF(
                0, 0, size.width() / m_nativeSize.width(), size.height() / m_nativeSize.height());
        m_sourceRect.moveCenter(QPointF(0.5, 0.5));
    }
}

QWindowVideoWidgetBackend::QWindowVideoWidgetBackend(
        QMediaService *service, QVideoWindowControl *control, QWidget *widget)
    : m_service(service)
    , m_windowControl(control)
    , m_widget(widget)
{
    connect(control, SIGNAL(brightnessChanged(int)), m_widget, SLOT(_q_brightnessChanged(int)));
    connect(control, SIGNAL(contrastChanged(int)), m_widget, SLOT(_q_contrastChanged(int)));
    connect(control, SIGNAL(hueChanged(int)), m_widget, SLOT(_q_hueChanged(int)));
    connect(control, SIGNAL(saturationChanged(int)), m_widget, SLOT(_q_saturationChanged(int)));
    connect(control, SIGNAL(fullScreenChanged(bool)), m_widget, SLOT(_q_fullScreenChanged(bool)));
    connect(control, SIGNAL(nativeSizeChanged()), m_widget, SLOT(_q_dimensionsChanged()));

    control->setWinId(widget->winId());
#if defined(Q_OS_WIN)
    // Disable updates to avoid flickering while resizing/moving.
    m_widget->setUpdatesEnabled(false);
#endif
}

QWindowVideoWidgetBackend::~QWindowVideoWidgetBackend()
{
}

void QWindowVideoWidgetBackend::releaseControl()
{
    m_service->releaseControl(m_windowControl);
}

void QWindowVideoWidgetBackend::setBrightness(int brightness)
{
    m_windowControl->setBrightness(brightness);
}

void QWindowVideoWidgetBackend::setContrast(int contrast)
{
    m_windowControl->setContrast(contrast);
}

void QWindowVideoWidgetBackend::setHue(int hue)
{
    m_windowControl->setHue(hue);
}

void QWindowVideoWidgetBackend::setSaturation(int saturation)
{
    m_windowControl->setSaturation(saturation);
}

void QWindowVideoWidgetBackend::setFullScreen(bool fullScreen)
{
    m_windowControl->setFullScreen(fullScreen);
}

Qt::AspectRatioMode QWindowVideoWidgetBackend::aspectRatioMode() const
{
    return m_windowControl->aspectRatioMode();
}

void QWindowVideoWidgetBackend::setAspectRatioMode(Qt::AspectRatioMode mode)
{
    m_windowControl->setAspectRatioMode(mode);
}

QSize QWindowVideoWidgetBackend::sizeHint() const
{
    return m_windowControl->nativeSize();
}

void QWindowVideoWidgetBackend::updateDisplayRect()
{
    QRect rect = m_widget->rect();
    if (QHighDpiScaling::isActive()) {
        const qreal factor = QHighDpiScaling::factor(m_widget->windowHandle());
        if (!qFuzzyCompare(factor, qreal(1))) {
            rect = QRectF(QPointF(rect.topLeft()) * factor,
                          QSizeF(rect.size()) * factor).toRect();
        }
    }
    m_windowControl->setDisplayRect(rect);
}

void QWindowVideoWidgetBackend::showEvent()
{
    m_windowControl->setWinId(m_widget->winId());
    updateDisplayRect();

#if defined(Q_OS_WIN)
    m_windowControl->repaint();
#endif
}

void QWindowVideoWidgetBackend::hideEvent(QHideEvent *)
{
}

void QWindowVideoWidgetBackend::moveEvent(QMoveEvent *)
{
    updateDisplayRect();
}

void QWindowVideoWidgetBackend::resizeEvent(QResizeEvent *)
{
    updateDisplayRect();
}

void QWindowVideoWidgetBackend::paintEvent(QPaintEvent *event)
{
    if (m_widget->testAttribute(Qt::WA_OpaquePaintEvent)) {
        QPainter painter(m_widget);

        painter.fillRect(event->rect(), m_widget->palette().window());
    }

    m_windowControl->repaint();

    event->accept();
}

void QVideoWidgetPrivate::setCurrentControl(QVideoWidgetControlInterface *control)
{
    if (currentControl != control) {
        currentControl = control;

        currentControl->setBrightness(brightness);
        currentControl->setContrast(contrast);
        currentControl->setHue(hue);
        currentControl->setSaturation(saturation);
        currentControl->setAspectRatioMode(aspectRatioMode);
    }
}

void QVideoWidgetPrivate::clearService()
{
    if (service) {
        QObject::disconnect(service, SIGNAL(destroyed()), q_func(), SLOT(_q_serviceDestroyed()));

        if (widgetBackend) {
            QLayout *layout = q_func()->layout();

            for (QLayoutItem *item = layout->takeAt(0); item; item = layout->takeAt(0)) {
                item->widget()->setParent(0);
                delete item;
            }
            delete layout;

            widgetBackend->releaseControl();

            delete widgetBackend;
            widgetBackend = 0;
        } else if (rendererBackend) {
            rendererBackend->clearSurface();
            rendererBackend->releaseControl();

            delete rendererBackend;
            rendererBackend = 0;
        } else if (windowBackend) {
            windowBackend->releaseControl();

            delete windowBackend;
            windowBackend = 0;
        }

        currentBackend = 0;
        currentControl = 0;
        service = 0;
    }
}

bool QVideoWidgetPrivate::createWidgetBackend()
{
    if (QMediaControl *control = service->requestControl(QVideoWidgetControl_iid)) {
        if (QVideoWidgetControl *widgetControl = qobject_cast<QVideoWidgetControl *>(control)) {
            widgetBackend = new QVideoWidgetControlBackend(service, widgetControl, q_func());

            setCurrentControl(widgetBackend);

            return true;
        }
        service->releaseControl(control);
    }
    return false;
}

bool QVideoWidgetPrivate::createWindowBackend()
{
    if (QMediaControl *control = service->requestControl(QVideoWindowControl_iid)) {
        if (QVideoWindowControl *windowControl = qobject_cast<QVideoWindowControl *>(control)) {
            windowBackend = new QWindowVideoWidgetBackend(service, windowControl, q_func());
            currentBackend = windowBackend;

            setCurrentControl(windowBackend);

            return true;
        }
        service->releaseControl(control);
    }
    return false;
}

bool QVideoWidgetPrivate::createRendererBackend()
{
    QMediaControl *control = service
                           ? service->requestControl(QVideoRendererControl_iid)
                           : nullptr;
    rendererBackend = new QRendererVideoWidgetBackend(service,
        qobject_cast<QVideoRendererControl *>(control), q_func());
    currentBackend = rendererBackend;
    setCurrentControl(rendererBackend);

    return !service || (service && control);
}

void QVideoWidgetPrivate::_q_serviceDestroyed()
{
    if (widgetBackend)
        delete q_func()->layout();

    delete widgetBackend;
    delete windowBackend;
    delete rendererBackend;

    widgetBackend = 0;
    windowBackend = 0;
    rendererBackend = 0;
    currentControl = 0;
    currentBackend = 0;
    service = 0;
}

void QVideoWidgetPrivate::_q_brightnessChanged(int b)
{
    if (b != brightness)
        emit q_func()->brightnessChanged(brightness = b);
}

void QVideoWidgetPrivate::_q_contrastChanged(int c)
{
    if (c != contrast)
        emit q_func()->contrastChanged(contrast = c);
}

void QVideoWidgetPrivate::_q_hueChanged(int h)
{
    if (h != hue)
        emit q_func()->hueChanged(hue = h);
}

void QVideoWidgetPrivate::_q_saturationChanged(int s)
{
    if (s != saturation)
        emit q_func()->saturationChanged(saturation = s);
}


void QVideoWidgetPrivate::_q_fullScreenChanged(bool fullScreen)
{
    if (!fullScreen && q_func()->isFullScreen())
        q_func()->showNormal();
}

void QVideoWidgetPrivate::_q_dimensionsChanged()
{
    q_func()->updateGeometry();
    q_func()->update();
}

/*!
    \class QVideoWidget


    \brief The QVideoWidget class provides a widget which presents video
    produced by a media object.
    \ingroup multimedia
    \inmodule QtMultimediaWidgets

    Attaching a QVideoWidget to a QMediaObject allows it to display the
    video or image output of that media object.  A QVideoWidget is attached
    to media object by passing a pointer to the QMediaObject in its
    constructor, and detached by destroying the QVideoWidget.

    \snippet multimedia-snippets/video.cpp Video widget

    \b {Note}: Only a single display output can be attached to a media
    object at one time.

    \sa QMediaObject, QMediaPlayer, QGraphicsVideoItem
*/

/*!
    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;
}

/*!
  \internal
*/
QVideoWidget::QVideoWidget(QVideoWidgetPrivate &dd, QWidget *parent)
    : QWidget(parent, {})
    , d_ptr(&dd)
{
    d_ptr->q_ptr = this;

    QPalette palette = QWidget::palette();
    palette.setColor(QPalette::Window, Qt::black);
    setPalette(palette);
}

/*!
    Destroys a video widget.
*/
QVideoWidget::~QVideoWidget()
{
    d_ptr->clearService();

    delete d_ptr;
}

/*!
    \property QVideoWidget::mediaObject
    \brief the media object which provides the video displayed by a widget.
*/

QMediaObject *QVideoWidget::mediaObject() const
{
    return d_func()->mediaObject;
}

/*!
    \internal
*/
bool QVideoWidget::setMediaObject(QMediaObject *object)
{
    Q_D(QVideoWidget);

    if (object == d->mediaObject)
        return true;

    d->clearService();

    d->mediaObject = object;

    if (d->mediaObject)
        d->service = d->mediaObject->service();

    if (d->service) {
        if (d->createWidgetBackend()) {
            // Nothing to do here.
        } else if ((!window() || !window()->testAttribute(Qt::WA_DontShowOnScreen))
                && d->createWindowBackend()) {
            if (isVisible())
                d->windowBackend->showEvent();
        } else if (d->createRendererBackend()) {
            if (isVisible())
                d->rendererBackend->showEvent();
        } else {
            d->service = 0;
            d->mediaObject = 0;

            return false;
        }

        connect(d->service, SIGNAL(destroyed()), SLOT(_q_serviceDestroyed()));
    } else {
        d->mediaObject = 0;

        return false;
    }

    return true;
}

/*!
    \since 5.15
    \property QVideoWidget::videoSurface
    \brief Returns the underlaying video surface that can render video frames
    to the current widget.
    This property is never \c nullptr.
    Example of how to render video frames to QVideoWidget:
    \snippet multimedia-snippets/video.cpp Widget Surface
    \sa QMediaPlayer::setVideoOutput
*/

QAbstractVideoSurface *QVideoWidget::videoSurface() const
{
    auto d = const_cast<QVideoWidgetPrivate *>(d_func());

    if (!d->rendererBackend) {
        d->clearService();
        d->createRendererBackend();
    }

    return d->rendererBackend->videoSurface();
}

/*!
    \property QVideoWidget::aspectRatioMode
    \brief how video is scaled with respect to its aspect ratio.
*/

Qt::AspectRatioMode QVideoWidget::aspectRatioMode() const
{
    return d_func()->aspectRatioMode;
}

void QVideoWidget::setAspectRatioMode(Qt::AspectRatioMode mode)
{
    Q_D(QVideoWidget);

    if (d->currentControl) {
        d->currentControl->setAspectRatioMode(mode);
        d->aspectRatioMode = d->currentControl->aspectRatioMode();
    } else {
        d->aspectRatioMode = mode;
    }
}

/*!
    \property QVideoWidget::fullScreen
    \brief whether video display is confined to a window or is fullScreen.
*/

void QVideoWidget::setFullScreen(bool fullScreen)
{
    Q_D(QVideoWidget);

    Qt::WindowFlags flags = windowFlags();

    if (fullScreen) {
        d->nonFullScreenFlags = flags & (Qt::Window | Qt::SubWindow);
        flags |= Qt::Window;
        flags &= ~Qt::SubWindow;
        setWindowFlags(flags);

        showFullScreen();
    } else {
        flags &= ~(Qt::Window | Qt::SubWindow); //clear the flags...
        flags |= d->nonFullScreenFlags; //then we reset the flags (window and subwindow)
        setWindowFlags(flags);

        showNormal();
    }
}

/*!
    \fn QVideoWidget::fullScreenChanged(bool fullScreen)

    Signals that the \a fullScreen mode of a video widget has changed.

    \sa isFullScreen()
*/

/*!
    \property QVideoWidget::brightness
    \brief an adjustment to the brightness of displayed video.

    Valid brightness values range between -100 and 100, the default is 0.
*/

int QVideoWidget::brightness() const
{
    return d_func()->brightness;
}

void QVideoWidget::setBrightness(int brightness)
{
    Q_D(QVideoWidget);

    int boundedBrightness = qBound(-100, brightness, 100);

    if (d->currentControl)
        d->currentControl->setBrightness(boundedBrightness);
    else if (d->brightness != boundedBrightness)
        emit brightnessChanged(d->brightness = boundedBrightness);
}

/*!
    \fn QVideoWidget::brightnessChanged(int brightness)

    Signals that a video widgets's \a brightness adjustment has changed.

    \sa brightness()
*/

/*!
    \property QVideoWidget::contrast
    \brief an adjustment to the contrast of displayed video.

    Valid contrast values range between -100 and 100, the default is 0.

*/

int QVideoWidget::contrast() const
{
    return d_func()->contrast;
}

void QVideoWidget::setContrast(int contrast)
{
    Q_D(QVideoWidget);

    int boundedContrast = qBound(-100, contrast, 100);

    if (d->currentControl)
        d->currentControl->setContrast(boundedContrast);
    else if (d->contrast != boundedContrast)
        emit contrastChanged(d->contrast = boundedContrast);
}

/*!
    \fn QVideoWidget::contrastChanged(int contrast)

    Signals that a video widgets's \a contrast adjustment has changed.

    \sa contrast()
*/

/*!
    \property QVideoWidget::hue
    \brief an adjustment to the hue of displayed video.

    Valid hue values range between -100 and 100, the default is 0.
*/

int QVideoWidget::hue() const
{
    return d_func()->hue;
}

void QVideoWidget::setHue(int hue)
{
    Q_D(QVideoWidget);

    int boundedHue = qBound(-100, hue, 100);

    if (d->currentControl)
        d->currentControl->setHue(boundedHue);
    else if (d->hue != boundedHue)
        emit hueChanged(d->hue = boundedHue);
}

/*!
    \fn QVideoWidget::hueChanged(int hue)

    Signals that a video widgets's \a hue has changed.

    \sa hue()
*/

/*!
    \property QVideoWidget::saturation
    \brief an adjustment to the saturation of displayed video.

    Valid saturation values range between -100 and 100, the default is 0.
*/

int QVideoWidget::saturation() const
{
    return d_func()->saturation;
}

void QVideoWidget::setSaturation(int saturation)
{
    Q_D(QVideoWidget);

    int boundedSaturation = qBound(-100, saturation, 100);

    if (d->currentControl)
        d->currentControl->setSaturation(boundedSaturation);
    else if (d->saturation != boundedSaturation)
        emit saturationChanged(d->saturation = boundedSaturation);

}

/*!
    \fn QVideoWidget::saturationChanged(int saturation)

    Signals that a video widgets's \a saturation has changed.

    \sa saturation()
*/

/*!
  Returns the size hint for the current back end,
  if there is one, or else the size hint from QWidget.
 */
QSize QVideoWidget::sizeHint() const
{
    Q_D(const QVideoWidget);

    if (d->currentBackend)
        return d->currentBackend->sizeHint();
    else
        return QWidget::sizeHint();


}

/*!
  \reimp
  Current event \a event.
  Returns the value of the baseclass QWidget::event(QEvent *event) function.
*/
bool QVideoWidget::event(QEvent *event)
{
    Q_D(QVideoWidget);

    if (event->type() == QEvent::WindowStateChange) {
        if (windowState() & Qt::WindowFullScreen) {
            if (d->currentControl)
                d->currentControl->setFullScreen(true);

            if (!d->wasFullScreen)
                emit fullScreenChanged(d->wasFullScreen = true);
        } else {
            if (d->currentControl)
                d->currentControl->setFullScreen(false);

            if (d->wasFullScreen)
                emit fullScreenChanged(d->wasFullScreen = false);
        }
    }
    return QWidget::event(event);
}

/*!
  \reimp
  Handles the show \a event.
 */
void QVideoWidget::showEvent(QShowEvent *event)
{
    Q_D(QVideoWidget);

    QWidget::showEvent(event);

    // The window backend won't work for re-directed windows so use the renderer backend instead.
    if (d->windowBackend && window()->testAttribute(Qt::WA_DontShowOnScreen)) {
        d->windowBackend->releaseControl();

        delete d->windowBackend;
        d->windowBackend = 0;

        d->createRendererBackend();
    }

    if (d->currentBackend)
        d->currentBackend->showEvent();
}

/*!
  \reimp
  Handles the hide \a event.
*/
void QVideoWidget::hideEvent(QHideEvent *event)
{
    Q_D(QVideoWidget);

    if (d->currentBackend)
        d->currentBackend->hideEvent(event);

    QWidget::hideEvent(event);
}

/*!
  \reimp
  Handles the resize \a event.
 */
void QVideoWidget::resizeEvent(QResizeEvent *event)
{
    Q_D(QVideoWidget);

    QWidget::resizeEvent(event);

    if (d->currentBackend)
        d->currentBackend->resizeEvent(event);
}

/*!
  \reimp
  Handles the move \a event.
 */
void QVideoWidget::moveEvent(QMoveEvent *event)
{
    Q_D(QVideoWidget);

    if (d->currentBackend)
        d->currentBackend->moveEvent(event);
}

/*!
  \reimp
  Handles the paint \a event.
 */
void QVideoWidget::paintEvent(QPaintEvent *event)
{
    Q_D(QVideoWidget);

    if (d->currentBackend) {
        d->currentBackend->paintEvent(event);
    } else if (testAttribute(Qt::WA_OpaquePaintEvent)) {
        QPainter painter(this);

        painter.fillRect(event->rect(), palette().window());
    }
}

#if defined(Q_OS_WIN)
#  if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool QVideoWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
#  else
bool QVideoWidget::nativeEvent(const QByteArray &eventType, void *message, long *result)
#  endif
{
    Q_D(QVideoWidget);
    Q_UNUSED(eventType);
    Q_UNUSED(result);

    MSG *mes = reinterpret_cast<MSG *>(message);
    if (mes->message == WM_PAINT || mes->message == WM_ERASEBKGND) {
        if (d->windowBackend)
            d->windowBackend->showEvent();
    }

    return false;
}
#endif

QT_END_NAMESPACE

#include "moc_qvideowidget.cpp"
#include "moc_qvideowidget_p.cpp"
