summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/dialogs/qmessagebox.cpp4
-rw-r--r--src/widgets/dialogs/qprogressdialog.cpp17
-rw-r--r--src/widgets/dialogs/qwizard.cpp40
-rw-r--r--src/widgets/doc/snippets/layouts/layouts.cpp12
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc2
-rw-r--r--src/widgets/kernel/qapplication.cpp64
-rw-r--r--src/widgets/kernel/qboxlayout.cpp54
-rw-r--r--src/widgets/kernel/qformlayout.cpp4
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp1
-rw-r--r--src/widgets/kernel/qgridlayout.cpp6
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp8
-rw-r--r--src/widgets/kernel/qstackedlayout.cpp4
-rw-r--r--src/widgets/kernel/qwidget.cpp32
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp6
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp8
-rw-r--r--src/widgets/util/qscroller.cpp3
-rw-r--r--src/widgets/widgets/qmenu.cpp16
17 files changed, 165 insertions, 116 deletions
diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp
index ac1952a642..08d5e5213a 100644
--- a/src/widgets/dialogs/qmessagebox.cpp
+++ b/src/widgets/dialogs/qmessagebox.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2018 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@@ -1890,7 +1890,7 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title)
"<p>Qt and the Qt logo are trademarks of The Qt Company Ltd.</p>"
"<p>Qt is The Qt Company Ltd product developed as an open source "
"project. See <a href=\"http://%3/\">%3</a> for more information.</p>"
- ).arg(QStringLiteral("2019"),
+ ).arg(QStringLiteral("2020"),
QStringLiteral("qt.io/licensing"),
QStringLiteral("qt.io"));
QMessageBox *msgBox = new QMessageBox(parent);
diff --git a/src/widgets/dialogs/qprogressdialog.cpp b/src/widgets/dialogs/qprogressdialog.cpp
index e1fb1055ae..38e506a857 100644
--- a/src/widgets/dialogs/qprogressdialog.cpp
+++ b/src/widgets/dialogs/qprogressdialog.cpp
@@ -718,14 +718,17 @@ void QProgressDialog::setValue(int progress)
QSize QProgressDialog::sizeHint() const
{
Q_D(const QProgressDialog);
- QSize sh = d->label ? d->label->sizeHint() : QSize(0, 0);
- QSize bh = d->bar->sizeHint();
- int margin = style()->pixelMetric(QStyle::PM_DefaultTopLevelMargin);
- int spacing = style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
- int h = margin * 2 + bh.height() + sh.height() + spacing;
+ QSize labelSize = d->label ? d->label->sizeHint() : QSize(0, 0);
+ QSize barSize = d->bar->sizeHint();
+ int marginBottom = style()->pixelMetric(QStyle::PM_LayoutBottomMargin, 0, this);
+ int spacing = style()->pixelMetric(QStyle::PM_LayoutVerticalSpacing, 0, this);
+ int marginLeft = style()->pixelMetric(QStyle::PM_LayoutLeftMargin, 0, this);
+ int marginRight = style()->pixelMetric(QStyle::PM_LayoutRightMargin, 0, this);
+
+ int height = marginBottom * 2 + barSize.height() + labelSize.height() + spacing;
if (d->cancel)
- h += d->cancel->sizeHint().height() + spacing;
- return QSize(qMax(200, sh.width() + 2 * margin), h);
+ height += d->cancel->sizeHint().height() + spacing;
+ return QSize(qMax(200, labelSize.width() + marginLeft + marginRight), height);
}
/*!\reimp
diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp
index f19a4e99af..29f9efb68a 100644
--- a/src/widgets/dialogs/qwizard.cpp
+++ b/src/widgets/dialogs/qwizard.cpp
@@ -601,6 +601,7 @@ public:
QWizardLayoutInfo layoutInfoForCurrentPage();
void recreateLayout(const QWizardLayoutInfo &info);
void updateLayout();
+ void updatePalette();
void updateMinMaxSizes(const QWizardLayoutInfo &info);
void updateCurrentPage();
bool ensureButton(QWizard::WizardButton which) const;
@@ -898,6 +899,7 @@ void QWizardPrivate::switchToPage(int newId, Direction direction)
enableUpdates();
updateLayout();
+ updatePalette();
emit q->currentIdChanged(current);
}
@@ -1179,16 +1181,8 @@ void QWizardPrivate::recreateLayout(const QWizardLayoutInfo &info)
pageFrame->palette().brush(QPalette::Window).color().alpha() < 255
|| pageFrame->palette().brush(QPalette::Base).color().alpha() < 255;
if (mac) {
- if (!wasSemiTransparent) {
- QPalette pal = pageFrame->palette();
- pal.setBrush(QPalette::Window, QColor(255, 255, 255, 153));
- // ### The next line is required to ensure visual semitransparency when
- // ### switching from ModernStyle to MacStyle. See TAG1 below.
- pal.setBrush(QPalette::Base, QColor(255, 255, 255, 153));
- pageFrame->setPalette(pal);
- pageFrame->setAutoFillBackground(true);
- antiFlickerWidget->setAutoFillBackground(false);
- }
+ pageFrame->setAutoFillBackground(true);
+ antiFlickerWidget->setAutoFillBackground(false);
} else {
if (wasSemiTransparent)
pageFrame->setPalette(QPalette());
@@ -1329,6 +1323,30 @@ void QWizardPrivate::updateLayout()
updateMinMaxSizes(info);
}
+void QWizardPrivate::updatePalette() {
+ if (wizStyle == QWizard::MacStyle) {
+ // This is required to ensure visual semitransparency when
+ // switching from ModernStyle to MacStyle.
+ // See TAG1 in recreateLayout
+ // This additionally ensures that the colors are correct
+ // when the theme is changed.
+
+ // we should base the new palette on the default one
+ // so theme colors will be correct
+ QPalette newPalette = QApplication::palette(pageFrame);
+
+ QColor windowColor = newPalette.brush(QPalette::Window).color();
+ windowColor.setAlpha(153);
+ newPalette.setBrush(QPalette::Window, windowColor);
+
+ QColor baseColor = newPalette.brush(QPalette::Base).color();
+ baseColor.setAlpha(153);
+ newPalette.setBrush(QPalette::Base, baseColor);
+
+ pageFrame->setPalette(newPalette);
+ }
+}
+
void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info)
{
Q_Q(QWizard);
@@ -3174,6 +3192,8 @@ bool QWizard::event(QEvent *event)
if (event->type() == QEvent::StyleChange) { // Propagate style
d->setStyle(style());
d->updateLayout();
+ } else if (event->type() == QEvent::PaletteChange) { // Emitted on theme change
+ d->updatePalette();
}
#if QT_CONFIG(style_windowsvista)
else if (event->type() == QEvent::Show && d->vistaInitPending) {
diff --git a/src/widgets/doc/snippets/layouts/layouts.cpp b/src/widgets/doc/snippets/layouts/layouts.cpp
index 6d2ea580b4..4b15cc6d1a 100644
--- a/src/widgets/doc/snippets/layouts/layouts.cpp
+++ b/src/widgets/doc/snippets/layouts/layouts.cpp
@@ -67,7 +67,7 @@ int main(int argc, char *argv[])
//! [2]
//! [3]
- QHBoxLayout *layout = new QHBoxLayout;
+ QHBoxLayout *layout = new QHBoxLayout(window);
//! [3] //! [4]
layout->addWidget(button1);
layout->addWidget(button2);
@@ -75,7 +75,6 @@ int main(int argc, char *argv[])
layout->addWidget(button4);
layout->addWidget(button5);
- window->setLayout(layout);
//! [4]
window->setWindowTitle("QHBoxLayout");
//! [5]
@@ -96,7 +95,7 @@ int main(int argc, char *argv[])
//! [8]
//! [9]
- QVBoxLayout *layout = new QVBoxLayout;
+ QVBoxLayout *layout = new QVBoxLayout(window);
//! [9] //! [10]
layout->addWidget(button1);
layout->addWidget(button2);
@@ -104,7 +103,6 @@ int main(int argc, char *argv[])
layout->addWidget(button4);
layout->addWidget(button5);
- window->setLayout(layout);
//! [10]
window->setWindowTitle("QVBoxLayout");
//! [11]
@@ -125,7 +123,7 @@ int main(int argc, char *argv[])
//! [14]
//! [15]
- QGridLayout *layout = new QGridLayout;
+ QGridLayout *layout = new QGridLayout(window);
//! [15] //! [16]
layout->addWidget(button1, 0, 0);
layout->addWidget(button2, 0, 1);
@@ -133,7 +131,6 @@ int main(int argc, char *argv[])
layout->addWidget(button4, 2, 0);
layout->addWidget(button5, 2, 1);
- window->setLayout(layout);
//! [16]
window->setWindowTitle("QGridLayout");
//! [17]
@@ -156,14 +153,13 @@ int main(int argc, char *argv[])
QLineEdit *lineEdit3 = new QLineEdit();
//! [20]
//! [21]
- QFormLayout *layout = new QFormLayout;
+ QFormLayout *layout = new QFormLayout(window);
//! [21]
//! [22]
layout->addRow(button1, lineEdit1);
layout->addRow(button2, lineEdit2);
layout->addRow(button3, lineEdit3);
- window->setLayout(layout);
//! [22]
window->setWindowTitle("QFormLayout");
//! [23]
diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
index 43f9dda49a..61220cf400 100644
--- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
+++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
@@ -2979,7 +2979,7 @@
\li \c px: pixels
\li \c pt: the size of one point (i.e., 1/72 of an inch)
\li \c em: the em width of the font (i.e., the width of 'M')
- \li \c ex: the ex width of the font (i.e., the height of 'x')
+ \li \c ex: the x-height of the font (i.e., the height of 'x')
\endlist
However, Qt is limited to font sizes in \c pt and \c px and any other
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index f564475698..1efbca8490 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -2165,10 +2165,12 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
// \a next). This is to ensure that we can tab in and out of compound widgets
// without getting stuck in a tab-loop between parent and child.
QWidget *focusProxy = test->d_func()->deepestFocusProxy();
-
- if ((test->focusPolicy() & focus_flag) == focus_flag
- && !(next && focusProxy && focusProxy->isAncestorOf(test))
- && !(!next && focusProxy && test->isAncestorOf(focusProxy))
+ const bool canTakeFocus = ((focusProxy ? focusProxy->focusPolicy() : test->focusPolicy())
+ & focus_flag) == focus_flag;
+ const bool composites = focusProxy ? (next ? focusProxy->isAncestorOf(test)
+ : test->isAncestorOf(focusProxy))
+ : false;
+ if (canTakeFocus && !composites
&& test->isVisibleTo(toplevel) && test->isEnabled()
&& !(w->windowType() == Qt::SubWindow && !w->isAncestorOf(test))
&& (toplevel->windowType() != Qt::SubWindow || toplevel->isAncestorOf(test))) {
@@ -2907,59 +2909,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
return true; // Platform plugin ate the event
}
- if(e->spontaneous()) {
- // Capture the current mouse and keyboard states. Doing so here is
- // required in order to support Qt Test synthesized events. Real mouse
- // and keyboard state updates from the platform plugin are managed by
- // QGuiApplicationPrivate::process(Mouse|Wheel|Key|Touch|Tablet)Event();
- // ### FIXME: Qt Test should not call qapp->notify(), but rather route
- // the events through the proper QPA interface. This is required to
- // properly generate all other events such as enter/leave etc.
- switch (e->type()) {
- case QEvent::MouseButtonPress:
- {
- QMouseEvent *me = static_cast<QMouseEvent*>(e);
- QApplicationPrivate::modifier_buttons = me->modifiers();
- QApplicationPrivate::mouse_buttons |= me->button();
- break;
- }
- case QEvent::MouseButtonDblClick:
- {
- QMouseEvent *me = static_cast<QMouseEvent*>(e);
- QApplicationPrivate::modifier_buttons = me->modifiers();
- QApplicationPrivate::mouse_buttons |= me->button();
- break;
- }
- case QEvent::MouseButtonRelease:
- {
- QMouseEvent *me = static_cast<QMouseEvent*>(e);
- QApplicationPrivate::modifier_buttons = me->modifiers();
- QApplicationPrivate::mouse_buttons &= ~me->button();
- break;
- }
- case QEvent::KeyPress:
- case QEvent::KeyRelease:
- case QEvent::MouseMove:
-#if QT_CONFIG(wheelevent)
- case QEvent::Wheel:
-#endif
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- case QEvent::TouchEnd:
-#if QT_CONFIG(tabletevent)
- case QEvent::TabletMove:
- case QEvent::TabletPress:
- case QEvent::TabletRelease:
-#endif
- {
- QInputEvent *ie = static_cast<QInputEvent*>(e);
- QApplicationPrivate::modifier_buttons = ie->modifiers();
- break;
- }
- default:
- break;
- }
- }
+ QGuiApplicationPrivate::captureGlobalModifierState(e);
#ifndef QT_NO_GESTURES
// walk through parents and check for gestures
diff --git a/src/widgets/kernel/qboxlayout.cpp b/src/widgets/kernel/qboxlayout.cpp
index a368f379ad..39a3b5203c 100644
--- a/src/widgets/kernel/qboxlayout.cpp
+++ b/src/widgets/kernel/qboxlayout.cpp
@@ -548,7 +548,11 @@ QLayoutItem* QBoxLayoutPrivate::replaceAt(int index, QLayoutItem *item)
Constructs a new QBoxLayout with direction \a dir and parent widget \a
parent.
- \sa direction()
+ The layout is set directly as the top-level layout for \a parent.
+ There can be only one top-level layout for a widget. It is returned
+ by QWidget::layout().
+
+ \sa direction(), QWidget::setLayout()
*/
QBoxLayout::QBoxLayout(Direction dir, QWidget *parent)
: QLayout(*new QBoxLayoutPrivate, 0, parent)
@@ -1232,11 +1236,16 @@ QBoxLayout::Direction QBoxLayout::direction() const
\snippet layouts/layouts.cpp 4
\snippet layouts/layouts.cpp 5
- First, we create the widgets we want in the layout. Then, we
- create the QHBoxLayout object and add the widgets into the
- layout. Finally, we call QWidget::setLayout() to install the
- QHBoxLayout object onto the widget. At that point, the widgets in
- the layout are reparented to have \c window as their parent.
+ First, we create the widgets we want to add to the layout. Then,
+ we create the QHBoxLayout object, setting \c window as parent by
+ passing it in the constructor; next we add the widgets to the
+ layout. \c window will be the parent of the widgets that are
+ added to the layout.
+
+ If you don't pass parent \c window in the constrcutor, you can
+ at a later point use QWidget::setLayout() to install the QHBoxLayout
+ object onto \c window. At that point, the widgets in the layout are
+ reparented to have \c window as their parent.
\image qhboxlayout-with-5-children.png Horizontal box layout with five child widgets
@@ -1245,8 +1254,13 @@ QBoxLayout::Direction QBoxLayout::direction() const
/*!
- Constructs a new top-level horizontal box with
- parent \a parent.
+ Constructs a new top-level horizontal box with parent \a parent.
+
+ The layout is set directly as the top-level layout for \a parent.
+ There can be only one top-level layout for a widget. It is returned
+ by QWidget::layout().
+
+ \sa QWidget::setLayout()
*/
QHBoxLayout::QHBoxLayout(QWidget *parent)
: QBoxLayout(LeftToRight, parent)
@@ -1295,11 +1309,16 @@ QHBoxLayout::~QHBoxLayout()
\snippet layouts/layouts.cpp 10
\snippet layouts/layouts.cpp 11
- First, we create the widgets we want in the layout. Then, we
- create the QVBoxLayout object and add the widgets into the
- layout. Finally, we call QWidget::setLayout() to install the
- QVBoxLayout object onto the widget. At that point, the widgets in
- the layout are reparented to have \c window as their parent.
+ First, we create the widgets we want to add to the layout. Then,
+ we create the QVBoxLayout object, setting \c window as parent by
+ passing it in the constructor; next we add the widgets to the
+ layout. \c window will be the parent of the widgets that are
+ added to the layout.
+
+ If you don't pass parent \c window in the constrcutor, you can
+ at a later point use QWidget::setLayout() to install the QVBoxLayout
+ object onto \c window. At that point, the widgets in the layout are
+ reparented to have \c window as their parent.
\image qvboxlayout-with-5-children.png Horizontal box layout with five child widgets
@@ -1307,8 +1326,13 @@ QHBoxLayout::~QHBoxLayout()
*/
/*!
- Constructs a new top-level vertical box with
- parent \a parent.
+ Constructs a new top-level vertical box with parent \a parent.
+
+ The layout is set directly as the top-level layout for \a parent.
+ There can be only one top-level layout for a widget. It is returned
+ by QWidget::layout().
+
+ \sa QWidget::setLayout()
*/
QVBoxLayout::QVBoxLayout(QWidget *parent)
: QBoxLayout(TopToBottom, parent)
diff --git a/src/widgets/kernel/qformlayout.cpp b/src/widgets/kernel/qformlayout.cpp
index 600934b8a1..1852f8cdc3 100644
--- a/src/widgets/kernel/qformlayout.cpp
+++ b/src/widgets/kernel/qformlayout.cpp
@@ -1191,6 +1191,10 @@ QLayoutItem* QFormLayoutPrivate::replaceAt(int index, QLayoutItem *newitem)
/*!
Constructs a new form layout with the given \a parent widget.
+ The layout is set directly as the top-level layout for \a parent.
+ There can be only one top-level layout for a widget. It is returned
+ by QWidget::layout().
+
\sa QWidget::setLayout()
*/
QFormLayout::QFormLayout(QWidget *parent)
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 891858b035..cfa1759dd7 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -143,6 +143,7 @@ Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *r
void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type)
{
QList<QGestureRecognizer *> list = m_recognizers.values(type);
+ m_recognizers.remove(type);
foreach (QGesture *g, m_gestureToRecognizer.keys()) {
QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g);
if (list.contains(recognizer)) {
diff --git a/src/widgets/kernel/qgridlayout.cpp b/src/widgets/kernel/qgridlayout.cpp
index f1c6c96a6d..a410652dcb 100644
--- a/src/widgets/kernel/qgridlayout.cpp
+++ b/src/widgets/kernel/qgridlayout.cpp
@@ -1073,6 +1073,12 @@ QRect QGridLayoutPrivate::cellRect(int row, int col) const
Constructs a new QGridLayout with parent widget, \a parent. The
layout has one row and one column initially, and will expand when
new items are inserted.
+
+ The layout is set directly as the top-level layout for \a parent.
+ There can be only one top-level layout for a widget. It is returned
+ by QWidget::layout().
+
+ \sa QWidget::setLayout()
*/
QGridLayout::QGridLayout(QWidget *parent)
: QLayout(*new QGridLayoutPrivate, 0, parent)
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 7aef74c507..e58994b04c 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -788,10 +788,12 @@ void QOpenGLWidgetPrivate::initialize()
if (initialized)
return;
- // Get our toplevel's context with which we will share in order to make the
- // texture usable by the underlying window's backingstore.
+ // If no global shared context get our toplevel's context with which we
+ // will share in order to make the texture usable by the underlying window's backingstore.
QWidget *tlw = q->window();
- QOpenGLContext *shareContext = get(tlw)->shareContext();
+ QOpenGLContext *shareContext = qt_gl_global_share_context();
+ if (!shareContext)
+ shareContext = get(tlw)->shareContext();
// If shareContext is null, showing content on-screen will not work.
// However, offscreen rendering and grabFramebuffer() will stay fully functional.
diff --git a/src/widgets/kernel/qstackedlayout.cpp b/src/widgets/kernel/qstackedlayout.cpp
index 7430d833db..0b1641c141 100644
--- a/src/widgets/kernel/qstackedlayout.cpp
+++ b/src/widgets/kernel/qstackedlayout.cpp
@@ -44,6 +44,8 @@
#include "private/qwidget_p.h"
#include "private/qlayoutengine_p.h"
+#include <memory>
+
QT_BEGIN_NAMESPACE
class QStackedLayoutPrivate : public QLayoutPrivate
@@ -421,13 +423,13 @@ int QStackedLayout::count() const
*/
void QStackedLayout::addItem(QLayoutItem *item)
{
+ std::unique_ptr<QLayoutItem> guard(item);
QWidget *widget = item->widget();
if (Q_UNLIKELY(!widget)) {
qWarning("QStackedLayout::addItem: Only widgets can be added");
return;
}
addWidget(widget);
- delete item;
}
/*!
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index db08a1d04f..02a1980e09 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -910,6 +910,8 @@ void QWidget::setAutoFillBackground(bool enabled)
and a compositing window manager.
\li Windows: The widget needs to have the Qt::FramelessWindowHint window flag set
for the translucency to work.
+ \li \macos: The widget needs to have the Qt::FramelessWindowHint window flag set
+ for the translucency to work.
\endlist
@@ -6715,6 +6717,9 @@ void QWidget::clearFocus()
QApplication::sendEvent(this, &focusAboutToChange);
}
+ QTLWExtra *extra = window()->d_func()->maybeTopData();
+ QObject *originalFocusObject = (extra && extra->window) ? extra->window->focusObject() : nullptr;
+
QWidget *w = this;
while (w) {
// Just like setFocus(), we update (clear) the focus_child of our parents
@@ -6723,14 +6728,12 @@ void QWidget::clearFocus()
w = w->parentWidget();
}
- // Since we've unconditionally cleared the focus_child of our parents, we need
+ // We've potentially cleared the focus_child of our parents, so we need
// to report this to the rest of Qt. Note that the focus_child is not the same
// thing as the application's focusWidget, which is why this piece of code is
- // not inside the hasFocus() block below.
- if (QTLWExtra *extra = window()->d_func()->maybeTopData()) {
- if (extra->window)
- emit extra->window->focusObjectChanged(extra->window->focusObject());
- }
+ // not inside a hasFocus() block.
+ if (originalFocusObject && originalFocusObject != extra->window->focusObject())
+ emit extra->window->focusObjectChanged(extra->window->focusObject());
#if QT_CONFIG(graphicsview)
QWExtra *topData = d_func()->extra;
@@ -8934,6 +8937,23 @@ bool QWidget::event(QEvent *event)
}
}
switch (event->type()) {
+ case QEvent::PlatformSurface: {
+ // Sync up QWidget's view of whether or not the widget has been created
+ switch (static_cast<QPlatformSurfaceEvent*>(event)->surfaceEventType()) {
+ case QPlatformSurfaceEvent::SurfaceCreated:
+ if (!testAttribute(Qt::WA_WState_Created))
+ create();
+ break;
+ case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
+ if (testAttribute(Qt::WA_WState_Created)) {
+ // Child windows have already been destroyed by QWindow,
+ // so we skip them here.
+ destroy(false, false);
+ }
+ break;
+ }
+ break;
+ }
case QEvent::MouseMove:
mouseMoveEvent((QMouseEvent*)event);
break;
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index b9505a6ed0..38ea5966ae 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -717,7 +717,11 @@ void QWidgetBackingStore::markDirtyOnScreen(const QRegion &region, QWidget *widg
// Alien widgets.
if (!hasPlatformWindow(widget) && !widget->isWindow()) {
- QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case).
+ QWidget *nativeParent = widget->nativeParentWidget();
+ if (!nativeParent)
+ return;
+
+ // Alien widgets with the top-level as the native parent (common case).
if (nativeParent == tlw) {
dirtyOnScreen += region.translated(topLevelOffset);
return;
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index c3f570ce4f..e74243203a 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -243,10 +243,14 @@ bool QWidgetWindow::event(QEvent *event)
}
switch (event->type()) {
- case QEvent::Close:
+ case QEvent::Close: {
+ // The widget might be deleted in the close event handler.
+ QPointer<QObject> guard = this;
handleCloseEvent(static_cast<QCloseEvent *>(event));
- QWindow::event(event);
+ if (guard)
+ QWindow::event(event);
return true;
+ }
case QEvent::Enter:
case QEvent::Leave:
diff --git a/src/widgets/util/qscroller.cpp b/src/widgets/util/qscroller.cpp
index 1e84237253..8fd3437eaf 100644
--- a/src/widgets/util/qscroller.cpp
+++ b/src/widgets/util/qscroller.cpp
@@ -1031,7 +1031,8 @@ void QScrollerPrivate::setDpi(const QPointF &dpi)
*/
void QScrollerPrivate::setDpiFromWidget(QWidget *widget)
{
- const QScreen *screen = QGuiApplication::screens().at(QApplication::desktop()->screenNumber(widget));
+ const int screenNumber = QApplication::desktop()->screenNumber(widget);
+ const QScreen *screen = screenNumber < 0 ? QGuiApplication::primaryScreen() : QGuiApplication::screens().at(screenNumber);
setDpi(QPointF(screen->physicalDotsPerInchX(), screen->physicalDotsPerInchY()));
}
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index d60a484094..6e6825daea 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -40,6 +40,7 @@
#include "qmenu.h"
#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include <QtWidgets/private/qwidgetwindow_p.h>
#include "qdebug.h"
#include "qstyle.h"
@@ -791,6 +792,8 @@ void QMenuSloppyState::setSubMenuPopup(const QRect &actionRect, QAction *resetAc
m_use_reset_action = true;
m_time.stop();
m_action_rect = actionRect;
+ if (m_sub_menu)
+ QMenuPrivate::get(m_sub_menu)->sloppyState.m_parent = nullptr;
m_sub_menu = subMenu;
QMenuPrivate::get(subMenu)->sloppyState.m_parent = this;
m_reset_action = resetAction;
@@ -2364,15 +2367,24 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
// Use d->popupScreen to remember, because initialScreenIndex will be reset after the first showing.
// However if eventLoop exists, then exec() already did this by calling createWinId(); so leave it alone. (QTBUG-76162)
if (!d->eventLoop) {
+ bool screenSet = false;
const int screenIndex = d->topData()->initialScreenIndex;
if (screenIndex >= 0)
d->popupScreen = screenIndex;
if (auto s = QGuiApplication::screens().value(d->popupScreen)) {
if (d->setScreen(s))
d->itemsDirty = true;
- } else if (d->setScreenForPoint(p)) {
- d->itemsDirty = true;
+ screenSet = true;
+ } else if (QMenu *parentMenu = qobject_cast<QMenu *>(parent())) {
+ // a submenu is normally opened from an open parent menu,
+ // so show it on the same screen where the parent is.
+ if (QMenuPrivate::get(parentMenu)->windowHandle() &&
+ d->setScreen(QMenuPrivate::get(parentMenu)->windowHandle()->screen()))
+ d->itemsDirty = true;
+ screenSet = true;
}
+ if (!screenSet && d->setScreenForPoint(p))
+ d->itemsDirty = true;
}
const bool contextMenu = d->isContextMenu();