/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets 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 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 "qglobal.h"

#include <QtCore/qdebug.h>
#include <QtCore/qnumeric.h>
#include "qgraphicswidget_p.h"
#include "qgraphicslayoutitem_p.h"
#include "qgraphicslayout.h"
#include "qgraphicsscene_p.h"
#include <QtWidgets/qapplication.h>
#include <QtWidgets/qgraphicsscene.h>
#include <QtWidgets/qstyleoption.h>
#include <QtWidgets/QStyleOptionTitleBar>
#include <QtWidgets/QGraphicsSceneMouseEvent>

#include <private/qmemory_p.h>

QT_BEGIN_NAMESPACE

void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags)
{
    Q_Q(QGraphicsWidget);

    attributes = 0;
    isWidget = 1; // QGraphicsItem::isWidget() returns true.
    focusNext = focusPrev = q;
    focusPolicy = Qt::NoFocus;

    adjustWindowFlags(&wFlags);
    windowFlags = wFlags;

    q->setParentItem(parentItem);
    q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType));
    q->setGraphicsItem(q);

    resolveLayoutDirection();
    q->unsetWindowFrameMargins();
    flags |= QGraphicsItem::ItemUsesExtendedStyleOption;
    flags |= QGraphicsItem::ItemSendsGeometryChanges;
    if (windowFlags & Qt::Window)
        flags |= QGraphicsItem::ItemIsPanel;
}

qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
{
    Q_Q(const QGraphicsWidget);
    int height = q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options);
    return (qreal)height;
}

/*!
    \internal
*/
QGraphicsWidgetPrivate::QGraphicsWidgetPrivate()
    : margins(nullptr),
      layout(nullptr),
      inheritedPaletteResolveMask(0),
      inheritedFontResolveMask(0),
      inSetGeometry(false),
      polished(false),
      inSetPos(false),
      autoFillBackground(false),
      focusPolicy(Qt::NoFocus),
      focusNext(nullptr),
      focusPrev(nullptr),
      windowFlags(),
      windowData(nullptr),
      setWindowFrameMargins(false),
      windowFrameMargins(nullptr)
{
}

QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate()
{
}

/*!
    \internal

     Ensures that margins is allocated.
     This function must be called before any dereferencing.
*/
void QGraphicsWidgetPrivate::ensureMargins() const
{
    if (!margins)
        margins = qt_make_unique<QMarginsF>();
}

/*!
    \internal

     Ensures that windowFrameMargins is allocated.
     This function must be called before any dereferencing.
*/
void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const
{
    if (!windowFrameMargins)
        windowFrameMargins = qt_make_unique<QMarginsF>();
}

/*!
    \internal

     Ensures that windowData is allocated.
     This function must be called before any dereferencing.
*/
void QGraphicsWidgetPrivate::ensureWindowData()
{
    if (!windowData)
        windowData = qt_make_unique<WindowData>();
}

void QGraphicsWidgetPrivate::setPalette_helper(const QPalette &palette)
{
    if (this->palette == palette && this->palette.resolve() == palette.resolve())
        return;
    updatePalette(palette);
}

void QGraphicsWidgetPrivate::resolvePalette(uint inheritedMask)
{
    inheritedPaletteResolveMask = inheritedMask;
    QPalette naturalPalette = naturalWidgetPalette();
    QPalette resolvedPalette = palette.resolve(naturalPalette);
    updatePalette(resolvedPalette);
}

void QGraphicsWidgetPrivate::updatePalette(const QPalette &palette)
{
    Q_Q(QGraphicsWidget);
    // Update local palette setting.
    this->palette = palette;

    // Calculate new mask.
    if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
        inheritedPaletteResolveMask = 0;
    int mask = palette.resolve() | inheritedPaletteResolveMask;

    // Propagate to children.
    for (int i = 0; i < children.size(); ++i) {
        QGraphicsItem *item = children.at(i);
        if (item->isWidget()) {
            QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
            if (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
                w->d_func()->resolvePalette(mask);
        } else {
            item->d_ptr->resolvePalette(mask);
        }
    }

    // Notify change.
    QEvent event(QEvent::PaletteChange);
    QCoreApplication::sendEvent(q, &event);
}

void QGraphicsWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction)
{
    Q_Q(QGraphicsWidget);
    if ((direction == Qt::RightToLeft) == (testAttribute(Qt::WA_RightToLeft)))
        return;
    q->setAttribute(Qt::WA_RightToLeft, (direction == Qt::RightToLeft));

    // Propagate this change to all children.
    for (int i = 0; i < children.size(); ++i) {
        QGraphicsItem *item = children.at(i);
        if (item->isWidget()) {
            QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
            if (widget->parentWidget() && !widget->testAttribute(Qt::WA_SetLayoutDirection))
                widget->d_func()->setLayoutDirection_helper(direction);
        }
    }

    // Send the notification event to this widget item.
    QEvent e(QEvent::LayoutDirectionChange);
    QCoreApplication::sendEvent(q, &e);
}

void QGraphicsWidgetPrivate::resolveLayoutDirection()
{
    Q_Q(QGraphicsWidget);
    if (q->testAttribute(Qt::WA_SetLayoutDirection)) {
        return;
    }
    if (QGraphicsWidget *parentWidget = q->parentWidget()) {
        setLayoutDirection_helper(parentWidget->layoutDirection());
    } else if (scene) {
        // ### shouldn't the scene have a layoutdirection really? how does
        // ### QGraphicsWidget get changes from QApplication::layoutDirection?
        setLayoutDirection_helper(QGuiApplication::layoutDirection());
    } else {
        setLayoutDirection_helper(QGuiApplication::layoutDirection());
    }
}

QPalette QGraphicsWidgetPrivate::naturalWidgetPalette() const
{
    Q_Q(const QGraphicsWidget);
    QPalette palette;
    if (QGraphicsWidget *parent = q->parentWidget()) {
        palette = parent->palette();
    } else if (scene) {
        palette = scene->palette();
    }
    palette.resolve(0);
    return palette;
}

void QGraphicsWidgetPrivate::setFont_helper(const QFont &font)
{
    if (this->font == font && this->font.resolve() == font.resolve())
        return;
    updateFont(font);
}

void QGraphicsWidgetPrivate::resolveFont(uint inheritedMask)
{
    Q_Q(QGraphicsWidget);
    inheritedFontResolveMask = inheritedMask;
    if (QGraphicsWidget *p = q->parentWidget())
        inheritedFontResolveMask |= p->d_func()->inheritedFontResolveMask;
    QFont naturalFont = naturalWidgetFont();
    QFont resolvedFont = font.resolve(naturalFont);
    updateFont(resolvedFont);
}

void QGraphicsWidgetPrivate::updateFont(const QFont &font)
{
    Q_Q(QGraphicsWidget);
    // Update the local font setting.
    this->font = font;

    // Calculate new mask.
    if (q->isWindow() && !q->testAttribute(Qt::WA_WindowPropagation))
        inheritedFontResolveMask = 0;
    int mask = font.resolve() | inheritedFontResolveMask;

    // Propagate to children.
    for (int i = 0; i < children.size(); ++i) {
        QGraphicsItem *item = children.at(i);
        if (item->isWidget()) {
            QGraphicsWidget *w = static_cast<QGraphicsWidget *>(item);
            if (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation))
                w->d_func()->resolveFont(mask);
        } else {
            item->d_ptr->resolveFont(mask);
        }
    }

    if (!polished)
        return;
    // Notify change.
    QEvent event(QEvent::FontChange);
    QCoreApplication::sendEvent(q, &event);
}

QFont QGraphicsWidgetPrivate::naturalWidgetFont() const
{
    Q_Q(const QGraphicsWidget);
    QFont naturalFont; // ### no application font support
    if (QGraphicsWidget *parent = q->parentWidget()) {
        naturalFont = parent->font();
    } else if (scene) {
        naturalFont = scene->font();
    }
    naturalFont.resolve(0);
    return naturalFont;
}

void QGraphicsWidgetPrivate::initStyleOptionTitleBar(QStyleOptionTitleBar *option)
{
    Q_Q(QGraphicsWidget);
    ensureWindowData();
    q->initStyleOption(option);
    option->rect.setHeight(titleBarHeight(*option));
    option->titleBarFlags = windowFlags;
    option->subControls = QStyle::SC_TitleBarCloseButton | QStyle::SC_TitleBarLabel | QStyle::SC_TitleBarSysMenu;
    option->activeSubControls = windowData->hoveredSubControl;
    bool isActive = q->isActiveWindow();
    option->state.setFlag(QStyle::State_Active, isActive);
    if (isActive) {
        option->titleBarState = Qt::WindowActive;
        option->titleBarState |= QStyle::State_Active;
    } else {
        option->titleBarState = Qt::WindowNoState;
    }
    QFont windowTitleFont = QApplication::font("QMdiSubWindowTitleBar");
    QRect textRect = q->style()->subControlRect(QStyle::CC_TitleBar, option, QStyle::SC_TitleBarLabel, nullptr);
    option->text = QFontMetrics(windowTitleFont).elidedText(
        windowData->windowTitle, Qt::ElideRight, textRect.width());
}

void QGraphicsWidgetPrivate::adjustWindowFlags(Qt::WindowFlags *flags)
{
    bool customize =  (*flags & (Qt::CustomizeWindowHint
            | Qt::FramelessWindowHint
            | Qt::WindowTitleHint
            | Qt::WindowSystemMenuHint
            | Qt::WindowMinimizeButtonHint
            | Qt::WindowMaximizeButtonHint
            | Qt::WindowContextHelpButtonHint));

    uint type = (*flags & Qt::WindowType_Mask);
    if (customize)
        ;
    else if (type == Qt::Dialog || type == Qt::Sheet)
        *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint;
    else if (type == Qt::Tool)
        *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint;
    else if (type == Qt::Window || type == Qt::SubWindow)
        *flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint
                  | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint;
}

void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
    Q_Q(QGraphicsWidget);
    ensureWindowData();
    if (windowData->grabbedSection != Qt::NoSection) {
        if (windowData->grabbedSection == Qt::TitleBarArea) {
            windowData->buttonSunken = false;
            QStyleOptionTitleBar bar;
            initStyleOptionTitleBar(&bar);
            // make sure that the coordinates (rect and pos) we send to the style are positive.
            bar.rect = q->windowFrameRect().toRect();
            bar.rect.moveTo(0,0);
            bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar));
            QPointF pos = event->pos();
            if (windowFrameMargins) {
                pos.rx() += windowFrameMargins->left();
                pos.ry() += windowFrameMargins->top();
            }
            bar.subControls = QStyle::SC_TitleBarCloseButton;
            if (q->style()->subControlRect(QStyle::CC_TitleBar, &bar,
                                           QStyle::SC_TitleBarCloseButton,
                                           event->widget()).contains(pos.toPoint())) {
                q->close();
            }
        }
        if (!(static_cast<QGraphicsSceneMouseEvent *>(event)->buttons()))
            windowData->grabbedSection = Qt::NoSection;
        event->accept();
    }
}

void QGraphicsWidgetPrivate::windowFrameMousePressEvent(QGraphicsSceneMouseEvent *event)
{
    Q_Q(QGraphicsWidget);
    if (event->button() != Qt::LeftButton)
        return;

    ensureWindowData();
    windowData->startGeometry = q->geometry();
    windowData->grabbedSection = q->windowFrameSectionAt(event->pos());
    ensureWindowData();
    if (windowData->grabbedSection == Qt::TitleBarArea
        && windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton) {
        windowData->buttonSunken = true;
        q->update();
    }
    event->setAccepted(windowData->grabbedSection != Qt::NoSection);
}

/*
  Used to calculate the
  Precondition:
  \a widget should support either hfw or wfh

  If \a heightForWidth is set to false, this function will query the width for height
  instead. \a width will then be interpreted as height, \a minh and \a maxh will be interpreted
  as minimum width and maximum width.
 */
static qreal minimumHeightForWidth(qreal width, qreal minh, qreal maxh,
                                   const QGraphicsWidget *widget,
                                   bool heightForWidth = true)
{
    qreal minimumHeightForWidth = -1;
    const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth();
    if (hasHFW == heightForWidth) {
        minimumHeightForWidth = hasHFW
                                ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(width, -1)).height()
                                : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, width)).width();    //"width" is here height!
    } else {
        // widthForHeight
        const qreal constraint = width;
        while (maxh - minh > 0.1) {
            qreal middle = minh + (maxh - minh)/2;
            // ### really bad, if we are a widget with a layout it will call
            // layout->effectiveSizeHint(Qt::MiniumumSize), which again will call
            // sizeHint three times because of how the cache works
            qreal hfw = hasHFW
                        ? widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(middle, -1)).height()
                        : widget->effectiveSizeHint(Qt::MinimumSize, QSizeF(-1, middle)).width();
            if (hfw > constraint) {
                minh = middle;
            } else if (hfw <= constraint) {
                maxh = middle;
            }
        }
        minimumHeightForWidth = maxh;
    }
    return minimumHeightForWidth;
}

static qreal minimumWidthForHeight(qreal height, qreal minw, qreal maxw,
                                   const QGraphicsWidget *widget)
{
    return minimumHeightForWidth(height, minw, maxw, widget, false);
}

static QSizeF closestAcceptableSize(const QSizeF &proposed,
                                    const QGraphicsWidget *widget)
{
    const QSizeF current = widget->size();

    qreal minw = proposed.width();
    qreal maxw = current.width();
    qreal minh = proposed.height();
    qreal maxh = current.height();

    qreal middlew = maxw;
    qreal middleh = maxh;
    qreal min_hfw;
    min_hfw = minimumHeightForWidth(maxw, minh, maxh, widget);

    do {
        if (maxw - minw < 0.1) {
            // we still haven't found anything, cut off binary search
            minw = maxw;
            minh = maxh;
        }
        middlew = minw + (maxw - minw)/2.0;
        middleh = minh + (maxh - minh)/2.0;

        min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);

        if (min_hfw > middleh) {
            minw = middlew;
            minh = middleh;
        } else if (min_hfw <= middleh) {
            maxw = middlew;
            maxh = middleh;
        }
    } while (maxw != minw);

    min_hfw = minimumHeightForWidth(middlew, minh, maxh, widget);

    QSizeF result;
    if (min_hfw < maxh) {
        result = QSizeF(middlew, min_hfw);
    } else {
        // Needed because of the cut-off we do above.
        result = QSizeF(minimumWidthForHeight(maxh, proposed.width(), current.width(), widget), maxh);
    }
    return result;
}

static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry,
                                              QRectF *rect, Qt::WindowFrameSection section,
                                              const QSizeF &min, const QSizeF &max,
                                              const QGraphicsWidget *widget)
{
    const QRectF proposedRect = *rect;
    qreal width = qBound(min.width(), proposedRect.width(), max.width());
    qreal height = qBound(min.height(), proposedRect.height(), max.height());

    const bool hasHFW = QGraphicsLayoutItemPrivate::get(widget)->hasHeightForWidth();
    const bool hasWFH = QGraphicsLayoutItemPrivate::get(widget)->hasWidthForHeight();

    const bool widthChanged = proposedRect.width() != widget->size().width();
    const bool heightChanged = proposedRect.height() != widget->size().height();

    if (hasHFW || hasWFH) {
        if (widthChanged || heightChanged) {
            qreal minExtent;
            qreal maxExtent;
            qreal constraint;
            qreal proposed;
            if (hasHFW) {
                minExtent = min.height();
                maxExtent = max.height();
                constraint = width;
                proposed = proposedRect.height();
            } else {
                // width for height
                minExtent = min.width();
                maxExtent = max.width();
                constraint = height;
                proposed = proposedRect.width();
            }
            if (minimumHeightForWidth(constraint, minExtent, maxExtent, widget, hasHFW) > proposed) {
                QSizeF effectiveSize = closestAcceptableSize(QSizeF(width, height), widget);
                width = effectiveSize.width();
                height = effectiveSize.height();
            }
        }
    }

    switch (section) {
    case Qt::LeftSection:
        rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
                      qRound(width), startGeometry.height());
        break;
    case Qt::TopLeftSection:
        rect->setRect(startGeometry.right() - qRound(width), startGeometry.bottom() - qRound(height),
                      qRound(width), qRound(height));
        break;
    case Qt::TopSection:
        rect->setRect(startGeometry.left(), startGeometry.bottom() - qRound(height),
                      startGeometry.width(), qRound(height));
        break;
    case Qt::TopRightSection:
        rect->setTop(rect->bottom() - qRound(height));
        rect->setWidth(qRound(width));
        break;
    case Qt::RightSection:
        rect->setWidth(qRound(width));
        break;
    case Qt::BottomRightSection:
        rect->setWidth(qRound(width));
        rect->setHeight(qRound(height));
        break;
    case Qt::BottomSection:
        rect->setHeight(qRound(height));
        break;
    case Qt::BottomLeftSection:
        rect->setRect(startGeometry.right() - qRound(width), startGeometry.top(),
                      qRound(width), qRound(height));
        break;
    default:
        break;
    }
}

void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
    Q_Q(QGraphicsWidget);
    ensureWindowData();
    if (!(event->buttons() & Qt::LeftButton) || windowData->hoveredSubControl != QStyle::SC_TitleBarLabel)
        return;

    QLineF delta(q->mapFromScene(event->buttonDownScenePos(Qt::LeftButton)), event->pos());
    QLineF parentDelta(q->mapToParent(delta.p1()), q->mapToParent(delta.p2()));
    QLineF parentXDelta(q->mapToParent(QPointF(delta.p1().x(), 0)), q->mapToParent(QPointF(delta.p2().x(), 0)));
    QLineF parentYDelta(q->mapToParent(QPointF(0, delta.p1().y())), q->mapToParent(QPointF(0, delta.p2().y())));

    QRectF newGeometry;
    switch (windowData->grabbedSection) {
    case Qt::LeftSection:
        newGeometry = QRectF(windowData->startGeometry.topLeft()
                             + QPointF(parentXDelta.dx(), parentXDelta.dy()),
                             windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
        break;
    case Qt::TopLeftSection:
        newGeometry = QRectF(windowData->startGeometry.topLeft()
                             + QPointF(parentDelta.dx(), parentDelta.dy()),
                             windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
        break;
    case Qt::TopSection:
        newGeometry = QRectF(windowData->startGeometry.topLeft()
                             + QPointF(parentYDelta.dx(), parentYDelta.dy()),
                             windowData->startGeometry.size() - QSizeF(0, delta.dy()));
        break;
    case Qt::TopRightSection:
        newGeometry = QRectF(windowData->startGeometry.topLeft()
                             + QPointF(parentYDelta.dx(), parentYDelta.dy()),
                             windowData->startGeometry.size() - QSizeF(-delta.dx(), delta.dy()));
        break;
    case Qt::RightSection:
        newGeometry = QRectF(windowData->startGeometry.topLeft(),
                             windowData->startGeometry.size() + QSizeF(delta.dx(), 0));
        break;
    case Qt::BottomRightSection:
        newGeometry = QRectF(windowData->startGeometry.topLeft(),
                             windowData->startGeometry.size() + QSizeF(delta.dx(), delta.dy()));
        break;
    case Qt::BottomSection:
        newGeometry = QRectF(windowData->startGeometry.topLeft(),
                             windowData->startGeometry.size() + QSizeF(0, delta.dy()));
        break;
    case Qt::BottomLeftSection:
        newGeometry = QRectF(windowData->startGeometry.topLeft()
                             + QPointF(parentXDelta.dx(), parentXDelta.dy()),
                             windowData->startGeometry.size() - QSizeF(delta.dx(), -delta.dy()));
        break;
    case Qt::TitleBarArea:
        newGeometry = QRectF(windowData->startGeometry.topLeft()
                             + QPointF(parentDelta.dx(), parentDelta.dy()),
                             windowData->startGeometry.size());
        break;
    case Qt::NoSection:
        break;
    }

    if (windowData->grabbedSection != Qt::NoSection) {
        _q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry,
                                          windowData->grabbedSection,
                                          q->effectiveSizeHint(Qt::MinimumSize),
                                          q->effectiveSizeHint(Qt::MaximumSize),
                                          q);
        q->setGeometry(newGeometry);
    }
}

void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent *event)
{
    Q_Q(QGraphicsWidget);
    if (!hasDecoration())
        return;

    ensureWindowData();

    if (q->rect().contains(event->pos())) {
        if (windowData->buttonMouseOver || windowData->hoveredSubControl != QStyle::SC_None)
            windowFrameHoverLeaveEvent(event);
        return;
    }

    bool wasMouseOver = windowData->buttonMouseOver;
    QRect oldButtonRect = windowData->buttonRect;
    windowData->buttonRect = QRect();
    windowData->buttonMouseOver = false;
    QPointF pos = event->pos();
    QStyleOptionTitleBar bar;
    // make sure that the coordinates (rect and pos) we send to the style are positive.
    if (windowFrameMargins) {
        pos.rx() += windowFrameMargins->left();
        pos.ry() += windowFrameMargins->top();
    }
    initStyleOptionTitleBar(&bar);
    bar.rect = q->windowFrameRect().toRect();
    bar.rect.moveTo(0,0);
    bar.rect.setHeight(int(titleBarHeight(bar)));

    Qt::CursorShape cursorShape = Qt::ArrowCursor;
    bool needsSetCursorCall = true;
    switch (q->windowFrameSectionAt(event->pos())) {
        case Qt::TopLeftSection:
        case Qt::BottomRightSection:
            cursorShape = Qt::SizeFDiagCursor;
            break;
        case Qt::TopRightSection:
        case Qt::BottomLeftSection:
            cursorShape = Qt::SizeBDiagCursor;
            break;
        case Qt::LeftSection:
        case Qt::RightSection:
            cursorShape = Qt::SizeHorCursor;
            break;
        case Qt::TopSection:
        case Qt::BottomSection:
            cursorShape = Qt::SizeVerCursor;
            break;
        case Qt::TitleBarArea:
            windowData->buttonRect = q->style()->subControlRect(
                QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, nullptr);
            if (windowData->buttonRect.contains(pos.toPoint()))
                windowData->buttonMouseOver = true;
            event->ignore();
            break;
        default:
            needsSetCursorCall = false;
            event->ignore();
        }
#ifndef QT_NO_CURSOR
    if (needsSetCursorCall)
        q->setCursor(cursorShape);
#else
    Q_UNUSED(needsSetCursorCall);
    Q_UNUSED(cursorShape);
#endif
    // update buttons if we hover over them
    windowData->hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), nullptr);
    if (windowData->hoveredSubControl != QStyle::SC_TitleBarCloseButton)
        windowData->hoveredSubControl = QStyle::SC_TitleBarLabel;

    if (windowData->buttonMouseOver != wasMouseOver) {
        if (!oldButtonRect.isNull())
            q->update(QRectF(oldButtonRect).translated(q->windowFrameRect().topLeft()));
        if (!windowData->buttonRect.isNull())
            q->update(QRectF(windowData->buttonRect).translated(q->windowFrameRect().topLeft()));
    }
}

void QGraphicsWidgetPrivate::windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
    Q_UNUSED(event);
    Q_Q(QGraphicsWidget);
    if (hasDecoration()) {
        // ### restore the cursor, don't override it
#ifndef QT_NO_CURSOR
        q->unsetCursor();
#endif

        ensureWindowData();

        bool needsUpdate = false;
        if (windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton
            || windowData->buttonMouseOver)
            needsUpdate = true;

        // update the hover state (of buttons etc...)
        windowData->hoveredSubControl = QStyle::SC_None;
        windowData->buttonMouseOver = false;
        windowData->buttonRect = QRect();
        if (needsUpdate)
            q->update(windowData->buttonRect);
    }
}

bool QGraphicsWidgetPrivate::hasDecoration() const
{
    return (windowFlags & Qt::Window) && (windowFlags & Qt::WindowTitleHint);
}

/**
 * is called after a reparent has taken place to fix up the focus chain(s)
 */
void QGraphicsWidgetPrivate::fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *oldScene, QGraphicsScene *newScene)
{
    Q_Q(QGraphicsWidget);
    Q_ASSERT(focusNext && focusPrev);

    if (q_ptr->isPanel()) {
        // panels are never a part of their parent's or ancestors' focus
        // chains. so reparenting a panel is easy; there's nothing to
        // do.
        return;
    }

    // we're not a panel, so find the first widget in the focus chain
    // (this), and the last (this, or the last widget that is still
    // a descendent of this). also find the widgets that currently /
    // before reparenting point to this widgets' focus chain.
    QGraphicsWidget *focusFirst = q;
    QGraphicsWidget *focusBefore = focusPrev;
    QGraphicsWidget *focusLast = focusFirst;
    QGraphicsWidget *focusAfter = focusNext;
    do {
        if (!q->isAncestorOf(focusAfter))
            break;
        focusLast = focusAfter;
    } while ((focusAfter = focusAfter->d_func()->focusNext));

    if (!parent && oldScene && oldScene != newScene && oldScene->d_func()->tabFocusFirst == q) {
        // detach from old scene's top level focus chain.
        oldScene->d_func()->tabFocusFirst = (focusAfter != q) ? focusAfter : nullptr;
    }

    // detach from current focus chain; skip this widget subtree.
    focusBefore->d_func()->focusNext = focusAfter;
    focusAfter->d_func()->focusPrev = focusBefore;

    if (newParent) {
        // attach to new parent's focus chain as the last element
        // in its chain.
        QGraphicsWidget *newFocusFirst = newParent;
        QGraphicsWidget *newFocusLast = newFocusFirst;
        QGraphicsWidget *newFocusAfter = newFocusFirst->d_func()->focusNext;
        do {
            if (!newParent->isAncestorOf(newFocusAfter))
                break;
            newFocusLast = newFocusAfter;
        } while ((newFocusAfter = newFocusAfter->d_func()->focusNext));

        newFocusLast->d_func()->focusNext = q;
        focusLast->d_func()->focusNext = newFocusAfter;
        newFocusAfter->d_func()->focusPrev = focusLast;
        focusPrev = newFocusLast;
    } else {
        // no new parent, so just link up our own prev->last widgets.
        focusPrev = focusLast;
        focusLast->d_func()->focusNext = q;
    }
}

void QGraphicsWidgetPrivate::setLayout_helper(QGraphicsLayout *l)
{
    delete (this->layout);
    layout = l;
    if (!l) {
        Q_Q(QGraphicsWidget);
        q->updateGeometry();
    }
}

qreal QGraphicsWidgetPrivate::width() const
{
    Q_Q(const QGraphicsWidget);
    return q->geometry().width();
}

void QGraphicsWidgetPrivate::setWidth(qreal w)
{
    if (qIsNaN(w))
        return;
    Q_Q(QGraphicsWidget);
    if (q->geometry().width() == w)
        return;

    q->setGeometry(QRectF(q->x(), q->y(), w, height()));
}

void QGraphicsWidgetPrivate::resetWidth()
{
    Q_Q(QGraphicsWidget);
    q->setGeometry(QRectF(q->x(), q->y(), 0, height()));
}

qreal QGraphicsWidgetPrivate::height() const
{
    Q_Q(const QGraphicsWidget);
    return q->geometry().height();
}

void QGraphicsWidgetPrivate::setHeight(qreal h)
{
    if (qIsNaN(h))
        return;
    Q_Q(QGraphicsWidget);
    if (q->geometry().height() == h)
        return;

    q->setGeometry(QRectF(q->x(), q->y(), width(), h));
}

void QGraphicsWidgetPrivate::resetHeight()
{
    Q_Q(QGraphicsWidget);
    q->setGeometry(QRectF(q->x(), q->y(), width(), 0));
}

void QGraphicsWidgetPrivate::setGeometryFromSetPos()
{
    if (inSetGeometry)
        return;
    Q_Q(QGraphicsWidget);
    inSetPos = 1;
    // Ensure setGeometry is called (avoid recursion when setPos is
    // called from within setGeometry).
    q->setGeometry(QRectF(pos, q->size()));
    inSetPos = 0 ;
}

QT_END_NAMESPACE
