diff options
Diffstat (limited to 'src/widgets')
-rw-r--r-- | src/widgets/doc/src/external-resources.qdoc | 2 | ||||
-rw-r--r-- | src/widgets/doc/src/qtwidgets-examples.qdoc | 12 | ||||
-rw-r--r-- | src/widgets/doc/src/qtwidgets-toc.qdoc | 1 | ||||
-rw-r--r-- | src/widgets/itemviews/qabstractitemview.cpp | 3 | ||||
-rw-r--r-- | src/widgets/kernel/qapplication.cpp | 43 | ||||
-rw-r--r-- | src/widgets/kernel/qtooltip.cpp | 13 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 19 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 4 | ||||
-rw-r--r-- | src/widgets/util/qcompleter.cpp | 15 | ||||
-rw-r--r-- | src/widgets/widgets/qcombobox.cpp | 14 | ||||
-rw-r--r-- | src/widgets/widgets/qmainwindowlayout.cpp | 3 | ||||
-rw-r--r-- | src/widgets/widgets/qmenu.cpp | 21 |
12 files changed, 117 insertions, 33 deletions
diff --git a/src/widgets/doc/src/external-resources.qdoc b/src/widgets/doc/src/external-resources.qdoc index 17459b6a5bc..96117546a29 100644 --- a/src/widgets/doc/src/external-resources.qdoc +++ b/src/widgets/doc/src/external-resources.qdoc @@ -8,7 +8,7 @@ */ /*! - \externalpage http://www.nvg.ntnu.no/sinclair/computers/zxspectrum/zxspectrum.htm + \externalpage https://rk.nvg.ntnu.no/sinclair/computers/zxspectrum/zxspectrum.htm \title Sinclair Spectrum */ /*! diff --git a/src/widgets/doc/src/qtwidgets-examples.qdoc b/src/widgets/doc/src/qtwidgets-examples.qdoc index 45677c471ba..364c985b310 100644 --- a/src/widgets/doc/src/qtwidgets-examples.qdoc +++ b/src/widgets/doc/src/qtwidgets-examples.qdoc @@ -164,3 +164,15 @@ regular expressions for the Widget-based applications. */ +/*! + \group examples-user-input + \ingroup all-examples + \title User Input Examples + \brief Using user input in Qt Widgets applications. + + \image imagegestures-example.png {Application handling touch gestures} + + Qt provides the functionality for handling user input and drag-and-drop in + widget-based applications. + +*/ diff --git a/src/widgets/doc/src/qtwidgets-toc.qdoc b/src/widgets/doc/src/qtwidgets-toc.qdoc index bc447b8bd58..beddf853a22 100644 --- a/src/widgets/doc/src/qtwidgets-toc.qdoc +++ b/src/widgets/doc/src/qtwidgets-toc.qdoc @@ -53,6 +53,7 @@ \li \l{Rich Text Examples} \li \l{Graphics View Examples} \li \l{Widget Tools Examples} + \li \l{User Input Examples} \endlist \endlist diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp index e4159ad2cf0..51aea4079a1 100644 --- a/src/widgets/itemviews/qabstractitemview.cpp +++ b/src/widgets/itemviews/qabstractitemview.cpp @@ -3298,7 +3298,8 @@ void QAbstractItemView::closePersistentEditor(const QModelIndex &index) bool QAbstractItemView::isPersistentEditorOpen(const QModelIndex &index) const { Q_D(const QAbstractItemView); - return d->editorForIndex(index).widget; + QWidget *editor = d->editorForIndex(index).widget; + return editor && d->persistent.contains(editor); } /*! diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 6fcfcf1b1ef..fa95a1d2538 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -1432,8 +1432,8 @@ void QApplicationPrivate::notifyWindowIconChanged() // in case there are any plain QWindows in this QApplication-using // application, also send the notification to them - for (int i = 0; i < windowList.size(); ++i) - QCoreApplication::sendEvent(windowList.at(i), &ev); + for (QWindow *w : std::as_const(windowList)) + QCoreApplication::sendEvent(w, &ev); } /*! @@ -1508,11 +1508,15 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason) return; } - if (focus && (reason == Qt::BacktabFocusReason || reason == Qt::TabFocusReason) - && qt_in_tab_key_event) - focus->window()->setAttribute(Qt::WA_KeyboardFocusChange); - else if (focus && reason == Qt::ShortcutFocusReason) { - focus->window()->setAttribute(Qt::WA_KeyboardFocusChange); + if (focus) { + if ((reason == Qt::BacktabFocusReason || reason == Qt::TabFocusReason) + && qt_in_tab_key_event) + focus->window()->setAttribute(Qt::WA_KeyboardFocusChange); + else if (reason == Qt::ShortcutFocusReason) { + focus->window()->setAttribute(Qt::WA_KeyboardFocusChange); + } else { + focus->window()->setAttribute(Qt::WA_KeyboardFocusChange, false); + } } QWidget *prev = focus_widget; focus_widget = focus; @@ -1774,9 +1778,9 @@ void QApplicationPrivate::notifyLayoutDirectionChange() // in case there are any plain QWindows in this QApplication-using // application, also send the notification to them - for (int i = 0; i < windowList.size(); ++i) { + for (QWindow *w: std::as_const(windowList)) { QEvent ev(QEvent::ApplicationLayoutDirectionChange); - QCoreApplication::sendEvent(windowList.at(i), &ev); + QCoreApplication::sendEvent(w, &ev); } } @@ -1863,14 +1867,12 @@ void QApplicationPrivate::setActiveWindow(QWidget* act) QEvent windowActivate(QEvent::WindowActivate); QEvent windowDeactivate(QEvent::WindowDeactivate); - for (int i = 0; i < toBeActivated.size(); ++i) { - QWidget *w = toBeActivated.at(i); + for (QWidget *w : std::as_const(toBeActivated)) { QApplication::sendSpontaneousEvent(w, &windowActivate); QApplication::sendSpontaneousEvent(w, &activationChange); } - for(int i = 0; i < toBeDeactivated.size(); ++i) { - QWidget *w = toBeDeactivated.at(i); + for (QWidget *w : std::as_const(toBeDeactivated)) { QApplication::sendSpontaneousEvent(w, &windowDeactivate); QApplication::sendSpontaneousEvent(w, &activationChange); } @@ -2082,8 +2084,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con } QEvent leaveEvent(QEvent::Leave); - for (int i = 0; i < leaveList.size(); ++i) { - auto *w = leaveList.at(i); + for (QWidget *w : std::as_const(leaveList)) { if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, nullptr)) { QCoreApplication::sendEvent(w, &leaveEvent); if (w->testAttribute(Qt::WA_Hover) && @@ -2125,8 +2126,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, con // Whenever we leave an alien widget on X11/QPA, we need to reset its nativeParentWidget()'s cursor. // This is not required on Windows as the cursor is reset on every single mouse move. QWidget *parentOfLeavingCursor = nullptr; - for (int i = 0; i < leaveList.size(); ++i) { - auto *w = leaveList.at(i); + for (QWidget *w : std::as_const(leaveList)) { if (!isAlien(w)) break; if (w->testAttribute(Qt::WA_SetCursor)) { @@ -3085,7 +3085,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) const QPoint offset = w->pos(); w = w->parentWidget(); QMutableTouchEvent::setTarget(touchEvent, w); - for (int i = 0; i < touchEvent->pointCount(); ++i) { + for (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++i) { auto &pt = touchEvent->point(i); QMutableEventPoint::setPosition(pt, pt.position() + offset); } @@ -3164,8 +3164,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) res = d->notify_helper(w, &ge); gestureEvent->m_spont = false; eventAccepted = ge.isAccepted(); - for (int i = 0; i < gestures.size(); ++i) { - QGesture *g = gestures.at(i); + for (QGesture *g : std::as_const(gestures)) { // Ignore res [event return value] because handling of multiple gestures // packed into a single QEvent depends on not consuming the event if (eventAccepted || ge.isAccepted(g)) { @@ -3708,7 +3707,7 @@ bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven { bool containsPress = false; - for (int i = 0; i < touchEvent->pointCount(); ++i) { + for (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++i) { auto &pt = touchEvent->point(i); QMutableEventPoint::setPosition(pt, widget->mapFromGlobal(pt.globalPosition())); @@ -3768,7 +3767,7 @@ void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent // If the widget dispatched the event further (see QGraphicsProxyWidget), then // there might already be an implicit grabber. Don't override that. A widget that // has partially recognized a gesture needs to grab all points. - for (int i = 0; i < touchEvent->pointCount(); ++i) { + for (qsizetype cnt = touchEvent->pointCount(), i = 0; i < cnt; ++i) { auto &ep = touchEvent->point(i); if (!QMutableEventPoint::target(ep) && (ep.isAccepted() || grabMode == GrabAllPoints)) QMutableEventPoint::setTarget(ep, widget); diff --git a/src/widgets/kernel/qtooltip.cpp b/src/widgets/kernel/qtooltip.cpp index 9e6aaf4b95f..d989feb7f91 100644 --- a/src/widgets/kernel/qtooltip.cpp +++ b/src/widgets/kernel/qtooltip.cpp @@ -20,6 +20,8 @@ #if QT_CONFIG(style_stylesheet) #include <private/qstylesheetstyle_p.h> #endif +#include <qpa/qplatformwindow.h> +#include <qpa/qplatformwindow_p.h> #include <qlabel.h> #include <QtWidgets/private/qlabel_p.h> @@ -386,6 +388,17 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) p += offset; +#if QT_CONFIG(wayland) + create(); + if (auto waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow*>(windowHandle()->handle())) { + // based on the existing code below, by default position at 'p' stored at the bottom right of our rect + // then flip to the other arbitrary 4x24 space if constrained + const QRect controlGeometry(QRect(p.x() - 4, p.y() - 24, 4, 24)); + waylandWindow->setParentControlGeometry(controlGeometry); + waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::ToolTip); + } +#endif + QRect screenRect = screen->geometry(); if (p.x() + this->width() > screenRect.x() + screenRect.width()) p.rx() -= 4 + this->width(); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 36446c3e5c4..9499c88af12 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -13144,11 +13144,22 @@ int QWidget::metric(PaintDeviceMetric m) const void QWidget::initPainter(QPainter *painter) const { const QPalette &pal = palette(); - painter->d_func()->state->pen = QPen(pal.brush(foregroundRole()), 1); - painter->d_func()->state->bgBrush = pal.brush(backgroundRole()); + QPainterPrivate *painterPrivate = QPainterPrivate::get(painter); + + painterPrivate->state->pen = QPen(pal.brush(foregroundRole()), 1); + painterPrivate->state->bgBrush = pal.brush(backgroundRole()); QFont f(font(), this); - painter->d_func()->state->deviceFont = f; - painter->d_func()->state->font = f; + painterPrivate->state->deviceFont = f; + painterPrivate->state->font = f; + + painterPrivate->setEngineDirtyFlags({ + QPaintEngine::DirtyPen, + QPaintEngine::DirtyBrush, + QPaintEngine::DirtyFont, + }); + + if (painterPrivate->extended) + painterPrivate->extended->penChanged(); } /*! diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 737ccb0e807..622f1548756 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -591,6 +591,10 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) } } + // Event delivery above might have destroyed this object. See QTBUG-138419. + if (self.isNull()) + return; + if (QApplication::activePopupWidget() != activePopupWidget && QApplicationPrivate::replayMousePress && QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::ReplayMousePressOutsidePopup).toBool()) { diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp index 220f600ea41..735b574d293 100644 --- a/src/widgets/util/qcompleter.cpp +++ b/src/widgets/util/qcompleter.cpp @@ -122,6 +122,8 @@ #include "QtGui/qevent.h" #include <private/qapplication_p.h> #include <private/qwidget_p.h> +#include <qpa/qplatformwindow.h> +#include <qpa/qplatformwindow_p.h> #if QT_CONFIG(lineedit) #include "QtWidgets/qlineedit.h" #endif @@ -925,10 +927,15 @@ void QCompleterPrivate::showPopup(const QRect& rect) popup->setGeometry(pos.x(), pos.y(), w, h); if (!popup->isVisible()) { - // Make sure popup has a transient parent set, Wayland needs it. QTBUG-130474 - popup->winId(); // force creation of windowHandle - popup->windowHandle()->setTransientParent(widget->window()->windowHandle()); - +#if QT_CONFIG(wayland) + popup->createWinId(); + if (auto waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow*>(popup->windowHandle()->handle())) { + popup->windowHandle()->setTransientParent(widget->window()->windowHandle()); + const QRect controlGeometry = QRect(widget->mapTo(widget->topLevelWidget(), QPoint(0,0)), widget->size()); + waylandWindow->setParentControlGeometry(controlGeometry); + waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::ComboBox); + } +#endif popup->show(); } } diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index 6f25b8bde67..2f51b83a49d 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -7,6 +7,9 @@ #include <qstylepainter.h> #include <qpa/qplatformtheme.h> #include <qpa/qplatformmenu.h> +#include <qpa/qplatformwindow.h> +#include <qpa/qplatformwindow_p.h> + #include <qlineedit.h> #include <qapplication.h> #include <qlistview.h> @@ -2868,6 +2871,17 @@ void QComboBox::showPopup() container->hide(); } } + +#if QT_CONFIG(wayland) + if (auto waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow*>(container->windowHandle()->handle())) { + const QRect popup(style->subControlRect(QStyle::CC_ComboBox, &opt, + QStyle::SC_ComboBoxListBoxPopup, this)); + const QRect controlGeometry = QRect(mapTo(window(), popup.topLeft()), popup.size()); + waylandWindow->setParentControlGeometry(controlGeometry); + waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::ComboBox); + } +#endif + container->show(); if (!neededHorizontalScrollBar && needHorizontalScrollBar()) { listRect.adjust(0, 0, 0, sb->height()); diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 055d8f3d11e..1708a53f163 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -572,6 +572,8 @@ bool QDockWidgetGroupWindow::hasNativeDecos() const #endif } +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Waggressive-loop-optimizations") /* The given widget is hovered over this floating group. This function will save the state and create a gap in the actual state. @@ -623,6 +625,7 @@ bool QDockWidgetGroupWindow::hover(QLayoutItem *widgetItem, const QPoint &mouseP layoutInfo()->apply(opts & QMainWindow::AnimatedDocks); return true; } +QT_WARNING_POP void QDockWidgetGroupWindow::updateCurrentGapRect() { diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index 5cda8f33f4c..3177ed5c2d4 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -40,6 +40,8 @@ #include <private/qaction_p.h> #include <private/qguiapplication_p.h> #include <qpa/qplatformtheme.h> +#include <qpa/qplatformwindow.h> +#include <qpa/qplatformwindow_p.h> #include <private/qstyle_p.h> QT_BEGIN_NAMESPACE @@ -2535,6 +2537,23 @@ void QMenuPrivate::popup(const QPoint &p, QAction *atAction, PositionFunction po } popupScreen = QGuiApplication::screenAt(pos); q->setGeometry(QRect(pos, size)); + +#if QT_CONFIG(wayland) + q->create(); + if (auto waylandWindow = dynamic_cast<QNativeInterface::Private::QWaylandWindow*>(q->windowHandle()->handle())) { + if (causedButton) { + waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::Menu); + waylandWindow->setParentControlGeometry(causedButton->geometry()); + } else if (caused) { + waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::SubMenu); + waylandWindow->setParentControlGeometry(caused->d_func()->actionRect(caused->d_func()->currentAction)); + } else if (auto menubar = qobject_cast<QMenuBar*>(causedPopup.widget)) { + waylandWindow->setExtendedWindowType(QNativeInterface::Private::QWaylandWindow::Menu); + waylandWindow->setParentControlGeometry(menubar->actionGeometry(causedPopup.action)); + } + } +#endif + #if QT_CONFIG(effects) int hGuess = q->isRightToLeft() ? QEffects::LeftScroll : QEffects::RightScroll; int vGuess = QEffects::DownScroll; @@ -2952,7 +2971,7 @@ void QMenu::mouseReleaseEvent(QMouseEvent *e) #endif d->activateAction(action, QAction::Trigger); } - } else if (!action || action->isEnabled()) { + } else if ((!action || action->isEnabled()) && !action->isSeparator()) { d->hideUpToMenuBar(); } } |