diff options
Diffstat (limited to 'src/widgets/kernel')
38 files changed, 1499 insertions, 2470 deletions
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri index c2f6e4ce75..693af7eb80 100644 --- a/src/widgets/kernel/kernel.pri +++ b/src/widgets/kernel/kernel.pri @@ -12,7 +12,7 @@ HEADERS += \ kernel/qactiongroup.h \ kernel/qapplication.h \ kernel/qapplication_p.h \ - kernel/qwidgetbackingstore_p.h \ + kernel/qwidgetrepaintmanager_p.h \ kernel/qboxlayout.h \ kernel/qdesktopwidget.h \ kernel/qgridlayout.h \ @@ -23,7 +23,6 @@ HEADERS += \ kernel/qshortcut.h \ kernel/qsizepolicy.h \ kernel/qstackedlayout.h \ - kernel/qtooltip.h \ kernel/qwidget.h \ kernel/qwidget_p.h \ kernel/qwidgetaction.h \ @@ -42,7 +41,7 @@ SOURCES += \ kernel/qaction.cpp \ kernel/qactiongroup.cpp \ kernel/qapplication.cpp \ - kernel/qwidgetbackingstore.cpp \ + kernel/qwidgetrepaintmanager.cpp \ kernel/qboxlayout.cpp \ kernel/qgridlayout.cpp \ kernel/qlayout.cpp \ @@ -51,7 +50,6 @@ SOURCES += \ kernel/qshortcut.cpp \ kernel/qsizepolicy.cpp \ kernel/qstackedlayout.cpp \ - kernel/qtooltip.cpp \ kernel/qwidget.cpp \ kernel/qwidgetaction.cpp \ kernel/qgesture.cpp \ @@ -79,6 +77,11 @@ qtConfig(formlayout) { SOURCES += kernel/qformlayout.cpp } +qtConfig(tooltip) { + HEADERS += kernel/qtooltip.h + SOURCES += kernel/qtooltip.cpp +} + qtConfig(whatsthis) { HEADERS += kernel/qwhatsthis.h SOURCES += kernel/qwhatsthis.cpp diff --git a/src/widgets/kernel/mac.pri b/src/widgets/kernel/mac.pri index f7e7aa869a..d21e5d4a74 100644 --- a/src/widgets/kernel/mac.pri +++ b/src/widgets/kernel/mac.pri @@ -1,4 +1 @@ -macos { - LIBS_PRIVATE += -framework AppKit -lz - *-mwerks:INCLUDEPATH += compat -} +macos: LIBS_PRIVATE += -framework AppKit -lz diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp index 1ca5514655..19ad65692b 100644 --- a/src/widgets/kernel/qaction.cpp +++ b/src/widgets/kernel/qaction.cpp @@ -47,15 +47,15 @@ #include "qlist.h" #include "qstylehints.h" #include <private/qshortcutmap_p.h> -#include <private/qapplication_p.h> +#include <private/qguiapplication_p.h> #if QT_CONFIG(menu) #include <private/qmenu_p.h> #endif #include <private/qdebug_p.h> #define QAPP_CHECK(functionName) \ - if (Q_UNLIKELY(!qApp)) { \ - qWarning("QAction: Initialize QApplication before calling '" functionName "'."); \ + if (Q_UNLIKELY(!QCoreApplication::instance())) { \ + qWarning("QAction: Initialize Q(Gui)Application before calling '" functionName "'."); \ return; \ } @@ -75,24 +75,18 @@ static QString qt_strippedText(QString s) } -QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0), - visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false), - iconVisibleInMenu(-1), - shortcutVisibleInContextMenu(-1), - menuRole(QAction::TextHeuristicRole), - priority(QAction::NormalPriority) -{ -#ifndef QT_NO_SHORTCUT - shortcutId = 0; - shortcutContext = Qt::WindowShortcut; - autorepeat = true; +QActionPrivate::QActionPrivate() : +#if QT_CONFIG(shortcut) + autorepeat(1), #endif -} - -QActionPrivate::~QActionPrivate() + enabled(1), forceDisabled(0), visible(1), forceInvisible(0), checkable(0), + checked(0), separator(0), fontSet(false), + iconVisibleInMenu(-1), shortcutVisibleInContextMenu(-1) { } +QActionPrivate::~QActionPrivate() = default; + bool QActionPrivate::showStatusText(QWidget *widget, const QString &str) { #if !QT_CONFIG(statustip) @@ -101,7 +95,7 @@ bool QActionPrivate::showStatusText(QWidget *widget, const QString &str) #else if(QObject *object = widget ? widget : parent) { QStatusTipEvent tip(str); - QApplication::sendEvent(object, &tip); + QCoreApplication::sendEvent(object, &tip); return true; } #endif @@ -114,20 +108,20 @@ void QActionPrivate::sendDataChanged() QActionEvent e(QEvent::ActionChanged, q); for (int i = 0; i < widgets.size(); ++i) { QWidget *w = widgets.at(i); - QApplication::sendEvent(w, &e); + QCoreApplication::sendEvent(w, &e); } #if QT_CONFIG(graphicsview) for (int i = 0; i < graphicsWidgets.size(); ++i) { QGraphicsWidget *w = graphicsWidgets.at(i); - QApplication::sendEvent(w, &e); + QCoreApplication::sendEvent(w, &e); } #endif - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); emit q->changed(); } -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) void QActionPrivate::redoGrab(QShortcutMap &map) { Q_Q(QAction); @@ -345,7 +339,7 @@ QWidget *QAction::parentWidget() const QObject *ret = parent(); while (ret && !ret->isWidgetType()) ret = ret->parent(); - return (QWidget*)ret; + return static_cast<QWidget*>(ret); } /*! @@ -374,7 +368,7 @@ QList<QGraphicsWidget *> QAction::associatedGraphicsWidgets() const } #endif -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) /*! \property QAction::shortcut \brief the action's primary shortcut key @@ -391,7 +385,7 @@ void QAction::setShortcut(const QKeySequence &shortcut) return; d->shortcut = shortcut; - d->redoGrab(qApp->d_func()->shortcutMap); + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); d->sendDataChanged(); } @@ -420,8 +414,8 @@ void QAction::setShortcuts(const QList<QKeySequence> &shortcuts) d->shortcut = primary; d->alternateShortcuts = listCopy; - d->redoGrab(qApp->d_func()->shortcutMap); - d->redoGrabAlternate(qApp->d_func()->shortcutMap); + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap); d->sendDataChanged(); } @@ -485,8 +479,8 @@ void QAction::setShortcutContext(Qt::ShortcutContext context) return; QAPP_CHECK("setShortcutContext"); d->shortcutContext = context; - d->redoGrab(qApp->d_func()->shortcutMap); - d->redoGrabAlternate(qApp->d_func()->shortcutMap); + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap); d->sendDataChanged(); } @@ -513,8 +507,8 @@ void QAction::setAutoRepeat(bool on) return; QAPP_CHECK("setAutoRepeat"); d->autorepeat = on; - d->redoGrab(qApp->d_func()->shortcutMap); - d->redoGrabAlternate(qApp->d_func()->shortcutMap); + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); + d->redoGrabAlternate(QGuiApplicationPrivate::instance()->shortcutMap); d->sendDataChanged(); } @@ -573,12 +567,12 @@ QAction::~QAction() #endif if (d->group) d->group->removeAction(this); -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) if (d->shortcutId && qApp) { - qApp->d_func()->shortcutMap.removeShortcut(d->shortcutId, this); + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->shortcutId, this); for(int i = 0; i < d->alternateShortcutIds.count(); ++i) { const int id = d->alternateShortcutIds.at(i); - qApp->d_func()->shortcutMap.removeShortcut(id, this); + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this); } } #endif @@ -1027,8 +1021,8 @@ void QAction::setEnabled(bool b) return; QAPP_CHECK("setEnabled"); d->enabled = b; -#ifndef QT_NO_SHORTCUT - d->setShortcutEnabled(b, qApp->d_func()->shortcutMap); +#if QT_CONFIG(shortcut) + d->setShortcutEnabled(b, QGuiApplicationPrivate::instance()->shortcutMap); #endif d->sendDataChanged(); } @@ -1061,8 +1055,8 @@ void QAction::setVisible(bool b) d->forceInvisible = !b; d->visible = b; d->enabled = b && !d->forceDisabled && (!d->group || d->group->isEnabled()) ; -#ifndef QT_NO_SHORTCUT - d->setShortcutEnabled(d->enabled, qApp->d_func()->shortcutMap); +#if QT_CONFIG(shortcut) + d->setShortcutEnabled(d->enabled, QGuiApplicationPrivate::instance()->shortcutMap); #endif d->sendDataChanged(); } @@ -1080,7 +1074,7 @@ bool QAction::isVisible() const bool QAction::event(QEvent *e) { -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) if (e->type() == QEvent::Shortcut) { QShortcutEvent *se = static_cast<QShortcutEvent *>(e); Q_ASSERT_X(se->key() == d_func()->shortcut || d_func()->alternateShortcuts.contains(se->key()), @@ -1153,8 +1147,9 @@ void QAction::activate(ActionEvent event) if(event == Trigger) { QPointer<QObject> guard = this; if(d->checkable) { - // the checked action of an exclusive group cannot be unchecked - if (d->checked && (d->group && d->group->isExclusive() + // the checked action of an exclusive group may not be unchecked + if (d->checked && (d->group + && d->group->exclusionPolicy() == QActionGroup::ExclusionPolicy::Exclusive && d->group->checkedAction() == this)) { if (!guard.isNull()) emit triggered(true); @@ -1284,7 +1279,7 @@ void QAction::setIconVisibleInMenu(bool visible) d->iconVisibleInMenu = visible; // Only send data changed if we really need to. if (oldValue != -1 - || visible == !QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus)) { + || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus)) { d->sendDataChanged(); } } @@ -1294,7 +1289,7 @@ bool QAction::isIconVisibleInMenu() const { Q_D(const QAction); if (d->iconVisibleInMenu == -1) { - return !QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus); + return !QCoreApplication::testAttribute(Qt::AA_DontShowIconsInMenus); } return d->iconVisibleInMenu; } @@ -1322,7 +1317,7 @@ void QAction::setShortcutVisibleInContextMenu(bool visible) d->shortcutVisibleInContextMenu = visible; // Only send data changed if we really need to. if (oldValue != -1 - || visible == !QApplication::instance()->testAttribute(Qt::AA_DontShowShortcutsInContextMenus)) { + || visible == !QCoreApplication::testAttribute(Qt::AA_DontShowShortcutsInContextMenus)) { d->sendDataChanged(); } } @@ -1350,7 +1345,7 @@ Q_WIDGETS_EXPORT QDebug operator<<(QDebug d, const QAction *action) d << " toolTip=" << action->toolTip(); if (action->isCheckable()) d << " checked=" << action->isChecked(); -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) if (!action->shortcut().isEmpty()) d << " shortcut=" << action->shortcut(); #endif diff --git a/src/widgets/kernel/qaction.h b/src/widgets/kernel/qaction.h index 84bf92d2ac..f7693f4dde 100644 --- a/src/widgets/kernel/qaction.h +++ b/src/widgets/kernel/qaction.h @@ -72,7 +72,7 @@ class Q_WIDGETS_EXPORT QAction : public QObject Q_PROPERTY(QString statusTip READ statusTip WRITE setStatusTip NOTIFY changed) Q_PROPERTY(QString whatsThis READ whatsThis WRITE setWhatsThis NOTIFY changed) Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY changed) -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut NOTIFY changed) Q_PROPERTY(Qt::ShortcutContext shortcutContext READ shortcutContext WRITE setShortcutContext NOTIFY changed) Q_PROPERTY(bool autoRepeat READ autoRepeat WRITE setAutoRepeat NOTIFY changed) @@ -129,7 +129,7 @@ public: void setSeparator(bool b); bool isSeparator() const; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) void setShortcut(const QKeySequence &shortcut); QKeySequence shortcut() const; diff --git a/src/widgets/kernel/qaction_p.h b/src/widgets/kernel/qaction_p.h index 19ae47c7b9..6b6ca8076f 100644 --- a/src/widgets/kernel/qaction_p.h +++ b/src/widgets/kernel/qaction_p.h @@ -89,15 +89,15 @@ public: QString tooltip; QString statustip; QString whatsthis; -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) QKeySequence shortcut; QList<QKeySequence> alternateShortcuts; #endif QVariant userData; -#ifndef QT_NO_SHORTCUT - int shortcutId; +#if QT_CONFIG(shortcut) + int shortcutId = 0; QVector<int> alternateShortcutIds; - Qt::ShortcutContext shortcutContext; + Qt::ShortcutContext shortcutContext = Qt::WindowShortcut; uint autorepeat : 1; #endif QFont font; @@ -112,19 +112,17 @@ public: int iconVisibleInMenu : 2; // Only has values -1, 0, and 1 int shortcutVisibleInContextMenu : 2; // Only has values -1, 0, and 1 - QAction::MenuRole menuRole; - QAction::Priority priority; + QAction::MenuRole menuRole = QAction::TextHeuristicRole; + QAction::Priority priority = QAction::NormalPriority; - QList<QWidget *> widgets; + QWidgetList widgets; #if QT_CONFIG(graphicsview) QList<QGraphicsWidget *> graphicsWidgets; #endif -#ifndef QT_NO_SHORTCUT +#if QT_CONFIG(shortcut) void redoGrab(QShortcutMap &map); void redoGrabAlternate(QShortcutMap &map); void setShortcutEnabled(bool enable, QShortcutMap &map); - - static QShortcutMap *globalMap; #endif // QT_NO_SHORTCUT void sendDataChanged(); diff --git a/src/widgets/kernel/qactiongroup.cpp b/src/widgets/kernel/qactiongroup.cpp index 4786437d7e..1d9213de0c 100644 --- a/src/widgets/kernel/qactiongroup.cpp +++ b/src/widgets/kernel/qactiongroup.cpp @@ -42,7 +42,6 @@ #ifndef QT_NO_ACTION #include "qaction_p.h" -#include "qapplication.h" #include "qevent.h" #include "qlist.h" @@ -52,12 +51,16 @@ class QActionGroupPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QActionGroup) public: - QActionGroupPrivate() : exclusive(1), enabled(1), visible(1) { } + QActionGroupPrivate() : enabled(1), + visible(1), + exclusionPolicy(QActionGroup::ExclusionPolicy::Exclusive) + { + } QList<QAction *> actions; QPointer<QAction> current; - uint exclusive : 1; uint enabled : 1; uint visible : 1; + QActionGroup::ExclusionPolicy exclusionPolicy; private: void _q_actionTriggered(); //private slot @@ -69,8 +72,8 @@ void QActionGroupPrivate::_q_actionChanged() { Q_Q(QActionGroup); QAction *action = qobject_cast<QAction*>(q->sender()); - Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionChanged", "internal error"); - if(exclusive) { + Q_ASSERT_X(action != nullptr, "QActionGroup::_q_actionChanged", "internal error"); + if (exclusionPolicy != QActionGroup::ExclusionPolicy::None) { if (action->isChecked()) { if (action != current) { if(current) @@ -87,7 +90,7 @@ void QActionGroupPrivate::_q_actionTriggered() { Q_Q(QActionGroup); QAction *action = qobject_cast<QAction*>(q->sender()); - Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionTriggered", "internal error"); + Q_ASSERT_X(action != nullptr, "QActionGroup::_q_actionTriggered", "internal error"); emit q->triggered(action); } @@ -95,7 +98,7 @@ void QActionGroupPrivate::_q_actionHovered() { Q_Q(QActionGroup); QAction *action = qobject_cast<QAction*>(q->sender()); - Q_ASSERT_X(action != 0, "QWidgetGroup::_q_actionHovered", "internal error"); + Q_ASSERT_X(action != nullptr, "QActionGroup::_q_actionHovered", "internal error"); emit q->hovered(action); } @@ -127,12 +130,17 @@ void QActionGroupPrivate::_q_actionHovered() actions is chosen. Each action in an action group emits its triggered() signal as usual. - As stated above, an action group is \l exclusive by default; it - ensures that only one checkable action is active at any one time. + As stated above, an action group is exclusive by default; it + ensures that at most only one checkable action is active at any one time. If you want to group checkable actions without making them - exclusive, you can turn of exclusiveness by calling + exclusive, you can turn off exclusiveness by calling setExclusive(false). + By default the active action of an exclusive group cannot be unchecked. + In some cases it may be useful to allow unchecking all the actions, + you can allow this by calling + setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional). + Actions can be added to an action group using addAction(), but it is usually more convenient to specify a group when creating actions; this ensures that actions are automatically created with @@ -146,10 +154,33 @@ void QActionGroupPrivate::_q_actionHovered() */ /*! + \enum QActionGroup::ExclusionPolicy + + This enum specifies the different policies that can be used to + control how the group performs exclusive checking on checkable actions. + + \value None + The actions in the group can be checked independently of each other. + + \value Exclusive + Exactly one action can be checked at any one time. + This is the default policy. + + \value ExclusiveOptional + At most one action can be checked at any one time. The actions + can also be all unchecked. + + \sa exclusionPolicy + \since 5.14 +*/ + +/*! Constructs an action group for the \a parent object. The action group is exclusive by default. Call setExclusive(false) - to make the action group non-exclusive. + to make the action group non-exclusive. To make the group exclusive + but allow unchecking the active action call instead + setExclusionPolicy(QActionGroup::ExclusionPolicy::ExclusiveOptional) */ QActionGroup::QActionGroup(QObject* parent) : QObject(*new QActionGroupPrivate, parent) { @@ -258,26 +289,56 @@ QList<QAction*> QActionGroup::actions() const } /*! - \property QActionGroup::exclusive - \brief whether the action group does exclusive checking + \brief Enable or disable the group exclusion checking - If exclusive is true, only one checkable action in the action group - can ever be active at any time. If the user chooses another - checkable action in the group, the one they chose becomes active and - the one that was active becomes inactive. + This is a convenience method that calls + setExclusionPolicy(ExclusionPolicy::Exclusive). - \sa QAction::checkable + \sa QActionGroup::exclusionPolicy */ void QActionGroup::setExclusive(bool b) { - Q_D(QActionGroup); - d->exclusive = b; + setExclusionPolicy(b ? QActionGroup::ExclusionPolicy::Exclusive + : QActionGroup::ExclusionPolicy::None); } +/*! + \brief Returs true if the group is exclusive + + The group is exclusive if the ExclusionPolicy is either Exclusive + or ExclusionOptional. + +*/ bool QActionGroup::isExclusive() const { + return exclusionPolicy() != QActionGroup::ExclusionPolicy::None; +} + +/*! + \property QActionGroup::exclusionPolicy + \brief This property holds the group exclusive checking policy + + If exclusionPolicy is set to Exclusive, only one checkable + action in the action group can ever be active at any time. If the user + chooses another checkable action in the group, the one they chose becomes + active and the one that was active becomes inactive. If exclusionPolicy is + set to ExclusionOptional the group is exclusive but the active checkable + action in the group can be unchecked leaving the group with no actions + checked. + + \sa QAction::checkable + \since 5.14 +*/ +void QActionGroup::setExclusionPolicy(QActionGroup::ExclusionPolicy policy) +{ + Q_D(QActionGroup); + d->exclusionPolicy = policy; +} + +QActionGroup::ExclusionPolicy QActionGroup::exclusionPolicy() const +{ Q_D(const QActionGroup); - return d->exclusive; + return d->exclusionPolicy; } /*! @@ -301,10 +362,10 @@ void QActionGroup::setEnabled(bool b) { Q_D(QActionGroup); d->enabled = b; - for(QList<QAction*>::const_iterator it = d->actions.constBegin(); it != d->actions.constEnd(); ++it) { - if(!(*it)->d_func()->forceDisabled) { - (*it)->setEnabled(b); - (*it)->d_func()->forceDisabled = false; + for (auto action : qAsConst(d->actions)) { + if (!action->d_func()->forceDisabled) { + action->setEnabled(b); + action->d_func()->forceDisabled = false; } } } @@ -338,10 +399,10 @@ void QActionGroup::setVisible(bool b) { Q_D(QActionGroup); d->visible = b; - for(QList<QAction*>::Iterator it = d->actions.begin(); it != d->actions.end(); ++it) { - if(!(*it)->d_func()->forceInvisible) { - (*it)->setVisible(b); - (*it)->d_func()->forceInvisible = false; + for (auto action : qAsConst(d->actions)) { + if (!action->d_func()->forceInvisible) { + action->setVisible(b); + action->d_func()->forceInvisible = false; } } } diff --git a/src/widgets/kernel/qactiongroup.h b/src/widgets/kernel/qactiongroup.h index 61c90b911d..90f488bedb 100644 --- a/src/widgets/kernel/qactiongroup.h +++ b/src/widgets/kernel/qactiongroup.h @@ -55,11 +55,18 @@ class Q_WIDGETS_EXPORT QActionGroup : public QObject Q_OBJECT Q_DECLARE_PRIVATE(QActionGroup) - Q_PROPERTY(bool exclusive READ isExclusive WRITE setExclusive) + Q_PROPERTY(QActionGroup::ExclusionPolicy exclusionPolicy READ exclusionPolicy WRITE setExclusionPolicy) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) Q_PROPERTY(bool visible READ isVisible WRITE setVisible) public: + enum class ExclusionPolicy { + None, + Exclusive, + ExclusiveOptional + }; + Q_ENUM(ExclusionPolicy) + explicit QActionGroup(QObject* parent); ~QActionGroup(); @@ -73,6 +80,7 @@ public: bool isExclusive() const; bool isEnabled() const; bool isVisible() const; + ExclusionPolicy exclusionPolicy() const; public Q_SLOTS: @@ -80,6 +88,7 @@ public Q_SLOTS: inline void setDisabled(bool b) { setEnabled(!b); } void setVisible(bool); void setExclusive(bool); + void setExclusionPolicy(ExclusionPolicy policy); Q_SIGNALS: void triggered(QAction *); diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 486c424391..dfa1bc23b1 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -111,6 +111,9 @@ #include <qtwidgets_tracepoints_p.h> +#include <algorithm> +#include <iterator> + //#define ALIEN_DEBUG static void initResources() @@ -233,9 +236,6 @@ void QApplicationPrivate::createEventDispatcher() encapsulated in a QStyle object. This can be changed at runtime with setStyle(). - \li It specifies how the application is to allocate colors. See - setColorSpec() for details. - \li It provides localization of strings that are visible to the user via translate(). @@ -296,11 +296,6 @@ void QApplicationPrivate::createEventDispatcher() setStyle(). \row - \li Color usage - \li colorSpec(), - setColorSpec(). - - \row \li Text handling \li installTranslator(), removeTranslator() @@ -334,6 +329,7 @@ void QApplicationPrivate::createEventDispatcher() \sa QCoreApplication, QAbstractEventDispatcher, QEventLoop, QSettings */ +#if QT_DEPRECATED_SINCE(5, 8) // ### fixme: Qt 6: Remove ColorSpec and accessors. /*! \enum QApplication::ColorSpec @@ -347,15 +343,7 @@ void QApplicationPrivate::createEventDispatcher() See setColorSpec() for full details. */ - -/*! - \fn QApplication::setGraphicsSystem(const QString &) - \obsolete - - This call has no effect. - - Use the QPA framework instead. -*/ +#endif /*! \fn QWidget *QApplication::topLevelAt(const QPoint &point) @@ -570,10 +558,6 @@ void QApplicationPrivate::init() initialize(); eventDispatcher->startingUp(); -#ifdef QT_EVAL - extern void qt_gui_eval_init(QCoreApplicationPrivate::Type); - qt_gui_eval_init(application_type); -#endif #ifndef QT_NO_ACCESSIBILITY // factory for accessible interfaces for widgets shipped with Qt QAccessible::installFactory(&qAccessibleFactory); @@ -626,7 +610,7 @@ void QApplicationPrivate::initialize() if (qt_is_gui_used) initializeMultitouch(); - if (QApplication::desktopSettingsAware()) + if (QGuiApplication::desktopSettingsAware()) if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { QApplicationPrivate::enabledAnimations = theme->themeHint(QPlatformTheme::UiEffects).toInt(); } @@ -1176,7 +1160,7 @@ void QApplication::setStyle(QStyle *style) QWidget *w = *it; if (w->windowType() != Qt::Desktop && !w->testAttribute(Qt::WA_SetStyle)) { QEvent e(QEvent::StyleChange); - QApplication::sendEvent(w, &e); + QCoreApplication::sendEvent(w, &e); w->update(); } } @@ -1193,7 +1177,7 @@ void QApplication::setStyle(QStyle *style) if (QApplicationPrivate::focus_widget) { QFocusEvent in(QEvent::FocusIn, Qt::OtherFocusReason); - QApplication::sendEvent(QApplicationPrivate::focus_widget->style(), &in); + QCoreApplication::sendEvent(QApplicationPrivate::focus_widget->style(), &in); QApplicationPrivate::focus_widget->update(); } } @@ -1555,7 +1539,7 @@ void QApplication::setFont(const QFont &font, const char *className) if (QApplicationPrivate::is_app_running && !QApplicationPrivate::is_app_closing) { // Send ApplicationFontChange to qApp itself, and to the widgets. QEvent e(QEvent::ApplicationFontChange); - QApplication::sendEvent(QApplication::instance(), &e); + QCoreApplication::sendEvent(QApplication::instance(), &e); QWidgetList wids = QApplication::allWidgets(); for (QWidgetList::ConstIterator it = wids.constBegin(), cend = wids.constEnd(); it != cend; ++it) { @@ -1569,7 +1553,7 @@ void QApplication::setFont(const QFont &font, const char *className) QList<QGraphicsScene *> &scenes = qApp->d_func()->scene_list; for (QList<QGraphicsScene *>::ConstIterator it = scenes.constBegin(); it != scenes.constEnd(); ++it) { - QApplication::sendEvent(*it, &e); + QCoreApplication::sendEvent(*it, &e); } #endif // QT_CONFIG(graphicsview) } @@ -1662,12 +1646,12 @@ void QApplicationPrivate::notifyWindowIconChanged() QWidgetList QApplication::topLevelWidgets() { QWidgetList list; - QWidgetList all = allWidgets(); - - for (QWidgetList::ConstIterator it = all.constBegin(), cend = all.constEnd(); it != cend; ++it) { - QWidget *w = *it; - if (w->isWindow() && w->windowType() != Qt::Desktop) - list.append(w); + if (QWidgetPrivate::allWidgets != nullptr) { + const auto isTopLevelWidget = [] (const QWidget *w) { + return w->isWindow() && w->windowType() != Qt::Desktop; + }; + std::copy_if(QWidgetPrivate::allWidgets->cbegin(), QWidgetPrivate::allWidgets->cend(), + std::back_inserter(list), isTopLevelWidget); } return list; } @@ -1688,7 +1672,7 @@ QWidgetList QApplication::topLevelWidgets() QWidgetList QApplication::allWidgets() { if (QWidgetPrivate::allWidgets) - return QWidgetPrivate::allWidgets->toList(); + return QWidgetPrivate::allWidgets->values(); return QWidgetList(); } @@ -1743,16 +1727,16 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) #endif QFocusEvent out(QEvent::FocusOut, reason); QPointer<QWidget> that = prev; - QApplication::sendEvent(prev, &out); + QCoreApplication::sendEvent(prev, &out); if (that) - QApplication::sendEvent(that->style(), &out); + QCoreApplication::sendEvent(that->style(), &out); } if(focus && QApplicationPrivate::focus_widget == focus) { QFocusEvent in(QEvent::FocusIn, reason); QPointer<QWidget> that = focus; - QApplication::sendEvent(focus, &in); + QCoreApplication::sendEvent(focus, &in); if (that) - QApplication::sendEvent(that->style(), &in); + QCoreApplication::sendEvent(that->style(), &in); } emit qApp->focusChanged(prev, focus_widget); } @@ -1882,22 +1866,19 @@ void QApplication::aboutQt() bool QApplication::event(QEvent *e) { Q_D(QApplication); - if(e->type() == QEvent::Close) { - QCloseEvent *ce = static_cast<QCloseEvent*>(e); - ce->accept(); + if (e->type() == QEvent::Quit) { closeAllWindows(); - - const QWidgetList list = topLevelWidgets(); - for (auto *w : list) { + for (auto *w : topLevelWidgets()) { if (w->isVisible() && !(w->windowType() == Qt::Desktop) && !(w->windowType() == Qt::Popup) && (!(w->windowType() == Qt::Dialog) || !w->parentWidget())) { - ce->ignore(); - break; + e->ignore(); + return true; } } - if (ce->isAccepted()) { - return true; - } + // Explicitly call QCoreApplication instead of QGuiApplication so that + // we don't let QGuiApplication close any windows we skipped earlier in + // closeAllWindows(). FIXME: Unify all this close magic through closeAllWindows. + return QCoreApplication::event(e); #ifndef Q_OS_WIN } else if (e->type() == QEvent::LocaleChange) { // on Windows the event propagation is taken care by the @@ -1928,7 +1909,7 @@ bool QApplication::event(QEvent *e) } if (showToolTip) { QHelpEvent e(QEvent::ToolTip, d->toolTipPos, d->toolTipGlobalPos); - QApplication::sendEvent(d->toolTipWidget, &e); + QCoreApplication::sendEvent(d->toolTipWidget, &e); if (e.isAccepted()) { QStyle *s = d->toolTipWidget->style(); int sleepDelay = s->styleHint(QStyle::SH_ToolTip_FallAsleepDelay, 0, d->toolTipWidget, 0); @@ -1957,13 +1938,6 @@ bool QApplication::event(QEvent *e) return QGuiApplication::event(e); } -/*! - \fn void QApplication::syncX() - Was used to synchronize with the X server in 4.x, here for source compatibility. - \internal - \obsolete -*/ - // ### FIXME: topLevelWindows does not contain QWidgets without a parent // until QWidgetPrivate::create is called. So we have to override the // QGuiApplication::notifyLayoutDirectionChange @@ -2040,7 +2014,7 @@ void QApplication::setActiveWindow(QWidget* act) QGuiApplication::inputMethod()->commit(); QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, Qt::ActiveWindowFocusReason); - QApplication::sendEvent(QApplicationPrivate::focus_widget, &focusAboutToChange); + QCoreApplication::sendEvent(QApplicationPrivate::focus_widget, &focusAboutToChange); } QApplicationPrivate::active_window = window; @@ -2115,7 +2089,7 @@ QWidget *qt_tlw_for_window(QWindow *wnd) wnd = wnd->parent(); } if (wnd) { - const auto tlws = qApp->topLevelWidgets(); + const auto tlws = QApplication::topLevelWidgets(); for (QWidget *tlw : tlws) { if (tlw->windowHandle() == wnd) return tlw; @@ -2209,12 +2183,12 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con #if 0 if (leave) { QEvent e(QEvent::Leave); - QApplication::sendEvent(leave, & e); + QCoreApplication::sendEvent(leave, & e); } if (enter) { const QPoint windowPos = enter->window()->mapFromGlobal(globalPos); QEnterEvent e(enter->mapFromGlobal(globalPos), windowPos, globalPos); - QApplication::sendEvent(enter, & e); + QCoreApplication::sendEvent(enter, & e); } return; #endif @@ -2275,12 +2249,12 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con for (int i = 0; i < leaveList.size(); ++i) { auto *w = leaveList.at(i); if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) { - QApplication::sendEvent(w, &leaveEvent); + QCoreApplication::sendEvent(w, &leaveEvent); if (w->testAttribute(Qt::WA_Hover) && (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) { Q_ASSERT(instance()); QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1), w->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos), - QApplication::keyboardModifiers()); + QGuiApplication::keyboardModifiers()); qApp->d_func()->notify_helper(w, &he); } } @@ -2296,11 +2270,11 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) { const QPointF localPos = w->mapFromGlobal(globalPos); QEnterEvent enterEvent(localPos, windowPos, globalPosF); - QApplication::sendEvent(w, &enterEvent); + QCoreApplication::sendEvent(w, &enterEvent); if (w->testAttribute(Qt::WA_Hover) && (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) { QHoverEvent he(QEvent::HoverEnter, localPos, QPoint(-1, -1), - QApplication::keyboardModifiers()); + QGuiApplication::keyboardModifiers()); qApp->d_func()->notify_helper(w, &he); } } @@ -2648,7 +2622,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, if (spontaneous) result = QApplication::sendSpontaneousEvent(receiver, event); else - result = QApplication::sendEvent(receiver, event); + result = QCoreApplication::sendEvent(receiver, event); } if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease @@ -2902,7 +2876,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } #ifndef QT_NO_DEBUG - d->checkReceiverThread(receiver); + QCoreApplicationPrivate::checkReceiverThread(receiver); #endif if (receiver->isWindowType()) { @@ -3241,13 +3215,21 @@ bool QApplication::notify(QObject *receiver, QEvent *e) if (spontaneous && phase == Qt::ScrollBegin) QApplicationPrivate::wheel_widget = nullptr; - const QPoint &relpos = wheel->pos(); + QPoint relpos = wheel->position().toPoint(); if (spontaneous && (phase == Qt::NoScrollPhase || phase == Qt::ScrollUpdate)) QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); +#if QT_DEPRECATED_SINCE(5, 14) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), wheel->modifiers(), phase, wheel->source(), wheel->inverted()); +QT_WARNING_POP +#else + QWheelEvent we(relpos, wheel->globalPosition(), wheel->pixelDelta(), wheel->angleDelta(), wheel->buttons(), + wheel->modifiers(), phase, wheel->inverted(), wheel->source()); +#endif we.setTimestamp(wheel->timestamp()); bool eventAccepted; do { @@ -3282,9 +3264,17 @@ bool QApplication::notify(QObject *receiver, QEvent *e) // is set. Since it accepted the wheel event previously, we continue // sending those events until we get a ScrollEnd, which signifies // the end of the natural scrolling sequence. - const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPos()); + const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPosition().toPoint()); +#if QT_DEPRECATED_SINCE(5, 0) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), wheel->modifiers(), wheel->phase(), wheel->source()); +QT_WARNING_POP +#else + QWheelEvent we(relpos, wheel->globalPosition(), wheel->pixelDelta(), wheel->angleDelta(), wheel->buttons(), + wheel->modifiers(), wheel->phase(), wheel->inverted(), wheel->source()); +#endif we.setTimestamp(wheel->timestamp()); we.spont = true; we.ignore(); @@ -3401,7 +3391,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) #if QT_CONFIG(graphicsview) // QGraphicsProxyWidget handles its own propagation, // and we must not change QDragManagers currentTarget. - QWExtra *extra = w->window()->d_func()->extra; + const auto &extra = w->window()->d_func()->extra; if (extra && extra->proxyWidget) { res = d->notify_helper(w, dragEvent); break; @@ -3429,7 +3419,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) #if QT_CONFIG(graphicsview) // QGraphicsProxyWidget handles its own propagation, // and we must not change QDragManagers currentTarget. - QWExtra *extra = w->window()->d_func()->extra; + const auto &extra = w->window()->d_func()->extra; bool isProxyWidget = extra && extra->proxyWidget; if (!isProxyWidget) #endif @@ -3670,7 +3660,7 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e) // send to all application event filters if (threadRequiresCoreApplication() - && receiver->d_func()->threadData->thread == mainThread() + && receiver->d_func()->threadData->thread.loadAcquire() == mainThread() && sendThroughApplicationEventFilters(receiver, e)) { filtered = true; return filtered; @@ -3822,7 +3812,7 @@ void QApplicationPrivate::openPopup(QWidget *popup) } else if (popupWidgets->count() == 1) { // this was the first popup if (QWidget *fw = QApplication::focusWidget()) { QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); - QApplication::sendEvent(fw, &e); + QCoreApplication::sendEvent(fw, &e); } } } @@ -3834,8 +3824,6 @@ void QApplicationPrivate::openPopup(QWidget *popup) This feature is available in Qt for Embedded Linux only. \since 4.6 - - \sa keypadNavigationEnabled() */ void QApplication::setNavigationMode(Qt::NavigationMode mode) { @@ -3848,8 +3836,6 @@ void QApplication::setNavigationMode(Qt::NavigationMode mode) This feature is available in Qt for Embedded Linux only. \since 4.6 - - \sa keypadNavigationEnabled() */ Qt::NavigationMode QApplication::navigationMode() { @@ -3985,15 +3971,6 @@ int QApplication::doubleClickInterval() } /*! - \fn QApplication::keyboardInputDirection() - \since 4.2 - \deprecated - - Returns the current keyboard input direction. Replaced with QInputMethod::inputDirection() - \sa QInputMethod::inputDirection() -*/ - -/*! \property QApplication::keyboardInputInterval \brief the time limit in milliseconds that distinguishes a key press from two consecutive key presses @@ -4130,14 +4107,6 @@ void QApplication::beep() \sa QCoreApplication::instance(), qGuiApp */ -/*! - \fn QLocale QApplication::keyboardInputLocale() - \since 4.2 - \obsolete - - Returns the current keyboard input locale. Replaced with QInputMethod::locale() -*/ - bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event) { return QGuiApplication::sendSpontaneousEvent(receiver, event); @@ -4387,7 +4356,7 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, QTouchEvent touchEvent(eventType, device, - QApplication::keyboardModifiers(), + QGuiApplication::keyboardModifiers(), it.value().first, it.value().second); bool containsPress = updateTouchPointsForWidget(widget, &touchEvent); @@ -4430,7 +4399,7 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, void QApplicationPrivate::translateTouchCancel(QTouchDevice *device, ulong timestamp) { - QTouchEvent touchEvent(QEvent::TouchCancel, device, QApplication::keyboardModifiers()); + QTouchEvent touchEvent(QEvent::TouchCancel, device, QGuiApplication::keyboardModifiers()); touchEvent.setTimestamp(timestamp); QHash<ActiveTouchPointsKey, ActiveTouchPointsValue>::const_iterator it = self->activeTouchPoints.constBegin(), ite = self->activeTouchPoints.constEnd(); @@ -4466,12 +4435,12 @@ void QApplicationPrivate::sendApplicationPaletteChange(bool toAllWidgets, const const QWidgetList widgets = QApplication::allWidgets(); for (auto widget : widgets) { if (toAllWidgets || (!className && widget->isWindow()) || (className && widget->inherits(className))) - QApplication::sendEvent(widget, &event); + QCoreApplication::sendEvent(widget, &event); } #if QT_CONFIG(graphicsview) for (auto scene : qAsConst(scene_list)) - QApplication::sendEvent(scene, &event); + QCoreApplication::sendEvent(scene, &event); #endif // QT_CONFIG(graphicsview) } diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 133279f977..3167bd423f 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -112,52 +112,41 @@ public: virtual bool shouldQuit() override; bool tryCloseAllWindows() override; -#if 0 // Used to be included in Qt4 for Q_WS_X11 -#if QT_CONFIG(settings) - static bool x11_apply_settings(); -#endif - static void reset_instance_pointer(); -#endif static bool autoSipEnabled; static QString desktopStyleKey(); - void createEventDispatcher() override; static void dispatchEnterLeave(QWidget *enter, QWidget *leave, const QPointF &globalPosF); void notifyWindowIconChanged() override; //modality - bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = 0) const override; + bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = nullptr) const override; static bool isBlockedByModal(QWidget *widget); static bool modalState(); - static bool tryModalHelper(QWidget *widget, QWidget **rettop = 0); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - static QWidget *tryModalHelper_sys(QWidget *top); - bool canQuit(); + static bool tryModalHelper(QWidget *widget, QWidget **rettop = nullptr); + +#ifdef QT_KEYPAD_NAVIGATION + static bool keypadNavigationEnabled() + { + return navigationMode == Qt::NavigationModeKeypadTabOrder || + navigationMode == Qt::NavigationModeKeypadDirectional; + } #endif bool notify_helper(QObject *receiver, QEvent * e); - void init( -#if 0 // Used to be included in Qt4 for Q_WS_X11 - Display *dpy = 0, Qt::HANDLE visual = 0, Qt::HANDLE cmap = 0 -#endif - ); + void init(); void initialize(); void process_cmdline(); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - static void x11_initialize_style(); -#endif - static bool inPopupMode(); bool popupActive() override { return inPopupMode(); } void closePopup(QWidget *popup); void openPopup(QWidget *popup); static void setFocusWidget(QWidget *focus, Qt::FocusReason reason); static QWidget *focusNextPrevChild_helper(QWidget *toplevel, bool next, - bool *wrappingOccurred = 0); + bool *wrappingOccurred = nullptr); #if QT_CONFIG(graphicsview) // Maintain a list of all scenes to ensure font and palette propagation to @@ -205,10 +194,6 @@ public: static void initializeWidgetFontHash(); static void setSystemFont(const QFont &font); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - static void applyX11SpecificCommandLineArguments(QWidget *main_widget); -#endif - static QApplicationPrivate *instance() { return self; } #ifdef QT_KEYPAD_NAVIGATION @@ -216,10 +201,6 @@ public: static Qt::NavigationMode navigationMode; #endif -#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ || 0 /* Used to be included in Qt4 for Q_WS_X11 */ - void _q_alertTimeOut(); - QHash<QWidget *, QTimer *> alertTimerHash; -#endif #ifndef QT_NO_STYLE_STYLESHEET static QString styleSheet; #endif @@ -238,7 +219,7 @@ public: return window; if (const QWidget *nativeParent = widget->nativeParentWidget()) return nativeParent->windowHandle(); - return 0; + return nullptr; } #ifdef Q_OS_WIN @@ -256,14 +237,6 @@ public: QGestureManager *gestureManager; QWidget *gestureWidget; #endif -#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ || 0 /* Used to be included in Qt4 for Q_WS_WIN */ - QPixmap *move_cursor; - QPixmap *copy_cursor; - QPixmap *link_cursor; -#endif -#if 0 // Used to be included in Qt4 for Q_WS_WIN - QPixmap *ignore_cursor; -#endif static bool updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); void initializeMultitouch(); @@ -292,14 +265,7 @@ private: static bool isAlien(QWidget *); }; -#if 0 // Used to be included in Qt4 for Q_WS_WIN - extern void qt_win_set_cursor(QWidget *, bool); -#elif 0 // Used to be included in Qt4 for Q_WS_X11 - extern void qt_x11_enforce_cursor(QWidget *, bool); - extern void qt_x11_enforce_cursor(QWidget *); -#else - extern void qt_qpa_set_cursor(QWidget * w, bool force); -#endif +extern void qt_qpa_set_cursor(QWidget * w, bool force); QT_END_NAMESPACE diff --git a/src/widgets/kernel/qboxlayout.cpp b/src/widgets/kernel/qboxlayout.cpp index a368f379ad..76d8533271 100644 --- a/src/widgets/kernel/qboxlayout.cpp +++ b/src/widgets/kernel/qboxlayout.cpp @@ -172,7 +172,7 @@ void QBoxLayoutPrivate::effectiveMargins(int *left, int *top, int *right, int *b rightDelta = w->geometry().right() - itm->geometry().right(); } QWidget *w = q->parentWidget(); - Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : QApplication::layoutDirection(); + Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : QGuiApplication::layoutDirection(); if (layoutDirection == Qt::RightToLeft) qSwap(leftDelta, rightDelta); diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp index d17c7eb36c..9e90adec46 100644 --- a/src/widgets/kernel/qdesktopwidget.cpp +++ b/src/widgets/kernel/qdesktopwidget.cpp @@ -111,7 +111,7 @@ const QRect QDesktopWidgetPrivate::availableGeometry(const QWidget *widget) QDesktopScreenWidget *QDesktopWidgetPrivate::widgetForScreen(QScreen *qScreen) const { foreach (QDesktopScreenWidget *widget, screens) { - if (widget->screen() == qScreen) + if (widget->assignedScreen() == qScreen) return widget; } return nullptr; @@ -211,7 +211,9 @@ QDesktopWidget::QDesktopWidget() setObjectName(QLatin1String("desktop")); d->_q_updateScreens(); connect(qApp, SIGNAL(screenAdded(QScreen*)), this, SLOT(_q_updateScreens())); +#if QT_DEPRECATED_SINCE(5, 11) connect(qApp, SIGNAL(primaryScreenChanged(QScreen*)), this, SIGNAL(primaryScreenChanged())); +#endif } QDesktopWidget::~QDesktopWidget() @@ -321,20 +323,12 @@ int QDesktopWidgetPrivate::screenNumber(const QWidget *w) if (screens.isEmpty()) // This should never happen return primaryScreen(); - const QWindow *winHandle = w->windowHandle(); - if (!winHandle) { - if (const QWidget *nativeParent = w->nativeParentWidget()) - winHandle = nativeParent->windowHandle(); - } - // If there is more than one virtual desktop if (screens.count() != screens.constFirst()->virtualSiblings().count()) { // Find the root widget, get a QScreen from it and use the // virtual siblings for checking the window position. - if (winHandle) { - if (const QScreen *winScreen = winHandle->screen()) - screens = winScreen->virtualSiblings(); - } + if (const QScreen *winScreen = qt_widget_private(const_cast<QWidget *>(w))->associatedScreen()) + screens = winScreen->virtualSiblings(); } // Get the screen number from window position using screen geometry diff --git a/src/widgets/kernel/qdesktopwidget_p.h b/src/widgets/kernel/qdesktopwidget_p.h index 69f87337b3..63949055aa 100644 --- a/src/widgets/kernel/qdesktopwidget_p.h +++ b/src/widgets/kernel/qdesktopwidget_p.h @@ -68,7 +68,7 @@ public: int screenNumber() const; void setScreenGeometry(const QRect &geometry); - QScreen *screen() const { return m_screen.data(); } + QScreen *assignedScreen() const { return m_screen.data(); } QRect screenGeometry() const { return m_geometry; } private: diff --git a/src/widgets/kernel/qformlayout.cpp b/src/widgets/kernel/qformlayout.cpp index bd0ea2598a..6f7527c013 100644 --- a/src/widgets/kernel/qformlayout.cpp +++ b/src/widgets/kernel/qformlayout.cpp @@ -783,7 +783,7 @@ void QFormLayoutPrivate::setupVerticalLayoutData(int width) vLayouts[vidx].expansive = expanding || (vLayouts[vidx].stretch > 0); vLayouts[vidx].empty = false; - if (vLayouts[vidx].stretch > 0) + if (vLayouts[vidx].expansive) addTopBottomStretch = false; if (vidx > 1) @@ -2178,7 +2178,7 @@ void QFormLayoutPrivate::arrangeWidgets(const QVector<QLayoutStruct>& layouts, Q int i; const int rr = m_matrix.rowCount(); QWidget *w = q->parentWidget(); - Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : QApplication::layoutDirection(); + Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : QGuiApplication::layoutDirection(); Qt::Alignment formAlignment = fixedAlignment(q->formAlignment(), layoutDirection); int leftOffset = 0; diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h index 636103c1e1..cbf8d60892 100644 --- a/src/widgets/kernel/qgesture_p.h +++ b/src/widgets/kernel/qgesture_p.h @@ -111,7 +111,7 @@ class QPinchGesturePrivate : public QGesturePrivate public: QPinchGesturePrivate() - : totalChangeFlags(0), changeFlags(0), + : totalChangeFlags(nullptr), changeFlags(nullptr), totalScaleFactor(1), lastScaleFactor(1), scaleFactor(1), totalRotationAngle(0), lastRotationAngle(0), rotationAngle(0), isNewSequence(true) diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp index 5d2adc1e1c..d0c6b882b5 100644 --- a/src/widgets/kernel/qgesturemanager.cpp +++ b/src/widgets/kernel/qgesturemanager.cpp @@ -54,9 +54,6 @@ #ifdef Q_OS_OSX #include "qmacgesturerecognizer_p.h" #endif -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ && !defined(QT_NO_NATIVE_GESTURES) -#include "qwinnativepangesturerecognizer_win_p.h" -#endif #include "qdebug.h" #include <QtCore/QLoggingCategory> @@ -102,14 +99,7 @@ QGestureManager::QGestureManager(QObject *parent) registerGestureRecognizer(new QSwipeGestureRecognizer); registerGestureRecognizer(new QTapGestureRecognizer); #endif -#if 0 // Used to be included in Qt4 for Q_WS_WIN - #if !defined(QT_NO_NATIVE_GESTURES) - if (QApplicationPrivate::HasTouchSupport) - registerGestureRecognizer(new QWinNativePanGestureRecognizer); - #endif -#else registerGestureRecognizer(new QTapAndHoldGestureRecognizer); -#endif } QGestureManager::~QGestureManager() @@ -168,30 +158,26 @@ void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type) void QGestureManager::cleanupCachedGestures(QObject *target, Qt::GestureType type) { - QMap<ObjectGesture, QList<QGesture *> >::Iterator iter = m_objectGestures.begin(); - while (iter != m_objectGestures.end()) { - ObjectGesture objectGesture = iter.key(); - if (objectGesture.gesture == type && target == objectGesture.object) { - QSet<QGesture *> gestures = iter.value().toSet(); - for (QHash<QGestureRecognizer *, QSet<QGesture *> >::iterator - it = m_obsoleteGestures.begin(), e = m_obsoleteGestures.end(); it != e; ++it) { - it.value() -= gestures; - } - foreach (QGesture *g, gestures) { - m_deletedRecognizers.remove(g); - m_gestureToRecognizer.remove(g); - m_maybeGestures.remove(g); - m_activeGestures.remove(g); - m_gestureOwners.remove(g); - m_gestureTargets.remove(g); - m_gesturesToDelete.insert(g); - } + const auto iter = m_objectGestures.find({target, type}); + if (iter == m_objectGestures.end()) + return; - iter = m_objectGestures.erase(iter); - } else { - ++iter; - } + const QList<QGesture *> &gestures = iter.value(); + for (auto &e : m_obsoleteGestures) { + for (QGesture *g : gestures) + e -= g; + } + for (QGesture *g : gestures) { + m_deletedRecognizers.remove(g); + m_gestureToRecognizer.remove(g); + m_maybeGestures.remove(g); + m_activeGestures.remove(g); + m_gestureOwners.remove(g); + m_gestureTargets.remove(g); + m_gesturesToDelete.insert(g); } + + m_objectGestures.erase(iter); } // get or create a QGesture object that will represent the state for a given object, used by the recognizer @@ -510,14 +496,14 @@ void QGestureManager::cleanupGesturesForRemovedRecognizer(QGesture *gesture) // return true if accepted (consumed) bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) { - QMap<Qt::GestureType, int> types; + QVarLengthArray<Qt::GestureType, 16> types; QMultiMap<QObject *, Qt::GestureType> contexts; QWidget *w = receiver; typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator; if (!w->d_func()->gestureContext.isEmpty()) { for(ContextIterator it = w->d_func()->gestureContext.constBegin(), e = w->d_func()->gestureContext.constEnd(); it != e; ++it) { - types.insert(it.key(), 0); + types.push_back(it.key()); contexts.insert(w, it.key()); } } @@ -529,7 +515,7 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) e = w->d_func()->gestureContext.constEnd(); it != e; ++it) { if (!(it.value() & Qt::DontStartGestureOnChildren)) { if (!types.contains(it.key())) { - types.insert(it.key(), 0); + types.push_back(it.key()); contexts.insert(w, it.key()); } } @@ -544,14 +530,14 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) #if QT_CONFIG(graphicsview) bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event) { - QMap<Qt::GestureType, int> types; + QVarLengthArray<Qt::GestureType, 16> types; QMultiMap<QObject *, Qt::GestureType> contexts; QGraphicsObject *item = receiver; if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) { typedef QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator ContextIterator; for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.constBegin(), e = item->QGraphicsItem::d_func()->gestureContext.constEnd(); it != e; ++it) { - types.insert(it.key(), 0); + types.push_back(it.key()); contexts.insert(item, it.key()); } } @@ -564,7 +550,7 @@ bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event) e = item->QGraphicsItem::d_func()->gestureContext.constEnd(); it != e; ++it) { if (!(it.value() & Qt::DontStartGestureOnChildren)) { if (!types.contains(it.key())) { - types.insert(it.key(), 0); + types.push_back(it.key()); contexts.insert(item, it.key()); } } @@ -712,7 +698,7 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures, foreach(QGesture *g, gestures) event.setAccepted(g, false); - QApplication::sendEvent(receiver, &event); + QCoreApplication::sendEvent(receiver, &event); bool eventAccepted = event.isAccepted(); const auto eventGestures = event.gestures(); for (QGesture *gesture : eventGestures) { @@ -739,7 +725,7 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures, qCDebug(lcGestureManager) << "QGestureManager::deliverEvents: sending to" << it.key() << "gestures:" << it.value(); QGestureEvent event(it.value()); - QApplication::sendEvent(it.key(), &event); + QCoreApplication::sendEvent(it.key(), &event); bool eventAccepted = event.isAccepted(); const auto eventGestures = event.gestures(); for (QGesture *gesture : eventGestures) { diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp index 53c4de49c6..3ce81a390b 100644 --- a/src/widgets/kernel/qlayout.cpp +++ b/src/widgets/kernel/qlayout.cpp @@ -1040,7 +1040,7 @@ void QLayout::update() if (layout->d_func()->topLevel) { Q_ASSERT(layout->parent()->isWidgetType()); QWidget *mw = static_cast<QWidget*>(layout->parent()); - QApplication::postEvent(mw, new QEvent(QEvent::LayoutRequest)); + QCoreApplication::postEvent(mw, new QEvent(QEvent::LayoutRequest)); break; } layout = static_cast<QLayout*>(layout->parent()); @@ -1156,6 +1156,8 @@ QLayoutItem *QLayout::replaceWidget(QWidget *from, QWidget *to, Qt::FindChildOpt Q_D(QLayout); if (!from || !to) return 0; + if (from == to) // Do not return a QLayoutItem for \a from, since ownership still + return nullptr; // belongs to the layout (since nothing was changed) int index = -1; QLayoutItem *item = 0; @@ -1364,7 +1366,7 @@ QRect QLayout::alignmentRect(const QRect &r) const y += (r.height() - s.height()) / 2; QWidget *parent = parentWidget(); - a = QStyle::visualAlignment(parent ? parent->layoutDirection() : QApplication::layoutDirection(), a); + a = QStyle::visualAlignment(parent ? parent->layoutDirection() : QGuiApplication::layoutDirection(), a); if (a & Qt::AlignRight) x += (r.width() - s.width()); else if (!(a & Qt::AlignLeft)) diff --git a/src/widgets/kernel/qlayout_p.h b/src/widgets/kernel/qlayout_p.h index 8a1b12a6be..8e1d773355 100644 --- a/src/widgets/kernel/qlayout_p.h +++ b/src/widgets/kernel/qlayout_p.h @@ -80,7 +80,7 @@ public: static QWidgetItem *createWidgetItem(const QLayout *layout, QWidget *widget); static QSpacerItem *createSpacerItem(const QLayout *layout, int w, int h, QSizePolicy::Policy hPolicy = QSizePolicy::Minimum, QSizePolicy::Policy vPolicy = QSizePolicy::Minimum); - virtual QLayoutItem* replaceAt(int index, QLayoutItem *newitem) { Q_UNUSED(index); Q_UNUSED(newitem); return 0; } + virtual QLayoutItem* replaceAt(int index, QLayoutItem *newitem) { Q_UNUSED(index); Q_UNUSED(newitem); return nullptr; } static QWidgetItemFactoryMethod widgetItemFactoryMethod; static QSpacerItemFactoryMethod spacerItemFactoryMethod; diff --git a/src/widgets/kernel/qlayoutengine_p.h b/src/widgets/kernel/qlayoutengine_p.h index 812fa7cf3b..948c2424e6 100644 --- a/src/widgets/kernel/qlayoutengine_p.h +++ b/src/widgets/kernel/qlayoutengine_p.h @@ -105,9 +105,9 @@ Q_WIDGETS_EXPORT QSize qSmartMinSize(const QWidgetItem *i); Q_WIDGETS_EXPORT QSize qSmartMinSize(const QWidget *w); Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QSize &sizeHint, const QSize &minSize, const QSize &maxSize, - const QSizePolicy &sizePolicy, Qt::Alignment align = 0); -Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QWidgetItem *i, Qt::Alignment align = 0); -Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QWidget *w, Qt::Alignment align = 0); + const QSizePolicy &sizePolicy, Qt::Alignment align = nullptr); +Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QWidgetItem *i, Qt::Alignment align = nullptr); +Q_WIDGETS_EXPORT QSize qSmartMaxSize(const QWidget *w, Qt::Alignment align = nullptr); Q_WIDGETS_EXPORT int qSmartSpacing(const QLayout *layout, QStyle::PixelMetric pm); diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp index 9e6d1c5eac..0aab0bb06d 100644 --- a/src/widgets/kernel/qlayoutitem.cpp +++ b/src/widgets/kernel/qlayoutitem.cpp @@ -502,6 +502,17 @@ void QWidgetItem::setGeometry(const QRect &rect) else if (!(align & Qt::AlignTop)) y = y + (r.height() - s.height()) / 2; + // Make sure we don't move outside of the parent, e.g when styles demand + // surplus space that exceeds the available margins (f.ex macOS with QGroupBox) + if (x < 0) { + s.rwidth() += x; + x = 0; + } + if (y < 0) { + s.rheight() += y; + y = 0; + } + wid->setGeometry(x, y, s.width(), s.height()); } diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index a88054a0d0..bc5ca21b97 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -1335,11 +1335,8 @@ int QOpenGLWidget::metric(QPaintDevice::PaintDeviceMetric metric) const if (d->inBackingStorePaint) return QWidget::metric(metric); - QWidget *tlw = window(); - QWindow *window = tlw ? tlw->windowHandle() : 0; - QScreen *screen = tlw && tlw->windowHandle() ? tlw->windowHandle()->screen() : 0; - if (!screen && QGuiApplication::primaryScreen()) - screen = QGuiApplication::primaryScreen(); + auto window = d->windowHandle(QWidgetPrivate::WindowHandleMode::TopLevel); + QScreen *screen = window ? window->screen() : QGuiApplication::primaryScreen(); const float dpmx = qt_defaultDpiX() * 100. / 2.54; const float dpmy = qt_defaultDpiY() * 100. / 2.54; @@ -1437,7 +1434,7 @@ bool QOpenGLWidget::event(QEvent *e) Q_D(QOpenGLWidget); switch (e->type()) { case QEvent::WindowChangeInternal: - if (qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts)) + if (QCoreApplication::testAttribute(Qt::AA_ShareOpenGLContexts)) break; if (d->initialized) d->reset(); @@ -1450,7 +1447,7 @@ bool QOpenGLWidget::event(QEvent *e) { // Special case: did grabFramebuffer() for a hidden widget that then became visible. // Recreate all resources since the context now needs to share with the TLW's. - if (!qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts)) + if (!QCoreApplication::testAttribute(Qt::AA_ShareOpenGLContexts)) d->reset(); } if (!d->initialized && !size().isEmpty() && window()->windowHandle()) { diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp index db06dce042..eec65c8625 100644 --- a/src/widgets/kernel/qshortcut.cpp +++ b/src/widgets/kernel/qshortcut.cpp @@ -96,8 +96,7 @@ bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context) QWindow *qwindow = QGuiApplication::focusWindow(); if (qwindow && qwindow->isActive()) { while (qwindow) { - QWidgetWindow *widgetWindow = qobject_cast<QWidgetWindow *>(qwindow); - if (widgetWindow) { + if (auto widgetWindow = qobject_cast<QWidgetWindow *>(qwindow)) { active_window = widgetWindow->widget(); break; } @@ -110,27 +109,25 @@ bool qWidgetShortcutContextMatcher(QObject *object, Qt::ShortcutContext context) return false; #ifndef QT_NO_ACTION - if (QAction *a = qobject_cast<QAction *>(object)) + if (auto a = qobject_cast<QAction *>(object)) return correctActionContext(context, a, active_window); #endif #if QT_CONFIG(graphicsview) - if (QGraphicsWidget *gw = qobject_cast<QGraphicsWidget *>(object)) + if (auto gw = qobject_cast<QGraphicsWidget *>(object)) return correctGraphicsWidgetContext(context, gw, active_window); #endif - QWidget *w = qobject_cast<QWidget *>(object); + auto w = qobject_cast<QWidget *>(object); if (!w) { - QShortcut *s = qobject_cast<QShortcut *>(object); - if (s) + if (auto s = qobject_cast<QShortcut *>(object)) w = s->parentWidget(); } if (!w) { - QWindow *qwindow = qobject_cast<QWindow *>(object); + auto qwindow = qobject_cast<QWindow *>(object); while (qwindow) { - QWidgetWindow *widget_window = qobject_cast<QWidgetWindow *>(qwindow); - if (widget_window) { + if (auto widget_window = qobject_cast<QWidgetWindow *>(qwindow)) { w = widget_window->widget(); break; } @@ -148,7 +145,7 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge { bool visible = w->isVisible(); #if QT_CONFIG(menubar) - if (QMenuBar *menuBar = qobject_cast<QMenuBar *>(w)) { + if (auto menuBar = qobject_cast<QMenuBar *>(w)) { if (auto *pmb = menuBar->platformMenuBar()) { if (menuBar->parentWidget()) { visible = true; @@ -166,7 +163,7 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge return false; if (context == Qt::ApplicationShortcut) - return QApplicationPrivate::tryModalHelper(w, 0); // true, unless w is shadowed by a modal dialog + return QApplicationPrivate::tryModalHelper(w, nullptr); // true, unless w is shadowed by a modal dialog if (context == Qt::WidgetShortcut) return w == QApplication::focusWidget(); @@ -181,9 +178,9 @@ static bool correctWidgetContext(Qt::ShortcutContext context, QWidget *w, QWidge // Below is Qt::WindowShortcut context QWidget *tlw = w->window(); #if QT_CONFIG(graphicsview) - if (QWExtra *topData = static_cast<QWidgetPrivate *>(QObjectPrivate::get(tlw))->extra) { + if (auto topData = static_cast<QWidgetPrivate *>(QObjectPrivate::get(tlw))->extra.get()) { if (topData->proxyWidget) { - bool res = correctGraphicsWidgetContext(context, (QGraphicsWidget *)topData->proxyWidget, active_window); + bool res = correctGraphicsWidgetContext(context, topData->proxyWidget, active_window); return res; } } @@ -233,7 +230,7 @@ static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsW { bool visible = w->isVisible(); #if defined(Q_OS_DARWIN) && QT_CONFIG(menubar) - if (!qApp->testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w)) + if (!QCoreApplication::testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w)) visible = true; #endif @@ -244,9 +241,9 @@ static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsW // Applicationwide shortcuts are always reachable unless their owner // is shadowed by modality. In QGV there's no modality concept, but we // must still check if all views are shadowed. - QList<QGraphicsView *> views = w->scene()->views(); - for (int i = 0; i < views.size(); ++i) { - if (QApplicationPrivate::tryModalHelper(views.at(i), 0)) + const auto &views = w->scene()->views(); + for (auto view : views) { + if (QApplicationPrivate::tryModalHelper(view, nullptr)) return true; } return false; @@ -258,7 +255,7 @@ static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsW if (context == Qt::WidgetWithChildrenShortcut) { const QGraphicsItem *ti = w->scene()->focusItem(); if (ti && ti->isWidget()) { - const QGraphicsWidget *tw = static_cast<const QGraphicsWidget *>(ti); + const auto *tw = static_cast<const QGraphicsWidget *>(ti); while (tw && tw != w && (tw->windowType() == Qt::Widget || tw->windowType() == Qt::Popup)) tw = tw->parentWidget(); return tw == w; @@ -269,10 +266,9 @@ static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsW // Below is Qt::WindowShortcut context // Find the active view (if any). - QList<QGraphicsView *> views = w->scene()->views(); - QGraphicsView *activeView = 0; - for (int i = 0; i < views.size(); ++i) { - QGraphicsView *view = views.at(i); + const auto &views = w->scene()->views(); + QGraphicsView *activeView = nullptr; + for (auto view : views) { if (view->window() == active_window) { activeView = view; break; @@ -291,15 +287,14 @@ static bool correctGraphicsWidgetContext(Qt::ShortcutContext context, QGraphicsW #ifndef QT_NO_ACTION static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidget *active_window) { - const QList<QWidget *> &widgets = static_cast<QActionPrivate *>(QObjectPrivate::get(a))->widgets; + const QWidgetList &widgets = static_cast<QActionPrivate *>(QObjectPrivate::get(a))->widgets; #if defined(DEBUG_QSHORTCUTMAP) if (widgets.isEmpty()) qDebug() << a << "not connected to any widgets; won't trigger"; #endif - for (int i = 0; i < widgets.size(); ++i) { - QWidget *w = widgets.at(i); + for (auto w : widgets) { #if QT_CONFIG(menu) - if (QMenu *menu = qobject_cast<QMenu *>(w)) { + if (auto menu = qobject_cast<QMenu *>(w)) { #ifdef Q_OS_DARWIN // On Mac, menu item shortcuts are processed before reaching any window. // That means that if a menu action shortcut has not been already processed @@ -325,14 +320,13 @@ static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidge } #if QT_CONFIG(graphicsview) - const QList<QGraphicsWidget *> &graphicsWidgets = static_cast<QActionPrivate *>(QObjectPrivate::get(a))->graphicsWidgets; + const auto &graphicsWidgets = static_cast<QActionPrivate *>(QObjectPrivate::get(a))->graphicsWidgets; #if defined(DEBUG_QSHORTCUTMAP) if (graphicsWidgets.isEmpty()) qDebug() << a << "not connected to any widgets; won't trigger"; #endif - for (int i = 0; i < graphicsWidgets.size(); ++i) { - QGraphicsWidget *w = graphicsWidgets.at(i); - if (correctGraphicsWidgetContext(context, w, active_window)) + for (auto graphicsWidget : graphicsWidgets) { + if (correctGraphicsWidgetContext(context, graphicsWidget, active_window)) return true; } #endif @@ -433,12 +427,12 @@ class QShortcutPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QShortcut) public: - QShortcutPrivate() : sc_context(Qt::WindowShortcut), sc_enabled(true), sc_autorepeat(true), sc_id(0) {} + QShortcutPrivate() = default; QKeySequence sc_sequence; - Qt::ShortcutContext sc_context; - bool sc_enabled; - bool sc_autorepeat; - int sc_id; + Qt::ShortcutContext sc_context = Qt::WindowShortcut; + bool sc_enabled = true; + bool sc_autorepeat = true; + int sc_id = 0; QString sc_whatsthis; void redoGrab(QShortcutMap &map); }; @@ -472,7 +466,7 @@ void QShortcutPrivate::redoGrab(QShortcutMap &map) QShortcut::QShortcut(QWidget *parent) : QObject(*new QShortcutPrivate, parent) { - Q_ASSERT(parent != 0); + Q_ASSERT(parent != nullptr); } /*! @@ -493,7 +487,7 @@ QShortcut::QShortcut(const QKeySequence &key, QWidget *parent, Q_D(QShortcut); d->sc_context = context; d->sc_sequence = key; - d->redoGrab(qApp->d_func()->shortcutMap); + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); if (member) connect(this, SIGNAL(activated()), parent, member); if (ambiguousMember) @@ -507,7 +501,7 @@ QShortcut::~QShortcut() { Q_D(QShortcut); if (qApp) - qApp->d_func()->shortcutMap.removeShortcut(d->sc_id, this); + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(d->sc_id, this); } /*! @@ -528,7 +522,7 @@ void QShortcut::setKey(const QKeySequence &key) return; QAPP_CHECK("setKey"); d->sc_sequence = key; - d->redoGrab(qApp->d_func()->shortcutMap); + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); } QKeySequence QShortcut::key() const @@ -559,7 +553,7 @@ void QShortcut::setEnabled(bool enable) return; QAPP_CHECK("setEnabled"); d->sc_enabled = enable; - qApp->d_func()->shortcutMap.setShortcutEnabled(enable, d->sc_id, this); + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, d->sc_id, this); } bool QShortcut::isEnabled() const @@ -587,7 +581,7 @@ void QShortcut::setContext(Qt::ShortcutContext context) return; QAPP_CHECK("setContext"); d->sc_context = context; - d->redoGrab(qApp->d_func()->shortcutMap); + d->redoGrab(QGuiApplicationPrivate::instance()->shortcutMap); } Qt::ShortcutContext QShortcut::context() const @@ -639,7 +633,7 @@ void QShortcut::setAutoRepeat(bool on) return; QAPP_CHECK("setAutoRepeat"); d->sc_autorepeat = on; - qApp->d_func()->shortcutMap.setShortcutAutoRepeat(on, d->sc_id, this); + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(on, d->sc_id, this); } bool QShortcut::autoRepeat() const @@ -666,7 +660,7 @@ bool QShortcut::event(QEvent *e) { Q_D(QShortcut); if (d->sc_enabled && e->type() == QEvent::Shortcut) { - QShortcutEvent *se = static_cast<QShortcutEvent *>(e); + auto se = static_cast<QShortcutEvent *>(e); if (se->shortcutId() == d->sc_id && se->key() == d->sc_sequence){ #if QT_CONFIG(whatsthis) if (QWhatsThis::inWhatsThisMode()) { diff --git a/src/widgets/kernel/qsizepolicy.cpp b/src/widgets/kernel/qsizepolicy.cpp index b5a0cd3940..54bf8fe0dc 100644 --- a/src/widgets/kernel/qsizepolicy.cpp +++ b/src/widgets/kernel/qsizepolicy.cpp @@ -232,7 +232,7 @@ QT_BEGIN_NAMESPACE Returns the control type associated with the widget for which this size policy applies. */ -QSizePolicy::ControlType QSizePolicy::controlType() const Q_DECL_NOTHROW +QSizePolicy::ControlType QSizePolicy::controlType() const noexcept { return QSizePolicy::ControlType(1 << bits.ctype); } @@ -253,7 +253,7 @@ QSizePolicy::ControlType QSizePolicy::controlType() const Q_DECL_NOTHROW \sa QStyle::layoutSpacing() */ -void QSizePolicy::setControlType(ControlType type) Q_DECL_NOTHROW +void QSizePolicy::setControlType(ControlType type) noexcept { bits.ctype = toControlTypeFieldValue(type); } diff --git a/src/widgets/kernel/qsizepolicy.h b/src/widgets/kernel/qsizepolicy.h index dba742dec5..f26923eeb0 100644 --- a/src/widgets/kernel/qsizepolicy.h +++ b/src/widgets/kernel/qsizepolicy.h @@ -65,7 +65,7 @@ QT_BEGIN_NAMESPACE class QVariant; class QSizePolicy; -Q_DECL_CONST_FUNCTION inline uint qHash(QSizePolicy key, uint seed = 0) Q_DECL_NOTHROW; +Q_DECL_CONST_FUNCTION inline uint qHash(QSizePolicy key, uint seed = 0) noexcept; class Q_WIDGETS_EXPORT QSizePolicy { @@ -110,60 +110,60 @@ public: Q_DECLARE_FLAGS(ControlTypes, ControlType) Q_FLAG(ControlTypes) - QT_SIZEPOLICY_CONSTEXPR QSizePolicy() Q_DECL_NOTHROW : data(0) { } + QT_SIZEPOLICY_CONSTEXPR QSizePolicy() noexcept : data(0) { } #if defined(Q_COMPILER_UNIFORM_INIT) && !defined(Q_QDOC) - QT_SIZEPOLICY_CONSTEXPR QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType) Q_DECL_NOTHROW + QT_SIZEPOLICY_CONSTEXPR QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType) noexcept : bits{0, 0, quint32(horizontal), quint32(vertical), type == DefaultType ? 0 : toControlTypeFieldValue(type), 0, 0, 0} {} #else - QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType) Q_DECL_NOTHROW + QSizePolicy(Policy horizontal, Policy vertical, ControlType type = DefaultType) noexcept : data(0) { bits.horPolicy = horizontal; bits.verPolicy = vertical; setControlType(type); } #endif // uniform-init - QT_SIZEPOLICY_CONSTEXPR Policy horizontalPolicy() const Q_DECL_NOTHROW { return static_cast<Policy>(bits.horPolicy); } - QT_SIZEPOLICY_CONSTEXPR Policy verticalPolicy() const Q_DECL_NOTHROW { return static_cast<Policy>(bits.verPolicy); } - ControlType controlType() const Q_DECL_NOTHROW; + QT_SIZEPOLICY_CONSTEXPR Policy horizontalPolicy() const noexcept { return static_cast<Policy>(bits.horPolicy); } + QT_SIZEPOLICY_CONSTEXPR Policy verticalPolicy() const noexcept { return static_cast<Policy>(bits.verPolicy); } + ControlType controlType() const noexcept; - Q_DECL_RELAXED_CONSTEXPR void setHorizontalPolicy(Policy d) Q_DECL_NOTHROW { bits.horPolicy = d; } - Q_DECL_RELAXED_CONSTEXPR void setVerticalPolicy(Policy d) Q_DECL_NOTHROW { bits.verPolicy = d; } - void setControlType(ControlType type) Q_DECL_NOTHROW; + Q_DECL_RELAXED_CONSTEXPR void setHorizontalPolicy(Policy d) noexcept { bits.horPolicy = d; } + Q_DECL_RELAXED_CONSTEXPR void setVerticalPolicy(Policy d) noexcept { bits.verPolicy = d; } + void setControlType(ControlType type) noexcept; - QT_SIZEPOLICY_CONSTEXPR Qt::Orientations expandingDirections() const Q_DECL_NOTHROW { + QT_SIZEPOLICY_CONSTEXPR Qt::Orientations expandingDirections() const noexcept { return ( (verticalPolicy() & ExpandFlag) ? Qt::Vertical : Qt::Orientations() ) | ( (horizontalPolicy() & ExpandFlag) ? Qt::Horizontal : Qt::Orientations() ) ; } - Q_DECL_RELAXED_CONSTEXPR void setHeightForWidth(bool b) Q_DECL_NOTHROW { bits.hfw = b; } - QT_SIZEPOLICY_CONSTEXPR bool hasHeightForWidth() const Q_DECL_NOTHROW { return bits.hfw; } - Q_DECL_RELAXED_CONSTEXPR void setWidthForHeight(bool b) Q_DECL_NOTHROW { bits.wfh = b; } - QT_SIZEPOLICY_CONSTEXPR bool hasWidthForHeight() const Q_DECL_NOTHROW { return bits.wfh; } + Q_DECL_RELAXED_CONSTEXPR void setHeightForWidth(bool b) noexcept { bits.hfw = b; } + QT_SIZEPOLICY_CONSTEXPR bool hasHeightForWidth() const noexcept { return bits.hfw; } + Q_DECL_RELAXED_CONSTEXPR void setWidthForHeight(bool b) noexcept { bits.wfh = b; } + QT_SIZEPOLICY_CONSTEXPR bool hasWidthForHeight() const noexcept { return bits.wfh; } - QT_SIZEPOLICY_CONSTEXPR bool operator==(const QSizePolicy& s) const Q_DECL_NOTHROW { return data == s.data; } - QT_SIZEPOLICY_CONSTEXPR bool operator!=(const QSizePolicy& s) const Q_DECL_NOTHROW { return data != s.data; } + QT_SIZEPOLICY_CONSTEXPR bool operator==(const QSizePolicy& s) const noexcept { return data == s.data; } + QT_SIZEPOLICY_CONSTEXPR bool operator!=(const QSizePolicy& s) const noexcept { return data != s.data; } - friend Q_DECL_CONST_FUNCTION uint qHash(QSizePolicy key, uint seed) Q_DECL_NOTHROW { return qHash(key.data, seed); } + friend Q_DECL_CONST_FUNCTION uint qHash(QSizePolicy key, uint seed) noexcept { return qHash(key.data, seed); } operator QVariant() const; - QT_SIZEPOLICY_CONSTEXPR int horizontalStretch() const Q_DECL_NOTHROW { return static_cast<int>(bits.horStretch); } - QT_SIZEPOLICY_CONSTEXPR int verticalStretch() const Q_DECL_NOTHROW { return static_cast<int>(bits.verStretch); } + QT_SIZEPOLICY_CONSTEXPR int horizontalStretch() const noexcept { return static_cast<int>(bits.horStretch); } + QT_SIZEPOLICY_CONSTEXPR int verticalStretch() const noexcept { return static_cast<int>(bits.verStretch); } Q_DECL_RELAXED_CONSTEXPR void setHorizontalStretch(int stretchFactor) { bits.horStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); } Q_DECL_RELAXED_CONSTEXPR void setVerticalStretch(int stretchFactor) { bits.verStretch = static_cast<quint32>(qBound(0, stretchFactor, 255)); } - QT_SIZEPOLICY_CONSTEXPR bool retainSizeWhenHidden() const Q_DECL_NOTHROW { return bits.retainSizeWhenHidden; } - Q_DECL_RELAXED_CONSTEXPR void setRetainSizeWhenHidden(bool retainSize) Q_DECL_NOTHROW { bits.retainSizeWhenHidden = retainSize; } + QT_SIZEPOLICY_CONSTEXPR bool retainSizeWhenHidden() const noexcept { return bits.retainSizeWhenHidden; } + Q_DECL_RELAXED_CONSTEXPR void setRetainSizeWhenHidden(bool retainSize) noexcept { bits.retainSizeWhenHidden = retainSize; } - Q_DECL_RELAXED_CONSTEXPR void transpose() Q_DECL_NOTHROW { *this = transposed(); } + Q_DECL_RELAXED_CONSTEXPR void transpose() noexcept { *this = transposed(); } Q_REQUIRED_RESULT #ifndef Q_QDOC QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT #endif - QSizePolicy transposed() const Q_DECL_NOTHROW + QSizePolicy transposed() const noexcept { return QSizePolicy(bits.transposed()); } @@ -173,11 +173,11 @@ private: friend Q_WIDGETS_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &); friend Q_WIDGETS_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &); #endif - QT_SIZEPOLICY_CONSTEXPR QSizePolicy(int i) Q_DECL_NOTHROW : data(i) { } + QT_SIZEPOLICY_CONSTEXPR QSizePolicy(int i) noexcept : data(i) { } struct Bits; - QT_SIZEPOLICY_CONSTEXPR explicit QSizePolicy(Bits b) Q_DECL_NOTHROW : bits(b) { } + QT_SIZEPOLICY_CONSTEXPR explicit QSizePolicy(Bits b) noexcept : bits(b) { } - static Q_DECL_RELAXED_CONSTEXPR quint32 toControlTypeFieldValue(ControlType type) Q_DECL_NOTHROW + static Q_DECL_RELAXED_CONSTEXPR quint32 toControlTypeFieldValue(ControlType type) noexcept { /* The control type is a flag type, with values 0x1, 0x2, 0x4, 0x8, 0x10, @@ -207,7 +207,7 @@ private: quint32 retainSizeWhenHidden : 1; QT_SIZEPOLICY_CONSTEXPR_AND_UNIFORM_INIT - Bits transposed() const Q_DECL_NOTHROW + Bits transposed() const noexcept { return {verStretch, // \ swap horStretch, // / diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index f81cb471fa..97a279d65d 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -36,12 +36,8 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# include <private/qcore_mac_p.h> -#endif #include <QtWidgets/private/qtwidgetsglobal_p.h> -#include <QtWidgets/private/qlabel_p.h> #include <qapplication.h> #include <qdesktopwidget.h> @@ -61,13 +57,9 @@ #ifndef QT_NO_TOOLTIP #include <qlabel.h> +#include <QtWidgets/private/qlabel_p.h> #include <qtooltip.h> -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# include <private/qcore_mac_p.h> -#include <private/qt_cocoa_helpers_mac_p.h> -#endif - QT_BEGIN_NAMESPACE /*! @@ -317,20 +309,7 @@ void QTipLabel::timerEvent(QTimerEvent *e) || e->timerId() == expireTimer.timerId()){ hideTimer.stop(); expireTimer.stop(); -#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && QT_CONFIG(effects) - if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)){ - // Fade out tip on mac (makes it invisible). - // The tip will not be deleted until a new tip is shown. - - // DRSWAT - Cocoa - macWindowFade(qt_mac_window_for(this)); - QTipLabel::instance->fadingOut = true; // will never be false again. - } - else - hideTipImmediately(); -#else hideTipImmediately(); -#endif } } @@ -420,29 +399,11 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) #endif //QT_NO_STYLE_STYLESHEET -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // When in full screen mode, there is no Dock nor Menu so we can use - // the whole screen for displaying the tooltip. However when not in - // full screen mode we need to save space for the dock, so we use - // availableGeometry instead. - extern bool qt_mac_app_fullscreen; //qapplication_mac.mm - QRect screen; - if(qt_mac_app_fullscreen) - screen = QDesktopWidgetPrivate::screenGeometry(getTipScreen(pos, w)); - else - screen = QDesktopWidgetPrivate::availableGeometry(getTipScreen(pos, w)); -#else QRect screen = QDesktopWidgetPrivate::screenGeometry(getTipScreen(pos, w)); -#endif QPoint p = pos; - p += QPoint(2, -#if 0 // Used to be included in Qt4 for Q_WS_WIN - 21 -#else - 16 -#endif - ); + p += QPoint(2, 16); + if (p.x() + this->width() > screen.x() + screen.width()) p.rx() -= 4 + this->width(); if (p.y() + this->height() > screen.y() + screen.height()) @@ -541,7 +502,7 @@ QT_WARNING_POP QTipLabel::instance->setObjectName(QLatin1String("qtooltip_label")); -#if QT_CONFIG(effects) && !0 /* Used to be included in Qt4 for Q_WS_MAC */ +#if QT_CONFIG(effects) if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)) qFadeEffect(QTipLabel::instance); else if (QApplication::isEffectEnabled(Qt::UI_AnimateTooltip)) diff --git a/src/widgets/kernel/qtooltip.h b/src/widgets/kernel/qtooltip.h index edf1de0c1d..1b263a6629 100644 --- a/src/widgets/kernel/qtooltip.h +++ b/src/widgets/kernel/qtooltip.h @@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE class Q_WIDGETS_EXPORT QToolTip { - QToolTip() Q_DECL_EQ_DELETE; + QToolTip() = delete; public: // ### Qt 6 - merge the three showText functions below static void showText(const QPoint &pos, const QString &text, QWidget *w = nullptr); diff --git a/src/widgets/kernel/qwhatsthis.cpp b/src/widgets/kernel/qwhatsthis.cpp index 4a798a7490..228ca4d38a 100644 --- a/src/widgets/kernel/qwhatsthis.cpp +++ b/src/widgets/kernel/qwhatsthis.cpp @@ -263,7 +263,7 @@ void QWhatsThat::mouseReleaseEvent(QMouseEvent* e) anchor.clear(); if (!href.isEmpty()) { QWhatsThisClickedEvent e(href); - if (QApplication::sendEvent(widget, &e)) + if (QCoreApplication::sendEvent(widget, &e)) return; } } @@ -380,7 +380,7 @@ void QWhatsThisPrivate::notifyToplevels(QEvent *e) { const QWidgetList toplevels = QApplication::topLevelWidgets(); for (auto *w : toplevels) - QApplication::sendEvent(w, e); + QCoreApplication::sendEvent(w, e); } QWhatsThisPrivate *QWhatsThisPrivate::instance = 0; @@ -394,7 +394,7 @@ QWhatsThisPrivate::QWhatsThisPrivate() QPoint pos = QCursor::pos(); if (QWidget *w = QApplication::widgetAt(pos)) { QHelpEvent e(QEvent::QueryWhatsThis, w->mapFromGlobal(pos), pos); - bool sentEvent = QApplication::sendEvent(w, &e); + const bool sentEvent = QCoreApplication::sendEvent(w, &e); #ifdef QT_NO_CURSOR Q_UNUSED(sentEvent); #else @@ -439,7 +439,7 @@ bool QWhatsThisPrivate::eventFilter(QObject *o, QEvent *e) if (me->button() == Qt::RightButton || customWhatsThis) return false; QHelpEvent e(QEvent::WhatsThis, me->pos(), me->globalPos()); - if (!QApplication::sendEvent(w, &e) || !e.isAccepted()) + if (!QCoreApplication::sendEvent(w, &e) || !e.isAccepted()) leaveOnMouseRelease = true; } break; @@ -448,12 +448,12 @@ bool QWhatsThisPrivate::eventFilter(QObject *o, QEvent *e) { QMouseEvent *me = static_cast<QMouseEvent*>(e); QHelpEvent e(QEvent::QueryWhatsThis, me->pos(), me->globalPos()); - bool sentEvent = QApplication::sendEvent(w, &e); + const bool sentEvent = QCoreApplication::sendEvent(w, &e); #ifdef QT_NO_CURSOR Q_UNUSED(sentEvent); #else - QApplication::changeOverrideCursor((!sentEvent || !e.isAccepted())? - Qt::ForbiddenCursor:Qt::WhatsThisCursor); + QGuiApplication::changeOverrideCursor((!sentEvent || !e.isAccepted())? + Qt::ForbiddenCursor:Qt::WhatsThisCursor); #endif Q_FALLTHROUGH(); } @@ -577,26 +577,12 @@ void QWhatsThisPrivate::say(QWidget * widget, const QString &text, int x, int y) if (text.size() == 0) return; // make a fresh widget, and set it up - QWhatsThat *whatsThat = new QWhatsThat( - text, -#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ && !defined(QT_NO_CURSOR) - QApplication::desktop()->screen(widget ? widget->x11Info().screen() : QCursor::x11Screen()), -#else - 0, -#endif - widget - ); - + QWhatsThat *whatsThat = new QWhatsThat(text, 0, widget); // okay, now to find a suitable location - int scr = (widget ? QDesktopWidgetPrivate::screenNumber(widget) : -#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ && !defined(QT_NO_CURSOR) - QCursor::x11Screen() -#else QDesktopWidgetPrivate::screenNumber(QPoint(x,y)) -#endif ); QRect screen = QDesktopWidgetPrivate::screenGeometry(scr); diff --git a/src/widgets/kernel/qwhatsthis.h b/src/widgets/kernel/qwhatsthis.h index 59c0b01c9b..fa5b97d98a 100644 --- a/src/widgets/kernel/qwhatsthis.h +++ b/src/widgets/kernel/qwhatsthis.h @@ -54,7 +54,7 @@ class QAction; class Q_WIDGETS_EXPORT QWhatsThis { - QWhatsThis() Q_DECL_EQ_DELETE; + QWhatsThis() = delete; public: static void enterWhatsThisMode(); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 0fa5907744..74aebd1223 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -61,13 +61,6 @@ #ifndef QT_NO_ACCESSIBILITY # include "qaccessible.h" #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# include "qt_mac_p.h" -# include "qt_cocoa_helpers_mac_p.h" -# include "qmainwindow.h" -# include "qtoolbar.h" -# include <private/qmainwindowlayout_p.h> -#endif #include <qpa/qplatformwindow.h> #include "private/qwidgetwindow_p.h" #include "qpainter.h" @@ -79,6 +72,7 @@ #include "private/qstylesheetstyle_p.h" #include "private/qstyle_p.h" #include "qfileinfo.h" +#include "qscopeguard.h" #include <QtGui/private/qhighdpiscaling_p.h> #include <QtGui/qinputmethod.h> #include <QtGui/qopenglcontext.h> @@ -89,10 +83,7 @@ #include <private/qgraphicseffect_p.h> #endif #include <qbackingstore.h> -#include <private/qwidgetbackingstore_p.h> -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# include <private/qpaintengine_mac_p.h> -#endif +#include <private/qwidgetrepaintmanager_p.h> #include <private/qpaintengine_raster_p.h> #include "qwidget_p.h" @@ -120,15 +111,15 @@ #include <QtPlatformHeaders/qxcbwindowfunctions.h> +#include <private/qmemory_p.h> + // widget/widget data creation count //#define QWIDGET_EXTRA_DEBUG //#define ALIEN_DEBUG QT_BEGIN_NAMESPACE -#if 0 // Used to be included in Qt4 for Q_WS_MAC -bool qt_mac_clearDirtyOnWidgetInsideDrawWidget = false; -#endif +Q_LOGGING_CATEGORY(lcWidgetPainting, "qt.widgets.painting", QtWarningMsg); static inline bool qRectIntersects(const QRect &r1, const QRect &r2) { @@ -136,101 +127,11 @@ static inline bool qRectIntersects(const QRect &r1, const QRect &r2) qMax(r1.top(), r2.top()) <= qMin(r1.bottom(), r2.bottom())); } -#if 0 // Used to be included in Qt4 for Q_WS_MAC -# define QT_NO_PAINT_DEBUG -#endif - extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp -/*! - \internal - \class QWidgetBackingStoreTracker - \brief Class which allows tracking of which widgets are using a given backing store - - QWidgetBackingStoreTracker is a thin wrapper around a QWidgetBackingStore pointer, - which maintains a list of the QWidgets which are currently using the backing - store. This list is modified via the registerWidget and unregisterWidget functions. - */ - -QWidgetBackingStoreTracker::QWidgetBackingStoreTracker() - : m_ptr(0) -{ - -} - -QWidgetBackingStoreTracker::~QWidgetBackingStoreTracker() -{ - delete m_ptr; -} - -/*! - \internal - Destroy the contained QWidgetBackingStore, if not null, and clear the list of - widgets using the backing store, then create a new QWidgetBackingStore, providing - the QWidget. - */ -void QWidgetBackingStoreTracker::create(QWidget *widget) -{ - destroy(); - m_ptr = new QWidgetBackingStore(widget); -} - -/*! - \internal - Destroy the contained QWidgetBackingStore, if not null, and clear the list of - widgets using the backing store. - */ -void QWidgetBackingStoreTracker::destroy() -{ - delete m_ptr; - m_ptr = 0; - m_widgets.clear(); -} - -/*! - \internal - Add the widget to the list of widgets currently using the backing store. - If the widget was already in the list, this function is a no-op. - */ -void QWidgetBackingStoreTracker::registerWidget(QWidget *w) -{ - Q_ASSERT(m_ptr); - Q_ASSERT(w->internalWinId()); - Q_ASSERT(qt_widget_private(w)->maybeBackingStore() == m_ptr); - m_widgets.insert(w); -} - -/*! - \internal - Remove the widget from the list of widgets currently using the backing store. - If the widget was in the list, and removing it causes the list to be empty, - the backing store is deleted. - If the widget was not in the list, this function is a no-op. - */ -void QWidgetBackingStoreTracker::unregisterWidget(QWidget *w) -{ - if (m_widgets.remove(w) && m_widgets.isEmpty()) { - delete m_ptr; - m_ptr = 0; - } -} - -/*! - \internal - Recursively remove widget and all of its descendents. - */ -void QWidgetBackingStoreTracker::unregisterWidgetSubtree(QWidget *widget) -{ - unregisterWidget(widget); - foreach (QObject *child, widget->children()) - if (QWidget *childWidget = qobject_cast<QWidget *>(child)) - unregisterWidgetSubtree(childWidget); -} - QWidgetPrivate::QWidgetPrivate(int version) : QObjectPrivate(version) - , extra(0) , focus_next(0) , focus_prev(0) , focus_child(0) @@ -284,17 +185,6 @@ QWidgetPrivate::QWidgetPrivate(int version) #if defined(Q_OS_WIN) , noPaintOnScreen(0) #endif -#if 0 // Used to be included in Qt4 for Q_WS_X11 - , picture(0) -#elif 0 // Used to be included in Qt4 for Q_WS_WIN - #ifndef QT_NO_GESTURES - , nativeGesturePanEnabled(0) - #endif -#elif 0 // Used to be included in Qt4 for Q_WS_MAC - , needWindowChange(0) - , window_event(0) - , qd_hd(0) -#endif { if (Q_UNLIKELY(!qApp)) { qFatal("QWidget: Must construct a QApplication before a QWidget"); @@ -313,16 +203,7 @@ QWidgetPrivate::QWidgetPrivate(int version) isWidget = true; memset(high_attributes, 0, sizeof(high_attributes)); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - drawRectOriginalAdded = false; - originalDrawMethod = true; - changeMethods = false; - isInUnifiedToolbar = false; - unifiedSurface = 0; - toolbar_ancestor = 0; - flushRequested = false; - touchEventsEnabled = false; -#endif + #ifdef QWIDGET_EXTRA_DEBUG static int count = 0; qDebug() << "widgets" << ++count; @@ -358,7 +239,7 @@ void QWidgetPrivate::scrollChildren(int dx, int dy) w->d_func()->setWSGeometry(); w->d_func()->setDirtyOpaqueRegion(); QMoveEvent e(r.topLeft(), oldp); - QApplication::sendEvent(w, &e); + QCoreApplication::sendEvent(w, &e); } } } @@ -392,7 +273,7 @@ QPointer<QWidget> QWidgetPrivate::editingWidget; This feature is only available in Qt for Embedded Linux. - \sa setEditFocus(), QApplication::keypadNavigationEnabled() + \sa setEditFocus(), QApplication::navigationMode() */ bool QWidget::hasEditFocus() const { @@ -412,7 +293,7 @@ bool QWidget::hasEditFocus() const This feature is only available in Qt for Embedded Linux. - \sa hasEditFocus(), QApplication::keypadNavigationEnabled() + \sa hasEditFocus(), QApplication::navigationMode() */ void QWidget::setEditFocus(bool on) { @@ -434,13 +315,13 @@ void QWidget::setEditFocus(bool on) if (!on && QWidgetPrivate::editingWidget == f) { QWidgetPrivate::editingWidget = 0; QEvent event(QEvent::LeaveEditFocus); - QApplication::sendEvent(f, &event); - QApplication::sendEvent(f->style(), &event); + QCoreApplication::sendEvent(f, &event); + QCoreApplication::sendEvent(f->style(), &event); } else if (on) { QWidgetPrivate::editingWidget = f; QEvent event(QEvent::EnterEditFocus); - QApplication::sendEvent(f, &event); - QApplication::sendEvent(f->style(), &event); + QCoreApplication::sendEvent(f, &event); + QCoreApplication::sendEvent(f->style(), &event); } } #endif @@ -943,22 +824,6 @@ QWidgetSet *QWidgetPrivate::allWidgets = 0; // widgets with no wid /***************************************************************************** - QWidget utility functions - *****************************************************************************/ - -QRegion qt_dirtyRegion(QWidget *widget) -{ - if (!widget) - return QRegion(); - - QWidgetBackingStore *bs = qt_widget_private(widget)->maybeBackingStore(); - if (!bs) - return QRegion(); - - return bs->dirtyRegion(widget); -} - -/***************************************************************************** QWidget member functions *****************************************************************************/ @@ -1083,17 +948,12 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w) // Only enable this on non-Mac platforms. Since the old way of doing this would // interpret WindowSystemMenuHint as a close button and we can't change that behavior // we can't just add this in. -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC if ((flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint)) # ifdef Q_OS_WIN && type != Qt::Dialog // QTBUG-2027, allow for menu-less dialogs. # endif ) { flags |= Qt::WindowSystemMenuHint; -#else - if (flags & (Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint - | Qt::WindowSystemMenuHint)) { -#endif flags |= Qt::WindowTitleHint; flags &= ~Qt::FramelessWindowHint; } @@ -1123,6 +983,8 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w) void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) { Q_Q(QWidget); + Q_ASSERT_X(q != parentWidget, Q_FUNC_INFO, "Cannot parent a QWidget to itself"); + if (Q_UNLIKELY(!qobject_cast<QApplication *>(QCoreApplication::instance()))) qFatal("QWidget: Cannot create a QWidget without QApplication"); @@ -1146,13 +1008,6 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) } #endif -#if 0 // Used to be included in Qt4 for Q_WS_X11 - if (desktopWidget) { - // make sure the widget is created on the same screen as the - // programmer specified desktop widget - xinfo = desktopWidget->d_func()->xinfo; - } -#endif if (targetScreen >= 0) { topData()->initialScreenIndex = targetScreen; if (QWindow *window = q->windowHandle()) @@ -1180,9 +1035,6 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) mustHaveWindowHandle = 1; q->setAttribute(Qt::WA_NativeWindow); } -//#if 0 // Used to be included in Qt4 for Q_WS_MAC -// q->setAttribute(Qt::WA_NativeWindow); -//#endif q->setAttribute(Qt::WA_QuitOnClose); // might be cleared in adjustQuitOnCloseAttribute() adjustQuitOnCloseAttribute(); @@ -1206,9 +1058,6 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) setOpaque(q->isWindow() && background.style() != Qt::NoBrush && background.isOpaque()); } data.fnt = QFont(data.fnt, q); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - data.fnt.x11SetScreen(xinfo.screen()); -#endif q->setAttribute(Qt::WA_PendingMoveEvent); q->setAttribute(Qt::WA_PendingResizeEvent); @@ -1220,24 +1069,12 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) q->create(); QEvent e(QEvent::Create); - QApplication::sendEvent(q, &e); - QApplication::postEvent(q, new QEvent(QEvent::PolishRequest)); + QCoreApplication::sendEvent(q, &e); + QCoreApplication::postEvent(q, new QEvent(QEvent::PolishRequest)); extraPaintEngine = 0; - -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // If we add a child to the unified toolbar, we have to redirect the painting. - if (parentWidget && parentWidget->d_func() && parentWidget->d_func()->isInUnifiedToolbar) { - if (parentWidget->d_func()->unifiedSurface) { - QWidget *toolbar = parentWidget->d_func()->toolbar_ancestor; - parentWidget->d_func()->unifiedSurface->recursiveRedirect(toolbar, toolbar, toolbar->d_func()->toolbar_offset); - } - } -#endif } - - void QWidgetPrivate::createRecursively() { Q_Q(QWidget); @@ -1249,6 +1086,35 @@ void QWidgetPrivate::createRecursively() } } +QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const +{ + if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) { + if (QTLWExtra *x = maybeTopData()) { + if (x->window != nullptr || mode == WindowHandleMode::Direct) + return x->window; + } + } + if (mode == WindowHandleMode::Closest) { + if (auto nativeParent = q_func()->nativeParentWidget()) { + if (auto window = nativeParent->windowHandle()) + return window; + } + } + if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) { + if (auto topLevel = q_func()->topLevelWidget()) { + if (auto window = topLevel ->windowHandle()) + return window; + } + } + return nullptr; +} + +QScreen *QWidgetPrivate::associatedScreen() const +{ + if (auto window = windowHandle(WindowHandleMode::Closest)) + return window->screen(); + return nullptr; +} // ### fixme: Qt 6: Remove parameter window from QWidget::create() @@ -1315,36 +1181,20 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) << "Alien?" << !testAttribute(Qt::WA_NativeWindow); #endif -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ && QT_CONFIG(draganddrop) - // Unregister the dropsite (if already registered) before we - // re-create the widget with a native window. - if (testAttribute(Qt::WA_WState_Created) && !internalWinId() && testAttribute(Qt::WA_NativeWindow) - && d->extra && d->extra->dropTarget) { - d->registerDropSite(false); - } -#endif - d->updateIsOpaque(); setAttribute(Qt::WA_WState_Created); // set created flag d->create(); - // a real toplevel window needs a backing store - if (isWindow() && windowType() != Qt::Desktop) { - d->topData()->backingStoreTracker.destroy(); - d->topData()->backingStoreTracker.create(this); - } + // A real toplevel window needs a paint manager + if (isWindow() && windowType() != Qt::Desktop) + d->topData()->repaintManager.reset(new QWidgetRepaintManager(this)); d->setModal_sys(); if (!isWindow() && parentWidget() && parentWidget()->testAttribute(Qt::WA_DropSiteRegistered)) setAttribute(Qt::WA_DropSiteRegistered, true); -#ifdef QT_EVAL - extern void qt_eval_init_widget(QWidget *w); - qt_eval_init_widget(this); -#endif - // need to force the resting of the icon after changing parents if (testAttribute(Qt::WA_SetWindowIcon)) d->setWindowIcon_sys(); @@ -1587,7 +1437,7 @@ QWidget::~QWidget() // Remove all shortcuts grabbed by this // widget, unless application is closing if (!QApplicationPrivate::is_app_closing && testAttribute(Qt::WA_GrabbedShortcut)) - qApp->d_func()->shortcutMap.removeShortcut(0, this, QKeySequence()); + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(0, this, QKeySequence()); #endif // delete layout while we still are a valid widget @@ -1611,7 +1461,7 @@ QWidget::~QWidget() while (w->d_func()->extra && w->d_func()->extra->focus_proxy) w = w->d_func()->extra->focus_proxy; QWidget *window = w->window(); - QWExtra *e = window ? window->d_func()->extra : 0; + QWExtra *e = window ? window->d_func()->extra.get() : nullptr ; if (!e || !e->proxyWidget || (w->parentWidget() && w->parentWidget()->d_func()->focus_child == this)) #endif clearFocus(); @@ -1632,21 +1482,14 @@ QWidget::~QWidget() // and if that also doesn't work, then give up } } - } - -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_X11 */|| 0 /* Used to be included in Qt4 for Q_WS_MAC */ - else if (!internalWinId() && isVisible()) { - qApp->d_func()->sendSyntheticEnterLeave(this); - } -#endif - else if (isVisible()) { + } else if (isVisible()) { qApp->d_func()->sendSyntheticEnterLeave(this); } - if (QWidgetBackingStore *bs = d->maybeBackingStore()) { - bs->removeDirtyWidget(this); + if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) { + repaintManager->removeDirtyWidget(this); if (testAttribute(Qt::WA_StaticContents)) - bs->removeStaticWidget(this); + repaintManager->removeStaticWidget(this); } delete d->needsFlush; @@ -1683,19 +1526,10 @@ QWidget::~QWidget() d->blockSig = blocked; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // QCocoaView holds a pointer back to this widget. Clear it now - // to make sure it's not followed later on. The lifetime of the - // QCocoaView might exceed the lifetime of this widget in cases - // where Cocoa itself holds references to it. - extern void qt_mac_clearCocoaViewQWidgetPointers(QWidget *); - qt_mac_clearCocoaViewQWidgetPointers(this); -#endif - if (!d->children.isEmpty()) d->deleteChildren(); - QApplication::removePostedEvents(this); + QCoreApplication::removePostedEvents(this); QT_TRY { destroy(); // platform-dependent cleanup @@ -1738,9 +1572,6 @@ void QWidgetPrivate::setWinId(WId id) // set widget identifier const WId oldWinId = data.winid; data.winid = id; -#if 0 // Used to be included in Qt4 for Q_WS_X11 - hd = id; // X11: hd == ident -#endif if (mapper && id && !userDesktopWidget) { mapper->insert(data.winid, q); } @@ -1756,8 +1587,8 @@ void QWidgetPrivate::createTLExtra() if (!extra) createExtra(); if (!extra->topextra) { - QTLWExtra* x = extra->topextra = new QTLWExtra; - x->icon = 0; + extra->topextra = qt_make_unique<QTLWExtra>(); + QTLWExtra* x = extra->topextra.get(); x->backingStore = 0; x->sharedPainter = 0; x->incw = x->inch = 0; @@ -1771,11 +1602,8 @@ void QWidgetPrivate::createTLExtra() x->inTopLevelResize = false; x->embedded = 0; x->window = 0; - x->shareContext = 0; x->initialScreenIndex = -1; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - x->wasMaximized = false; -#endif + #ifdef QWIDGET_EXTRA_DEBUG static int count = 0; qDebug() << "tlextra" << ++count; @@ -1791,15 +1619,11 @@ void QWidgetPrivate::createTLExtra() void QWidgetPrivate::createExtra() { if (!extra) { // if not exists - extra = new QWExtra; + extra = qt_make_unique<QWExtra>(); extra->glContext = 0; - extra->topextra = 0; #if QT_CONFIG(graphicsview) extra->proxyWidget = 0; #endif -#ifndef QT_NO_CURSOR - extra->curs = 0; -#endif extra->minw = 0; extra->minh = 0; extra->maxw = QWIDGETSIZE_MAX; @@ -1833,9 +1657,6 @@ void QWidgetPrivate::createSysExtra() void QWidgetPrivate::deleteExtra() { if (extra) { // if exists -#ifndef QT_NO_CURSOR - delete extra->curs; -#endif deleteSysExtra(); #ifndef QT_NO_STYLE_STYLESHEET // dereference the stylesheet style @@ -1845,12 +1666,9 @@ void QWidgetPrivate::deleteExtra() if (extra->topextra) { deleteTLSysExtra(); // extra->topextra->backingStore destroyed in QWidgetPrivate::deleteTLSysExtra() - delete extra->topextra->icon; - delete extra->topextra; } - delete extra; // extra->xic destroyed in QWidget::destroy() - extra = 0; + extra.reset(); } } @@ -1872,13 +1690,11 @@ void QWidgetPrivate::deleteTLSysExtra() //the qplatformbackingstore may hold a reference to the window, so the backingstore //needs to be deleted first. - extra->topextra->backingStoreTracker.destroy(); + extra->topextra->repaintManager.reset(nullptr); deleteBackingStore(this); #ifndef QT_NO_OPENGL - qDeleteAll(extra->topextra->widgetTextures); extra->topextra->widgetTextures.clear(); - delete extra->topextra->shareContext; - extra->topextra->shareContext = 0; + extra->topextra->shareContext.reset(); #endif //the toplevel might have a context with a "qglcontext associated with it. We need to @@ -1923,7 +1739,7 @@ QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst const QRect siblingRect = sibling->d_func()->effectiveRectFor(sibling->data->crect); if (qRectIntersects(siblingRect, r)) { - const QWExtra *siblingExtra = sibling->d_func()->extra; + const auto &siblingExtra = sibling->d_func()->extra; if (siblingExtra && siblingExtra->hasMask && !sibling->d_func()->graphicsEffect && !siblingExtra->mask.translated(sibling->data->crect.topLeft()).intersects(r)) { continue; @@ -1942,23 +1758,59 @@ QRegion QWidgetPrivate::overlappedRegion(const QRect &rect, bool breakAfterFirst void QWidgetPrivate::syncBackingStore() { - if (paintOnScreen()) { - repaint_sys(dirty); + if (shouldPaintOnScreen()) { + paintOnScreen(dirty); dirty = QRegion(); - } else if (QWidgetBackingStore *bs = maybeBackingStore()) { - bs->sync(); + } else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) { + repaintManager->sync(); } } void QWidgetPrivate::syncBackingStore(const QRegion ®ion) { - if (paintOnScreen()) - repaint_sys(region); - else if (QWidgetBackingStore *bs = maybeBackingStore()) { - bs->sync(q_func(), region); + if (shouldPaintOnScreen()) + paintOnScreen(region); + else if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) { + repaintManager->sync(q_func(), region); } } +void QWidgetPrivate::paintOnScreen(const QRegion &rgn) +{ + if (data.in_destructor) + return; + + if (shouldDiscardSyncRequest()) + return; + + Q_Q(QWidget); + if (q->testAttribute(Qt::WA_StaticContents)) { + if (!extra) + createExtra(); + extra->staticContentsSize = data.crect.size(); + } + + QPaintEngine *engine = q->paintEngine(); + + // QGLWidget does not support partial updates if: + // 1) The context is double buffered + // 2) The context is single buffered and auto-fill background is enabled. + const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL + || engine->type() == QPaintEngine::OpenGL2)) + && (usesDoubleBufferedGLContext || q->autoFillBackground()); + QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn); + + toBePainted &= clipRect(); + clipToEffectiveMask(toBePainted); + if (toBePainted.isEmpty()) + return; // Nothing to repaint. + + drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, 0); + + if (Q_UNLIKELY(q->paintingActive())) + qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent"); +} + void QWidgetPrivate::setUpdatesEnabled_helper(bool enable) { Q_Q(QWidget); @@ -2007,7 +1859,7 @@ void QWidgetPrivate::propagatePaletteChange() QCoreApplication::testAttribute(Qt::AA_UseStyleSheetPropagationInWidgetStyles); QEvent pc(QEvent::PaletteChange); - QApplication::sendEvent(q, &pc); + QCoreApplication::sendEvent(q, &pc); for (int i = 0; i < children.size(); ++i) { QWidget *w = qobject_cast<QWidget*>(children.at(i)); if (w && (!w->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) @@ -2183,11 +2035,6 @@ void QWidgetPrivate::subtractOpaqueSiblings(QRegion &sourceRegion, bool *hasDirt if (disableSubtractOpaqueSiblings || q->isWindow()) return; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (q->d_func()->isInUnifiedToolbar) - return; -#endif - QRect clipBoundingRect; bool dirtyClipBoundingRect = true; @@ -2291,7 +2138,7 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion ®ion) const } } -bool QWidgetPrivate::paintOnScreen() const +bool QWidgetPrivate::shouldPaintOnScreen() const { #if defined(QT_NO_BACKINGSTORE) return true; @@ -2320,13 +2167,6 @@ void QWidgetPrivate::updateIsOpaque() #endif // QT_CONFIG(graphicseffect) Q_Q(QWidget); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - if (q->testAttribute(Qt::WA_X11OpenGLOverlay)) { - setOpaque(false); - return; - } -#endif - if (q->testAttribute(Qt::WA_OpaquePaintEvent) || q->testAttribute(Qt::WA_PaintOnScreen)) { setOpaque(true); return; @@ -2379,20 +2219,9 @@ static inline void fillRegion(QPainter *painter, const QRegion &rgn, const QBrus Q_ASSERT(painter); if (brush.style() == Qt::TexturePattern) { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // Optimize pattern filling on mac by using HITheme directly - // when filling with the standard widget background. - // Defined in qmacstyle_mac.cpp - extern void qt_mac_fill_background(QPainter *painter, const QRegion &rgn, const QBrush &brush); - qt_mac_fill_background(painter, rgn, brush); -#else - { - const QRect rect(rgn.boundingRect()); - painter->setClipRegion(rgn); - painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); - } -#endif - + const QRect rect(rgn.boundingRect()); + painter->setClipRegion(rgn); + painter->drawTiledPixmap(rect, brush.texture(), rect.topLeft()); } else if (brush.gradient() && (brush.gradient()->coordinateMode() == QGradient::ObjectBoundingMode || brush.gradient()->coordinateMode() == QGradient::ObjectMode)) { @@ -2423,7 +2252,7 @@ bool QWidgetPrivate::updateBrushOrigin(QPainter *painter, const QBrush &brush) c return true; } -void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int flags) const +void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, DrawWidgetFlags flags) const { Q_Q(const QWidget); @@ -2466,11 +2295,7 @@ void QWidgetPrivate::paintBackground(QPainter *painter, const QRegion &rgn, int visible widgets. */ -#if 0 // Used to be included in Qt4 for Q_WS_MAC - extern QPointer<QWidget> qt_button_down; -#else - extern QWidget *qt_button_down; -#endif +extern QWidget *qt_button_down; void QWidgetPrivate::deactivateWidgetCleanup() { @@ -2656,7 +2481,7 @@ WId QWidget::effectiveWinId() const \since 5.0 - \sa winId() + \sa winId(), screen() */ QWindow *QWidget::windowHandle() const { @@ -2664,6 +2489,29 @@ QWindow *QWidget::windowHandle() const return d->windowHandle(); } +/*! + Returns the screen the widget is on. + + \since 5.14 + + \sa windowHandle() +*/ +QScreen *QWidget::screen() const +{ + Q_D(const QWidget); + if (auto associatedScreen = d->associatedScreen()) + return associatedScreen; + if (auto topLevel = window()) { + if (auto topData = qt_widget_private(topLevel)->topData()) { + if (auto initialScreen = QGuiApplicationPrivate::screen_list.value(topData->initialScreenIndex)) + return initialScreen; + } + if (auto screenByPos = QGuiApplication::screenAt(topLevel->geometry().center())) + return screenByPos; + } + return QGuiApplication::primaryScreen(); +} + #ifndef QT_NO_STYLE_STYLESHEET /*! @@ -2811,7 +2659,7 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate) #endif QEvent e(QEvent::StyleChange); - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); #ifndef QT_NO_STYLE_STYLESHEET // dereference the old stylesheet style @@ -3029,7 +2877,7 @@ void QWidget::overrideWindowState(Qt::WindowStates newstate) { QWindowStateChangeEvent e(Qt::WindowStates(data->window_state), true); data->window_state = newstate; - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); } /*! @@ -3066,6 +2914,8 @@ void QWidget::setWindowState(Qt::WindowStates newstate) { Q_D(QWidget); Qt::WindowStates oldstate = windowState(); + if (newstate.testFlag(Qt::WindowMinimized)) // QTBUG-46763 + newstate.setFlag(Qt::WindowActive, false); if (oldstate == newstate) return; if (isWindow() && !testAttribute(Qt::WA_WState_Created)) @@ -3091,7 +2941,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate) activateWindow(); QWindowStateChangeEvent e(oldstate); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); } /*! @@ -3139,15 +2989,6 @@ bool QWidget::isFullScreen() const */ void QWidget::showFullScreen() { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // If the unified toolbar is enabled, we have to disable it before going fullscreen. - QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this); - if (mainWindow && mainWindow->unifiedTitleAndToolBarOnMac()) { - mainWindow->setUnifiedTitleAndToolBarOnMac(false); - QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout()); - mainLayout->activateUnifiedToolbarAfterFullScreen = true; - } -#endif ensurePolished(); setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized)) @@ -3175,18 +3016,6 @@ void QWidget::showMaximized() setWindowState((windowState() & ~(Qt::WindowMinimized | Qt::WindowFullScreen)) | Qt::WindowMaximized); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // If the unified toolbar was enabled before going fullscreen, we have to enable it back. - QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this); - if (mainWindow) - { - QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout()); - if (mainLayout->activateUnifiedToolbarAfterFullScreen) { - mainWindow->setUnifiedTitleAndToolBarOnMac(true); - mainLayout->activateUnifiedToolbarAfterFullScreen = false; - } - } -#endif setVisible(true); } @@ -3204,18 +3033,6 @@ void QWidget::showNormal() setWindowState(windowState() & ~(Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // If the unified toolbar was enabled before going fullscreen, we have to enable it back. - QMainWindow *mainWindow = qobject_cast<QMainWindow*>(this); - if (mainWindow) - { - QMainWindowLayout *mainLayout = qobject_cast<QMainWindowLayout*>(mainWindow->layout()); - if (mainLayout->activateUnifiedToolbarAfterFullScreen) { - mainWindow->setUnifiedTitleAndToolBarOnMac(true); - mainLayout->activateUnifiedToolbarAfterFullScreen = false; - } - } -#endif setVisible(true); } @@ -3317,7 +3134,7 @@ void QWidget::insertAction(QAction *before, QAction *action) apriv->widgets.append(this); QActionEvent e(QEvent::ActionAdded, action, before); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); } /*! @@ -3355,7 +3172,7 @@ void QWidget::removeAction(QAction *action) if (d->actions.removeAll(action)) { QActionEvent e(QEvent::ActionRemoved, action); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); } } @@ -3431,13 +3248,6 @@ void QWidgetPrivate::setEnabled_helper(bool enable) if (w && !w->testAttribute(attribute)) w->d_func()->setEnabled_helper(enable); } -#if 0 // Used to be included in Qt4 for Q_WS_X11 - if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) { - // enforce the windows behavior of clearing the cursor on - // disabled widgets - qt_x11_enforce_cursor(q); - } -#endif #ifndef QT_NO_CURSOR if (q->testAttribute(Qt::WA_SetCursor) || q->isWindow()) { // enforce the windows behavior of clearing the cursor on @@ -3445,9 +3255,6 @@ void QWidgetPrivate::setEnabled_helper(bool enable) qt_qpa_set_cursor(q, false); } #endif -#if 0 // Used to be included in Qt4 for Q_WS_MAC - setEnabled_helper_sys(enable); -#endif #ifndef QT_NO_IM if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) { QWidget *focusWidget = effectiveFocusWidget(); @@ -3462,7 +3269,7 @@ void QWidgetPrivate::setEnabled_helper(bool enable) } #endif //QT_NO_IM QEvent e(QEvent::EnabledChange); - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); } /*! @@ -3928,7 +3735,7 @@ QSize QWidget::sizeIncrement() const QSize QWidget::baseSize() const { Q_D(const QWidget); - return (d->extra != 0 && d->extra->topextra != 0) + return (d->extra && d->extra->topextra) ? QSize(d->extra->topextra->basew, d->extra->topextra->baseh) : QSize(0, 0); } @@ -4529,7 +4336,7 @@ void QWidget::setForegroundRole(QPalette::ColorRole role) the "color", "background-color", "selection-color", "selection-background-color" and "alternate-background-color". - \sa QApplication::palette(), QWidget::font(), {Qt Style Sheets} + \sa QGuiApplication::palette(), QWidget::font(), {Qt Style Sheets} */ const QPalette &QWidget::palette() const { @@ -4542,13 +4349,7 @@ const QPalette &QWidget::palette() const ) { data->pal.setCurrentColorGroup(QPalette::Active); } else { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - extern bool qt_mac_can_clickThrough(const QWidget *); //qwidget_mac.cpp - if (qt_mac_can_clickThrough(this)) - data->pal.setCurrentColorGroup(QPalette::Active); - else -#endif - data->pal.setCurrentColorGroup(QPalette::Inactive); + data->pal.setCurrentColorGroup(QPalette::Inactive); } return data->pal; } @@ -4592,7 +4393,7 @@ QPalette QWidgetPrivate::naturalWidgetPalette(uint inheritedMask) const )) { if (QWidget *p = q->parentWidget()) { if (!p->testAttribute(Qt::WA_StyleSheet) || useStyleSheetPropagationInWidgetStyles) { - if (!naturalPalette.isCopyOf(QApplication::palette())) { + if (!naturalPalette.isCopyOf(QGuiApplication::palette())) { QPalette inheritedPalette = p->palette(); inheritedPalette.resolve(inheritedMask); naturalPalette = inheritedPalette.resolve(naturalPalette); @@ -4811,10 +4612,7 @@ void QWidgetPrivate::updateFont(const QFont &font) #endif data.fnt = QFont(font, q); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - // make sure the font set on this widget is associated with the correct screen - data.fnt.x11SetScreen(xinfo.screen()); -#endif + // Combine new mask with natural mask and propagate to children. #if QT_CONFIG(graphicsview) if (!q->parentWidget() && extra && extra->proxyWidget) { @@ -4858,7 +4656,7 @@ void QWidgetPrivate::updateFont(const QFont &font) #endif QEvent e(QEvent::FontChange); - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); } void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction) @@ -4876,14 +4674,14 @@ void QWidgetPrivate::setLayoutDirection_helper(Qt::LayoutDirection direction) } } QEvent e(QEvent::LayoutDirectionChange); - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); } void QWidgetPrivate::resolveLayoutDirection() { Q_Q(const QWidget); if (!q->testAttribute(Qt::WA_SetLayoutDirection)) - setLayoutDirection_helper(q->isWindow() ? QApplication::layoutDirection() : q->parentWidget()->layoutDirection()); + setLayoutDirection_helper(q->isWindow() ? QGuiApplication::layoutDirection() : q->parentWidget()->layoutDirection()); } /*! @@ -4988,22 +4786,17 @@ QCursor QWidget::cursor() const void QWidget::setCursor(const QCursor &cursor) { Q_D(QWidget); -// On Mac we must set the cursor even if it is the ArrowCursor. -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC if (cursor.shape() != Qt::ArrowCursor || (d->extra && d->extra->curs)) -#endif { d->createExtra(); - QCursor *newCursor = new QCursor(cursor); - delete d->extra->curs; - d->extra->curs = newCursor; + d->extra->curs = qt_make_unique<QCursor>(cursor); } setAttribute(Qt::WA_SetCursor); d->setCursor_sys(cursor); QEvent event(QEvent::CursorChange); - QApplication::sendEvent(this, &event); + QCoreApplication::sendEvent(this, &event); } void QWidgetPrivate::setCursor_sys(const QCursor &cursor) @@ -5016,16 +4809,14 @@ void QWidgetPrivate::setCursor_sys(const QCursor &cursor) void QWidget::unsetCursor() { Q_D(QWidget); - if (d->extra) { - delete d->extra->curs; - d->extra->curs = 0; - } + if (d->extra) + d->extra->curs.reset(); if (!isWindow()) setAttribute(Qt::WA_SetCursor, false); d->unsetCursor_sys(); QEvent event(QEvent::CursorChange); - QApplication::sendEvent(this, &event); + QCoreApplication::sendEvent(this, &event); } void QWidgetPrivate::unsetCursor_sys() @@ -5223,7 +5014,7 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset, static void sendResizeEvents(QWidget *target) { QResizeEvent e(target->size(), QSize()); - QApplication::sendEvent(target, &e); + QCoreApplication::sendEvent(target, &e); const QObjectList children = target->children(); for (int i = 0; i < children.size(); ++i) { @@ -5423,11 +5214,9 @@ void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset Q_ASSERT(!toBePainted.isEmpty()); Q_Q(QWidget); -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC const QTransform originalTransform = painter->worldTransform(); const bool useDeviceCoordinates = originalTransform.isScaling(); if (!useDeviceCoordinates) { -#endif // Render via a pixmap. const QRect rect = toBePainted.boundingRect(); const QSize size = rect.size(); @@ -5450,7 +5239,6 @@ void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset if (restore) painter->setRenderHints(QPainter::SmoothPixmapTransform, false); -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC } else { // Render via a pixmap in device coordinates (to avoid pixmap scaling). QTransform transform = originalTransform; @@ -5481,26 +5269,29 @@ void QWidgetPrivate::render_helper(QPainter *painter, const QPoint &targetOffset painter->drawPixmap(deviceRect.topLeft(), pixmap); painter->setTransform(originalTransform); } -#endif } -void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags, - QPainter *sharedPainter, QWidgetBackingStore *backingStore) +void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags, + QPainter *sharedPainter, QWidgetRepaintManager *repaintManager) { if (rgn.isEmpty()) return; + Q_Q(QWidget); + + qCInfo(lcWidgetPainting) << "Drawing" << rgn << "of" << q << "at" << offset + << "into paint device" << pdev << "with" << flags; + const bool asRoot = flags & DrawAsRoot; - bool onScreen = paintOnScreen(); + bool onScreen = shouldPaintOnScreen(); - Q_Q(QWidget); #if QT_CONFIG(graphicseffect) if (graphicsEffect && graphicsEffect->isEnabled()) { QGraphicsEffectSource *source = graphicsEffect->d_func()->source; QWidgetEffectSourcePrivate *sourced = static_cast<QWidgetEffectSourcePrivate *> (source->d_func()); if (!sourced->context) { - QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore); + QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, repaintManager); sourced->context = &context; if (!sharedPainter) { setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), rgn.translated(offset)); @@ -5524,10 +5315,8 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP } sourced->context = 0; - // Native widgets need to be marked dirty on screen so painting will be done in correct context - // Same check as in the no effects case below. - if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow())) - backingStore->markDirtyOnScreen(rgn, q, offset); + if (repaintManager) + repaintManager->markNeedsFlush(q, rgn, offset); return; } @@ -5554,22 +5343,10 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP q->setAttribute(Qt::WA_WState_InPaintEvent); //clip away the new area -#ifndef QT_NO_PAINT_DEBUG - bool flushed = QWidgetBackingStore::flushPaint(q, toBePainted); -#endif QPaintEngine *paintEngine = pdev->paintEngine(); if (paintEngine) { setRedirected(pdev, -offset); -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // (Alien support) Special case for Mac when redirecting: If the paint device - // is of the Widget type we need to set WA_WState_InPaintEvent since painting - // outside the paint event is not supported on QWidgets. The attributeis - // restored further down. - if (pdev->devType() == QInternal::Widget) - static_cast<QWidget *>(pdev)->setAttribute(Qt::WA_WState_InPaintEvent); - -#endif if (sharedPainter) setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted); else @@ -5582,7 +5359,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP beginBackingStorePainting(); #endif QPainter p(q); - paintBackground(&p, toBePainted, (asRoot || onScreen) ? flags | DrawAsRoot : 0); + paintBackground(&p, toBePainted, (asRoot || onScreen) ? (flags | DrawAsRoot) : DrawWidgetFlags()); #ifndef QT_NO_OPENGL endBackingStorePainting(); #endif @@ -5617,11 +5394,11 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP // This widget renders into a texture which is composed later. We just need to // punch a hole in the backingstore, so the texture will be visible. beginBackingStorePainting(); - if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && backingStore) { + if (!q->testAttribute(Qt::WA_AlwaysStackOnTop) && repaintManager) { QPainter p(q); p.setCompositionMode(QPainter::CompositionMode_Source); p.fillRect(q->rect(), Qt::transparent); - } else if (!backingStore) { + } else if (!repaintManager) { // We are not drawing to a backingstore: fall back to QImage QImage img = grabFramebuffer(); // grabFramebuffer() always sets the format to RGB32 @@ -5645,16 +5422,11 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP sendPaintEvent(toBePainted); } - // Native widgets need to be marked dirty on screen so painting will be done in correct context - if (backingStore && !onScreen && !asRoot && (q->internalWinId() || (q->nativeParentWidget() && !q->nativeParentWidget()->isWindow()))) - backingStore->markDirtyOnScreen(toBePainted, q, offset); + if (repaintManager) + repaintManager->markNeedsFlush(q, toBePainted, offset); //restore if (paintEngine) { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (pdev->devType() == QInternal::Widget) - static_cast<QWidget *>(pdev)->setAttribute(Qt::WA_WState_InPaintEvent, false); -#endif restoreRedirected(); if (!sharedPainter) paintEngine->d_func()->systemRect = QRect(); @@ -5670,11 +5442,6 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP if (paintEngine && paintEngine->autoDestruct()) { delete paintEngine; } - -#ifndef QT_NO_PAINT_DEBUG - if (flushed) - QWidgetBackingStore::unflushPaint(q, toBePainted); -#endif } else if (q->isWindow()) { QPaintEngine *engine = pdev->paintEngine(); if (engine) { @@ -5693,8 +5460,8 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP } if (recursive && !children.isEmpty()) { - paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot - , sharedPainter, backingStore); + paintSiblingsRecursive(pdev, children, children.size() - 1, rgn, offset, flags & ~DrawAsRoot, + sharedPainter, repaintManager); } } @@ -5725,7 +5492,6 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset, if (paintRegion.isEmpty()) return; -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC QPainter *oldSharedPainter = inRenderWithPainter ? sharedPainter() : 0; // Use the target's shared painter if set (typically set when doing @@ -5738,7 +5504,6 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset, setSharedPainter(targetPainter); } } -#endif // Use the target's redirected device if set and adjust offset and paint // region accordingly. This is typically the case when people call render @@ -5765,7 +5530,7 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset, } // Set backingstore flags. - int flags = DrawPaintOnScreen | DrawInvisible; + DrawWidgetFlags flags = DrawPaintOnScreen | DrawInvisible; if (renderFlags & QWidget::DrawWindowBackground) flags |= DrawAsRoot; @@ -5785,8 +5550,8 @@ void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset, } void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& siblings, int index, const QRegion &rgn, - const QPoint &offset, int flags - , QPainter *sharedPainter, QWidgetBackingStore *backingStore) + const QPoint &offset, DrawWidgetFlags flags + , QPainter *sharedPainter, QWidgetRepaintManager *repaintManager) { QWidget *w = 0; QRect boundingRect; @@ -5821,8 +5586,8 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis QRegion wr(rgn); if (wd->isOpaque) wr -= hasMask ? wd->extra->mask.translated(widgetPos) : w->data->crect; - paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags - , sharedPainter, backingStore); + paintSiblingsRecursive(pdev, siblings, --index, wr, offset, flags, + sharedPainter, repaintManager); } if (w->updatesEnabled() @@ -5835,7 +5600,7 @@ void QWidgetPrivate::paintSiblingsRecursive(QPaintDevice *pdev, const QObjectLis wRegion.translate(-widgetPos); if (hasMask) wRegion &= wd->extra->mask; - wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, backingStore); + wd->drawWidget(pdev, wRegion, offset + widgetPos, flags, sharedPainter, repaintManager); } } @@ -5870,7 +5635,7 @@ void QWidgetEffectSourcePrivate::draw(QPainter *painter) toBePainted &= wd->extra->mask; wd->drawWidget(context->pdev, toBePainted, context->offset, context->flags, - context->sharedPainter, context->backingStore); + context->sharedPainter, context->repaintManager); } QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset, @@ -5932,7 +5697,7 @@ QPixmap QWidgetEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint * QGraphicsProxyWidget *QWidgetPrivate::nearestGraphicsProxyWidget(const QWidget *origin) { if (origin) { - QWExtra *extra = origin->d_func()->extra; + const auto &extra = origin->d_func()->extra; if (extra && extra->proxyWidget) return extra->proxyWidget; return nearestGraphicsProxyWidget(origin->parentWidget()); @@ -5977,7 +5742,7 @@ void QWidgetPrivate::setLocale_helper(const QLocale &loc, bool forceUpdate) } } QEvent e(QEvent::LocaleChange); - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); } void QWidget::setLocale(const QLocale &locale) @@ -6063,13 +5828,7 @@ QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widg { Q_ASSERT(widget); -#ifdef QT_EVAL - extern QString qt_eval_adapt_window_title(const QString &title); - QString cap = qt_eval_adapt_window_title(title); -#else QString cap = title; -#endif - if (cap.isEmpty()) return cap; @@ -6158,7 +5917,7 @@ void QWidget::setWindowIconText(const QString &iconText) d->setWindowIconText_helper(iconText); QEvent e(QEvent::IconTextChange); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); emit windowIconTextChanged(iconText); } @@ -6182,7 +5941,7 @@ void QWidget::setWindowTitle(const QString &title) d->setWindowTitle_helper(title); QEvent e(QEvent::WindowTitleChange); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); emit windowTitleChanged(title); } @@ -6220,11 +5979,11 @@ void QWidgetPrivate::setWindowIcon_helper() // QWidgetWindow to the top level QWidget ensures that the event reaches // the top level anyhow if (!q->windowHandle()) - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); for (int i = 0; i < children.size(); ++i) { QWidget *w = qobject_cast<QWidget *>(children.at(i)); if (w && !w->isWindow()) - QApplication::sendEvent(w, &e); + QCoreApplication::sendEvent(w, &e); } } @@ -6245,8 +6004,9 @@ void QWidget::setWindowIcon(const QIcon &icon) d->createTLExtra(); if (!d->extra->topextra->icon) - d->extra->topextra->icon = new QIcon(); - *d->extra->topextra->icon = icon; + d->extra->topextra->icon = qt_make_unique<QIcon>(icon); + else + *d->extra->topextra->icon = icon; d->setWindowIcon_sys(); d->setWindowIcon_helper(); @@ -6460,7 +6220,7 @@ void QWidget::setFocusProxy(QWidget * w) QWidget *QWidget::focusProxy() const { Q_D(const QWidget); - return d->extra ? (QWidget *)d->extra->focus_proxy : nullptr; + return d->extra ? d->extra->focus_proxy.data() : nullptr; } @@ -6483,7 +6243,7 @@ bool QWidget::hasFocus() const w = w->d_func()->extra->focus_proxy; #if QT_CONFIG(graphicsview) if (QWidget *window = w->window()) { - QWExtra *e = window->d_func()->extra; + const auto &e = window->d_func()->extra; if (e && e->proxyWidget && e->proxyWidget->hasFocus() && window->focusWidget() == w) return true; } @@ -6535,16 +6295,12 @@ void QWidget::setFocus(Qt::FocusReason reason) if (!f) f = this; - if (QApplication::focusWidget() == f -#if 0 // Used to be included in Qt4 for Q_WS_WIN - && GetFocus() == f->internalWinId() -#endif - ) + if (QApplication::focusWidget() == f) return; #if QT_CONFIG(graphicsview) QWidget *previousProxyFocus = 0; - if (QWExtra *topData = window()->d_func()->extra) { + if (const auto &topData = window()->d_func()->extra) { if (topData->proxyWidget && topData->proxyWidget->hasFocus()) { previousProxyFocus = topData->proxyWidget->widget()->focusWidget(); if (previousProxyFocus && previousProxyFocus->focusProxy()) @@ -6557,7 +6313,7 @@ void QWidget::setFocus(Qt::FocusReason reason) #if QT_CONFIG(graphicsview) // Update proxy state - if (QWExtra *topData = window()->d_func()->extra) { + if (const auto &topData = window()->d_func()->extra) { if (topData->proxyWidget && !topData->proxyWidget->hasFocus()) { f->d_func()->updateFocusChild(); topData->proxyWidget->d_func()->focusFromWidgetToProxy = 1; @@ -6577,7 +6333,7 @@ void QWidget::setFocus(Qt::FocusReason reason) if (reason != Qt::NoFocusReason) { QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange, reason); - QApplication::sendEvent(prev, &focusAboutToChange); + QCoreApplication::sendEvent(prev, &focusAboutToChange); } } @@ -6598,29 +6354,29 @@ void QWidget::setFocus(Qt::FocusReason reason) } #endif #if QT_CONFIG(graphicsview) - if (QWExtra *topData = window()->d_func()->extra) { + if (const auto &topData = window()->d_func()->extra) { if (topData->proxyWidget) { if (previousProxyFocus && previousProxyFocus != f) { // Send event to self QFocusEvent event(QEvent::FocusOut, reason); QPointer<QWidget> that = previousProxyFocus; - QApplication::sendEvent(previousProxyFocus, &event); + QCoreApplication::sendEvent(previousProxyFocus, &event); if (that) - QApplication::sendEvent(that->style(), &event); + QCoreApplication::sendEvent(that->style(), &event); } if (!isHidden()) { #if QT_CONFIG(graphicsview) // Update proxy state - if (QWExtra *topData = window()->d_func()->extra) + if (const auto &topData = window()->d_func()->extra) if (topData->proxyWidget && topData->proxyWidget->hasFocus()) topData->proxyWidget->d_func()->updateProxyInputMethodAcceptanceFromWidget(); #endif // Send event to self QFocusEvent event(QEvent::FocusIn, reason); QPointer<QWidget> that = f; - QApplication::sendEvent(f, &event); + QCoreApplication::sendEvent(f, &event); if (that) - QApplication::sendEvent(that->style(), &event); + QCoreApplication::sendEvent(that->style(), &event); } } } @@ -6727,7 +6483,7 @@ void QWidget::clearFocus() QGuiApplication::inputMethod()->commit(); QFocusEvent focusAboutToChange(QEvent::FocusAboutToChange); - QApplication::sendEvent(this, &focusAboutToChange); + QCoreApplication::sendEvent(this, &focusAboutToChange); } QWidget *w = this; @@ -6748,7 +6504,7 @@ void QWidget::clearFocus() } #if QT_CONFIG(graphicsview) - QWExtra *topData = d_func()->extra; + const auto &topData = d_func()->extra; if (topData && topData->proxyWidget) topData->proxyWidget->clearFocus(); #endif @@ -6756,17 +6512,10 @@ void QWidget::clearFocus() if (hasFocus()) { // Update proxy state QApplicationPrivate::setFocusWidget(0, Qt::OtherFocusReason); -#if 0 // Used to be included in Qt4 for Q_WS_WIN - if (!(windowType() == Qt::Popup) && GetFocus() == internalWinId()) - SetFocus(0); - else -#endif - { #ifndef QT_NO_ACCESSIBILITY - QAccessibleEvent event(this, QAccessible::Focus); - QAccessible::updateAccessibility(&event); + QAccessibleEvent event(this, QAccessible::Focus); + QAccessible::updateAccessibility(&event); #endif - } } } @@ -6914,7 +6663,7 @@ bool QWidget::isActiveWindow() const return true; #if QT_CONFIG(graphicsview) - if (QWExtra *tlwExtra = tlw->d_func()->extra) { + if (const auto &tlwExtra = tlw->d_func()->extra) { if (isVisible() && tlwExtra->proxyWidget) return tlwExtra->proxyWidget->isActiveWindow(); } @@ -7374,11 +7123,11 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) if (isMove) { QMoveEvent e(q->pos(), oldPos); - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); } if (isResize) { QResizeEvent e(r.size(), olds); - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); if (q->windowHandle()) q->update(); } @@ -7410,18 +7159,6 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) */ QByteArray QWidget::saveGeometry() const { -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // We check if the window was maximized during this invocation. If so, we need to record the - // starting position as 0,0. - Q_D(const QWidget); - QRect newFramePosition = frameGeometry(); - QRect newNormalPosition = normalGeometry(); - if(d->topData()->wasMaximized && !(windowState() & Qt::WindowMaximized)) { - // Change the starting position - newFramePosition.moveTo(0, 0); - newNormalPosition.moveTo(0, 0); - } -#endif QByteArray array; QDataStream stream(&array, QIODevice::WriteOnly); stream.setVersion(QDataStream::Qt_4_0); @@ -7436,13 +7173,8 @@ QByteArray QWidget::saveGeometry() const stream << magicNumber << majorVersion << minorVersion -#if 0 // Used to be included in Qt4 for Q_WS_MAC - << newFramePosition - << newNormalPosition -#else << frameGeometry() << normalGeometry() -#endif << qint32(screenNumber) << quint8(windowState() & Qt::WindowMaximized) << quint8(windowState() & Qt::WindowFullScreen) @@ -7562,11 +7294,6 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) // that would make the window "lost". This happens if: // - The restored geometry is completely oustside the available geometry // - The title bar is outside the available geometry. - // - (Mac only) The window is higher than the available geometry. It must - // be possible to bring the size grip on screen by moving the window. -#if 0 // Used to be included in Qt4 for Q_WS_MAC - restoredNormalGeometry.setHeight(qMin(restoredNormalGeometry.height(), availableGeometry.height() - frameHeight)); -#endif checkRestoredGeometry(availableGeometry, &restoredGeometry, frameHeight); checkRestoredGeometry(availableGeometry, &restoredNormalGeometry, frameHeight); @@ -7623,7 +7350,7 @@ bool QWidget::restoreGeometry(const QByteArray &geometry) Changing the margins will trigger a resizeEvent(). - \sa contentsRect(), getContentsMargins() + \sa contentsRect(), contentsMargins() */ void QWidget::setContentsMargins(int left, int top, int right, int bottom) { @@ -7653,7 +7380,7 @@ void QWidget::setContentsMargins(int left, int top, int right, int bottom) Changing the margins will trigger a resizeEvent(). - \sa contentsRect(), getContentsMargins() + \sa contentsRect(), contentsMargins() */ void QWidget::setContentsMargins(const QMargins &margins) { @@ -7673,16 +7400,20 @@ void QWidgetPrivate::updateContentsRect() if (q->isVisible()) { q->update(); QResizeEvent e(q->data->crect.size(), q->data->crect.size()); - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); } else { q->setAttribute(Qt::WA_PendingResizeEvent, true); } QEvent e(QEvent::ContentsRectChange); - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); } +#if QT_DEPRECATED_SINCE(5, 14) /*! + \obsolete + Use contentsMargins(). + Returns the widget's contents margins for \a left, \a top, \a right, and \a bottom. @@ -7700,6 +7431,7 @@ void QWidget::getContentsMargins(int *left, int *top, int *right, int *bottom) c if (bottom) *bottom = m.bottom(); } +#endif // FIXME: Move to qmargins.h for next minor Qt release QMargins operator|(const QMargins &m1, const QMargins &m2) @@ -7713,7 +7445,7 @@ QMargins operator|(const QMargins &m1, const QMargins &m2) \brief The contentsMargins function returns the widget's contents margins. - \sa getContentsMargins(), setContentsMargins(), contentsRect() + \sa setContentsMargins(), contentsRect() */ QMargins QWidget::contentsMargins() const { @@ -7726,7 +7458,7 @@ QMargins QWidget::contentsMargins() const /*! Returns the area inside the widget's margins. - \sa setContentsMargins(), getContentsMargins() + \sa setContentsMargins(), contentsMargins() */ QRect QWidget::contentsRect() const { @@ -7939,7 +7671,7 @@ void QWidget::show() else if (defaultState == Qt::WindowMaximized) showMaximized(); else - setVisible(true); // FIXME: Why not showNormal(), like QWindow::show()? + setVisible(true); // Don't call showNormal() as not to clobber Qt::Window(Max/Min)imized } /*! \internal @@ -7975,13 +7707,13 @@ void QWidgetPrivate::sendPendingMoveAndResizeEvents(bool recursive, bool disable if (q->testAttribute(Qt::WA_PendingMoveEvent)) { QMoveEvent e(data.crect.topLeft(), data.crect.topLeft()); - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); q->setAttribute(Qt::WA_PendingMoveEvent, false); } if (q->testAttribute(Qt::WA_PendingResizeEvent)) { QResizeEvent e(data.crect.size(), QSize()); - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); q->setAttribute(Qt::WA_PendingResizeEvent, false); } @@ -8081,17 +7813,9 @@ void QWidgetPrivate::show_helper() Q_UNUSED(isEmbedded); #endif - // On Windows, show the popup now so that our own focus handling - // stores the correct old focus widget even if it's stolen in the - // showevent -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_MAC */ - if (!isEmbedded && q->windowType() == Qt::Popup) - qApp->d_func()->openPopup(q); -#endif - // send the show event before showing the window QShowEvent showEvent; - QApplication::sendEvent(q, &showEvent); + QCoreApplication::sendEvent(q, &showEvent); show_sys(); @@ -8114,7 +7838,7 @@ void QWidgetPrivate::show_helper() // is spinnning; otherwise it might not show up on particular platforms. // This makes QSplashScreen behave the same on all platforms. if (!qApp->d_func()->in_exec && q->windowType() == Qt::SplashScreen) - QApplication::processEvents(); + QCoreApplication::processEvents(); data.in_show = false; // reset qws optimization } @@ -8123,7 +7847,7 @@ void QWidgetPrivate::show_sys() { Q_Q(QWidget); - QWidgetWindow *window = windowHandle(); + auto window = qobject_cast<QWidgetWindow *>(windowHandle()); if (q->testAttribute(Qt::WA_DontShowOnScreen)) { invalidateBackingStore(q->rect()); @@ -8140,9 +7864,9 @@ void QWidgetPrivate::show_sys() } if (renderToTexture && !q->isWindow()) - QApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry())); + QCoreApplication::postEvent(q->parentWidget(), new QUpdateLaterEvent(q->geometry())); else - QApplication::postEvent(q, new QUpdateLaterEvent(q->rect())); + QCoreApplication::postEvent(q, new QUpdateLaterEvent(q->rect())); if ((!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow)) || q->testAttribute(Qt::WA_OutsideWSRange)) { @@ -8213,12 +7937,6 @@ void QWidgetPrivate::hide_helper() if (!isEmbedded && (q->windowType() == Qt::Popup)) qApp->d_func()->closePopup(q); -#if 0 // Used to be included in Qt4 for Q_WS_WIN - if (q->isWindow() && !(q->windowType() == Qt::Popup) && q->parentWidget() - && !q->parentWidget()->isHidden() && q->isActiveWindow()) - q->parentWidget()->activateWindow(); // Activate parent -#endif - q->setAttribute(Qt::WA_Mapped, false); hide_sys(); @@ -8230,7 +7948,7 @@ void QWidgetPrivate::hide_helper() } QHideEvent hideEvent; - QApplication::sendEvent(q, &hideEvent); + QCoreApplication::sendEvent(q, &hideEvent); hideChildren(false); // next bit tries to move the focus if the focus widget is now @@ -8247,8 +7965,8 @@ void QWidgetPrivate::hide_helper() } } - if (QWidgetBackingStore *bs = maybeBackingStore()) - bs->removeDirtyWidget(q); + if (QWidgetRepaintManager *repaintManager = maybeRepaintManager()) + repaintManager->removeDirtyWidget(q); #ifndef QT_NO_ACCESSIBILITY if (wasVisible) { @@ -8262,7 +7980,7 @@ void QWidgetPrivate::hide_sys() { Q_Q(QWidget); - QWidgetWindow *window = windowHandle(); + auto window = qobject_cast<QWidgetWindow *>(windowHandle()); if (q->testAttribute(Qt::WA_DontShowOnScreen)) { q->setAttribute(Qt::WA_Mapped, false); @@ -8401,18 +8119,8 @@ void QWidgetPrivate::setVisible(bool visible) } QEvent showToParentEvent(QEvent::ShowToParent); - QApplication::sendEvent(q, &showToParentEvent); + QCoreApplication::sendEvent(q, &showToParentEvent); } else { // hide -#if 0 // Used to be included in Qt4 for Q_WS_WIN - // reset WS_DISABLED style in a Blocked window - if(isWindow() && testAttribute(Qt::WA_WState_Created) - && QApplicationPrivate::isBlockedByModal(this)) - { - LONG dwStyle = GetWindowLong(winId(), GWL_STYLE); - dwStyle &= ~WS_DISABLED; - SetWindowLong(winId(), GWL_STYLE, dwStyle); - } -#endif if (QApplicationPrivate::hidden_focus_widget == q) QApplicationPrivate::hidden_focus_widget = 0; @@ -8432,11 +8140,11 @@ void QWidgetPrivate::setVisible(bool visible) if (q->parentWidget()->d_func()->layout) q->parentWidget()->d_func()->layout->invalidate(); else if (q->parentWidget()->isVisible()) - QApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest)); + QCoreApplication::postEvent(q->parentWidget(), new QEvent(QEvent::LayoutRequest)); } QEvent hideToParentEvent(QEvent::HideToParent); - QApplication::sendEvent(q, &hideToParentEvent); + QCoreApplication::sendEvent(q, &hideToParentEvent); } } @@ -8485,23 +8193,7 @@ void QWidgetPrivate::hideChildren(bool spontaneous) QWidget *widget = qobject_cast<QWidget*>(childList.at(i)); if (!widget || widget->isWindow() || widget->testAttribute(Qt::WA_WState_Hidden)) continue; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // Before doing anything we need to make sure that we don't leave anything in a non-consistent state. - // When hiding a widget we need to make sure that no mouse_down events are active, because - // the mouse_up event will never be received by a hidden widget or one of its descendants. - // The solution is simple, before going through with this we check if there are any mouse_down events in - // progress, if so we check if it is related to this widget or not. If so, we just reset the mouse_down and - // then we continue. - // In X11 and Windows we send a mouse_release event, however we don't do that here because we were already - // ignoring that from before. I.e. Carbon did not send the mouse release event, so we will not send the - // mouse release event. There are two ways to interpret this: - // 1. If we don't send the mouse release event, the widget might get into an inconsistent state, i.e. it - // might be waiting for a release event that will never arrive. - // 2. If we send the mouse release event, then the widget might decide to trigger an action that is not - // supposed to trigger because it is not visible. - if(widget == qt_button_down) - qt_button_down = 0; -#endif + if (spontaneous) widget->setAttribute(Qt::WA_Mapped, false); else @@ -8511,7 +8203,7 @@ void QWidgetPrivate::hideChildren(bool spontaneous) if (spontaneous) { QApplication::sendSpontaneousEvent(widget, &e); } else { - QApplication::sendEvent(widget, &e); + QCoreApplication::sendEvent(widget, &e); if (widget->internalWinId() && widget->testAttribute(Qt::WA_DontCreateNativeAncestors)) { // hide_sys() on an ancestor won't have any affect on this @@ -8546,7 +8238,7 @@ bool QWidgetPrivate::close_helper(CloseMode mode) if (mode == CloseWithSpontaneousEvent) QApplication::sendSpontaneousEvent(q, &e); else - QApplication::sendEvent(q, &e); + QCoreApplication::sendEvent(q, &e); if (!that.isNull() && !e.isAccepted()) { data.is_closing = 0; return false; @@ -8736,11 +8428,9 @@ QSize QWidgetPrivate::adjustedSize() const s.setWidth(qMax(s.width(), 200)); if (exp & Qt::Vertical) s.setHeight(qMax(s.height(), 100)); -#if 0 // Used to be included in Qt4 for Q_WS_X11 - QRect screen = QDesktopWidgetPrivate::screenGeometry(q->x11Info().screen()); -#else // all others + QRect screen = QDesktopWidgetPrivate::screenGeometry(q->pos()); -#endif + s.setWidth(qMin(s.width(), screen.width()*2/3)); s.setHeight(qMin(s.height(), screen.height()*2/3)); @@ -8865,26 +8555,6 @@ bool QWidget::isAncestorOf(const QWidget *child) const return false; } -#if 0 // Used to be included in Qt4 for Q_WS_WIN -inline void setDisabledStyle(QWidget *w, bool setStyle) -{ - // set/reset WS_DISABLED style. - if(w && w->isWindow() && w->isVisible() && w->isEnabled()) { - LONG dwStyle = GetWindowLong(w->winId(), GWL_STYLE); - LONG newStyle = dwStyle; - if (setStyle) - newStyle |= WS_DISABLED; - else - newStyle &= ~WS_DISABLED; - if (newStyle != dwStyle) { - SetWindowLong(w->winId(), GWL_STYLE, newStyle); - // we might need to repaint in some situations (eg. menu) - w->repaint(); - } - } -} -#endif - /***************************************************************************** QWidget event handling *****************************************************************************/ @@ -9061,7 +8731,7 @@ bool QWidget::event(QEvent *event) setAttribute(Qt::WA_WState_Polished); if (!QApplication::font(this).isCopyOf(QApplication::font())) d->resolveFont(); - if (!QApplication::palette(this).isCopyOf(QApplication::palette())) + if (!QApplication::palette(this).isCopyOf(QGuiApplication::palette())) d->resolvePalette(); } break; @@ -9085,7 +8755,7 @@ bool QWidget::event(QEvent *event) #if QT_CONFIG(statustip) if (d->statusTip.size()) { QStatusTipEvent tip(d->statusTip); - QApplication::sendEvent(const_cast<QWidget *>(this), &tip); + QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip); } #endif enterEvent(event); @@ -9096,7 +8766,7 @@ bool QWidget::event(QEvent *event) if (d->statusTip.size()) { QString empty; QStatusTipEvent tip(empty); - QApplication::sendEvent(const_cast<QWidget *>(this), &tip); + QCoreApplication::sendEvent(const_cast<QWidget *>(this), &tip); } #endif leaveEvent(event); @@ -9247,7 +8917,7 @@ bool QWidget::event(QEvent *event) for (int i = 0; i < childList.size(); ++i) { QWidget *w = qobject_cast<QWidget *>(childList.at(i)); if (w && w->isVisible() && !w->isWindow()) - QApplication::sendEvent(w, event); + QCoreApplication::sendEvent(w, event); } break; } @@ -9258,7 +8928,7 @@ bool QWidget::event(QEvent *event) for (int i = 0; i < childList.size(); ++i) { QObject *o = childList.at(i); if (o) - QApplication::sendEvent(o, event); + QCoreApplication::sendEvent(o, event); } } update(); @@ -9297,13 +8967,10 @@ bool QWidget::event(QEvent *event) QWidget *w = static_cast<QWidget *>(o); // do not forward the event to child windows; QApplication does this for us if (!w->isWindow()) - QApplication::sendEvent(w, event); + QCoreApplication::sendEvent(w, event); } } } -#if 0 // Used to be included in Qt4 for Q_WS_WIN - setDisabledStyle(this, (event->type() == QEvent::WindowBlocked)); -#endif break; #ifndef QT_NO_TOOLTIP case QEvent::ToolTip: @@ -9328,9 +8995,6 @@ bool QWidget::event(QEvent *event) case QEvent::EmbeddingControl: d->topData()->frameStrut.setCoords(0 ,0, 0, 0); data->fstrut_dirty = false; -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_X11 */ - d->topData()->embedded = 1; -#endif break; #ifndef QT_NO_ACTION case QEvent::ActionAdded: @@ -9349,15 +9013,10 @@ bool QWidget::event(QEvent *event) for (int i = 0; i < childList.size(); ++i) { QWidget *w = qobject_cast<QWidget *>(childList.at(i)); if (w && w->isVisible() && !w->isWindow()) - QApplication::sendEvent(w, event); + QCoreApplication::sendEvent(w, event); } break; } -#if 0 // Used to be included in Qt4 for Q_WS_MAC - case QEvent::MacGLWindowChange: - d->needWindowChange = false; - break; -#endif case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: @@ -9452,8 +9111,8 @@ void QWidget::changeEvent(QEvent * event) break; case QEvent::ThemeChange: - if (QApplication::desktopSettingsAware() && windowType() != Qt::Desktop - && qApp && !QApplication::closingDown()) { + if (QGuiApplication::desktopSettingsAware() && windowType() != Qt::Desktop + && qApp && !QCoreApplication::closingDown()) { if (testAttribute(Qt::WA_WState_Polished)) QApplication::style()->unpolish(this); if (testAttribute(Qt::WA_WState_Polished)) @@ -9469,11 +9128,6 @@ void QWidget::changeEvent(QEvent * event) case QEvent::MacSizeChange: updateGeometry(); break; -#elif 0 // Used to be included in Qt4 for Q_WS_MAC - case QEvent::ToolTipChange: - case QEvent::MouseTrackingChange: - qt_mac_update_mouseTracking(this); - break; #endif default: @@ -9566,9 +9220,11 @@ void QWidget::mouseReleaseEvent(QMouseEvent *event) The default implementation calls mousePressEvent(). \note The widget will also receive mouse press and mouse release - events in addition to the double click event. It is up to the - developer to ensure that the application interprets these events - correctly. + events in addition to the double click event. And if another widget + that overlaps this widget disappears in response to press or + release events, then this widget will only receive the double click + event. It is up to the developer to ensure that the application + interprets these events correctly. \sa mousePressEvent(), mouseReleaseEvent(), mouseMoveEvent(), event(), QMouseEvent @@ -10180,7 +9836,11 @@ void QWidget::hideEvent(QHideEvent *) \endtable */ +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QWidget::nativeEvent(const QByteArray &eventType, void *message, qintptr *result) +#else bool QWidget::nativeEvent(const QByteArray &eventType, void *message, long *result) +#endif { Q_UNUSED(eventType); Q_UNUSED(message); @@ -10395,7 +10055,7 @@ void QWidget::setSizePolicy(QSizePolicy policy) d->size_policy = policy; #if QT_CONFIG(graphicsview) - if (QWExtra *extra = d->extra) { + if (const auto &extra = d->extra) { if (extra->proxyWidget) extra->proxyWidget->setSizePolicy(policy); } @@ -10516,7 +10176,7 @@ void QWidgetPrivate::updateGeometry_helper(bool forceUpdate) if (parent->d_func()->layout) parent->d_func()->layout->invalidate(); else if (parent->isVisible()) - QApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest)); + QCoreApplication::postEvent(parent, new QEvent(QEvent::LayoutRequest)); } } } @@ -10670,7 +10330,7 @@ static void sendWindowChangeToTextureChildrenRecursively(QWidget *widget) QWidgetPrivate *d = QWidgetPrivate::get(widget); if (d->renderToTexture) { QEvent e(QEvent::WindowChangeInternal); - QApplication::sendEvent(widget, &e); + QCoreApplication::sendEvent(widget, &e); } for (int i = 0; i < d->children.size(); ++i) { @@ -10690,6 +10350,22 @@ static void sendWindowChangeToTextureChildrenRecursively(QWidget *widget) void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) { Q_D(QWidget); + Q_ASSERT_X(this != parent, Q_FUNC_INFO, "Cannot parent a QWidget to itself"); +#ifdef QT_DEBUG + const auto checkForParentChildLoops = qScopeGuard([&](){ + int depth = 0; + auto p = parentWidget(); + while (p) { + if (++depth == QObjectPrivate::CheckForParentChildLoopsWarnDepth) { + qWarning("QWidget %p (class: '%s', object name: '%s') may have a loop in its parent-child chain; " + "this is undefined behavior", + this, metaObject()->className(), qPrintable(objectName())); + } + p = p->parentWidget(); + } + }); +#endif + bool resized = testAttribute(Qt::WA_Resized); bool wasCreated = testAttribute(Qt::WA_WState_Created); QWidget *oldtlw = window(); @@ -10703,7 +10379,7 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) bool newParent = (parent != parentWidget()) || !wasCreated || desktopWidget; if (newParent && parent && !desktopWidget) { - if (testAttribute(Qt::WA_NativeWindow) && !qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings)) + if (testAttribute(Qt::WA_NativeWindow) && !QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings)) parent->d_func()->enforceNativeChildren(); else if (parent->d_func()->nativeChildrenForced() || parent->testAttribute(Qt::WA_PaintOnScreen)) setAttribute(Qt::WA_NativeWindow); @@ -10716,22 +10392,14 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) } if (newParent) { QEvent e(QEvent::ParentAboutToChange); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); } } if (newParent && isAncestorOf(focusWidget())) focusWidget()->clearFocus(); - QTLWExtra *oldTopExtra = window()->d_func()->maybeTopData(); - QWidgetBackingStoreTracker *oldBsTracker = oldTopExtra ? &oldTopExtra->backingStoreTracker : 0; - d->setParent_sys(parent, f); - QTLWExtra *topExtra = window()->d_func()->maybeTopData(); - QWidgetBackingStoreTracker *bsTracker = topExtra ? &topExtra->backingStoreTracker : 0; - if (oldBsTracker && oldBsTracker != bsTracker) - oldBsTracker->unregisterWidgetSubtree(this); - if (desktopWidget) parent = 0; @@ -10742,12 +10410,12 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) } #endif - if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) { + if (QWidgetRepaintManager *oldPaintManager = oldtlw->d_func()->maybeRepaintManager()) { if (newParent) - oldBs->removeDirtyWidget(this); + oldPaintManager->removeDirtyWidget(this); // Move the widget and all its static children from // the old backing store to the new one. - oldBs->moveStaticWidgets(this); + oldPaintManager->moveStaticWidgets(this); } // ### fixme: Qt 6: Remove AA_ImmediateWidgetCreation. @@ -10773,7 +10441,7 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all // platforms). if (newParent -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || defined(QT_OPENGL_ES) +#if defined(QT_OPENGL_ES) || (f & Qt::MSWindowsOwnDC) #endif ) { @@ -10789,25 +10457,16 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f) // send and post remaining QObject events if (parent && d->sendChildEvents) { QChildEvent e(QEvent::ChildAdded, this); - QApplication::sendEvent(parent, &e); + QCoreApplication::sendEvent(parent, &e); } -//### already hidden above ---> must probably do something smart on the mac -// #if 0 // Used to be included in Qt4 for Q_WS_MAC -// extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp -// if(!qt_mac_is_macdrawer(q)) //special case -// q->setAttribute(Qt::WA_WState_Hidden); -// #else -// q->setAttribute(Qt::WA_WState_Hidden); -//#endif - if (parent && d->sendChildEvents && d->polished) { QChildEvent e(QEvent::ChildPolished, this); QCoreApplication::sendEvent(parent, &e); } QEvent e(QEvent::ParentChange); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); } #ifndef QT_NO_OPENGL //renderToTexture widgets also need to know when their top-level window changes @@ -11101,7 +10760,7 @@ void QWidgetPrivate::repaint(T r) QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(r, q, QWidgetBackingStore::UpdateNow); + tlwExtra->repaintManager->markDirty(r, q, QWidgetRepaintManager::UpdateNow); } /*! @@ -11170,13 +10829,13 @@ void QWidgetPrivate::update(T r) return; if (q->testAttribute(Qt::WA_WState_InPaintEvent)) { - QApplication::postEvent(q, new QUpdateLaterEvent(clipped)); + QCoreApplication::postEvent(q, new QUpdateLaterEvent(clipped)); return; } QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(clipped, q); + tlwExtra->repaintManager->markDirty(clipped, q); } /*! @@ -11207,7 +10866,7 @@ void QWidgetPrivate::macUpdateSizeAttribute() { Q_Q(QWidget); QEvent event(QEvent::MacSizeChange); - QApplication::sendEvent(q, &event); + QCoreApplication::sendEvent(q, &event); for (int i = 0; i < children.size(); ++i) { QWidget *w = qobject_cast<QWidget *>(children.at(i)); if (w && (!w->isWindow() || w->testAttribute(Qt::WA_WindowPropagation)) @@ -11263,7 +10922,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) else if (!on && (isWindow() || !parentWidget() || !parentWidget()->testAttribute(Qt::WA_DropSiteRegistered))) setAttribute(Qt::WA_DropSiteRegistered, false); QEvent e(QEvent::AcceptDropsChange); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); break; } case Qt::WA_DropSiteRegistered: { @@ -11282,23 +10941,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) case Qt::WA_NoChildEventsFromChildren: d->receiveChildEvents = !on; break; -#if 0 // Used to be included in Qt4 for Q_WS_MAC - case Qt::WA_MacOpaqueSizeGrip: - d->macUpdateOpaqueSizeGrip(); - break; - case Qt::WA_MacShowFocusRect: - if (hasFocus()) { - clearFocus(); - setFocus(); - } - break; - case Qt::WA_Hover: - qt_mac_update_mouseTracking(this); - break; - case Qt::WA_MacAlwaysShowToolWindow: - d->macUpdateHideOnSuspend(); - break; -#endif case Qt::WA_MacNormalSize: case Qt::WA_MacSmallSize: case Qt::WA_MacMiniSize: @@ -11346,11 +10988,11 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) break; case Qt::WA_MouseTracking: { QEvent e(QEvent::MouseTrackingChange); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); break; } case Qt::WA_TabletTracking: { QEvent e(QEvent::TabletTrackingChange); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); break; } case Qt::WA_NativeWindow: { d->createTLExtra(); @@ -11363,7 +11005,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) QGuiApplication::inputMethod()->commit(); QGuiApplication::inputMethod()->update(Qt::ImEnabled); } - if (!qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget()) + if (!QCoreApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings) && parentWidget()) parentWidget()->d_func()->enforceNativeChildren(); if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created)) d->createWinId(); @@ -11376,15 +11018,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) } case Qt::WA_PaintOnScreen: d->updateIsOpaque(); -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_X11 */ || 0 /* Used to be included in Qt4 for Q_WS_MAC */ - // Recreate the widget if it's already created as an alien widget and - // WA_PaintOnScreen is enabled. Paint on screen widgets must have win id. - // So must their children. - if (on) { - setAttribute(Qt::WA_NativeWindow); - d->enforceNativeChildren(); - } -#endif Q_FALLTHROUGH(); case Qt::WA_OpaquePaintEvent: d->updateIsOpaque(); @@ -11396,9 +11029,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) d->updateSystemBackground(); break; case Qt::WA_TransparentForMouseEvents: -#if 0 // Used to be included in Qt4 for Q_WS_MAC - d->macUpdateIgnoreMouseEvents(); -#endif break; case Qt::WA_InputMethodEnabled: { #ifndef QT_NO_IM @@ -11415,20 +11045,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) d->resolveFont(); d->resolveLocale(); break; -#if 0 // Used to be included in Qt4 for Q_WS_X11 - case Qt::WA_NoX11EventCompression: - if (!d->extra) - d->createExtra(); - d->extra->compress_events = on; - break; - case Qt::WA_X11OpenGLOverlay: - d->updateIsOpaque(); - break; - case Qt::WA_X11DoNotAcceptFocus: - if (testAttribute(Qt::WA_WState_Created)) - d->updateX11AcceptFocus(); - break; -#endif case Qt::WA_DontShowOnScreen: { if (on && isVisible()) { // Make sure we keep the current state and only hide the widget @@ -11457,11 +11073,11 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) break; case Qt::WA_StaticContents: - if (QWidgetBackingStore *bs = d->maybeBackingStore()) { + if (QWidgetRepaintManager *repaintManager = d->maybeRepaintManager()) { if (on) - bs->addStaticWidget(this); + repaintManager->addStaticWidget(this); else - bs->removeStaticWidget(this); + repaintManager->removeStaticWidget(this); } break; case Qt::WA_TranslucentBackground: @@ -11471,10 +11087,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) break; case Qt::WA_AcceptTouchEvents: -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ || 0 /* Used to be included in Qt4 for Q_WS_MAC */ - if (on) - d->registerTouchWindow(); -#endif break; default: break; @@ -11598,7 +11210,7 @@ void QWidget::setWindowModified(bool mod) d->setWindowModified_helper(); QEvent e(QEvent::ModifiedChange); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); } void QWidgetPrivate::setWindowModified_helper() @@ -11644,7 +11256,7 @@ void QWidget::setToolTip(const QString &s) d->toolTip = s; QEvent event(QEvent::ToolTipChange); - QApplication::sendEvent(this, &event); + QCoreApplication::sendEvent(this, &event); } QString QWidget::toolTip() const @@ -11821,7 +11433,7 @@ int QWidget::grabShortcut(const QKeySequence &key, Qt::ShortcutContext context) if (key.isEmpty()) return 0; setAttribute(Qt::WA_GrabbedShortcut); - return qApp->d_func()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher); + return QGuiApplicationPrivate::instance()->shortcutMap.addShortcut(this, key, context, qWidgetShortcutContextMatcher); } /*! @@ -11843,7 +11455,7 @@ void QWidget::releaseShortcut(int id) { Q_ASSERT(qApp); if (id) - qApp->d_func()->shortcutMap.removeShortcut(id, this, 0); + QGuiApplicationPrivate::instance()->shortcutMap.removeShortcut(id, this, 0); } /*! @@ -11862,7 +11474,7 @@ void QWidget::setShortcutEnabled(int id, bool enable) { Q_ASSERT(qApp); if (id) - qApp->d_func()->shortcutMap.setShortcutEnabled(enable, id, this, 0); + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutEnabled(enable, id, this, 0); } /*! @@ -11877,7 +11489,7 @@ void QWidget::setShortcutAutoRepeat(int id, bool enable) { Q_ASSERT(qApp); if (id) - qApp->d_func()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0); + QGuiApplicationPrivate::instance()->shortcutMap.setShortcutAutoRepeat(enable, id, this, 0); } #endif // QT_NO_SHORTCUT @@ -11932,7 +11544,7 @@ void QWidget::raise() QWindowContainer::parentWasRaised(this); QEvent e(QEvent::ZOrderChange); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); } void QWidgetPrivate::raise_sys() @@ -11982,7 +11594,7 @@ void QWidget::lower() QWindowContainer::parentWasLowered(this); QEvent e(QEvent::ZOrderChange); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); } void QWidgetPrivate::lower_sys() @@ -12029,7 +11641,7 @@ void QWidget::stackUnder(QWidget* w) d->stackUnder_sys(w); QEvent e(QEvent::ZOrderChange); - QApplication::sendEvent(this, &e); + QCoreApplication::sendEvent(this, &e); } void QWidgetPrivate::stackUnder_sys(QWidget*) @@ -12090,10 +11702,8 @@ QRect QWidgetPrivate::frameStrut() const } if (data.fstrut_dirty -#if 1 // Used to be excluded in Qt4 for Q_WS_WIN // ### Fix properly for 4.3 && q->isVisible() -#endif && q->testAttribute(Qt::WA_WState_Created)) const_cast<QWidgetPrivate *>(this)->updateFrameStrut(); @@ -12266,14 +11876,14 @@ void QWidget::setBackingStore(QBackingStore *store) deleteBackingStore(d); topData->backingStore = store; - QWidgetBackingStore *bs = d->maybeBackingStore(); - if (!bs) + QWidgetRepaintManager *repaintManager = d->maybeRepaintManager(); + if (!repaintManager) return; if (isTopLevel()) { - if (bs->store != oldStore && bs->store != store) - delete bs->store; - bs->store = store; + if (repaintManager->backingStore() != oldStore && repaintManager->backingStore() != store) + delete repaintManager->backingStore(); + repaintManager->setBackingStore(store); } } @@ -12289,9 +11899,8 @@ QBackingStore *QWidget::backingStore() const if (extra && extra->backingStore) return extra->backingStore; - QWidgetBackingStore *bs = d->maybeBackingStore(); - - return bs ? bs->store : 0; + QWidgetRepaintManager *repaintManager = d->maybeRepaintManager(); + return repaintManager ? repaintManager->backingStore() : nullptr; } void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const @@ -12364,19 +11973,18 @@ QOpenGLContext *QWidgetPrivate::shareContext() const #ifdef QT_NO_OPENGL return 0; #else - if (Q_UNLIKELY(!extra || !extra->topextra || !extra->topextra->window)) + if (!extra || !extra->topextra || !extra->topextra->window) return 0; - QWidgetPrivate *that = const_cast<QWidgetPrivate *>(this); if (!extra->topextra->shareContext) { - QOpenGLContext *ctx = new QOpenGLContext; + auto ctx = qt_make_unique<QOpenGLContext>(); ctx->setShareContext(qt_gl_global_share_context()); ctx->setFormat(extra->topextra->window->format()); ctx->setScreen(extra->topextra->window->screen()); ctx->create(); - that->extra->topextra->shareContext = ctx; + extra->topextra->shareContext = std::move(ctx); } - return that->extra->topextra->shareContext; + return extra->topextra->shareContext.get(); #endif // QT_NO_OPENGL } @@ -13022,10 +12630,8 @@ void QWidget::setMask(const QRegion &newMask) d->extra->mask = newMask; d->extra->hasMask = !newMask.isEmpty(); -#if 1 // Used to be excluded in Qt4 for Q_WS_MAC if (!testAttribute(Qt::WA_WState_Created)) return; -#endif d->setMask_sys(newMask); @@ -13201,7 +12807,7 @@ QDebug operator<<(QDebug debug, const QWidget *widget) if (widget->isWindow()) debug << ", window"; debug << ", " << geometry.width() << 'x' << geometry.height() - << forcesign << geometry.x() << geometry.y() << noforcesign; + << Qt::forcesign << geometry.x() << geometry.y() << Qt::noforcesign; if (frameGeometry != geometry) { const QMargins margins(geometry.x() - frameGeometry.x(), geometry.y() - frameGeometry.y(), @@ -13211,7 +12817,7 @@ QDebug operator<<(QDebug debug, const QWidget *widget) } debug << ", devicePixelRatio=" << widget->devicePixelRatioF(); if (const WId wid = widget->internalWinId()) - debug << ", winId=0x" << hex << wid << dec; + debug << ", winId=0x" << Qt::hex << wid << Qt::dec; } debug << ')'; } else { diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h index 4e5ef5a111..83a6e6d4b3 100644 --- a/src/widgets/kernel/qwidget.h +++ b/src/widgets/kernel/qwidget.h @@ -85,6 +85,7 @@ class QDragEnterEvent; class QDragMoveEvent; class QDragLeaveEvent; class QDropEvent; +class QScreen; class QShowEvent; class QHideEvent; class QIcon; @@ -524,7 +525,10 @@ public: void setContentsMargins(int left, int top, int right, int bottom); void setContentsMargins(const QMargins &margins); +#if QT_DEPRECATED_SINCE(5, 14) + QT_DEPRECATED_X("use contentsMargins()") void getContentsMargins(int *left, int *top, int *right, int *bottom) const; +#endif QMargins contentsMargins() const; QRect contentsRect() const; @@ -555,7 +559,7 @@ public: void addAction(QAction *action); #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) void addActions(const QList<QAction*> &actions); - void insertActions(const QAction *before, const QList<QAction*> &actions); + void insertActions(QAction *before, const QList<QAction*> &actions); #else void addActions(QList<QAction*> actions); void insertActions(QAction *before, QList<QAction*> actions); @@ -598,6 +602,7 @@ public: QBackingStore *backingStore() const; QWindow *windowHandle() const; + QScreen *screen() const; static QWidget *createWindowContainer(QWindow *window, QWidget *parent=nullptr, Qt::WindowFlags flags=Qt::WindowFlags()); @@ -648,7 +653,12 @@ protected: virtual void showEvent(QShowEvent *event); virtual void hideEvent(QHideEvent *event); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result); +#else virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result); +#endif // Misc. protected functions virtual void changeEvent(QEvent *); @@ -689,7 +699,7 @@ private: QLayout *takeLayout(); friend class QBackingStoreDevice; - friend class QWidgetBackingStore; + friend class QWidgetRepaintManager; friend class QApplication; friend class QApplicationPrivate; friend class QGuiApplication; diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 3dccd00b8b..698928b0b0 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -75,15 +75,20 @@ #include <private/qgesture_p.h> #include <qpa/qplatformbackingstore.h> +#include <vector> +#include <memory> + QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcWidgetPainting); + // Extra QWidget data // - to minimize memory usage for members that are seldom used. // - top-level widgets have extra extra data to reduce cost further class QWidgetWindow; class QPaintEngine; class QPixmap; -class QWidgetBackingStore; +class QWidgetRepaintManager; class QGraphicsProxyWidget; class QWidgetItemV2; class QOpenGLContext; @@ -113,60 +118,18 @@ protected: QRegion m_region; }; - - -class Q_AUTOTEST_EXPORT QWidgetBackingStoreTracker -{ - -public: - QWidgetBackingStoreTracker(); - ~QWidgetBackingStoreTracker(); - - void create(QWidget *tlw); - void destroy(); - - void registerWidget(QWidget *w); - void unregisterWidget(QWidget *w); - void unregisterWidgetSubtree(QWidget *w); - - inline QWidgetBackingStore* data() - { - return m_ptr; - } - - inline QWidgetBackingStore* operator->() - { - return m_ptr; - } - - inline QWidgetBackingStore& operator*() - { - return *m_ptr; - } - - inline operator bool() const - { - return (0 != m_ptr); - } - -private: - Q_DISABLE_COPY_MOVE(QWidgetBackingStoreTracker) - -private: - QWidgetBackingStore* m_ptr; - QSet<QWidget *> m_widgets; -}; - struct QTLWExtra { // *************************** Cross-platform variables ***************************** // Regular pointers (keep them together to avoid gaps on 64 bits architectures). - QIcon *icon; // widget icon - QWidgetBackingStoreTracker backingStoreTracker; + std::unique_ptr<QIcon> icon; // widget icon + std::unique_ptr<QWidgetRepaintManager> repaintManager; QBackingStore *backingStore; QPainter *sharedPainter; QWidgetWindow *window; - QOpenGLContext *shareContext; +#ifndef QT_NO_OPENGL + mutable std::unique_ptr<QOpenGLContext> shareContext; +#endif // Implicit pointers (shared_null). QString caption; // widget caption @@ -184,7 +147,9 @@ struct QTLWExtra { // ### TODO replace initialScreenIndex with QScreen *, in case the screens change at runtime int initialScreenIndex; // Screen number when passing a QDesktop[Screen]Widget as parent. - QVector<QPlatformTextureList *> widgetTextures; +#ifndef QT_NO_OPENGL + std::vector<std::unique_ptr<QPlatformTextureList>> widgetTextures; +#endif // *************************** Cross-platform bit fields **************************** uint opacity : 8; @@ -192,41 +157,6 @@ struct QTLWExtra { uint sizeAdjusted : 1; uint inTopLevelResize : 1; uint embedded : 1; - - // *************************** Platform specific values (bit fields first) ********** -#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ // <----------------------------------------------------------- X11 - uint spont_unmapped: 1; // window was spontaneously unmapped - uint dnd : 1; // DND properties installed - uint validWMState : 1; // is WM_STATE valid? - uint waitingForMapNotify : 1; // show() has been called, haven't got the MapNotify yet - WId parentWinId; // parent window Id (valid after reparenting) - WId userTimeWindow; // window id that contains user-time timestamp when WM supports a _NET_WM_USER_TIME_WINDOW atom - QPoint fullScreenOffset; -#ifndef QT_NO_XSYNC - WId syncUpdateCounter; - ulong syncRequestTimestamp; - qint32 newCounterValueHi; - quint32 newCounterValueLo; -#endif -#elif 0 /* Used to be included in Qt4 for Q_WS_WIN */ // <--------------------------------------------------------- WIN - uint hotkeyRegistered: 1; // Hot key from the STARTUPINFO has been registered. - HICON winIconBig; // internal big Windows icon - HICON winIconSmall; // internal small Windows icon -#elif 0 /* Used to be included in Qt4 for Q_WS_MAC */ // <--------------------------------------------------------- MAC - uint resizer : 4; - uint isSetGeometry : 1; - uint isMove : 1; - quint32 wattr; - quint32 wclass; - WindowGroupRef group; - IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys. - quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys() - // This value is just to make sure we maximize and restore to the right location, yet we allow apps to be maximized and - // manually resized. - // The name is misleading, since this is set when maximizing the window. It is a hint to saveGeometry(..) to record the - // starting position as 0,0 instead of the normal starting position. - bool wasMaximized; -#endif }; struct QWExtra { @@ -234,12 +164,12 @@ struct QWExtra { // Regular pointers (keep them together to avoid gaps on 64 bits architectures). void *glContext; // if the widget is hijacked by QGLWindowSurface - QTLWExtra *topextra; // only useful for TLWs + std::unique_ptr<QTLWExtra> topextra; // only useful for TLWs #if QT_CONFIG(graphicsview) QGraphicsProxyWidget *proxyWidget; // if the widget is embedded #endif #ifndef QT_NO_CURSOR - QCursor *curs; + std::unique_ptr<QCursor> curs; #endif QPointer<QStyle> style; QPointer<QWidget> focus_proxy; @@ -265,21 +195,6 @@ struct QWExtra { uint inRenderWithPainter : 1; uint hasMask : 1; uint hasWindowContainer : 1; - - // *************************** Platform specific values (bit fields first) ********** -#if 0 /* Used to be included in Qt4 for Q_WS_WIN */ // <----------------------------------------------------------- WIN -#if QT_CONFIG(draganddrop) - QOleDropTarget *dropTarget; // drop target - QList<QPointer<QWidget> > oleDropWidgets; -#endif -#elif 0 /* Used to be included in Qt4 for Q_WS_X11 */ // <--------------------------------------------------------- X11 - uint compress_events : 1; - WId xDndProxy; // XDND forwarding to embedded windows -#elif 0 /* Used to be included in Qt4 for Q_WS_MAC */ // <------------------------------------------------------ MAC - // Cocoa Mask stuff - QImage maskBits; - CGImageRef imageMask; -#endif }; /*! @@ -303,10 +218,11 @@ static inline bool bypassGraphicsProxyWidget(const QWidget *p) class Q_WIDGETS_EXPORT QWidgetPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QWidget) + Q_GADGET public: // *************************** Cross-platform *************************************** - enum DrawWidgetFlags { + enum DrawWidgetFlag { DrawAsRoot = 0x01, DrawPaintOnScreen = 0x02, DrawRecursive = 0x04, @@ -316,12 +232,15 @@ public: DontDrawNativeChildren = 0x40, DontSetCompositionMode = 0x80 }; + Q_DECLARE_FLAGS(DrawWidgetFlags, DrawWidgetFlag) + Q_FLAG(DrawWidgetFlags) enum CloseMode { CloseNoEvent, CloseWithEvent, CloseWithSpontaneousEvent }; + Q_ENUM(CloseMode) enum Direction { DirectionNorth = 0x01, @@ -329,6 +248,7 @@ public: DirectionSouth = 0x02, DirectionWest = 0x20 }; + Q_ENUM(Direction) // Functions. explicit QWidgetPrivate(int version = QObjectPrivateVersion); @@ -342,8 +262,16 @@ public: QTLWExtra *maybeTopData() const; QPainter *sharedPainter() const; void setSharedPainter(QPainter *painter); - QWidgetBackingStore *maybeBackingStore() const; - QWidgetWindow *windowHandle() const; + QWidgetRepaintManager *maybeRepaintManager() const; + + enum class WindowHandleMode { + Direct, + Closest, + TopLevel + }; + QWindow *windowHandle(WindowHandleMode mode = WindowHandleMode::Direct) const; + + QScreen *associatedScreen() const; template <typename T> void repaint(T t); @@ -405,38 +333,38 @@ public: void setUpdatesEnabled_helper(bool ); bool updateBrushOrigin(QPainter *, const QBrush &brush) const; - void paintBackground(QPainter *, const QRegion &, int flags = DrawAsRoot) const; + void paintBackground(QPainter *, const QRegion &, DrawWidgetFlags flags = DrawAsRoot) const; bool isAboutToShow() const; QRegion prepareToRender(const QRegion ®ion, QWidget::RenderFlags renderFlags); void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion, QWidget::RenderFlags renderFlags); void render(QPaintDevice *target, const QPoint &targetOffset, const QRegion &sourceRegion, QWidget::RenderFlags renderFlags); - void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, int flags, - QPainter *sharedPainter = 0, QWidgetBackingStore *backingStore = 0); + void drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags, + QPainter *sharedPainter = nullptr, QWidgetRepaintManager *repaintManager = nullptr); void sendPaintEvent(const QRegion &toBePainted); void paintSiblingsRecursive(QPaintDevice *pdev, const QObjectList& children, int index, - const QRegion &rgn, const QPoint &offset, int flags, - QPainter *sharedPainter, QWidgetBackingStore *backingStore); + const QRegion &rgn, const QPoint &offset, DrawWidgetFlags flags, + QPainter *sharedPainter, QWidgetRepaintManager *repaintManager); #if QT_CONFIG(graphicsview) static QGraphicsProxyWidget * nearestGraphicsProxyWidget(const QWidget *origin); #endif - void repaint_sys(const QRegion &rgn); + bool shouldPaintOnScreen() const; + void paintOnScreen(const QRegion &rgn); QRect clipRect() const; QRegion clipRegion() const; void setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion ®ion); void subtractOpaqueChildren(QRegion &rgn, const QRect &clipRect) const; - void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = 0, + void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = nullptr, bool alsoNonOpaque = false) const; void clipToEffectiveMask(QRegion ®ion) const; void updateIsOpaque(); void setOpaque(bool opaque); void updateIsTranslucent(); - bool paintOnScreen() const; #if QT_CONFIG(graphicseffect) void invalidateGraphicsEffectsRecursively(); #endif // QT_CONFIG(graphicseffect) @@ -463,6 +391,8 @@ public: void syncBackingStore(); void syncBackingStore(const QRegion ®ion); + bool shouldDiscardSyncRequest() const; + // tells the input method about the widgets transform void updateWidgetTransform(QEvent *event); @@ -527,7 +457,7 @@ public: void getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const; void setLayoutItemMargins(int left, int top, int right, int bottom); - void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0); + void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = nullptr); void updateContentsRect(); QMargins safeAreaMargins() const; @@ -557,7 +487,7 @@ public: QGraphicsProxyWidget *ancestorProxy = widget->d_func()->nearestGraphicsProxyWidget(widget); //It's embedded if it has an ancestor if (ancestorProxy) { - if (!bypassGraphicsProxyWidget(widget) && ancestorProxy->scene() != 0) { + if (!bypassGraphicsProxyWidget(widget) && ancestorProxy->scene() != nullptr) { // One view, let be smart and return the viewport rect then the popup is aligned if (ancestorProxy->scene()->views().size() == 1) { QGraphicsView *view = ancestorProxy->scene()->views().at(0); @@ -588,7 +518,7 @@ public: } inline void restoreRedirected() - { redirectDev = 0; } + { redirectDev = nullptr; } inline void enforceNativeChildren() { @@ -654,7 +584,7 @@ public: QOpenGLContext *shareContext() const; - virtual QObject *focusObject() { return 0; } + virtual QObject *focusObject() { return nullptr; } #ifndef QT_NO_OPENGL virtual GLuint textureId() const { return 0; } @@ -662,7 +592,7 @@ public: Q_Q(QWidget); return q->testAttribute(Qt::WA_AlwaysStackOnTop) ? QPlatformTextureList::StacksOnTop - : QPlatformTextureList::Flags(0); + : QPlatformTextureList::Flags(nullptr); } virtual QImage grabFramebuffer() { return QImage(); } virtual void beginBackingStorePainting() { } @@ -698,7 +628,7 @@ public: // Variables. // Regular pointers (keep them together to avoid gaps on 64 bit architectures). - QWExtra *extra; + std::unique_ptr<QWExtra> extra; QWidget *focus_next; QWidget *focus_prev; QWidget *focus_child; @@ -792,109 +722,8 @@ public: // *************************** Platform specific ************************************ #if defined(Q_OS_WIN) uint noPaintOnScreen : 1; // see qwidget.cpp ::paintEngine() -#endif -#if 0 /* Used to be included in Qt4 for Q_WS_X11 */ // <----------------------------------------------------------- X11 - Qt::HANDLE picture; - static QWidget *mouseGrabber; - static QWidget *keyboardGrabber; - - void setWindowRole(); - void sendStartupMessage(const char *message) const; - void x11UpdateIsOpaque(); - bool isBackgroundInherited() const; - void updateX11AcceptFocus(); - QPoint mapToGlobal(const QPoint &pos) const; - QPoint mapFromGlobal(const QPoint &pos) const; -#elif 0 /* Used to be included in Qt4 for Q_WS_WIN */ // <--------------------------------------------------------- WIN -#ifndef QT_NO_GESTURES - uint nativeGesturePanEnabled : 1; -#endif - bool shouldShowMaximizeButton(); - void winUpdateIsOpaque(); - void reparentChildren(); -#if QT_CONFIG(draganddrop) - QOleDropTarget *registerOleDnd(QWidget *widget); - void unregisterOleDnd(QWidget *widget, QOleDropTarget *target); -#endif - void grabMouseWhileInWindow(); - void registerTouchWindow(); - void winSetupGestures(); -#elif defined(Q_OS_MAC) // <--------------------------------------------------------- MAC +#elif defined(Q_OS_MAC) void macUpdateSizeAttribute(); -#elif 0 /* Used to be included in Qt4 for Q_WS_MAC */ // <--------------------------------------------------------- MAC (old stuff) - // This is new stuff - uint needWindowChange : 1; - - // Each wiget keeps a list of all its child and grandchild OpenGL widgets. - // This list is used to update the gl context whenever a parent and a granparent - // moves, and also to check for intersections with gl widgets within the window - // when a widget moves. - struct GlWidgetInfo - { - GlWidgetInfo(QWidget *widget) : widget(widget), lastUpdateWidget(0) { } - bool operator==(const GlWidgetInfo &other) const { return (widget == other.widget); } - QWidget * widget; - QWidget * lastUpdateWidget; - }; - - // dirtyOnWidget contains the areas in the widget that needs to be repained, - // in the same way as dirtyOnScreen does for the window. Areas are added in - // dirtyWidget_sys and cleared in the paint event. In scroll_sys we then use - // this information repaint invalid areas when widgets are scrolled. - QRegion dirtyOnWidget; - EventHandlerRef window_event; - QList<GlWidgetInfo> glWidgets; - - //these are here just for code compat (HIViews) - Qt::HANDLE qd_hd; - - void macUpdateHideOnSuspend(); - void macUpdateOpaqueSizeGrip(); - void macUpdateIgnoreMouseEvents(); - void macUpdateMetalAttribute(); - void macUpdateIsOpaque(); - void macSetNeedsDisplay(QRegion region); - void setEnabled_helper_sys(bool enable); - bool isRealWindow() const; - void adjustWithinMaxAndMinSize(int &w, int &h); - void applyMaxAndMinSizeOnWindow(); - void update_sys(const QRect &rect); - void update_sys(const QRegion &rgn); - void setGeometry_sys_helper(int, int, int, int, bool); - void updateMaximizeButton_sys(); - void createWindow_sys(); - void recreateMacWindow(); - void setSubWindowStacking(bool set); - void setWindowLevel(); - void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef); - void syncCocoaMask(); - void finishCocoaMaskSetup(); - // Did we add the drawRectOriginal method? - bool drawRectOriginalAdded; - // Is the original drawRect method available? - bool originalDrawMethod; - // Do we need to change the methods? - bool changeMethods; - - // Unified toolbar variables - bool isInUnifiedToolbar; - QUnifiedToolbarSurface *unifiedSurface; - QPoint toolbar_offset; - QWidget *toolbar_ancestor; - bool flushRequested; - bool touchEventsEnabled; - void determineWindowClass(); - void transferChildren(); - bool qt_mac_dnd_event(uint, DragRef); - void toggleDrawers(bool); - //mac event functions - static bool qt_create_root_win(); - static void qt_clean_root_win(); - static bool qt_mac_update_sizer(QWidget *, int up = 0); - static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *); - static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *); - static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool); - void registerTouchWindow(bool enable = true); #endif void setNetWmWindowTypes(bool skipIfMissing = false); @@ -902,18 +731,20 @@ public: bool stealMouseGrab(bool grab); }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QWidgetPrivate::DrawWidgetFlags) + struct QWidgetPaintContext { - inline QWidgetPaintContext(QPaintDevice *d, const QRegion &r, const QPoint &o, int f, - QPainter *p, QWidgetBackingStore *b) - : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), backingStore(b), painter(0) {} + inline QWidgetPaintContext(QPaintDevice *d, const QRegion &r, const QPoint &o, QWidgetPrivate::DrawWidgetFlags f, + QPainter *p, QWidgetRepaintManager *rpm) + : pdev(d), rgn(r), offset(o), flags(f), sharedPainter(p), repaintManager(rpm), painter(nullptr) {} QPaintDevice *pdev; QRegion rgn; QPoint offset; - int flags; + QWidgetPrivate::DrawWidgetFlags flags; QPainter *sharedPainter; - QWidgetBackingStore *backingStore; + QWidgetRepaintManager *repaintManager; QPainter *painter; }; @@ -922,14 +753,14 @@ class QWidgetEffectSourcePrivate : public QGraphicsEffectSourcePrivate { public: QWidgetEffectSourcePrivate(QWidget *widget) - : QGraphicsEffectSourcePrivate(), m_widget(widget), context(0), updateDueToGraphicsEffect(false) + : QGraphicsEffectSourcePrivate(), m_widget(widget), context(nullptr), updateDueToGraphicsEffect(false) {} void detach() override - { m_widget->d_func()->graphicsEffect = 0; } + { m_widget->d_func()->graphicsEffect = nullptr; } const QGraphicsItem *graphicsItem() const override - { return 0; } + { return nullptr; } const QWidget *widget() const override { return m_widget; } @@ -955,7 +786,7 @@ public: } const QStyleOption *styleOption() const override - { return 0; } + { return nullptr; } QRect deviceRect() const override { return m_widget->window()->rect(); } @@ -974,25 +805,25 @@ public: inline QWExtra *QWidgetPrivate::extraData() const { - return extra; + return extra.get(); } inline QTLWExtra *QWidgetPrivate::topData() const { const_cast<QWidgetPrivate *>(this)->createTLExtra(); - return extra->topextra; + return extra->topextra.get(); } inline QTLWExtra *QWidgetPrivate::maybeTopData() const { - return extra ? extra->topextra : 0; + return extra ? extra->topextra.get() : nullptr; } inline QPainter *QWidgetPrivate::sharedPainter() const { Q_Q(const QWidget); QTLWExtra *x = q->window()->d_func()->maybeTopData(); - return x ? x->sharedPainter : 0; + return x ? x->sharedPainter : nullptr; } inline void QWidgetPrivate::setSharedPainter(QPainter *painter) @@ -1009,18 +840,11 @@ inline bool QWidgetPrivate::pointInsideRectAndMask(const QPoint &p) const || extra->mask.contains(p)); } -inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const +inline QWidgetRepaintManager *QWidgetPrivate::maybeRepaintManager() const { Q_Q(const QWidget); QTLWExtra *x = q->window()->d_func()->maybeTopData(); - return x ? x->backingStoreTracker.data() : 0; -} - -inline QWidgetWindow *QWidgetPrivate::windowHandle() const -{ - if (QTLWExtra *x = maybeTopData()) - return x->window; - return nullptr; + return x ? x->repaintManager.get() : nullptr; } QT_END_NAMESPACE diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h deleted file mode 100644 index 4d15ab138e..0000000000 --- a/src/widgets/kernel/qwidgetbackingstore_p.h +++ /dev/null @@ -1,311 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QWIDGETBACKINGSTORE_P_H -#define QWIDGETBACKINGSTORE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtWidgets/private/qtwidgetsglobal_p.h> -#include <QDebug> -#include <QtWidgets/qwidget.h> -#include <private/qwidget_p.h> -#include <QtGui/qbackingstore.h> - -QT_BEGIN_NAMESPACE - -class QPlatformTextureList; -class QPlatformTextureListWatcher; -class QWidgetBackingStore; - -struct BeginPaintInfo { - inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), backingStoreRecreated(0) {} - uint wasFlushed : 1; - uint nothingToPaint : 1; - uint backingStoreRecreated : 1; -}; - -#ifndef QT_NO_OPENGL -class QPlatformTextureListWatcher : public QObject -{ - Q_OBJECT - -public: - QPlatformTextureListWatcher(QWidgetBackingStore *backingStore); - void watch(QPlatformTextureList *textureList); - bool isLocked() const; - -private slots: - void onLockStatusChanged(bool locked); - -private: - QHash<QPlatformTextureList *, bool> m_locked; - QWidgetBackingStore *m_backingStore; -}; -#endif - -class Q_AUTOTEST_EXPORT QWidgetBackingStore -{ -public: - enum UpdateTime { - UpdateNow, - UpdateLater - }; - - enum BufferState{ - BufferValid, - BufferInvalid - }; - - QWidgetBackingStore(QWidget *t); - ~QWidgetBackingStore(); - - static void showYellowThing(QWidget *widget, const QRegion &rgn, int msec, bool); - - void sync(QWidget *exposedWidget, const QRegion &exposedRegion); - void sync(); - void flush(QWidget *widget = 0); - - QBackingStore *backingStore() const { return store; } - - inline bool isDirty() const - { - return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && dirtyRenderToTextureWidgets.isEmpty()); - } - - template <class T> - void markDirty(const T &r, QWidget *widget, UpdateTime updateTime = UpdateLater, - BufferState bufferState = BufferValid); - -private: - QWidget *tlw; - QRegion dirtyOnScreen; // needsFlush - QRegion dirty; // needsRepaint - QRegion dirtyFromPreviousSync; - QVector<QWidget *> dirtyWidgets; - QVector<QWidget *> dirtyRenderToTextureWidgets; - QVector<QWidget *> *dirtyOnScreenWidgets; - QList<QWidget *> staticWidgets; - QBackingStore *store; - uint updateRequestSent : 1; - - QPlatformTextureListWatcher *textureListWatcher; - QElapsedTimer perfTime; - int perfFrames; - - void sendUpdateRequest(QWidget *widget, UpdateTime updateTime); - - static bool flushPaint(QWidget *widget, const QRegion &rgn); - static void unflushPaint(QWidget *widget, const QRegion &rgn); - static void qt_flush(QWidget *widget, const QRegion ®ion, QBackingStore *backingStore, - QWidget *tlw, - QPlatformTextureList *widgetTextures, - QWidgetBackingStore *widgetBackingStore); - - void doSync(); - bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget); - void releaseBuffer(); - - void beginPaint(QRegion &toClean, QWidget *widget, QBackingStore *backingStore, - BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates = true); - void endPaint(const QRegion &cleaned, QBackingStore *backingStore, BeginPaintInfo *beginPaintInfo); - - QRegion dirtyRegion(QWidget *widget = 0) const; - QRegion staticContents(QWidget *widget = 0, const QRect &withinClipRect = QRect()) const; - - void markDirtyOnScreen(const QRegion &dirtyOnScreen, QWidget *widget, const QPoint &topLevelOffset); - - void removeDirtyWidget(QWidget *w); - - void updateLists(QWidget *widget); - - bool syncAllowed(); - - inline void addDirtyWidget(QWidget *widget, const QRegion &rgn) - { - if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { - QWidgetPrivate *widgetPrivate = widget->d_func(); -#if QT_CONFIG(graphicseffect) - if (widgetPrivate->graphicsEffect) - widgetPrivate->dirty = widgetPrivate->effectiveRectFor(rgn.boundingRect()); - else -#endif // QT_CONFIG(graphicseffect) - widgetPrivate->dirty = rgn; - dirtyWidgets.append(widget); - widgetPrivate->inDirtyList = true; - } - } - - inline void addDirtyRenderToTextureWidget(QWidget *widget) - { - if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { - QWidgetPrivate *widgetPrivate = widget->d_func(); - Q_ASSERT(widgetPrivate->renderToTexture); - dirtyRenderToTextureWidgets.append(widget); - widgetPrivate->inDirtyList = true; - } - } - - inline void dirtyWidgetsRemoveAll(QWidget *widget) - { - int i = 0; - while (i < dirtyWidgets.size()) { - if (dirtyWidgets.at(i) == widget) - dirtyWidgets.remove(i); - else - ++i; - } - } - - inline void addStaticWidget(QWidget *widget) - { - if (!widget) - return; - - Q_ASSERT(widget->testAttribute(Qt::WA_StaticContents)); - if (!staticWidgets.contains(widget)) - staticWidgets.append(widget); - } - - inline void removeStaticWidget(QWidget *widget) - { staticWidgets.removeAll(widget); } - - // Move the reparented widget and all its static children from this backing store - // to the new backing store if reparented into another top-level / backing store. - inline void moveStaticWidgets(QWidget *reparented) - { - Q_ASSERT(reparented); - QWidgetBackingStore *newBs = reparented->d_func()->maybeBackingStore(); - if (newBs == this) - return; - - int i = 0; - while (i < staticWidgets.size()) { - QWidget *w = staticWidgets.at(i); - if (reparented == w || reparented->isAncestorOf(w)) { - staticWidgets.removeAt(i); - if (newBs) - newBs->addStaticWidget(w); - } else { - ++i; - } - } - } - - inline QRect topLevelRect() const - { - return tlw->data->crect; - } - - inline void appendDirtyOnScreenWidget(QWidget *widget) - { - if (!widget) - return; - - if (!dirtyOnScreenWidgets) { - dirtyOnScreenWidgets = new QVector<QWidget *>; - dirtyOnScreenWidgets->append(widget); - } else if (!dirtyOnScreenWidgets->contains(widget)) { - dirtyOnScreenWidgets->append(widget); - } - } - - inline void dirtyOnScreenWidgetsRemoveAll(QWidget *widget) - { - if (!widget || !dirtyOnScreenWidgets) - return; - - int i = 0; - while (i < dirtyOnScreenWidgets->size()) { - if (dirtyOnScreenWidgets->at(i) == widget) - dirtyOnScreenWidgets->remove(i); - else - ++i; - } - } - - inline void resetWidget(QWidget *widget) - { - if (widget) { - widget->d_func()->inDirtyList = false; - widget->d_func()->isScrolled = false; - widget->d_func()->isMoved = false; - widget->d_func()->dirty = QRegion(); - } - } - - inline void updateStaticContentsSize() - { - for (int i = 0; i < staticWidgets.size(); ++i) { - QWidgetPrivate *wd = staticWidgets.at(i)->d_func(); - if (!wd->extra) - wd->createExtra(); - wd->extra->staticContentsSize = wd->data.crect.size(); - } - } - - inline bool hasStaticContents() const - { -#if defined(Q_OS_WIN) - return !staticWidgets.isEmpty(); -#else - return !staticWidgets.isEmpty() && false; -#endif - } - - friend QRegion qt_dirtyRegion(QWidget *); - friend class QWidgetPrivate; - friend class QWidget; - friend class QBackingStore; - - Q_DISABLE_COPY_MOVE(QWidgetBackingStore) -}; - -QT_END_NAMESPACE - -#endif // QBACKINGSTORE_P_H diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetrepaintmanager.cpp index c51527f8bc..c3211e275f 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetrepaintmanager.cpp @@ -40,7 +40,7 @@ #include "qplatformdefs.h" -#include "qwidgetbackingstore_p.h" +#include "qwidgetrepaintmanager_p.h" #include <QtCore/qglobal.h> #include <QtCore/qdebug.h> @@ -63,459 +63,138 @@ #include <qpa/qplatformbackingstore.h> -#if defined(Q_OS_WIN) && !defined(QT_NO_PAINT_DEBUG) -# include <QtCore/qt_windows.h> -# include <qpa/qplatformnativeinterface.h> -#endif +#include <private/qmemory_p.h> QT_BEGIN_NAMESPACE -extern QRegion qt_dirtyRegion(QWidget *); - #ifndef QT_NO_OPENGL Q_GLOBAL_STATIC(QPlatformTextureList, qt_dummy_platformTextureList) -#endif -static bool hasPlatformWindow(QWidget *widget) -{ - return widget && widget->windowHandle() && widget->windowHandle()->handle(); -} - -/** - * Flushes the contents of the \a backingStore into the screen area of \a widget. - * \a region is the region to be updated in \a widget coordinates. - */ -void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion ®ion, QBackingStore *backingStore, - QWidget *tlw, QPlatformTextureList *widgetTextures, - QWidgetBackingStore *widgetBackingStore) +// Watches one or more QPlatformTextureLists for changes in the lock state and +// triggers a backingstore sync when all the registered lists turn into +// unlocked state. This is essential when a custom composeAndFlush() +// implementation in a platform plugin is not synchronous and keeps +// holding on to the textures for some time even after returning from there. +class QPlatformTextureListWatcher : public QObject { -#ifdef QT_NO_OPENGL - Q_UNUSED(widgetTextures); - Q_ASSERT(!region.isEmpty()); -#else - Q_ASSERT(!region.isEmpty() || widgetTextures); -#endif - Q_ASSERT(widget); - Q_ASSERT(backingStore); - Q_ASSERT(tlw); -#if !defined(QT_NO_PAINT_DEBUG) - static int flushUpdate = qEnvironmentVariableIntValue("QT_FLUSH_UPDATE"); - if (flushUpdate > 0) - QWidgetBackingStore::showYellowThing(widget, region, flushUpdate * 10, false); -#endif - - if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen)) - return; - - // Foreign Windows do not have backing store content and must not be flushed - if (QWindow *widgetWindow = widget->windowHandle()) { - if (widgetWindow->type() == Qt::ForeignWindow) - return; + Q_OBJECT +public: + QPlatformTextureListWatcher(QWidgetRepaintManager *repaintManager) + : m_repaintManager(repaintManager) {} + + void watch(QPlatformTextureList *textureList) { + connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool))); + m_locked[textureList] = textureList->isLocked(); } - static bool fpsDebug = qEnvironmentVariableIntValue("QT_DEBUG_FPS"); - if (fpsDebug) { - if (!widgetBackingStore->perfFrames++) - widgetBackingStore->perfTime.start(); - if (widgetBackingStore->perfTime.elapsed() > 5000) { - double fps = double(widgetBackingStore->perfFrames * 1000) / widgetBackingStore->perfTime.restart(); - qDebug("FPS: %.1f\n", fps); - widgetBackingStore->perfFrames = 0; + bool isLocked() const { + foreach (bool v, m_locked) { + if (v) + return true; } + return false; } - QPoint offset; - if (widget != tlw) - offset += widget->mapTo(tlw, QPoint()); - - QRegion effectiveRegion = region; -#ifndef QT_NO_OPENGL - const bool compositionWasActive = widget->d_func()->renderToTextureComposeActive; - if (!widgetTextures) { - widget->d_func()->renderToTextureComposeActive = false; - // Detect the case of falling back to the normal flush path when no - // render-to-texture widgets are visible anymore. We will force one - // last flush to go through the OpenGL-based composition to prevent - // artifacts. The next flush after this one will use the normal path. - if (compositionWasActive) - widgetTextures = qt_dummy_platformTextureList; - } else { - widget->d_func()->renderToTextureComposeActive = true; - } - // When changing the composition status, make sure the dirty region covers - // the entire widget. Just having e.g. the shown/hidden render-to-texture - // widget's area marked as dirty is incorrect when changing flush paths. - if (compositionWasActive != widget->d_func()->renderToTextureComposeActive) - effectiveRegion = widget->rect(); - - // re-test since we may have been forced to this path via the dummy texture list above - if (widgetTextures) { - qt_window_private(tlw->windowHandle())->compositing = true; - widget->window()->d_func()->sendComposeStatus(widget->window(), false); - // A window may have alpha even when the app did not request - // WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends - // to rely on translucency, in order to decide if it should clear to transparent or opaque. - const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground); - backingStore->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset, - widgetTextures, translucentBackground); - widget->window()->d_func()->sendComposeStatus(widget->window(), true); - } else -#endif - backingStore->flush(effectiveRegion, widget->windowHandle(), offset); -} - -#ifndef QT_NO_PAINT_DEBUG -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - -static void showYellowThing_win(QWidget *widget, const QRegion ®ion, int msec) -{ - // We expect to be passed a native parent. - QWindow *nativeWindow = widget->windowHandle(); - if (!nativeWindow) - return; - void *hdcV = QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("getDC"), nativeWindow); - if (!hdcV) - return; - const HDC hdc = reinterpret_cast<HDC>(hdcV); - - static const COLORREF colors[] = {RGB(255, 255, 0), RGB(255, 200, 55), RGB(200, 255, 55), RGB(200, 200, 0)}; - - static size_t i = 0; - const HBRUSH brush = CreateSolidBrush(colors[i]); - i = (i + 1) % (sizeof(colors) / sizeof(colors[0])); - - for (const QRect &rect : region) { - RECT winRect; - SetRect(&winRect, rect.left(), rect.top(), rect.right(), rect.bottom()); - FillRect(hdc, &winRect, brush); - } - DeleteObject(brush); - QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("releaseDC"), nativeWindow); - ::Sleep(msec); -} -#endif // defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - -void QWidgetBackingStore::showYellowThing(QWidget *widget, const QRegion &toBePainted, int msec, bool unclipped) -{ -#ifdef Q_OS_WINRT - Q_UNUSED(msec) +private slots: + void onLockStatusChanged(bool locked) { + QPlatformTextureList *tl = static_cast<QPlatformTextureList *>(sender()); + m_locked[tl] = locked; + if (!isLocked()) + m_repaintManager->sync(); + } + +private: + QHash<QPlatformTextureList *, bool> m_locked; + QWidgetRepaintManager *m_repaintManager; +}; #endif - QRegion paintRegion = toBePainted; - QRect widgetRect = widget->rect(); - - if (!hasPlatformWindow(widget)) { - QWidget *nativeParent = widget->nativeParentWidget(); - const QPoint offset = widget->mapTo(nativeParent, QPoint(0, 0)); - paintRegion.translate(offset); - widgetRect.translate(offset); - widget = nativeParent; - } - -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - Q_UNUSED(unclipped); - showYellowThing_win(widget, paintRegion, msec); -#else - //flags to fool painter - bool paintUnclipped = widget->testAttribute(Qt::WA_PaintUnclipped); - if (unclipped && !widget->d_func()->paintOnScreen()) - widget->setAttribute(Qt::WA_PaintUnclipped); - - const bool setFlag = !widget->testAttribute(Qt::WA_WState_InPaintEvent); - if (setFlag) - widget->setAttribute(Qt::WA_WState_InPaintEvent); - - //setup the engine - QPaintEngine *pe = widget->paintEngine(); - if (pe) { - pe->setSystemClip(paintRegion); - { - QPainter p(widget); - p.setClipRegion(paintRegion); - static int i = 0; - switch (i) { - case 0: - p.fillRect(widgetRect, QColor(255,255,0)); - break; - case 1: - p.fillRect(widgetRect, QColor(255,200,55)); - break; - case 2: - p.fillRect(widgetRect, QColor(200,255,55)); - break; - case 3: - p.fillRect(widgetRect, QColor(200,200,0)); - break; - } - i = (i+1) & 3; - p.end(); - } - } - if (setFlag) - widget->setAttribute(Qt::WA_WState_InPaintEvent, false); - - //restore - widget->setAttribute(Qt::WA_PaintUnclipped, paintUnclipped); - - if (pe) - pe->setSystemClip(QRegion()); - -#if defined(Q_OS_UNIX) - ::usleep(1000 * msec); -#endif -#endif // !Q_OS_WIN -} +// --------------------------------------------------------------------------- -bool QWidgetBackingStore::flushPaint(QWidget *widget, const QRegion &rgn) +QWidgetRepaintManager::QWidgetRepaintManager(QWidget *topLevel) + : tlw(topLevel), store(tlw->backingStore()) { - if (!widget) - return false; - - int delay = 0; - if (widget->testAttribute(Qt::WA_WState_InPaintEvent)) { - static int flushPaintEvent = qEnvironmentVariableIntValue("QT_FLUSH_PAINT_EVENT"); - if (!flushPaintEvent) - return false; - delay = flushPaintEvent; - } else { - static int flushPaint = qEnvironmentVariableIntValue("QT_FLUSH_PAINT"); - if (!flushPaint) - return false; - delay = flushPaint; - } + Q_ASSERT(store); - QWidgetBackingStore::showYellowThing(widget, rgn, delay * 10, true); - return true; + // Ensure all existing subsurfaces and static widgets are added to their respective lists. + updateLists(topLevel); } -void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn) +void QWidgetRepaintManager::updateLists(QWidget *cur) { - if (widget->d_func()->paintOnScreen() || rgn.isEmpty()) - return; - - QWidget *tlw = widget->window(); - QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); - if (!tlwExtra) + if (!cur) return; - qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, 0, tlw->d_func()->maybeBackingStore()); -} -#endif // QT_NO_PAINT_DEBUG - -/* - Moves the whole rect by (dx, dy) in widget's coordinate system. - Doesn't generate any updates. -*/ -bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *widget) -{ - const QPoint pos(widget->mapTo(tlw, rect.topLeft())); - const QRect tlwRect(QRect(pos, rect.size())); - if (dirty.intersects(tlwRect)) - return false; // We don't want to scroll junk. - return store->scroll(tlwRect, dx, dy); -} - -void QWidgetBackingStore::releaseBuffer() -{ - if (store) - store->resize(QSize()); -} - -/*! - Prepares the window surface to paint a\ toClean region of the \a widget and - updates the BeginPaintInfo struct accordingly. - - The \a toClean region might be clipped by the window surface. -*/ -void QWidgetBackingStore::beginPaint(QRegion &toClean, QWidget *widget, QBackingStore *backingStore, - BeginPaintInfo *returnInfo, bool toCleanIsInTopLevelCoordinates) -{ - Q_UNUSED(widget); - Q_UNUSED(toCleanIsInTopLevelCoordinates); - - // Always flush repainted areas. - dirtyOnScreen += toClean; - -#ifdef QT_NO_PAINT_DEBUG - backingStore->beginPaint(toClean); -#else - returnInfo->wasFlushed = QWidgetBackingStore::flushPaint(tlw, toClean); - // Avoid deadlock with QT_FLUSH_PAINT: the server will wait for - // the BackingStore lock, so if we hold that, the server will - // never release the Communication lock that we are waiting for in - // sendSynchronousCommand - if (!returnInfo->wasFlushed) - backingStore->beginPaint(toClean); -#endif - - Q_UNUSED(returnInfo); -} + QList<QObject*> children = cur->children(); + for (int i = 0; i < children.size(); ++i) { + QWidget *child = qobject_cast<QWidget*>(children.at(i)); + if (!child || child->isWindow()) + continue; -void QWidgetBackingStore::endPaint(const QRegion &cleaned, QBackingStore *backingStore, - BeginPaintInfo *beginPaintInfo) -{ -#ifndef QT_NO_PAINT_DEBUG - if (!beginPaintInfo->wasFlushed) - backingStore->endPaint(); - else - QWidgetBackingStore::unflushPaint(tlw, cleaned); -#else - Q_UNUSED(beginPaintInfo); - Q_UNUSED(cleaned); - backingStore->endPaint(); -#endif + updateLists(child); + } - flush(); + if (cur->testAttribute(Qt::WA_StaticContents)) + addStaticWidget(cur); } -/*! - Returns the region (in top-level coordinates) that needs repaint and/or flush. - - If the widget is non-zero, only the dirty region for the widget is returned - and the region will be in widget coordinates. -*/ -QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const +QWidgetRepaintManager::~QWidgetRepaintManager() { - const bool widgetDirty = widget && widget != tlw; - const QRect tlwRect(topLevelRect()); - const QRect surfaceGeometry(tlwRect.topLeft(), store->size()); - if (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size()) { - if (widgetDirty) { - const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size()); - const QPoint offset(widget->mapTo(tlw, QPoint())); - const QRect dirtyWidgetRect(dirtyTlwRect & widget->rect().translated(offset)); - return dirtyWidgetRect.translated(-offset); - } - return QRect(QPoint(), tlwRect.size()); - } - - // Calculate the region that needs repaint. - QRegion r(dirty); - for (int i = 0; i < dirtyWidgets.size(); ++i) { - QWidget *w = dirtyWidgets.at(i); - if (widgetDirty && w != widget && !widget->isAncestorOf(w)) - continue; - r += w->d_func()->dirty.translated(w->mapTo(tlw, QPoint())); - } - - // Append the region that needs flush. - r += dirtyOnScreen; - - if (dirtyOnScreenWidgets) { // Only in use with native child widgets. - for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) { - QWidget *w = dirtyOnScreenWidgets->at(i); - if (widgetDirty && w != widget && !widget->isAncestorOf(w)) - continue; - QWidgetPrivate *wd = w->d_func(); - Q_ASSERT(wd->needsFlush); - r += wd->needsFlush->translated(w->mapTo(tlw, QPoint())); - } - } - - if (widgetDirty) { - // Intersect with the widget geometry and translate to its coordinates. - const QPoint offset(widget->mapTo(tlw, QPoint())); - r &= widget->rect().translated(offset); - r.translate(-offset); - } - return r; + for (int c = 0; c < dirtyWidgets.size(); ++c) + resetWidget(dirtyWidgets.at(c)); + for (int c = 0; c < dirtyRenderToTextureWidgets.size(); ++c) + resetWidget(dirtyRenderToTextureWidgets.at(c)); } /*! - Returns the static content inside the \a parent if non-zero; otherwise the static content - for the entire backing store is returned. The content will be clipped to \a withinClipRect - if non-empty. + \internal + Invalidates the \a r (in widget's coordinates) of the backing store, i.e. + all widgets intersecting with the region will be repainted when the backing + store is synced. */ -QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &withinClipRect) const +template <class T> +void QWidgetPrivate::invalidateBackingStore(const T &r) { - if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) { - const QSize surfaceGeometry(store->size()); - QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height()); - if (!withinClipRect.isEmpty()) - surfaceRect &= withinClipRect; - return QRegion(surfaceRect); - } - - QRegion region; - if (parent && parent->d_func()->children.isEmpty()) - return region; - - const bool clipToRect = !withinClipRect.isEmpty(); - const int count = staticWidgets.count(); - for (int i = 0; i < count; ++i) { - QWidget *w = staticWidgets.at(i); - QWidgetPrivate *wd = w->d_func(); - if (!wd->isOpaque || !wd->extra || wd->extra->staticContentsSize.isEmpty() - || !w->isVisible() || (parent && !parent->isAncestorOf(w))) { - continue; - } - - QRect rect(0, 0, wd->extra->staticContentsSize.width(), wd->extra->staticContentsSize.height()); - const QPoint offset = w->mapTo(parent ? parent : tlw, QPoint()); - if (clipToRect) - rect &= withinClipRect.translated(-offset); - if (rect.isEmpty()) - continue; - - rect &= wd->clipRect(); - if (rect.isEmpty()) - continue; + if (r.isEmpty()) + return; - QRegion visible(rect); - wd->clipToEffectiveMask(visible); - if (visible.isEmpty()) - continue; - wd->subtractOpaqueSiblings(visible, 0, /*alsoNonOpaque=*/true); + if (QCoreApplication::closingDown()) + return; - visible.translate(offset); - region += visible; - } + Q_Q(QWidget); + if (!q->isVisible() || !q->updatesEnabled()) + return; - return region; -} + QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); + if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore) + return; -void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTime) -{ - if (!widget) + T clipped(r); + clipped &= clipRect(); + if (clipped.isEmpty()) return; -#ifndef QT_NO_OPENGL - // Having every repaint() leading to a sync/flush is bad as it causes - // compositing and waiting for vsync each and every time. Change to - // UpdateLater, except for approx. once per frame to prevent starvation in - // case the control does not get back to the event loop. - QWidget *w = widget->window(); - if (updateTime == UpdateNow && w && w->windowHandle() && QWindowPrivate::get(w->windowHandle())->compositing) { - int refresh = 60; - QScreen *ws = w->windowHandle()->screen(); - if (ws) - refresh = ws->refreshRate(); - QWindowPrivate *wd = QWindowPrivate::get(w->windowHandle()); - if (wd->lastComposeTime.isValid()) { - const qint64 elapsed = wd->lastComposeTime.elapsed(); - if (elapsed <= qint64(1000.0f / refresh)) - updateTime = UpdateLater; - } - } -#endif + if (!graphicsEffect && extra && extra->hasMask) { + QRegion masked(extra->mask); + masked &= clipped; + if (masked.isEmpty()) + return; - switch (updateTime) { - case UpdateLater: - updateRequestSent = true; - QApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority); - break; - case UpdateNow: { - QEvent event(QEvent::UpdateRequest); - QApplication::sendEvent(widget, &event); - break; - } + tlwExtra->repaintManager->markDirty(masked, q, + QWidgetRepaintManager::UpdateLater, QWidgetRepaintManager::BufferInvalid); + } else { + tlwExtra->repaintManager->markDirty(clipped, q, + QWidgetRepaintManager::UpdateLater, QWidgetRepaintManager::BufferInvalid); } } +// Needed by tst_QWidget +template Q_AUTOTEST_EXPORT void QWidgetPrivate::invalidateBackingStore<QRect>(const QRect &r); static inline QRect widgetRectFor(QWidget *, const QRect &r) { return r; } static inline QRect widgetRectFor(QWidget *widget, const QRegion &) { return widget->rect(); } /*! + \internal Marks the region of the widget as dirty (if not already marked as dirty) and posts an UpdateRequest event to the top-level widget (if not already posted). @@ -527,8 +206,11 @@ static inline QRect widgetRectFor(QWidget *widget, const QRegion &) { return wid instead of the top-level widget, and bufferState is completely ignored. */ template <class T> -void QWidgetBackingStore::markDirty(const T &r, QWidget *widget, UpdateTime updateTime, BufferState bufferState) +void QWidgetRepaintManager::markDirty(const T &r, QWidget *widget, UpdateTime updateTime, BufferState bufferState) { + qCInfo(lcWidgetPainting) << "Marking" << r << "of" << widget << "dirty" + << "with" << updateTime; + Q_ASSERT(tlw->d_func()->extra); Q_ASSERT(tlw->d_func()->extra->topextra); Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize); @@ -544,7 +226,7 @@ void QWidgetBackingStore::markDirty(const T &r, QWidget *widget, UpdateTime upda // --------------------------------------------------------------------------- - if (widget->d_func()->paintOnScreen()) { + if (widget->d_func()->shouldPaintOnScreen()) { if (widget->d_func()->dirty.isEmpty()) { widget->d_func()->dirty = r; sendUpdateRequest(widget, updateTime); @@ -631,70 +313,35 @@ void QWidgetBackingStore::markDirty(const T &r, QWidget *widget, UpdateTime upda if (updateTime == UpdateNow) sendUpdateRequest(tlw, updateTime); } -template void QWidgetBackingStore::markDirty<QRect>(const QRect &, QWidget *, UpdateTime, BufferState); -template void QWidgetBackingStore::markDirty<QRegion>(const QRegion &, QWidget *, UpdateTime, BufferState); +template void QWidgetRepaintManager::markDirty<QRect>(const QRect &, QWidget *, UpdateTime, BufferState); +template void QWidgetRepaintManager::markDirty<QRegion>(const QRegion &, QWidget *, UpdateTime, BufferState); -/*! - Marks the \a region of the \a widget as dirty on screen. The \a region will be copied from - the backing store to the \a widget's native parent next time flush() is called. - - Paint on screen widgets are ignored. -*/ -void QWidgetBackingStore::markDirtyOnScreen(const QRegion ®ion, QWidget *widget, const QPoint &topLevelOffset) +void QWidgetRepaintManager::addDirtyWidget(QWidget *widget, const QRegion &rgn) { - if (!widget || widget->d_func()->paintOnScreen() || region.isEmpty()) - return; - -#if 0 // Used to be included in Qt4 for Q_WS_MAC - if (!widget->testAttribute(Qt::WA_WState_InPaintEvent)) - dirtyOnScreen += region.translated(topLevelOffset); - return; -#endif - - // Top-level. - if (widget == tlw) { - if (!widget->testAttribute(Qt::WA_WState_InPaintEvent)) - dirtyOnScreen += region; - return; - } - - // Alien widgets. - if (!hasPlatformWindow(widget) && !widget->isWindow()) { - QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case). - if (nativeParent == tlw) { - if (!widget->testAttribute(Qt::WA_WState_InPaintEvent)) - dirtyOnScreen += region.translated(topLevelOffset); - return; - } - - // Alien widgets with native parent != tlw. - QWidgetPrivate *nativeParentPrivate = nativeParent->d_func(); - if (!nativeParentPrivate->needsFlush) - nativeParentPrivate->needsFlush = new QRegion; - const QPoint nativeParentOffset = widget->mapTo(nativeParent, QPoint()); - *nativeParentPrivate->needsFlush += region.translated(nativeParentOffset); - appendDirtyOnScreenWidget(nativeParent); - return; + if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { + QWidgetPrivate *widgetPrivate = widget->d_func(); +#if QT_CONFIG(graphicseffect) + if (widgetPrivate->graphicsEffect) + widgetPrivate->dirty = widgetPrivate->effectiveRectFor(rgn.boundingRect()); + else +#endif // QT_CONFIG(graphicseffect) + widgetPrivate->dirty = rgn; + dirtyWidgets.append(widget); + widgetPrivate->inDirtyList = true; } - - // Native child widgets. - QWidgetPrivate *widgetPrivate = widget->d_func(); - if (!widgetPrivate->needsFlush) - widgetPrivate->needsFlush = new QRegion; - *widgetPrivate->needsFlush += region; - appendDirtyOnScreenWidget(widget); } -void QWidgetBackingStore::removeDirtyWidget(QWidget *w) +void QWidgetRepaintManager::removeDirtyWidget(QWidget *w) { if (!w) return; - dirtyWidgetsRemoveAll(w); - dirtyOnScreenWidgetsRemoveAll(w); + dirtyWidgets.removeAll(w); dirtyRenderToTextureWidgets.removeAll(w); resetWidget(w); + needsFlushWidgets.removeAll(w); + QWidgetPrivate *wd = w->d_func(); const int n = wd->children.count(); for (int i = 0; i < n; ++i) { @@ -703,46 +350,71 @@ void QWidgetBackingStore::removeDirtyWidget(QWidget *w) } } -void QWidgetBackingStore::updateLists(QWidget *cur) +void QWidgetRepaintManager::resetWidget(QWidget *widget) { - if (!cur) - return; - - QList<QObject*> children = cur->children(); - for (int i = 0; i < children.size(); ++i) { - QWidget *child = qobject_cast<QWidget*>(children.at(i)); - if (!child || child->isWindow()) - continue; - - updateLists(child); + if (widget) { + widget->d_func()->inDirtyList = false; + widget->d_func()->isScrolled = false; + widget->d_func()->isMoved = false; + widget->d_func()->dirty = QRegion(); } +} - if (cur->testAttribute(Qt::WA_StaticContents)) - addStaticWidget(cur); +void QWidgetRepaintManager::addDirtyRenderToTextureWidget(QWidget *widget) +{ + if (widget && !widget->d_func()->inDirtyList && !widget->data->in_destructor) { + QWidgetPrivate *widgetPrivate = widget->d_func(); + Q_ASSERT(widgetPrivate->renderToTexture); + dirtyRenderToTextureWidgets.append(widget); + widgetPrivate->inDirtyList = true; + } } -QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel) - : tlw(topLevel), - dirtyOnScreenWidgets(0), - updateRequestSent(0), - textureListWatcher(0), - perfFrames(0) +void QWidgetRepaintManager::sendUpdateRequest(QWidget *widget, UpdateTime updateTime) { - store = tlw->backingStore(); - Q_ASSERT(store); + if (!widget) + return; - // Ensure all existing subsurfaces and static widgets are added to their respective lists. - updateLists(topLevel); + qCInfo(lcWidgetPainting) << "Sending update request to" << widget << "with" << updateTime; + +#ifndef QT_NO_OPENGL + // Having every repaint() leading to a sync/flush is bad as it causes + // compositing and waiting for vsync each and every time. Change to + // UpdateLater, except for approx. once per frame to prevent starvation in + // case the control does not get back to the event loop. + QWidget *w = widget->window(); + if (updateTime == UpdateNow && w && w->windowHandle() && QWindowPrivate::get(w->windowHandle())->compositing) { + int refresh = 60; + QScreen *ws = w->windowHandle()->screen(); + if (ws) + refresh = ws->refreshRate(); + QWindowPrivate *wd = QWindowPrivate::get(w->windowHandle()); + if (wd->lastComposeTime.isValid()) { + const qint64 elapsed = wd->lastComposeTime.elapsed(); + if (elapsed <= qint64(1000.0f / refresh)) + updateTime = UpdateLater; + } + } +#endif + + switch (updateTime) { + case UpdateLater: + updateRequestSent = true; + QCoreApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority); + break; + case UpdateNow: { + QEvent event(QEvent::UpdateRequest); + QCoreApplication::sendEvent(widget, &event); + break; + } + } } -QWidgetBackingStore::~QWidgetBackingStore() -{ - for (int c = 0; c < dirtyWidgets.size(); ++c) - resetWidget(dirtyWidgets.at(c)); - for (int c = 0; c < dirtyRenderToTextureWidgets.size(); ++c) - resetWidget(dirtyRenderToTextureWidgets.at(c)); +// --------------------------------------------------------------------------- - delete dirtyOnScreenWidgets; +static bool hasPlatformWindow(QWidget *widget) +{ + return widget && widget->windowHandle() && widget->windowHandle()->handle(); } static QVector<QRect> getSortedRectsToScroll(const QRegion ®ion, int dx, int dy) @@ -810,7 +482,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) invalidateBackingStore((newRect & clipR).translated(-data.crect.topLeft())); } else { - QWidgetBackingStore *wbs = x->backingStoreTracker.data(); + QWidgetRepaintManager *repaintManager = x->repaintManager.get(); QRegion childExpose(newRect & clipR); QRegion overlappedExpose; @@ -822,7 +494,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) const QVector<QRect> rectsToScroll = getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy); for (QRect rect : rectsToScroll) { - if (wbs->bltRect(rect, dx, dy, pw)) { + if (repaintManager->bltRect(rect, dx, dy, pw)) { childExpose -= rect.translated(dx, dy); } } @@ -842,7 +514,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) } if (!childExpose.isEmpty()) { childExpose.translate(-data.crect.topLeft()); - wbs->markDirty(childExpose, q); + repaintManager->markDirty(childExpose, q); isMoved = true; } } @@ -853,14 +525,14 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) parentExpose += QRegion(newRect) - extra->mask.translated(data.crect.topLeft()); if (!parentExpose.isEmpty()) { - wbs->markDirty(parentExpose, pw); + repaintManager->markDirty(parentExpose, pw); pd->isMoved = true; } if (childUpdatesEnabled) { QRegion needsFlush(sourceRect); needsFlush += destRect; - wbs->markDirtyOnScreen(needsFlush, pw, toplevelOffset); + repaintManager->markNeedsFlush(pw, needsFlush, toplevelOffset); } } } @@ -874,8 +546,8 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) if (x->inTopLevelResize) return; - QWidgetBackingStore *wbs = x->backingStoreTracker.data(); - if (!wbs) + QWidgetRepaintManager *repaintManager = x->repaintManager.get(); + if (!repaintManager) return; static const bool accelEnv = qEnvironmentVariableIntValue("QT_NO_FAST_SCROLL") == 0; @@ -906,7 +578,7 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) const QVector<QRect> rectsToScroll = getSortedRectsToScroll(QRegion(sourceRect) - overlappedExpose, dx, dy); for (const QRect &rect : rectsToScroll) { - if (wbs->bltRect(rect, dx, dy, q)) { + if (repaintManager->bltRect(rect, dx, dy, q)) { childExpose -= rect.translated(dx, dy); } } @@ -933,17 +605,32 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) if (!overlappedExpose.isEmpty()) invalidateBackingStore(overlappedExpose); if (!childExpose.isEmpty()) { - wbs->markDirty(childExpose, q); + repaintManager->markDirty(childExpose, q); isScrolled = true; } // Instead of using native scroll-on-screen, we copy from // backingstore, giving only one screen update for each // scroll, and a solid appearance - wbs->markDirtyOnScreen(destRect, q, toplevelOffset); + repaintManager->markNeedsFlush(q, destRect, toplevelOffset); } } +/* + Moves the whole rect by (dx, dy) in widget's coordinate system. + Doesn't generate any updates. +*/ +bool QWidgetRepaintManager::bltRect(const QRect &rect, int dx, int dy, QWidget *widget) +{ + const QPoint pos(widget->mapTo(tlw, rect.topLeft())); + const QRect tlwRect(QRect(pos, rect.size())); + if (dirty.intersects(tlwRect)) + return false; // We don't want to scroll junk. + return store->scroll(tlwRect, dx, dy); +} + +// --------------------------------------------------------------------------- + #ifndef QT_NO_OPENGL static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures, QVector<QWidget *> *nativeChildren) { @@ -969,15 +656,15 @@ static void findAllTextureWidgetsRecursively(QWidget *tlw, QWidget *widget) // textureChildSeen does not take native child widgets into account and that's good. if (QWidgetPrivate::get(widget)->textureChildSeen) { QVector<QWidget *> nativeChildren; - QScopedPointer<QPlatformTextureList> tl(new QPlatformTextureList); + auto tl = qt_make_unique<QPlatformTextureList>(); // Look for texture widgets (incl. widget itself) from 'widget' down, // but skip subtrees with a parent of a native child widget. - findTextureWidgetsRecursively(tlw, widget, tl.data(), &nativeChildren); + findTextureWidgetsRecursively(tlw, widget, tl.get(), &nativeChildren); // tl may be empty regardless of textureChildSeen if we have native or hidden children. if (!tl->isEmpty()) - QWidgetPrivate::get(tlw)->topData()->widgetTextures.append(tl.take()); + QWidgetPrivate::get(tlw)->topData()->widgetTextures.push_back(std::move(tl)); // Native child widgets, if there was any, get their own separate QPlatformTextureList. - foreach (QWidget *ncw, nativeChildren) { + for (QWidget *ncw : qAsConst(nativeChildren)) { if (QWidgetPrivate::get(ncw)->textureChildSeen) findAllTextureWidgetsRecursively(tlw, ncw); } @@ -986,12 +673,12 @@ static void findAllTextureWidgetsRecursively(QWidget *tlw, QWidget *widget) static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) { - foreach (QPlatformTextureList *tl, QWidgetPrivate::get(tlw)->topData()->widgetTextures) { + for (const auto &tl : QWidgetPrivate::get(tlw)->topData()->widgetTextures) { Q_ASSERT(!tl->isEmpty()); for (int i = 0; i < tl->count(); ++i) { QWidget *w = static_cast<QWidget *>(tl->source(i)); if ((hasPlatformWindow(w) && w == widget) || (!hasPlatformWindow(w) && w->nativeParentWidget() == widget)) - return tl; + return tl.get(); } } @@ -1011,39 +698,6 @@ static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) return 0; } -// Watches one or more QPlatformTextureLists for changes in the lock state and -// triggers a backingstore sync when all the registered lists turn into -// unlocked state. This is essential when a custom composeAndFlush() -// implementation in a platform plugin is not synchronous and keeps -// holding on to the textures for some time even after returning from there. -QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore) - : m_backingStore(backingStore) -{ -} - -void QPlatformTextureListWatcher::watch(QPlatformTextureList *textureList) -{ - connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool))); - m_locked[textureList] = textureList->isLocked(); -} - -bool QPlatformTextureListWatcher::isLocked() const -{ - foreach (bool v, m_locked) { - if (v) - return true; - } - return false; -} - -void QPlatformTextureListWatcher::onLockStatusChanged(bool locked) -{ - QPlatformTextureList *tl = static_cast<QPlatformTextureList *>(sender()); - m_locked[tl] = locked; - if (!isLocked()) - m_backingStore->sync(); -} - #else static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) @@ -1055,48 +709,19 @@ static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) #endif // QT_NO_OPENGL -static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra) -{ - if (!tlw || !tlwExtra || !tlw->testAttribute(Qt::WA_Mapped) || !tlw->isVisible()) - return true; - - return false; -} - -bool QWidgetBackingStore::syncAllowed() -{ -#ifndef QT_NO_OPENGL - QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); - if (textureListWatcher && !textureListWatcher->isLocked()) { - textureListWatcher->deleteLater(); - textureListWatcher = 0; - } else if (!tlwExtra->widgetTextures.isEmpty()) { - bool skipSync = false; - foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) { - if (tl->isLocked()) { - if (!textureListWatcher) - textureListWatcher = new QPlatformTextureListWatcher(this); - if (!textureListWatcher->isLocked()) - textureListWatcher->watch(tl); - skipSync = true; - } - } - if (skipSync) // cannot compose due to widget textures being in use - return false; - } -#endif - return true; -} +// --------------------------------------------------------------------------- /*! Synchronizes the \a exposedRegion of the \a exposedWidget with the backing store. - If there's nothing to repaint, the area is flushed and painting does not occur; - otherwise the area is marked as dirty on screen and will be flushed right after - we are done with all painting. + If there are dirty widgets, including but not limited to the \a exposedWidget, + these will be repainted first. The backingstore is then flushed to the screen, + regardless of whether or not there were any repaints. */ -void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedRegion) +void QWidgetRepaintManager::sync(QWidget *exposedWidget, const QRegion &exposedRegion) { + qCInfo(lcWidgetPainting) << "Syncing" << exposedRegion << "of" << exposedWidget; + QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); if (!tlw->isVisible() || !tlwExtra || tlwExtra->inTopLevelResize) return; @@ -1109,28 +734,30 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg // Nothing to repaint. if (!isDirty() && store->size().isValid()) { - QPlatformTextureList *tl = widgetTexturesFor(tlw, exposedWidget); - qt_flush(exposedWidget, tl ? QRegion() : exposedRegion, store, tlw, tl, this); + QPlatformTextureList *widgetTextures = widgetTexturesFor(tlw, exposedWidget); + flush(exposedWidget, widgetTextures ? QRegion() : exposedRegion, widgetTextures); return; } - if (exposedWidget != tlw) - markDirtyOnScreen(exposedRegion, exposedWidget, exposedWidget->mapTo(tlw, QPoint())); - else - markDirtyOnScreen(exposedRegion, exposedWidget, QPoint()); + // As requests to sync a specific widget typically comes from an expose event + // we can't rely solely on our own dirty tracking to decide what to flush, and + // need to respect the platform's request to at least flush the entire widget, + QPoint offset = exposedWidget != tlw ? exposedWidget->mapTo(tlw, QPoint()) : QPoint(); + markNeedsFlush(exposedWidget, exposedRegion, offset); if (syncAllowed()) - doSync(); + paintAndFlush(); } /*! Synchronizes the backing store, i.e. dirty areas are repainted and flushed. */ -void QWidgetBackingStore::sync() +void QWidgetRepaintManager::sync() { + qCInfo(lcWidgetPainting) << "Syncing dirty widgets"; + updateRequestSent = false; - QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); - if (discardSyncRequest(tlw, tlwExtra)) { + if (qt_widget_private(tlw)->shouldDiscardSyncRequest()) { // If the top-level is minimized, it's not visible on the screen so we can delay the // update until it's shown again. In order to do that we must keep the dirty states. // These will be cleared when we receive the first expose after showNormal(). @@ -1146,16 +773,50 @@ void QWidgetBackingStore::sync() } if (syncAllowed()) - doSync(); + paintAndFlush(); } -void QWidgetBackingStore::doSync() +bool QWidgetPrivate::shouldDiscardSyncRequest() const { + Q_Q(const QWidget); + return !maybeTopData() || !q->testAttribute(Qt::WA_Mapped) || !q->isVisible(); +} + +bool QWidgetRepaintManager::syncAllowed() +{ +#ifndef QT_NO_OPENGL + QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); + if (textureListWatcher && !textureListWatcher->isLocked()) { + textureListWatcher->deleteLater(); + textureListWatcher = 0; + } else if (!tlwExtra->widgetTextures.empty()) { + bool skipSync = false; + for (const auto &tl : tlwExtra->widgetTextures) { + if (tl->isLocked()) { + if (!textureListWatcher) + textureListWatcher = new QPlatformTextureListWatcher(this); + if (!textureListWatcher->isLocked()) + textureListWatcher->watch(tl.get()); + skipSync = true; + } + } + if (skipSync) // cannot compose due to widget textures being in use + return false; + } +#endif + return true; +} + +void QWidgetRepaintManager::paintAndFlush() +{ + qCInfo(lcWidgetPainting) << "Painting and flushing dirty" + << "top level" << dirty << "and dirty widgets" << dirtyWidgets; + const bool updatesDisabled = !tlw->updatesEnabled(); bool repaintAllWidgets = false; const bool inTopLevelResize = tlw->d_func()->maybeTopData()->inTopLevelResize; - const QRect tlwRect(topLevelRect()); + const QRect tlwRect = tlw->data->crect; const QRect surfaceGeometry(tlwRect.topLeft(), store->size()); if ((inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) { if (hasStaticContents() && !store->size().isEmpty() ) { @@ -1249,10 +910,9 @@ void QWidgetBackingStore::doSync() // The search is cut at native widget boundaries, meaning that each native child widget // has its own list for the subtree below it. QTLWExtra *tlwExtra = tlw->d_func()->topData(); - qDeleteAll(tlwExtra->widgetTextures); tlwExtra->widgetTextures.clear(); findAllTextureWidgetsRecursively(tlw, tlw); - qt_window_private(tlw->windowHandle())->compositing = false; // will get updated in qt_flush() + qt_window_private(tlw->windowHandle())->compositing = false; // will get updated in flush() #endif if (toClean.isEmpty()) { @@ -1278,10 +938,7 @@ void QWidgetBackingStore::doSync() if (hasPlatformWindow(w) || (npw && npw != tlw)) { if (!hasPlatformWindow(w)) w = npw; - QWidgetPrivate *wPrivate = w->d_func(); - if (!wPrivate->needsFlush) - wPrivate->needsFlush = new QRegion; - appendDirtyOnScreenWidget(w); + markNeedsFlush(w); } } } @@ -1295,7 +952,7 @@ void QWidgetBackingStore::doSync() } #ifndef QT_NO_OPENGL - foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) { + for (const auto &tl : tlwExtra->widgetTextures) { for (int i = 0; i < tl->count(); ++i) { QWidget *w = static_cast<QWidget *>(tl->source(i)); if (dirtyRenderToTextureWidgets.contains(w)) { @@ -1324,15 +981,7 @@ void QWidgetBackingStore::doSync() } #endif - BeginPaintInfo beginPaintInfo; - beginPaint(toClean, tlw, store, &beginPaintInfo); - if (beginPaintInfo.nothingToPaint) { - for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) - resetWidget(opaqueNonOverlappedWidgets[i]); - dirty = QRegion(); - updateRequestSent = false; - return; - } + store->beginPaint(toClean); // Must do this before sending any paint events because // the size may change in the paint event. @@ -1346,7 +995,7 @@ void QWidgetBackingStore::doSync() QWidget *w = opaqueNonOverlappedWidgets[i]; QWidgetPrivate *wd = w->d_func(); - int flags = QWidgetPrivate::DrawRecursive; + QWidgetPrivate::DrawWidgetFlags flags = QWidgetPrivate::DrawRecursive; // Scrolled and moved widgets must draw all children. if (!wd->isScrolled && !wd->isMoved) flags |= QWidgetPrivate::DontDrawOpaqueChildren; @@ -1364,56 +1013,301 @@ void QWidgetBackingStore::doSync() // Paint the rest with composition. if (repaintAllWidgets || !dirtyCopy.isEmpty()) { - const int flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive; + QWidgetPrivate::DrawWidgetFlags flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive; tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, QPoint(), flags, 0, this); } - endPaint(toClean, store, &beginPaintInfo); + store->endPaint(); + + flush(); +} + +/*! + Marks the \a region of the \a widget as needing a flush. The \a region will be copied from + the backing store to the \a widget's native parent next time flush() is called. + + Paint on screen widgets are ignored. +*/ +void QWidgetRepaintManager::markNeedsFlush(QWidget *widget, const QRegion ®ion, const QPoint &topLevelOffset) +{ + if (!widget || widget->d_func()->shouldPaintOnScreen() || region.isEmpty()) + return; + + if (widget == tlw) { + // Top-level (native) + qCInfo(lcWidgetPainting) << "Marking" << region << "of top level" + << widget << "as needing flush"; + topLevelNeedsFlush += region; + } else if (!hasPlatformWindow(widget) && !widget->isWindow()) { + QWidget *nativeParent = widget->nativeParentWidget(); + qCInfo(lcWidgetPainting) << "Marking" << region << "of" + << widget << "as needing flush in" << nativeParent + << "at offset" << topLevelOffset; + if (nativeParent == tlw) { + // Alien widgets with the top-level as the native parent (common case) + topLevelNeedsFlush += region.translated(topLevelOffset); + } else { + // Alien widgets with native parent != tlw + const QPoint nativeParentOffset = widget->mapTo(nativeParent, QPoint()); + markNeedsFlush(nativeParent, region.translated(nativeParentOffset)); + } + } else { + // Native child widgets + qCInfo(lcWidgetPainting) << "Marking" << region + << "of native child" << widget << "as needing flush"; + markNeedsFlush(widget, region); + } +} + +void QWidgetRepaintManager::markNeedsFlush(QWidget *widget, const QRegion ®ion) +{ + if (!widget) + return; + + auto *widgetPrivate = qt_widget_private(widget); + if (!widgetPrivate->needsFlush) + widgetPrivate->needsFlush = new QRegion; + + *widgetPrivate->needsFlush += region; + + if (!needsFlushWidgets.contains(widget)) + needsFlushWidgets.append(widget); } /*! Flushes the contents of the backing store into the top-level widget. - If the \a widget is non-zero, the content is flushed to the \a widget. - If the \a surface is non-zero, the content of the \a surface is flushed. */ -void QWidgetBackingStore::flush(QWidget *widget) +void QWidgetRepaintManager::flush() { - const bool hasDirtyOnScreenWidgets = dirtyOnScreenWidgets && !dirtyOnScreenWidgets->isEmpty(); + qCInfo(lcWidgetPainting) << "Flushing top level" + << topLevelNeedsFlush << "and children" << needsFlushWidgets; + + const bool hasNeedsFlushWidgets = !needsFlushWidgets.isEmpty(); bool flushed = false; - // Flush the region in dirtyOnScreen. - if (!dirtyOnScreen.isEmpty()) { - QWidget *target = widget ? widget : tlw; - qt_flush(target, dirtyOnScreen, store, tlw, widgetTexturesFor(tlw, tlw), this); - dirtyOnScreen = QRegion(); + // Flush the top level widget + if (!topLevelNeedsFlush.isEmpty()) { + flush(tlw, topLevelNeedsFlush, widgetTexturesFor(tlw, tlw)); + topLevelNeedsFlush = QRegion(); flushed = true; } - // Render-to-texture widgets are not in dirtyOnScreen so flush if we have not done it above. - if (!flushed && !hasDirtyOnScreenWidgets) { + // Render-to-texture widgets are not in topLevelNeedsFlush so flush if we have not done it above. + if (!flushed && !hasNeedsFlushWidgets) { #ifndef QT_NO_OPENGL - if (!tlw->d_func()->topData()->widgetTextures.isEmpty()) { - QPlatformTextureList *tl = widgetTexturesFor(tlw, tlw); - if (tl) { - QWidget *target = widget ? widget : tlw; - qt_flush(target, QRegion(), store, tlw, tl, this); - } + if (!tlw->d_func()->topData()->widgetTextures.empty()) { + if (QPlatformTextureList *widgetTextures = widgetTexturesFor(tlw, tlw)) + flush(tlw, QRegion(), widgetTextures); } #endif } - if (!hasDirtyOnScreenWidgets) + if (!hasNeedsFlushWidgets) return; - for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) { - QWidget *w = dirtyOnScreenWidgets->at(i); + for (QWidget *w : qExchange(needsFlushWidgets, {})) { QWidgetPrivate *wd = w->d_func(); Q_ASSERT(wd->needsFlush); QPlatformTextureList *widgetTexturesForNative = wd->textureChildSeen ? widgetTexturesFor(tlw, w) : 0; - qt_flush(w, *wd->needsFlush, store, tlw, widgetTexturesForNative, this); + flush(w, *wd->needsFlush, widgetTexturesForNative); *wd->needsFlush = QRegion(); } - dirtyOnScreenWidgets->clear(); +} + +/* + Flushes the contents of the backingstore into the screen area of \a widget. + + \a region is the region to be updated in \a widget coordinates. + */ +void QWidgetRepaintManager::flush(QWidget *widget, const QRegion ®ion, QPlatformTextureList *widgetTextures) +{ +#ifdef QT_NO_OPENGL + Q_UNUSED(widgetTextures); + Q_ASSERT(!region.isEmpty()); +#else + Q_ASSERT(!region.isEmpty() || widgetTextures); +#endif + Q_ASSERT(widget); + Q_ASSERT(tlw); + + if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen)) + return; + + // Foreign Windows do not have backing store content and must not be flushed + if (QWindow *widgetWindow = widget->windowHandle()) { + if (widgetWindow->type() == Qt::ForeignWindow) + return; + } + + qCInfo(lcWidgetPainting) << "Flushing" << region << "of" << widget; + + static bool fpsDebug = qEnvironmentVariableIntValue("QT_DEBUG_FPS"); + if (fpsDebug) { + if (!perfFrames++) + perfTime.start(); + if (perfTime.elapsed() > 5000) { + double fps = double(perfFrames * 1000) / perfTime.restart(); + qDebug("FPS: %.1f\n", fps); + perfFrames = 0; + } + } + + QPoint offset; + if (widget != tlw) + offset += widget->mapTo(tlw, QPoint()); + + QRegion effectiveRegion = region; +#ifndef QT_NO_OPENGL + const bool compositionWasActive = widget->d_func()->renderToTextureComposeActive; + if (!widgetTextures) { + widget->d_func()->renderToTextureComposeActive = false; + // Detect the case of falling back to the normal flush path when no + // render-to-texture widgets are visible anymore. We will force one + // last flush to go through the OpenGL-based composition to prevent + // artifacts. The next flush after this one will use the normal path. + if (compositionWasActive) + widgetTextures = qt_dummy_platformTextureList; + } else { + widget->d_func()->renderToTextureComposeActive = true; + } + // When changing the composition status, make sure the dirty region covers + // the entire widget. Just having e.g. the shown/hidden render-to-texture + // widget's area marked as dirty is incorrect when changing flush paths. + if (compositionWasActive != widget->d_func()->renderToTextureComposeActive) + effectiveRegion = widget->rect(); + + // re-test since we may have been forced to this path via the dummy texture list above + if (widgetTextures) { + qt_window_private(tlw->windowHandle())->compositing = true; + widget->window()->d_func()->sendComposeStatus(widget->window(), false); + // A window may have alpha even when the app did not request + // WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends + // to rely on translucency, in order to decide if it should clear to transparent or opaque. + const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground); + store->handle()->composeAndFlush(widget->windowHandle(), effectiveRegion, offset, + widgetTextures, translucentBackground); + widget->window()->d_func()->sendComposeStatus(widget->window(), true); + } else +#endif + store->flush(effectiveRegion, widget->windowHandle(), offset); +} + +// --------------------------------------------------------------------------- + +void QWidgetRepaintManager::addStaticWidget(QWidget *widget) +{ + if (!widget) + return; + + Q_ASSERT(widget->testAttribute(Qt::WA_StaticContents)); + if (!staticWidgets.contains(widget)) + staticWidgets.append(widget); +} + +// Move the reparented widget and all its static children from this backing store +// to the new backing store if reparented into another top-level / backing store. +void QWidgetRepaintManager::moveStaticWidgets(QWidget *reparented) +{ + Q_ASSERT(reparented); + QWidgetRepaintManager *newPaintManager = reparented->d_func()->maybeRepaintManager(); + if (newPaintManager == this) + return; + + int i = 0; + while (i < staticWidgets.size()) { + QWidget *w = staticWidgets.at(i); + if (reparented == w || reparented->isAncestorOf(w)) { + staticWidgets.removeAt(i); + if (newPaintManager) + newPaintManager->addStaticWidget(w); + } else { + ++i; + } + } +} + +void QWidgetRepaintManager::removeStaticWidget(QWidget *widget) +{ + staticWidgets.removeAll(widget); +} + +bool QWidgetRepaintManager::hasStaticContents() const +{ +#if defined(Q_OS_WIN) + return !staticWidgets.isEmpty(); +#else + return !staticWidgets.isEmpty() && false; +#endif +} + +/*! + Returns the static content inside the \a parent if non-zero; otherwise the static content + for the entire backing store is returned. The content will be clipped to \a withinClipRect + if non-empty. +*/ +QRegion QWidgetRepaintManager::staticContents(QWidget *parent, const QRect &withinClipRect) const +{ + if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) { + const QSize surfaceGeometry(store->size()); + QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height()); + if (!withinClipRect.isEmpty()) + surfaceRect &= withinClipRect; + return QRegion(surfaceRect); + } + + QRegion region; + if (parent && parent->d_func()->children.isEmpty()) + return region; + + const bool clipToRect = !withinClipRect.isEmpty(); + const int count = staticWidgets.count(); + for (int i = 0; i < count; ++i) { + QWidget *w = staticWidgets.at(i); + QWidgetPrivate *wd = w->d_func(); + if (!wd->isOpaque || !wd->extra || wd->extra->staticContentsSize.isEmpty() + || !w->isVisible() || (parent && !parent->isAncestorOf(w))) { + continue; + } + + QRect rect(0, 0, wd->extra->staticContentsSize.width(), wd->extra->staticContentsSize.height()); + const QPoint offset = w->mapTo(parent ? parent : tlw, QPoint()); + if (clipToRect) + rect &= withinClipRect.translated(-offset); + if (rect.isEmpty()) + continue; + + rect &= wd->clipRect(); + if (rect.isEmpty()) + continue; + + QRegion visible(rect); + wd->clipToEffectiveMask(visible); + if (visible.isEmpty()) + continue; + wd->subtractOpaqueSiblings(visible, 0, /*alsoNonOpaque=*/true); + + visible.translate(offset); + region += visible; + } + + return region; +} + +void QWidgetRepaintManager::updateStaticContentsSize() +{ + for (int i = 0; i < staticWidgets.size(); ++i) { + QWidgetPrivate *wd = staticWidgets.at(i)->d_func(); + if (!wd->extra) + wd->createExtra(); + wd->extra->staticContentsSize = wd->data.crect.size(); + } +} + +// --------------------------------------------------------------------------- + +bool QWidgetRepaintManager::isDirty() const +{ + return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && dirtyRenderToTextureWidgets.isEmpty()); } /*! @@ -1437,8 +1331,8 @@ void QWidgetPrivate::invalidateBackingStore_resizeHelper(const QPoint &oldPos, c if (!staticContents || graphicsEffect) { QRegion staticChildren; - QWidgetBackingStore *bs = 0; - if (offset.isNull() && (bs = maybeBackingStore())) + QWidgetRepaintManager *bs = 0; + if (offset.isNull() && (bs = maybeRepaintManager())) staticChildren = bs->staticContents(q, oldWidgetRect); const bool hasStaticChildren = !staticChildren.isEmpty(); @@ -1508,101 +1402,6 @@ void QWidgetPrivate::invalidateBackingStore_resizeHelper(const QPoint &oldPos, c } } -/*! - Invalidates the \a r (in widget's coordinates) of the backing store, i.e. - all widgets intersecting with the region will be repainted when the backing - store is synced. -*/ -template <class T> -void QWidgetPrivate::invalidateBackingStore(const T &r) -{ - if (r.isEmpty()) - return; - - if (QApplication::closingDown()) - return; - - Q_Q(QWidget); - if (!q->isVisible() || !q->updatesEnabled()) - return; - - QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData(); - if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore) - return; - - T clipped(r); - clipped &= clipRect(); - if (clipped.isEmpty()) - return; - - if (!graphicsEffect && extra && extra->hasMask) { - QRegion masked(extra->mask); - masked &= clipped; - if (masked.isEmpty()) - return; - - tlwExtra->backingStoreTracker->markDirty(masked, q, - QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid); - } else { - tlwExtra->backingStoreTracker->markDirty(clipped, q, - QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid); - } -} -// Needed by tst_QWidget -template Q_AUTOTEST_EXPORT void QWidgetPrivate::invalidateBackingStore<QRect>(const QRect &r); - -void QWidgetPrivate::repaint_sys(const QRegion &rgn) -{ - if (data.in_destructor) - return; - - Q_Q(QWidget); - if (discardSyncRequest(q, maybeTopData())) - return; - - if (q->testAttribute(Qt::WA_StaticContents)) { - if (!extra) - createExtra(); - extra->staticContentsSize = data.crect.size(); - } - - QPaintEngine *engine = q->paintEngine(); - - // QGLWidget does not support partial updates if: - // 1) The context is double buffered - // 2) The context is single buffered and auto-fill background is enabled. - const bool noPartialUpdateSupport = (engine && (engine->type() == QPaintEngine::OpenGL - || engine->type() == QPaintEngine::OpenGL2)) - && (usesDoubleBufferedGLContext || q->autoFillBackground()); - QRegion toBePainted(noPartialUpdateSupport ? q->rect() : rgn); - -#if 0 // Used to be included in Qt4 for Q_WS_MAC - // No difference between update() and repaint() on the Mac. - update_sys(toBePainted); - return; -#endif - - toBePainted &= clipRect(); - clipToEffectiveMask(toBePainted); - if (toBePainted.isEmpty()) - return; // Nothing to repaint. - -#ifndef QT_NO_PAINT_DEBUG - bool flushed = QWidgetBackingStore::flushPaint(q, toBePainted); -#endif - - drawWidget(q, toBePainted, QPoint(), QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawPaintOnScreen, 0); - -#ifndef QT_NO_PAINT_DEBUG - if (flushed) - QWidgetBackingStore::unflushPaint(q, toBePainted); -#endif - - if (Q_UNLIKELY(q->paintingActive())) - qWarning("QWidget::repaint: It is dangerous to leave painters active on a widget outside of the PaintEvent"); -} - - QT_END_NAMESPACE -#include "moc_qwidgetbackingstore_p.cpp" +#include "qwidgetrepaintmanager.moc" diff --git a/src/widgets/kernel/qwidgetrepaintmanager_p.h b/src/widgets/kernel/qwidgetrepaintmanager_p.h new file mode 100644 index 0000000000..58687383f4 --- /dev/null +++ b/src/widgets/kernel/qwidgetrepaintmanager_p.h @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QWIDGETREPAINTMANAGER_P_H +#define QWIDGETREPAINTMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtWidgets/private/qtwidgetsglobal_p.h> +#include <QDebug> +#include <QtWidgets/qwidget.h> +#include <private/qwidget_p.h> +#include <QtGui/qbackingstore.h> + +QT_BEGIN_NAMESPACE + +class QPlatformTextureList; +class QPlatformTextureListWatcher; +class QWidgetRepaintManager; + +class Q_AUTOTEST_EXPORT QWidgetRepaintManager +{ + Q_GADGET +public: + enum UpdateTime { + UpdateNow, + UpdateLater + }; + Q_ENUM(UpdateTime) + + enum BufferState{ + BufferValid, + BufferInvalid + }; + Q_ENUM(BufferState) + + QWidgetRepaintManager(QWidget *t); + ~QWidgetRepaintManager(); + + QBackingStore *backingStore() const { return store; } + void setBackingStore(QBackingStore *backingStore) { store = backingStore; } + + template <class T> + void markDirty(const T &r, QWidget *widget, UpdateTime updateTime = UpdateLater, + BufferState bufferState = BufferValid); + + void removeDirtyWidget(QWidget *w); + + void sync(QWidget *exposedWidget, const QRegion &exposedRegion); + void sync(); + + void markNeedsFlush(QWidget *widget, const QRegion ®ion, const QPoint &topLevelOffset); + + void addStaticWidget(QWidget *widget); + void moveStaticWidgets(QWidget *reparented); + void removeStaticWidget(QWidget *widget); + QRegion staticContents(QWidget *widget = nullptr, const QRect &withinClipRect = QRect()) const; + + bool bltRect(const QRect &rect, int dx, int dy, QWidget *widget); + +private: + void updateLists(QWidget *widget); + + void addDirtyWidget(QWidget *widget, const QRegion &rgn); + void resetWidget(QWidget *widget); + + void addDirtyRenderToTextureWidget(QWidget *widget); + + void sendUpdateRequest(QWidget *widget, UpdateTime updateTime); + + bool syncAllowed(); + void paintAndFlush(); + + void markNeedsFlush(QWidget *widget, const QRegion ®ion = QRegion()); + + void flush(); + void flush(QWidget *widget, const QRegion ®ion, QPlatformTextureList *widgetTextures); + + bool isDirty() const; + + bool hasStaticContents() const; + void updateStaticContentsSize(); + + QWidget *tlw = nullptr; + QBackingStore *store = nullptr; + + QRegion dirty; // needsRepaint + QVector<QWidget *> dirtyWidgets; + QVector<QWidget *> dirtyRenderToTextureWidgets; + + QRegion topLevelNeedsFlush; + QVector<QWidget *> needsFlushWidgets; + + QList<QWidget *> staticWidgets; + + QPlatformTextureListWatcher *textureListWatcher = nullptr; + + bool updateRequestSent = false; + + QElapsedTimer perfTime; + int perfFrames = 0; + + Q_DISABLE_COPY_MOVE(QWidgetRepaintManager) +}; + +QT_END_NAMESPACE + +#endif // QWIDGETREPAINTMANAGER_P_H diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index aad505ed29..24f8c5ce43 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -46,7 +46,7 @@ #ifndef QT_NO_ACCESSIBILITY #include <QtGui/qaccessible.h> #endif -#include <private/qwidgetbackingstore_p.h> +#include <private/qwidgetrepaintmanager_p.h> #include <qpa/qwindowsysteminterface_p.h> #include <qpa/qplatformtheme.h> #include <qpa/qplatformwindow.h> @@ -106,6 +106,7 @@ public: if (QWidget *widget = q->widget()) QWidgetPrivate::get(widget)->updateContentsRect(); } + bool allowClickThrough(const QPoint &) const override; }; QRectF QWidgetWindowPrivate::closestAcceptableGeometry(const QRectF &rect) const @@ -154,7 +155,7 @@ QWidgetWindow::QWidgetWindow(QWidget *widget) // Enable QOpenGLWidget/QQuickWidget children if the platform plugin supports it, // and the application developer has not explicitly disabled it. if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface) - && !QApplication::testAttribute(Qt::AA_ForceRasterWidgets)) { + && !QCoreApplication::testAttribute(Qt::AA_ForceRasterWidgets)) { setSurfaceType(QSurface::RasterGLSurface); } connect(widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName); @@ -221,6 +222,11 @@ static inline bool shouldBePropagatedToWidget(QEvent *event) } } +bool QWidgetWindowPrivate::allowClickThrough(const QPoint &) const +{ + return true; +} + bool QWidgetWindow::event(QEvent *event) { if (!m_widget) @@ -490,8 +496,8 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) static const QEvent::Type contextMenuTrigger = QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::ContextMenuOnMouseRelease).toBool() ? QEvent::MouseButtonRelease : QEvent::MouseButtonPress; - if (qApp->d_func()->inPopupMode()) { - QWidget *activePopupWidget = qApp->activePopupWidget(); + if (QApplicationPrivate::inPopupMode()) { + QWidget *activePopupWidget = QApplication::activePopupWidget(); QPoint mapped = event->pos(); if (activePopupWidget != m_widget) mapped = activePopupWidget->mapFromGlobal(event->globalPos()); @@ -571,7 +577,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) } } - if (qApp->activePopupWidget() != activePopupWidget + if (QApplication::activePopupWidget() != activePopupWidget && qt_replay_popup_mouse_event && QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::ReplayMousePressOutsidePopup).toBool()) { if (m_widget->windowType() != Qt::Popup) @@ -586,10 +592,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) w->window()->raise(); } - QWindow *win = w->windowHandle(); - if (!win) - win = w->nativeParentWidget()->windowHandle(); - if (win) { + if (auto win = qt_widget_private(w)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest)) { const QRect globalGeometry = win->isTopLevel() ? win->geometry() : QRect(win->mapToGlobal(QPoint(0, 0)), win->size()); @@ -677,7 +680,7 @@ void QWidgetWindow::handleTouchEvent(QTouchEvent *event) if (event->type() == QEvent::TouchCancel) { QApplicationPrivate::translateTouchCancel(event->device(), event->timestamp()); event->accept(); - } else if (qApp->d_func()->inPopupMode()) { + } else if (QApplicationPrivate::inPopupMode()) { // Ignore touch events for popups. This will cause QGuiApplication to synthesise mouse // events instead, which QWidgetWindow::handleMouseEvent will forward correctly: event->ignore(); @@ -741,7 +744,7 @@ void QWidgetWindow::updateMargins() static void sendScreenChangeRecursively(QWidget *widget) { QEvent e(QEvent::ScreenChangeInternal); - QApplication::sendEvent(widget, &e); + QCoreApplication::sendEvent(widget, &e); QWidgetPrivate *d = QWidgetPrivate::get(widget); for (int i = 0; i < d->children.size(); ++i) { QWidget *w = qobject_cast<QWidget *>(d->children.at(i)); @@ -767,8 +770,8 @@ void QWidgetWindow::repaintWindow() QTLWExtra *tlwExtra = m_widget->window()->d_func()->maybeTopData(); if (tlwExtra && !tlwExtra->inTopLevelResize && tlwExtra->backingStore) - tlwExtra->backingStoreTracker->markDirty(m_widget->rect(), m_widget, - QWidgetBackingStore::UpdateNow, QWidgetBackingStore::BufferInvalid); + tlwExtra->repaintManager->markDirty(m_widget->rect(), m_widget, + QWidgetRepaintManager::UpdateNow, QWidgetRepaintManager::BufferInvalid); } // Store normal geometry used for saving application settings. @@ -800,7 +803,7 @@ void QWidgetWindow::handleResizeEvent(QResizeEvent *event) if (updateSize()) { QGuiApplication::forwardEvent(m_widget, event); - if (m_widget->d_func()->paintOnScreen()) { + if (m_widget->d_func()->shouldPaintOnScreen()) { QRegion updateRegion(geometry()); if (m_widget->testAttribute(Qt::WA_StaticContents)) updateRegion -= QRect(0, 0, oldSize.width(), oldSize.height()); @@ -825,14 +828,14 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event) return; QWidget *rootWidget = m_widget; - QPoint pos = event->pos(); + QPoint pos = event->position().toPoint(); // Use proper popup window for wheel event. Some QPA sends the wheel // event to the root menu, so redirect it to the proper popup window. QWidget *activePopupWidget = QApplication::activePopupWidget(); if (activePopupWidget && activePopupWidget != m_widget) { rootWidget = activePopupWidget; - pos = rootWidget->mapFromGlobal(event->globalPos()); + pos = rootWidget->mapFromGlobal(event->globalPosition().toPoint()); } // which child should have it? @@ -843,7 +846,12 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event) QPoint mapped = widget->mapFrom(rootWidget, pos); +#if QT_DEPRECATED_SINCE(5, 0) QWheelEvent translated(mapped, event->globalPos(), event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted()); +#else + QWheelEvent translated(QPointF(mapped), event->globalPosition(), event->pixelDelta(), event->angleDelta(), + event->buttons(), event->modifiers(), event->phase(), event->inverted(), event->source()); +#endif translated.setTimestamp(event->timestamp()); QGuiApplication::forwardEvent(widget, &translated, event); } @@ -1022,7 +1030,11 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event } } +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) +bool QWidgetWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result) +#else bool QWidgetWindow::nativeEvent(const QByteArray &eventType, void *message, long *result) +#endif { return m_widget->nativeEvent(eventType, message, result); } @@ -1100,7 +1112,7 @@ void QWidgetWindow::handleContextMenuEvent(QContextMenuEvent *e) } } if (fw && fw->isEnabled()) { - QPoint pos = fw->inputMethodQuery(Qt::ImMicroFocus).toRect().center(); + QPoint pos = fw->inputMethodQuery(Qt::ImCursorRectangle).toRect().center(); QContextMenuEvent widgetEvent(QContextMenuEvent::Keyboard, pos, fw->mapToGlobal(pos), e->modifiers()); QGuiApplication::forwardEvent(fw, &widgetEvent, e); diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h index 0728135467..80a345465d 100644 --- a/src/widgets/kernel/qwidgetwindow_p.h +++ b/src/widgets/kernel/qwidgetwindow_p.h @@ -103,7 +103,11 @@ protected: #endif void handleExposeEvent(QExposeEvent *); void handleWindowStateChangedEvent(QWindowStateChangeEvent *event); +#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) + bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override; +#else bool nativeEvent(const QByteArray &eventType, void *message, long *result) override; +#endif #if QT_CONFIG(tabletevent) void handleTabletEvent(QTabletEvent *); #endif diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 4b289d2d33..fd8581edbb 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -223,7 +223,7 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt: // Otherwise we may end up with BadMatch failures on X11. if (embeddedWindow->surfaceType() == QSurface::RasterSurface && QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface) - && !QApplication::testAttribute(Qt::AA_ForceRasterWidgets)) + && !QCoreApplication::testAttribute(Qt::AA_ForceRasterWidgets)) embeddedWindow->setSurfaceType(QSurface::RasterGLSurface); d->window = embeddedWindow; diff --git a/src/widgets/kernel/qwindowcontainer_p.h b/src/widgets/kernel/qwindowcontainer_p.h index a8754232a8..c6de168c10 100644 --- a/src/widgets/kernel/qwindowcontainer_p.h +++ b/src/widgets/kernel/qwindowcontainer_p.h @@ -64,7 +64,7 @@ class Q_WIDGETS_EXPORT QWindowContainer : public QWidget Q_DECLARE_PRIVATE(QWindowContainer) public: - explicit QWindowContainer(QWindow *embeddedWindow, QWidget *parent = 0, Qt::WindowFlags f = 0); + explicit QWindowContainer(QWindow *embeddedWindow, QWidget *parent = nullptr, Qt::WindowFlags f = nullptr); ~QWindowContainer(); QWindow *containedWindow() const; diff --git a/src/widgets/kernel/win.pri b/src/widgets/kernel/win.pri index f6877b02db..3b3170beb1 100644 --- a/src/widgets/kernel/win.pri +++ b/src/widgets/kernel/win.pri @@ -2,4 +2,7 @@ # -------------------------------------------------------------------- INCLUDEPATH += ../3rdparty/wintab -!winrt: LIBS_PRIVATE *= -lshell32 -luxtheme -ldwmapi +!winrt { + LIBS_PRIVATE *= -luxtheme -ldwmapi + QMAKE_USE_PRIVATE += shell32 +} |