summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qguiapplication.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/kernel/qguiapplication.cpp')
-rw-r--r--src/gui/kernel/qguiapplication.cpp215
1 files changed, 164 insertions, 51 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 385264d70a..a79a602088 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1,31 +1,38 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtGui module of the Qt Toolkit.
**
-** $QT_BEGIN_LICENSE:LGPL21$
+** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
-** As a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
@@ -37,6 +44,7 @@
#include <qpa/qplatformintegrationfactory_p.h>
#include "private/qevent_p.h"
#include "qfont.h"
+#include "qtouchdevice.h"
#include <qpa/qplatformfontdatabase.h>
#include <qpa/qplatformwindow.h>
#include <qpa/qplatformnativeinterface.h>
@@ -123,8 +131,6 @@ Qt::KeyboardModifiers QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier;
QPointF QGuiApplicationPrivate::lastCursorPosition(qInf(), qInf());
-Qt::MouseButtons QGuiApplicationPrivate::tabletState = Qt::NoButton;
-QWindow *QGuiApplicationPrivate::tabletPressTarget = 0;
QWindow *QGuiApplicationPrivate::currentMouseWindow = 0;
QString QGuiApplicationPrivate::styleOverride;
@@ -133,11 +139,17 @@ Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationI
bool QGuiApplicationPrivate::highDpiScalingUpdated = false;
+QVector<QGuiApplicationPrivate::TabletPointData> QGuiApplicationPrivate::tabletDevicePoints;
+
QPlatformIntegration *QGuiApplicationPrivate::platform_integration = 0;
QPlatformTheme *QGuiApplicationPrivate::platform_theme = 0;
QList<QObject *> QGuiApplicationPrivate::generic_plugin_list;
+#ifndef QT_NO_SESSIONMANAGER
+bool QGuiApplicationPrivate::is_fallback_session_management_enabled = true;
+#endif
+
enum ApplicationResourceFlags
{
ApplicationPaletteExplicitlySet = 0x1,
@@ -150,6 +162,7 @@ QIcon *QGuiApplicationPrivate::app_icon = 0;
QString *QGuiApplicationPrivate::platform_name = 0;
QString *QGuiApplicationPrivate::displayName = 0;
+QString *QGuiApplicationPrivate::desktopFileName = 0;
QPalette *QGuiApplicationPrivate::app_pal = 0; // default application palette
@@ -614,6 +627,8 @@ QGuiApplication::~QGuiApplication()
QGuiApplicationPrivate::displayName = 0;
delete QGuiApplicationPrivate::m_inputDeviceManager;
QGuiApplicationPrivate::m_inputDeviceManager = 0;
+ delete QGuiApplicationPrivate::desktopFileName;
+ QGuiApplicationPrivate::desktopFileName = 0;
}
QGuiApplicationPrivate::QGuiApplicationPrivate(int &argc, char **argv, int flags)
@@ -655,6 +670,34 @@ QString QGuiApplication::applicationDisplayName()
}
/*!
+ \property QGuiApplication::desktopFileName
+ \brief the base name of the desktop entry for this application
+ \since 5.7
+
+ This is the file name, without the full path, of the desktop entry
+ that represents this application according to the freedesktop desktop
+ entry specification.
+
+ This property gives a precise indication of what desktop entry represents
+ the application and it is needed by the windowing system to retrieve
+ such information without resorting to imprecise heuristics.
+
+ The latest version of the freedesktop desktop entry specification can be obtained
+ \l{http://standards.freedesktop.org/desktop-entry-spec/latest/}{here}.
+*/
+void QGuiApplication::setDesktopFileName(const QString &name)
+{
+ if (!QGuiApplicationPrivate::desktopFileName)
+ QGuiApplicationPrivate::desktopFileName = new QString;
+ *QGuiApplicationPrivate::desktopFileName = name;
+}
+
+QString QGuiApplication::desktopFileName()
+{
+ return QGuiApplicationPrivate::desktopFileName ? *QGuiApplicationPrivate::desktopFileName : QString();
+}
+
+/*!
Returns the most recently shown modal window. If no modal windows are
visible, this function returns zero.
@@ -683,9 +726,10 @@ static void updateBlockedStatusRecursion(QWindow *window, bool shouldBeBlocked)
p->blockedByModalWindow = shouldBeBlocked;
QEvent e(shouldBeBlocked ? QEvent::WindowBlocked : QEvent::WindowUnblocked);
QGuiApplication::sendEvent(window, &e);
- foreach (QObject *c, window->children())
+ for (QObject *c : window->children()) {
if (c->isWindowType())
updateBlockedStatusRecursion(static_cast<QWindow *>(c), shouldBeBlocked);
+ }
}
}
@@ -954,9 +998,8 @@ qreal QGuiApplication::devicePixelRatio() const
}
topDevicePixelRatio = 1.0; // make sure we never return 0.
- foreach (QScreen *screen, QGuiApplicationPrivate::screen_list) {
+ for (QScreen *screen : qAsConst(QGuiApplicationPrivate::screen_list))
topDevicePixelRatio = qMax(topDevicePixelRatio, screen->devicePixelRatio());
- }
return topDevicePixelRatio;
}
@@ -972,7 +1015,7 @@ QWindow *QGuiApplication::topLevelAt(const QPoint &pos)
QScreen *windowScreen = Q_NULLPTR;
// Find the window on the primary virtual desktop first
- foreach (QScreen *screen, primaryScreens) {
+ for (QScreen *screen : primaryScreens) {
if (screen->geometry().contains(pos)) {
windowScreen = screen;
break;
@@ -1052,9 +1095,7 @@ static void init_platform(const QString &pluginArgument, const QString &platform
// Create the platform integration.
QGuiApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name, arguments, argc, argv, platformPluginPath);
- if (QGuiApplicationPrivate::platform_integration) {
- QGuiApplicationPrivate::platform_name = new QString(name);
- } else {
+ if (Q_UNLIKELY(!QGuiApplicationPrivate::platform_integration)) {
QStringList keys = QPlatformIntegrationFactory::keys(platformPluginPath);
QString fatalMessage
@@ -1074,6 +1115,8 @@ static void init_platform(const QString &pluginArgument, const QString &platform
return;
}
+ QGuiApplicationPrivate::platform_name = new QString(name);
+
// Many platforms have created QScreens at this point. Finish initializing
// QHighDpiScaling to be prepared for early calls to qt_defaultDpi().
if (QGuiApplication::primaryScreen()) {
@@ -1091,7 +1134,7 @@ static void init_platform(const QString &pluginArgument, const QString &platform
// 2) Ask the platform integration for a list of theme names
themeNames += QGuiApplicationPrivate::platform_integration->themeNames();
// 3) Look for a theme plugin.
- foreach (const QString &themeName, themeNames) {
+ for (const QString &themeName : qAsConst(themeNames)) {
QGuiApplicationPrivate::platform_theme = QPlatformThemeFactory::create(themeName, platformPluginPath);
if (QGuiApplicationPrivate::platform_theme)
break;
@@ -1100,7 +1143,7 @@ static void init_platform(const QString &pluginArgument, const QString &platform
// 4) If no theme plugin was found ask the platform integration to
// create a theme
if (!QGuiApplicationPrivate::platform_theme) {
- foreach (const QString &themeName, themeNames) {
+ for (const QString &themeName : qAsConst(themeNames)) {
QGuiApplicationPrivate::platform_theme = QGuiApplicationPrivate::platform_integration->createPlatformTheme(themeName);
if (QGuiApplicationPrivate::platform_theme)
break;
@@ -1117,7 +1160,7 @@ static void init_platform(const QString &pluginArgument, const QString &platform
// boolean 'foo' or strings: 'foo=bar'
if (!arguments.isEmpty()) {
if (QObject *nativeInterface = QGuiApplicationPrivate::platform_integration->nativeInterface()) {
- foreach (const QString &argument, arguments) {
+ for (const QString &argument : qAsConst(arguments)) {
const int equalsPos = argument.indexOf(QLatin1Char('='));
const QByteArray name =
equalsPos != -1 ? argument.left(equalsPos).toUtf8() : argument.toUtf8();
@@ -1344,10 +1387,8 @@ void QGuiApplicationPrivate::init()
// Load environment exported generic plugins
QByteArray envPlugins = qgetenv("QT_QPA_GENERIC_PLUGINS");
- if (!envPlugins.isEmpty()) {
- foreach (const QByteArray &plugin, envPlugins.split(','))
- pluginList << plugin;
- }
+ if (!envPlugins.isEmpty())
+ pluginList += envPlugins.split(',');
if (platform_integration == 0)
createPlatformIntegration();
@@ -1399,16 +1440,16 @@ void QGuiApplicationPrivate::init()
if (loadTestability) {
QLibrary testLib(QStringLiteral("qttestability"));
- if (testLib.load()) {
+ if (Q_UNLIKELY(!testLib.load())) {
+ qCritical() << "Library qttestability load failed:" << testLib.errorString();
+ } else {
typedef void (*TasInitialize)(void);
TasInitialize initFunction = (TasInitialize)testLib.resolve("qt_testability_init");
- if (initFunction) {
- initFunction();
+ if (Q_UNLIKELY(!initFunction)) {
+ qCritical("Library qttestability resolve failed!");
} else {
- qCritical() << "Library qttestability resolve failed!";
+ initFunction();
}
- } else {
- qCritical() << "Library qttestability load failed:" << testLib.errorString();
}
}
#else
@@ -1565,7 +1606,7 @@ QFunctionPointer QGuiApplication::platformFunction(const QByteArray &function)
{
QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration();
if (!pi) {
- qWarning() << "QGuiApplication::platformFunction(): Must construct a QGuiApplication before accessing a platform function";
+ qWarning("QGuiApplication::platformFunction(): Must construct a QGuiApplication before accessing a platform function");
return Q_NULLPTR;
}
@@ -1944,7 +1985,8 @@ void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wh
return;
}
- QWheelEvent ev(localPoint, globalPoint, e->pixelDelta, e->angleDelta, e->qt4Delta, e->qt4Orientation, buttons, e->modifiers, e->phase, e->source);
+ QWheelEvent ev(localPoint, globalPoint, e->pixelDelta, e->angleDelta, e->qt4Delta, e->qt4Orientation,
+ buttons, e->modifiers, e->phase, e->source, e->inverted);
ev.setTimestamp(e->timestamp);
QGuiApplication::sendSpontaneousEvent(window, &ev);
#endif /* ifndef QT_NO_WHEELEVENT */
@@ -2200,12 +2242,26 @@ void QGuiApplicationPrivate::processFileOpenEvent(QWindowSystemInterfacePrivate:
QGuiApplication::sendSpontaneousEvent(qApp, &event);
}
+QGuiApplicationPrivate::TabletPointData &QGuiApplicationPrivate::tabletDevicePoint(qint64 deviceId)
+{
+ for (int i = 0; i < tabletDevicePoints.size(); ++i) {
+ TabletPointData &pointData = tabletDevicePoints[i];
+ if (pointData.deviceId == deviceId)
+ return pointData;
+ }
+
+ tabletDevicePoints.append(TabletPointData(deviceId));
+ return tabletDevicePoints.last();
+}
+
void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::TabletEvent *e)
{
#ifndef QT_NO_TABLETEVENT
+ TabletPointData &pointData = tabletDevicePoint(e->uid);
+
QEvent::Type type = QEvent::TabletMove;
- if (e->buttons != tabletState)
- type = (e->buttons > tabletState) ? QEvent::TabletPress : QEvent::TabletRelease;
+ if (e->buttons != pointData.state)
+ type = (e->buttons > pointData.state) ? QEvent::TabletPress : QEvent::TabletRelease;
QWindow *window = e->window.data();
modifier_buttons = e->modifiers;
@@ -2221,14 +2277,14 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T
}
if (!window)
return;
- tabletPressTarget = window;
+ pointData.target = window;
} else {
if (e->nullWindow()) {
- window = tabletPressTarget;
+ window = pointData.target;
localValid = false;
}
if (type == QEvent::TabletRelease)
- tabletPressTarget = 0;
+ pointData.target = Q_NULLPTR;
if (!window)
return;
}
@@ -2237,7 +2293,7 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T
QPointF delta = e->global - e->global.toPoint();
local = window->mapFromGlobal(e->global.toPoint()) + delta;
}
- Qt::MouseButtons stateChange = e->buttons ^ tabletState;
+ Qt::MouseButtons stateChange = e->buttons ^ pointData.state;
Qt::MouseButton button = Qt::NoButton;
for (int check = Qt::LeftButton; check <= int(Qt::MaxMouseButton); check = check << 1) {
if (check & stateChange) {
@@ -2251,7 +2307,7 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T
e->modifiers, e->uid, button, e->buttons);
ev.setTimestamp(e->timestamp);
QGuiApplication::sendSpontaneousEvent(window, &ev);
- tabletState = e->buttons;
+ pointData.state = e->buttons;
#else
Q_UNUSED(e)
#endif
@@ -2263,7 +2319,7 @@ void QGuiApplicationPrivate::processTabletEnterProximityEvent(QWindowSystemInter
QTabletEvent ev(QEvent::TabletEnterProximity, QPointF(), QPointF(),
e->device, e->pointerType, 0, 0, 0,
0, 0, 0,
- Qt::NoModifier, e->uid, Qt::NoButton, tabletState);
+ Qt::NoModifier, e->uid, Qt::NoButton, tabletDevicePoint(e->uid).state);
ev.setTimestamp(e->timestamp);
QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev);
#else
@@ -2277,7 +2333,7 @@ void QGuiApplicationPrivate::processTabletLeaveProximityEvent(QWindowSystemInter
QTabletEvent ev(QEvent::TabletLeaveProximity, QPointF(), QPointF(),
e->device, e->pointerType, 0, 0, 0,
0, 0, 0,
- Qt::NoModifier, e->uid, Qt::NoButton, tabletState);
+ Qt::NoModifier, e->uid, Qt::NoButton, tabletDevicePoint(e->uid).state);
ev.setTimestamp(e->timestamp);
QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev);
#else
@@ -2668,7 +2724,8 @@ void QGuiApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate:
emit s->availableGeometryChanged(s->availableGeometry());
if (geometryChanged || availableGeometryChanged) {
- foreach (QScreen* sibling, s->virtualSiblings())
+ const auto siblings = s->virtualSiblings();
+ for (QScreen* sibling : siblings)
emit sibling->virtualGeometryChanged(sibling->virtualGeometry());
}
}
@@ -3091,6 +3148,57 @@ void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state, boo
emit qApp->applicationStateChanged(applicationState);
}
+#ifndef QT_NO_SESSIONMANAGER
+// ### Qt6: consider removing the feature or making it less intrusive
+/*!
+ \since 5.6
+
+ Returns whether QGuiApplication will use fallback session management.
+
+ The default is \c true.
+
+ If this is \c true and the session manager allows user interaction,
+ QGuiApplication will try to close toplevel windows after
+ commitDataRequest() has been emitted. If a window cannot be closed, session
+ shutdown will be canceled and the application will keep running.
+
+ Fallback session management only benefits applications that have an
+ "are you sure you want to close this window?" feature or other logic that
+ prevents closing a toplevel window depending on certain conditions, and
+ that do nothing to explicitly implement session management. In applications
+ that \e do implement session management using the proper session management
+ API, fallback session management interferes and may break session
+ management logic.
+
+ \warning If all windows \e are closed due to fallback session management
+ and quitOnLastWindowClosed() is \c true, the application will quit before
+ it is explicitly instructed to quit through the platform's session
+ management protocol. That violation of protocol may prevent the platform
+ session manager from saving application state.
+
+ \sa setFallbackSessionManagementEnabled(),
+ QSessionManager::allowsInteraction(), saveStateRequest(),
+ commitDataRequest(), {Session Management}
+*/
+bool QGuiApplication::isFallbackSessionManagementEnabled()
+{
+ return QGuiApplicationPrivate::is_fallback_session_management_enabled;
+}
+
+/*!
+ \since 5.6
+
+ Sets whether QGuiApplication will use fallback session management to
+ \a enabled.
+
+ \sa isFallbackSessionManagementEnabled()
+*/
+void QGuiApplication::setFallbackSessionManagementEnabled(bool enabled)
+{
+ QGuiApplicationPrivate::is_fallback_session_management_enabled = enabled;
+}
+#endif // QT_NO_SESSIONMANAGER
+
/*!
\since 4.2
\fn void QGuiApplication::commitDataRequest(QSessionManager &manager)
@@ -3115,7 +3223,8 @@ void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state, boo
\note You should use Qt::DirectConnection when connecting to this signal.
- \sa isSessionRestored(), sessionId(), saveStateRequest(), {Session Management}
+ \sa setFallbackSessionManagementEnabled(), isSessionRestored(),
+ sessionId(), saveStateRequest(), {Session Management}
*/
/*!
@@ -3245,9 +3354,13 @@ void QGuiApplicationPrivate::commitData()
{
Q_Q(QGuiApplication);
is_saving_session = true;
+
emit q->commitDataRequest(*session_manager);
- if (session_manager->allowsInteraction() && !tryCloseAllWindows())
+ if (is_fallback_session_management_enabled && session_manager->allowsInteraction()
+ && !tryCloseAllWindows()) {
session_manager->cancel();
+ }
+
is_saving_session = false;
}
@@ -3562,7 +3675,7 @@ void QGuiApplicationPrivate::_q_updateFocusObject(QObject *object)
emit q->focusObjectChanged(object);
}
-enum {
+enum MouseMasks {
MouseCapsMask = 0xFF,
MouseSourceMaskDst = 0xFF00,
MouseSourceMaskSrc = MouseCapsMask,