diff options
Diffstat (limited to 'src/widgets')
-rw-r--r-- | src/widgets/dialogs/qmessagebox.cpp | 4 | ||||
-rw-r--r-- | src/widgets/dialogs/qprogressdialog.cpp | 17 | ||||
-rw-r--r-- | src/widgets/dialogs/qwizard.cpp | 40 | ||||
-rw-r--r-- | src/widgets/doc/snippets/layouts/layouts.cpp | 12 | ||||
-rw-r--r-- | src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc | 2 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 64 | ||||
-rw-r--r-- | src/widgets/kernel/qboxlayout.cpp | 54 | ||||
-rw-r--r-- | src/widgets/kernel/qformlayout.cpp | 4 | ||||
-rw-r--r-- | src/widgets/kernel/qgesturemanager.cpp | 1 | ||||
-rw-r--r-- | src/widgets/kernel/qgridlayout.cpp | 6 | ||||
-rw-r--r-- | src/widgets/kernel/qopenglwidget.cpp | 8 | ||||
-rw-r--r-- | src/widgets/kernel/qstackedlayout.cpp | 4 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 32 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetbackingstore.cpp | 6 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 8 | ||||
-rw-r--r-- | src/widgets/util/qscroller.cpp | 3 | ||||
-rw-r--r-- | src/widgets/widgets/qmenu.cpp | 16 |
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 ®ion, 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(); |