summaryrefslogtreecommitdiffstats
path: root/src/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets')
-rw-r--r--src/widgets/doc/src/external-resources.qdoc2
-rw-r--r--src/widgets/doc/src/qtwidgets-examples.qdoc12
-rw-r--r--src/widgets/doc/src/qtwidgets-toc.qdoc1
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp30
-rw-r--r--src/widgets/itemviews/qabstractitemview.h5
-rw-r--r--src/widgets/itemviews/qabstractitemview_p.h1
-rw-r--r--src/widgets/itemviews/qtreeview.cpp3
-rw-r--r--src/widgets/kernel/qapplication.cpp43
-rw-r--r--src/widgets/kernel/qtooltip.cpp13
-rw-r--r--src/widgets/kernel/qwidget.cpp19
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp4
-rw-r--r--src/widgets/util/qcompleter.cpp15
-rw-r--r--src/widgets/widgets/qcombobox.cpp14
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp3
-rw-r--r--src/widgets/widgets/qmenu.cpp26
-rw-r--r--src/widgets/widgets/qmenu_p.h3
-rw-r--r--src/widgets/widgets/qtoolbutton.cpp21
17 files changed, 170 insertions, 45 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..6288aae096a 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -3108,7 +3108,8 @@ void QAbstractItemView::keyboardSearch(const QString &search)
QModelIndex startMatch;
QModelIndexList previous;
do {
- match = d->model->match(current, Qt::DisplayRole, d->keyboardInput);
+ match = d->model->match(current, Qt::DisplayRole, d->keyboardInput, 1,
+ d->keyboardSearchFlags);
if (match == previous)
break;
firstMatch = match.value(0);
@@ -3251,6 +3252,30 @@ void QAbstractItemView::setUpdateThreshold(int threshold)
}
/*!
+ \property QAbstractItemView::keyboardSearchFlags
+ \since 6.11
+ This property determines how the default implementation of
+ keyboardSearch() matches the given string against the model's data.
+
+ The default value is \c{Qt::MatchStartsWith|Qt::MatchWrap}.
+
+ \sa keyboardSearch()
+ \sa QAbstractItemModel::match()
+*/
+
+Qt::MatchFlags QAbstractItemView::keyboardSearchFlags() const
+{
+ Q_D(const QAbstractItemView);
+ return d->keyboardSearchFlags;
+}
+
+void QAbstractItemView::setKeyboardSearchFlags(Qt::MatchFlags searchFlags)
+{
+ Q_D(QAbstractItemView);
+ d->keyboardSearchFlags = searchFlags;
+}
+
+/*!
Opens a persistent editor on the item at the given \a index.
If no editor exists, the delegate will create a new editor.
@@ -3298,7 +3323,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/itemviews/qabstractitemview.h b/src/widgets/itemviews/qabstractitemview.h
index 63adac8d6f2..973a9b044cb 100644
--- a/src/widgets/itemviews/qabstractitemview.h
+++ b/src/widgets/itemviews/qabstractitemview.h
@@ -48,6 +48,8 @@ class Q_WIDGETS_EXPORT QAbstractItemView : public QAbstractScrollArea
Q_PROPERTY(ScrollMode horizontalScrollMode READ horizontalScrollMode
WRITE setHorizontalScrollMode RESET resetHorizontalScrollMode)
Q_PROPERTY(int updateThreshold READ updateThreshold WRITE setUpdateThreshold)
+ Q_PROPERTY(Qt::MatchFlags keyboardSearchFlags READ keyboardSearchFlags
+ WRITE setKeyboardSearchFlags)
public:
enum SelectionMode {
@@ -182,6 +184,9 @@ public:
int updateThreshold() const;
void setUpdateThreshold(int threshold);
+ Qt::MatchFlags keyboardSearchFlags() const;
+ void setKeyboardSearchFlags(Qt::MatchFlags searchFlags);
+
void openPersistentEditor(const QModelIndex &index);
void closePersistentEditor(const QModelIndex &index);
bool isPersistentEditorOpen(const QModelIndex &index) const;
diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h
index b24b2d21c33..60799fb8a50 100644
--- a/src/widgets/itemviews/qabstractitemview_p.h
+++ b/src/widgets/itemviews/qabstractitemview_p.h
@@ -383,6 +383,7 @@ public:
QString keyboardInput;
QElapsedTimer keyboardInputTime;
+ Qt::MatchFlags keyboardSearchFlags = Qt::MatchStartsWith | Qt::MatchWrap;
bool autoScroll;
QBasicTimer autoScrollTimer;
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index da1fbbd60df..84ff04c9f34 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -1030,7 +1030,8 @@ void QTreeView::keyboardSearch(const QString &search)
searchFrom = searchFrom.sibling(searchFrom.row(), start.column());
if (searchFrom.parent() == start.parent())
searchFrom = start;
- QModelIndexList match = d->model->match(searchFrom, Qt::DisplayRole, searchString);
+ QModelIndexList match = d->model->match(searchFrom, Qt::DisplayRole, searchString, 1,
+ keyboardSearchFlags());
if (match.size()) {
int hitIndex = d->viewIndex(match.at(0));
if (hitIndex >= 0 && hitIndex < startIndex)
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..69548c4e17e 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
@@ -769,7 +771,8 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
#endif
hideMenu(hideActiveMenu);
} else if (!currentAction || !currentAction->menu()) {
- sloppyState.startTimerIfNotRunning();
+ if (reason != SelectionReason::SelectedFromAPI)
+ sloppyState.startTimerIfNotRunning();
}
}
}
@@ -2170,7 +2173,7 @@ void QMenu::hideTearOffMenu()
void QMenu::setActiveAction(QAction *act)
{
Q_D(QMenu);
- d->setCurrentAction(act, 0);
+ d->setCurrentAction(act, 0, QMenuPrivate::SelectionReason::SelectedFromAPI);
if (d->scroll && act)
d->scrollMenu(act, QMenuPrivate::QMenuScroller::ScrollCenter);
}
@@ -2535,6 +2538,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 +2972,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();
}
}
diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h
index dd1f058a288..d9dcd7d0362 100644
--- a/src/widgets/widgets/qmenu_p.h
+++ b/src/widgets/widgets/qmenu_p.h
@@ -362,7 +362,8 @@ public:
} delayState;
enum SelectionReason {
SelectedFromKeyboard,
- SelectedFromElsewhere
+ SelectedFromAPI,
+ SelectedFromElsewhere,
};
enum class SelectionDirection {
Up,
diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp
index e6f7edc1ac1..01150cd39b2 100644
--- a/src/widgets/widgets/qtoolbutton.cpp
+++ b/src/widgets/widgets/qtoolbutton.cpp
@@ -58,7 +58,8 @@ public:
Qt::ArrowType arrowType;
Qt::ToolButtonStyle toolButtonStyle;
QToolButton::ToolButtonPopupMode popupMode;
- enum { NoButtonPressed=0, MenuButtonPressed=1, ToolButtonPressed=2 };
+ uint popupModeSetByUser : 1; // true if popupMode was set through setPopupMode
+ enum { NoButtonPressed = 0, MenuButtonPressed = 1, ToolButtonPressed = 2 };
uint buttonPressed : 2;
uint menuButtonDown : 1;
uint autoRaise : 1;
@@ -178,6 +179,7 @@ void QToolButtonPrivate::init()
arrowType = Qt::NoArrow;
menuButtonDown = false;
popupMode = QToolButton::DelayedPopup;
+ popupModeSetByUser = false;
buttonPressed = QToolButtonPrivate::NoButtonPressed;
toolButtonStyle = Qt::ToolButtonIconOnly;
@@ -827,7 +829,7 @@ void QToolButtonPrivate::onMenuTriggered(QAction *action)
void QToolButtonPrivate::onDefaultActionChanged()
{
Q_Q(QToolButton);
- if (defaultAction && defaultAction->menu())
+ if (defaultAction && defaultAction->menu() && !popupModeSetByUser)
q->setPopupMode(QToolButton::MenuButtonPopup);
}
@@ -864,6 +866,7 @@ void QToolButtonPrivate::onDefaultActionChanged()
void QToolButton::setPopupMode(ToolButtonPopupMode mode)
{
Q_D(QToolButton);
+ d->popupModeSetByUser = true;
d->popupMode = mode;
}
@@ -922,10 +925,11 @@ void QToolButton::setDefaultAction(QAction *action)
{
Q_D(QToolButton);
#if QT_CONFIG(menu)
- if (d->defaultAction) {
+ if (d->defaultAction && d->defaultAction != action) {
QObjectPrivate::disconnect(d->defaultAction, &QAction::changed, d,
&QToolButtonPrivate::onDefaultActionChanged);
}
+ const bool hadMenu = d->hasMenu();
#endif
d->defaultAction = action;
if (!action)
@@ -949,15 +953,18 @@ void QToolButton::setDefaultAction(QAction *action)
setWhatsThis(action->whatsThis());
#endif
#if QT_CONFIG(menu)
- if (action->menu()) {
+ if (!hadMenu && !d->popupModeSetByUser) {
// ### Qt7 Fixme
// new 'default' popup mode defined introduced by tool bar. We
// should have changed QToolButton's default instead. Do that
// in 4.2.
- setPopupMode(QToolButton::MenuButtonPopup);
+ if (action->menu()) {
+ setPopupMode(QToolButton::MenuButtonPopup);
+ } else {
+ QObjectPrivate::connect(d->defaultAction, &QAction::changed, d,
+ &QToolButtonPrivate::onDefaultActionChanged);
+ }
}
- QObjectPrivate::connect(d->defaultAction, &QAction::changed, d,
- &QToolButtonPrivate::onDefaultActionChanged);
#endif
setCheckable(action->isCheckable());
setChecked(action->isChecked());