diff options
Diffstat (limited to 'src/gui/kernel/qguiapplication.cpp')
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 132 |
1 files changed, 100 insertions, 32 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index e81c88cc71..9bf2a33e2a 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -114,6 +114,10 @@ # include <QtCore/QLibraryInfo> #endif // Q_OS_WIN +#ifdef Q_OS_WASM +#include <emscripten.h> +#endif + #include <qtgui_tracepoints_p.h> #include <ctype.h> @@ -143,6 +147,8 @@ Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationI bool QGuiApplicationPrivate::highDpiScalingUpdated = false; +QPointer<QWindow> QGuiApplicationPrivate::currentDragWindow; + QVector<QGuiApplicationPrivate::TabletPointData> QGuiApplicationPrivate::tabletDevicePoints; QPlatformIntegration *QGuiApplicationPrivate::platform_integration = 0; @@ -250,10 +256,10 @@ static inline void clearFontUnlocked() QGuiApplicationPrivate::app_font = 0; } -static bool checkRunningUnderFlatpak() +static bool checkNeedPortalSupport() { #if QT_CONFIG(dbus) - return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty(); + return !QStandardPaths::locate(QStandardPaths::RuntimeLocation, QLatin1String("flatpak-info")).isEmpty() || qEnvironmentVariableIsSet("SNAP"); #else return false; #endif // QT_CONFIG(dbus) @@ -592,6 +598,9 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME By default, they will be used if the application is not an instance of QApplication or for Qt Quick Controls 2 applications. + + \li \c {altgr}, detect the key \c {AltGr} found on some keyboards as + Qt::GroupSwitchModifier. \endlist The following parameter is available for \c {-platform cocoa} (on macOS): @@ -668,6 +677,7 @@ QGuiApplication::~QGuiApplication() QGuiApplicationPrivate::currentMousePressWindow = QGuiApplicationPrivate::currentMouseWindow = nullptr; QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive; QGuiApplicationPrivate::highDpiScalingUpdated = false; + QGuiApplicationPrivate::currentDragWindow = nullptr; QGuiApplicationPrivate::tabletDevicePoints.clear(); #ifndef QT_NO_SESSIONMANAGER QGuiApplicationPrivate::is_fallback_session_management_enabled = true; @@ -1215,9 +1225,9 @@ static void init_platform(const QString &pluginNamesWithArguments, const QString if (!platformThemeName.isEmpty()) themeNames.append(platformThemeName); - // 2) Special case - check whether we are in sandbox to use flatpak platform theme for portals support - if (checkRunningUnderFlatpak()) { - themeNames.append(QStringLiteral("flatpak")); + // 2) Special case - check whether it's a flatpak or snap app to use xdg-desktop-portal platform theme for portals support + if (checkNeedPortalSupport()) { + themeNames.append(QStringLiteral("xdgdesktopportal")); } // 3) Ask the platform integration for a list of theme names @@ -1409,7 +1419,7 @@ void QGuiApplicationPrivate::eventDispatcherReady() void QGuiApplicationPrivate::init() { - Q_TRACE(qguiapplicationprivate_init_entry); + Q_TRACE(QGuiApplicationPrivate_init_entry); #if defined(Q_OS_MACOS) QMacAutoReleasePool pool; @@ -1574,7 +1584,7 @@ void QGuiApplicationPrivate::init() QObject::connect(q, &QGuiApplication::applicationNameChanged, q, &QGuiApplication::applicationDisplayNameChanged); - Q_TRACE(qguiapplicationprivate_init_exit); + Q_TRACE(QGuiApplicationPrivate_init_exit); } extern void qt_cleanupFontDatabase(); @@ -1614,7 +1624,13 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate() qt_gl_set_global_share_context(0); } #endif - +#ifdef Q_OS_WASM + EM_ASM( + // unmount persistent directory as IDBFS + // see QTBUG-70002 + FS.unmount('/home/web_user'); + ); +#endif platform_integration->destroy(); delete platform_theme; @@ -1690,7 +1706,7 @@ Qt::KeyboardModifiers QGuiApplication::queryKeyboardModifiers() /*! Returns the current state of the buttons on the mouse. The current state is - updated syncronously as the event queue is emptied of events that will + updated synchronously as the event queue is emptied of events that will spontaneously change the mouse state (QEvent::MouseButtonPress and QEvent::MouseButtonRelease events). @@ -1765,8 +1781,11 @@ int QGuiApplication::exec() */ bool QGuiApplication::notify(QObject *object, QEvent *event) { - if (object->isWindowType()) - QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(static_cast<QWindow *>(object), event); + if (object->isWindowType()) { + if (QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(static_cast<QWindow *>(object), event)) + return true; // Platform plugin ate the event + } + return QCoreApplication::notify(object, event); } @@ -1788,18 +1807,18 @@ bool QGuiApplication::compressEvent(QEvent *event, QObject *receiver, QPostEvent return QCoreApplication::compressEvent(event, receiver, postedEvents); } -void QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(QWindow *window, QEvent *event) +bool QGuiApplicationPrivate::sendQWindowEventToQPlatformWindow(QWindow *window, QEvent *event) { if (!window) - return; + return false; QPlatformWindow *platformWindow = window->handle(); if (!platformWindow) - return; + return false; // spontaneous events come from the platform integration already, we don't need to send the events back if (event->spontaneous()) - return; + return false; // let the platform window do any handling it needs to as well - platformWindow->windowEvent(event); + return platformWindow->windowEvent(event); } bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result) @@ -1809,7 +1828,7 @@ bool QGuiApplicationPrivate::processNativeEvent(QWindow *window, const QByteArra void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) { - Q_TRACE(qguiapplicationprivate_processwsevents_entry, e->type); + Q_TRACE(QGuiApplicationPrivate_processWindowSystemEvent_entry, e->type); switch(e->type) { case QWindowSystemInterfacePrivate::Mouse: @@ -1920,7 +1939,7 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv break; } - Q_TRACE(qguiapplicationprivate_processwsevents_exit, e->type); + Q_TRACE(QGuiApplicationPrivate_processWindowSystemEvent_exit, e->type); } /*! \internal @@ -2332,11 +2351,11 @@ void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterf if (QWindow *window = wse->window.data()) { if (window->screen() == wse->screen.data()) return; - if (window->isTopLevel()) { + if (QWindow *topLevelWindow = window->d_func()->topLevelWindow(QWindow::ExcludeTransients)) { if (QScreen *screen = wse->screen.data()) - window->d_func()->setTopLevelScreen(screen, false /* recreate */); + topLevelWindow->d_func()->setTopLevelScreen(screen, false /* recreate */); else // Fall back to default behavior, and try to find some appropriate screen - window->setScreen(0); + topLevelWindow->setScreen(0); } // we may have changed scaling, so trigger resize event if needed if (window->handle()) { @@ -3047,9 +3066,56 @@ void QGuiApplicationPrivate::processExposeEvent(QWindowSystemInterfacePrivate::E #if QT_CONFIG(draganddrop) -QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) +/*! \internal + + This function updates an internal state to keep the source compatibility. Documentation of + QGuiApplication::mouseButtons() states - "The current state is updated synchronously as + the event queue is emptied of events that will spontaneously change the mouse state + (QEvent::MouseButtonPress and QEvent::MouseButtonRelease events)". But internally we have + been updating these state variables from various places to keep buttons returned by + mouseButtons() in sync with the systems state. This is not the documented behavior. + + ### Qt6 - Remove QGuiApplication::mouseButtons()/keyboardModifiers() API? And here + are the reasons: + + - It is an easy to misuse API by: + + a) Application developers: The only place where the values of this API can be trusted is + when using within mouse handling callbacks. In these callbacks we work with the state + that was provided directly by the windowing system. Anywhere else it might not reflect what + user wrongly expects. We might not always receive a matching mouse release for a press event + (e.g. When dismissing a popup window on X11. Or when dnd enter Qt application with mouse + button down, we update mouse_buttons and then dnd leaves Qt application and does a drop + somewhere else) and hence mouseButtons() will be out-of-sync from users perspective, see + for example QTBUG-33161. BUT THIS IS NOT HOW THE API IS SUPPOSED TO BE USED. Since the only + safe place to use this API is from mouse event handlers, we might as well deprecate it and + pass down the button state if we are not already doing that everywhere where it matters. + + b) Qt framework developers: + + We see users complaining, we start adding hacks everywhere just to keep buttons in sync ;) + There are corner cases that can not be solved and adding this kind of hacks is never ending + task. + + - Real mouse events, tablet mouse events, etc: all go through QGuiApplication::processMouseEvent, + and all share mouse_buttons. What if we want to support multiple mice in future? The API must + go. + + - Motivation why this API is public is not clear. Could the same be achieved by a user by + installing an event filter? +*/ +static void updateMouseAndModifierButtonState(Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) { - static QPointer<QWindow> currentDragWindow; + QGuiApplicationPrivate::mouse_buttons = buttons; + QGuiApplicationPrivate::modifier_buttons = modifiers; +} + +QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) +{ + updateMouseAndModifierButtonState(buttons, modifiers); + static Qt::DropAction lastAcceptedDropAction = Qt::IgnoreAction; QPlatformDrag *platformDrag = platformIntegration()->drag(); if (!platformDrag || (w && w->d_func()->blockedByModalWindow)) { @@ -3058,15 +3124,13 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM } if (!dropData) { - if (currentDragWindow.data() == w) - currentDragWindow = 0; + currentDragWindow = nullptr; QDragLeaveEvent e; QGuiApplication::sendEvent(w, &e); lastAcceptedDropAction = Qt::IgnoreAction; return QPlatformDragQtResponse(false, lastAcceptedDropAction, QRect()); } - QDragMoveEvent me(p, supportedActions, dropData, - QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); + QDragMoveEvent me(p, supportedActions, dropData, buttons, modifiers); if (w != currentDragWindow) { lastAcceptedDropAction = Qt::IgnoreAction; @@ -3075,8 +3139,7 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM QGuiApplication::sendEvent(currentDragWindow, &e); } currentDragWindow = w; - QDragEnterEvent e(p, supportedActions, dropData, - QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); + QDragEnterEvent e(p, supportedActions, dropData, buttons, modifiers); QGuiApplication::sendEvent(w, &e); if (e.isAccepted() && e.dropAction() != Qt::IgnoreAction) lastAcceptedDropAction = e.dropAction(); @@ -3094,10 +3157,15 @@ QPlatformDragQtResponse QGuiApplicationPrivate::processDrag(QWindow *w, const QM return QPlatformDragQtResponse(me.isAccepted(), lastAcceptedDropAction, me.answerRect()); } -QPlatformDropQtResponse QGuiApplicationPrivate::processDrop(QWindow *w, const QMimeData *dropData, const QPoint &p, Qt::DropActions supportedActions) +QPlatformDropQtResponse QGuiApplicationPrivate::processDrop(QWindow *w, const QMimeData *dropData, + const QPoint &p, Qt::DropActions supportedActions, + Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) { - QDropEvent de(p, supportedActions, dropData, - QGuiApplication::mouseButtons(), QGuiApplication::keyboardModifiers()); + updateMouseAndModifierButtonState(buttons, modifiers); + + currentDragWindow = nullptr; + + QDropEvent de(p, supportedActions, dropData, buttons, modifiers); QGuiApplication::sendEvent(w, &de); Qt::DropAction acceptedAction = de.isAccepted() ? de.dropAction() : Qt::IgnoreAction; |