summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qapplication.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/kernel/qapplication.cpp')
-rw-r--r--src/widgets/kernel/qapplication.cpp151
1 files changed, 61 insertions, 90 deletions
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 8b6adc0176..bf6b41cbcd 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -98,6 +98,8 @@ static void initResources()
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcWidgetPopup, "qt.widgets.popup");
+
using namespace Qt::StringLiterals;
Q_TRACE_PREFIX(qtwidgets,
@@ -310,7 +312,6 @@ QWidget *QApplication::topLevelAt(const QPoint &pos)
*/
void qt_init_tooltip_palette();
-void qt_cleanup();
QStyle *QApplicationPrivate::app_style = nullptr; // default application style
#ifndef QT_NO_STYLE_STYLESHEET
@@ -353,8 +354,6 @@ Q_GLOBAL_STATIC(FontHash, app_fonts)
// Exported accessor for use outside of this file
FontHash *qt_app_fonts_hash() { return app_fonts(); }
-QWidgetList *QApplicationPrivate::popupWidgets = nullptr; // has keyboard input focus
-
QWidget *qt_desktopWidget = nullptr; // root window widgets
/*!
@@ -496,8 +495,11 @@ void QApplicationPrivate::init()
void qt_init_tooltip_palette()
{
#if QT_CONFIG(tooltip)
- if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette))
- QToolTip::setPalette(*toolTipPalette);
+ if (const QPalette *toolTipPalette = QGuiApplicationPrivate::platformTheme()->palette(QPlatformTheme::ToolTipPalette)) {
+ QPalette toolTipPal = *toolTipPalette;
+ toolTipPal.setResolveMask(0);
+ QToolTip::setPalette(toolTipPal);
+ }
#endif
}
@@ -625,8 +627,8 @@ void QApplicationPrivate::initializeWidgetFontHash()
QWidget *QApplication::activePopupWidget()
{
- return QApplicationPrivate::popupWidgets && !QApplicationPrivate::popupWidgets->isEmpty() ?
- QApplicationPrivate::popupWidgets->constLast() : nullptr;
+ auto *win = qobject_cast<QWidgetWindow *>(QGuiApplicationPrivate::activePopupWindow());
+ return win ? win->widget() : nullptr;
}
@@ -705,7 +707,10 @@ QApplication::~QApplication()
d->cleanupMultitouch();
- qt_cleanup();
+ QPixmapCache::clear();
+ QColormap::cleanup();
+
+ QApplicationPrivate::active_window = nullptr; //### this should not be necessary
if (QApplicationPrivate::widgetCount)
qDebug("Widgets left: %i Max widgets: %i \n", QWidgetPrivate::instanceCounter, QWidgetPrivate::maxInstances);
@@ -716,14 +721,6 @@ QApplication::~QApplication()
QApplicationPrivate::widgetCount = false;
}
-void qt_cleanup()
-{
- QPixmapCache::clear();
- QColormap::cleanup();
-
- QApplicationPrivate::active_window = nullptr; //### this should not be necessary
-}
-
/*!
\fn QWidget *QApplication::widgetAt(const QPoint &point)
@@ -789,6 +786,7 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis
const QEvent::Type type = event->type();
switch (type) {
case QEvent::UpdateRequest:
+ case QEvent::UpdateLater:
case QEvent::LayoutRequest:
case QEvent::Resize:
case QEvent::Move:
@@ -817,6 +815,10 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis
static_cast<QMoveEvent *>(postedEvent.event)->m_pos =
static_cast<const QMoveEvent *>(event)->pos();
break;
+ case QEvent::UpdateLater:
+ static_cast<QUpdateLaterEvent *>(postedEvent.event)->m_region +=
+ static_cast<const QUpdateLaterEvent *>(event)->region();
+ break;
case QEvent::UpdateRequest:
case QEvent::LanguageChange:
case QEvent::LayoutRequest:
@@ -1092,6 +1094,12 @@ QPalette QApplicationPrivate::basePalette() const
if (const QPalette *themePalette = platformTheme() ? platformTheme()->palette() : nullptr)
palette = themePalette->resolve(palette);
+ // This palette now is Qt-generated, so reset the resolve mask. This allows
+ // QStyle::polish implementations to respect palettes that are user provided,
+ // by checking if the palette has a brush set for a color that the style might
+ // otherwise overwrite.
+ palette.setResolveMask(0);
+
// Finish off by letting the application style polish the palette. This will
// not result in the polished palette becoming a user-set palette, as the
// resulting base palette is only used as a fallback, with the resolve mask
@@ -1774,7 +1782,7 @@ void QApplicationPrivate::notifyLayoutDirectionChange()
/*!
\fn void QApplication::setActiveWindow(QWidget* active)
- \deprecated Use QWidget::activateWindow() instead.
+ \deprecated [6.5] Use QWidget::activateWindow() instead.
Sets the active window to the \a active widget in response to a system
event. The function is called from the platform specific event handlers.
@@ -1867,7 +1875,7 @@ void QApplicationPrivate::setActiveWindow(QWidget* act)
QApplication::sendSpontaneousEvent(w, &activationChange);
}
- if (QApplicationPrivate::popupWidgets == nullptr) { // !inPopupMode()
+ if (!inPopupMode()) {
// then focus events
if (!QApplicationPrivate::active_window && QApplicationPrivate::focus_widget) {
QApplicationPrivate::setFocusWidget(nullptr, Qt::ActiveWindowFocusReason);
@@ -1967,7 +1975,7 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
f = toplevel;
QWidget *w = f;
- QWidget *test = f->d_func()->focus_next;
+ QWidget *test = f->nextInFocusChain();
bool seenWindow = false;
bool focusWidgetAfterWindow = false;
while (test && test != f) {
@@ -1998,7 +2006,7 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
if (next)
break;
}
- test = test->d_func()->focus_next;
+ test = test->nextInFocusChain();
}
if (wrappingOccurred != nullptr)
@@ -2023,19 +2031,6 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
*/
void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
{
-#if 0
- if (leave) {
- QEvent e(QEvent::Leave);
- QCoreApplication::sendEvent(leave, & e);
- }
- if (enter) {
- const QPoint windowPos = enter->window()->mapFromGlobal(globalPos);
- QEnterEvent e(enter->mapFromGlobal(globalPos), windowPos, globalPos);
- QCoreApplication::sendEvent(enter, & e);
- }
- return;
-#endif
-
if ((!enter && !leave) || (enter == leave))
return;
@@ -2546,8 +2541,9 @@ int QApplication::startDragDistance()
exec(), because modal widgets call exec() to start a local event loop.
To make your application perform idle processing, i.e., executing a special
- function whenever there are no pending events, use a QTimer with 0 timeout.
- More advanced idle processing schemes can be achieved using processEvents().
+ function whenever there are no pending events, use a QChronoTimer with 0ns
+ timeout. More advanced idle processing schemes can be achieved using
+ processEvents().
We recommend that you connect clean-up code to the
\l{QCoreApplication::}{aboutToQuit()} signal, instead of putting it in your
@@ -2656,6 +2652,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
Q_FALLTHROUGH();
case QEvent::Leave:
d->toolTipWakeUp.stop();
+ break;
default:
break;
}
@@ -2680,6 +2677,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
|| key == Qt::Key_Up
|| key == Qt::Key_Right
|| key == Qt::Key_Down);
+ break;
}
default:
break;
@@ -2941,6 +2939,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
tablet->tangentialPressure(), tablet->rotation(), tablet->z(),
tablet->modifiers(), tablet->button(), tablet->buttons());
te.m_spont = e->spontaneous();
+ te.setTimestamp(tablet->timestamp());
te.setAccepted(false);
res = d->notify_helper(w, w == receiver ? tablet : &te);
eventAccepted = ((w == receiver) ? tablet : &te)->isAccepted();
@@ -3036,8 +3035,16 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
#endif
w = qobject_cast<QWidget *>(QDragManager::self()->currentTarget());
- if (!w)
- break;
+ if (!w) {
+ // The widget that received DragEnter didn't accept the event, so we have no
+ // current drag target in the QDragManager. But DragLeave still needs to be
+ // dispatched so that enter/leave events are in balance (and so that UnderMouse
+ // gets cleared).
+ if (e->type() == QEvent::DragLeave)
+ w = static_cast<QWidget *>(receiver);
+ else
+ break;
+ }
if (e->type() == QEvent::DragMove || e->type() == QEvent::Drop) {
QDropEvent *dragEvent = static_cast<QDropEvent *>(e);
QWidget *origReceiver = static_cast<QWidget *>(receiver);
@@ -3292,11 +3299,12 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
bool QApplicationPrivate::inPopupMode()
{
- return QApplicationPrivate::popupWidgets != nullptr;
+ return QGuiApplicationPrivate::activePopupWindow() != nullptr;
}
static void ungrabKeyboardForPopup(QWidget *popup)
{
+ qCDebug(lcWidgetPopup) << "ungrab keyboard for" << popup;
if (QWidget::keyboardGrabber())
qt_widget_private(QWidget::keyboardGrabber())->stealKeyboardGrab(true);
else
@@ -3305,6 +3313,7 @@ static void ungrabKeyboardForPopup(QWidget *popup)
static void ungrabMouseForPopup(QWidget *popup)
{
+ qCDebug(lcWidgetPopup) << "ungrab mouse for" << popup;
if (QWidget::mouseGrabber())
qt_widget_private(QWidget::mouseGrabber())->stealMouseGrab(true);
else
@@ -3324,54 +3333,23 @@ static void grabForPopup(QWidget *popup)
ungrabKeyboardForPopup(popup);
}
}
-}
-
-extern QWidget *qt_popup_down;
-extern bool qt_replay_popup_mouse_event;
-extern bool qt_popup_down_closed;
-
-bool QApplicationPrivate::closeAllPopups()
-{
- // Close all popups: In case some popup refuses to close,
- // we give up after 1024 attempts (to avoid an infinite loop).
- int maxiter = 1024;
- QWidget *popup;
- while ((popup = QApplication::activePopupWidget()) && maxiter--)
- popup->close(); // this will call QApplicationPrivate::closePopup
- return true;
+ qCDebug(lcWidgetPopup) << "grabbed mouse and keyboard?" << popupGrabOk << "for popup" << popup;
}
void QApplicationPrivate::closePopup(QWidget *popup)
{
- if (!popupWidgets)
+ QWindow *win = popup->windowHandle();
+ if (!win)
+ return;
+ if (!QGuiApplicationPrivate::closePopup(win))
return;
- popupWidgets->removeAll(popup);
-
- if (popup == qt_popup_down) {
- qt_button_down = nullptr;
- qt_popup_down_closed = true;
- qt_popup_down = nullptr;
- }
- if (QApplicationPrivate::popupWidgets->size() == 0) { // this was the last popup
- delete QApplicationPrivate::popupWidgets;
- QApplicationPrivate::popupWidgets = nullptr;
- qt_popup_down_closed = false;
+ const QWindow *nextRemainingPopup = QGuiApplicationPrivate::activePopupWindow();
+ if (!nextRemainingPopup) { // this was the last popup
if (popupGrabOk) {
popupGrabOk = false;
- // TODO on multi-seat window systems, we have to know which mouse
- auto devPriv = QPointingDevicePrivate::get(QPointingDevice::primaryPointingDevice());
- auto mousePressPos = devPriv->pointById(0)->eventPoint.globalPressPosition();
- if (popup->geometry().contains(mousePressPos.toPoint())
- || popup->testAttribute(Qt::WA_NoMouseReplay)) {
- // mouse release event or inside
- qt_replay_popup_mouse_event = false;
- } else { // mouse press event
- qt_replay_popup_mouse_event = true;
- }
-
// transfer grab back to mouse grabber if any, otherwise release the grab
ungrabMouseForPopup(popup);
@@ -3390,30 +3368,23 @@ void QApplicationPrivate::closePopup(QWidget *popup)
}
}
- } else {
+ } else if (const auto *popupWin = qobject_cast<const QWidgetWindow *>(nextRemainingPopup)) {
// A popup was closed, so the previous popup gets the focus.
- QWidget* aw = QApplicationPrivate::popupWidgets->constLast();
- if (QWidget *fw = aw->focusWidget())
+ if (QWidget *fw = popupWin->widget()->focusWidget())
fw->setFocus(Qt::PopupFocusReason);
// can become nullptr due to setFocus() above
- if (QApplicationPrivate::popupWidgets &&
- QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard
- grabForPopup(aw);
+ if (QGuiApplicationPrivate::popupCount() == 1) // grab mouse/keyboard
+ grabForPopup(popupWin->widget());
}
}
-int openPopupCount = 0;
-
void QApplicationPrivate::openPopup(QWidget *popup)
{
- openPopupCount++;
- if (!popupWidgets) // create list
- popupWidgets = new QWidgetList;
- popupWidgets->append(popup); // add to end of list
+ QGuiApplicationPrivate::activatePopup(popup->windowHandle());
- if (QApplicationPrivate::popupWidgets->size() == 1) // grab mouse/keyboard
+ if (QGuiApplicationPrivate::popupCount() == 1) // grab mouse/keyboard
grabForPopup(popup);
// popups are not focus-handled by the window system (the first
@@ -3421,7 +3392,7 @@ void QApplicationPrivate::openPopup(QWidget *popup)
// new popup gets the focus
if (popup->focusWidget()) {
popup->focusWidget()->setFocus(Qt::PopupFocusReason);
- } else if (popupWidgets->size() == 1) { // this was the first popup
+ } else if (QGuiApplicationPrivate::popupCount() == 1) { // this was the first popup
if (QWidget *fw = QApplication::focusWidget()) {
QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
QCoreApplication::sendEvent(fw, &e);