diff options
Diffstat (limited to 'src/gui/kernel/qguiapplication.cpp')
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 190 |
1 files changed, 134 insertions, 56 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 4727e754cd..51b1db8cf1 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -82,6 +82,7 @@ #include <qpa/qwindowsysteminterface_p.h> #include "private/qwindow_p.h" #include "private/qcursor_p.h" +#include "private/qopenglcontext_p.h" #include "private/qdnd_p.h" #include <qpa/qplatformthemefactory_p.h> @@ -118,7 +119,7 @@ Qt::KeyboardModifiers QGuiApplicationPrivate::modifier_buttons = Qt::NoModifier; QPointF QGuiApplicationPrivate::lastCursorPosition(qInf(), qInf()); -bool QGuiApplicationPrivate::tabletState = false; +Qt::MouseButtons QGuiApplicationPrivate::tabletState = Qt::NoButton; QWindow *QGuiApplicationPrivate::tabletPressTarget = 0; QWindow *QGuiApplicationPrivate::currentMouseWindow = 0; @@ -509,6 +510,7 @@ static QWindowGeometrySpecification windowGeometrySpecification; \li \c {-qwindowgeometry} \e geometry, specifies window geometry for the main window using the X11-syntax. For example: \c {-qwindowgeometry 100x100+50+50} + \li \c {-qwindowicon}, sets the default window icon \li \c {-qwindowtitle}, sets the title of the first window \li \c{-reverse}, sets the application's layout direction to Qt::RightToLeft. This option is intended to aid debugging and should @@ -606,7 +608,8 @@ QGuiApplicationPrivate::QGuiApplicationPrivate(int &argc, char **argv, int flags : QCoreApplicationPrivate(argc, argv, flags), styleHints(0), inputMethod(0), - lastTouchType(QEvent::TouchEnd) + lastTouchType(QEvent::TouchEnd), + ownGlobalShareContext(false) { self = this; application_type = QCoreApplicationPrivate::Gui; @@ -903,7 +906,19 @@ QList<QScreen *> QGuiApplication::screens() This signal is emitted whenever a new screen \a screen has been added to the system. - \sa screens(), primaryScreen() + \sa screens(), primaryScreen(), screenRemoved() +*/ + +/*! + \fn void QGuiApplication::screenRemoved(QScreen *screen) + + This signal is emitted whenever a \a screen is removed from the system. It + provides an opportunity to manage the windows on the screen before Qt falls back + to moving them to the primary screen. + + \sa screens(), screenAdded(), QObject::destroyed(), QWindow::setScreen() + + \since 5.4 */ @@ -1115,12 +1130,15 @@ void QGuiApplicationPrivate::createPlatformIntegration() // Get command line params + QString icon; + int j = argc ? 1 : 0; for (int i=1; i<argc; i++) { if (argv[i] && *argv[i] != '-') { argv[j++] = argv[i]; continue; } + const bool isXcb = platformName == "xcb"; QByteArray arg = argv[i]; if (arg.startsWith("--")) arg.remove(0, 1); @@ -1133,12 +1151,16 @@ void QGuiApplicationPrivate::createPlatformIntegration() } else if (arg == "-platformtheme") { if (++i < argc) platformThemeName = QString::fromLocal8Bit(argv[i]); - } else if (arg == "-qwindowgeometry" || (platformName == "xcb" && arg == "-geometry")) { + } else if (arg == "-qwindowgeometry" || (isXcb && arg == "-geometry")) { if (++i < argc) windowGeometrySpecification = QWindowGeometrySpecification::fromArgument(argv[i]); - } else if (arg == "-qwindowtitle" || (platformName == "xcb" && arg == "-title")) { + } else if (arg == "-qwindowtitle" || (isXcb && arg == "-title")) { if (++i < argc) firstWindowTitle = QString::fromLocal8Bit(argv[i]); + } else if (arg == "-qwindowicon" || (isXcb && arg == "-icon")) { + if (++i < argc) { + icon = QString::fromLocal8Bit(argv[i]); + } } else { argv[j++] = argv[i]; } @@ -1151,6 +1173,8 @@ void QGuiApplicationPrivate::createPlatformIntegration() init_platform(QLatin1String(platformName), platformPluginPath, platformThemeName, argc, argv); + if (!icon.isEmpty()) + forcedWindowIcon = QDir::isAbsolutePath(icon) ? QIcon(icon) : QIcon::fromTheme(icon); } /*! @@ -1296,6 +1320,17 @@ void QGuiApplicationPrivate::init() qRegisterGuiGetInterpolator(); #endif + // set a global share context when enabled unless there is already one +#ifndef QT_NO_OPENGL + if (qApp->testAttribute(Qt::AA_ShareOpenGLContexts) && !qt_gl_global_share_context()) { + QOpenGLContext *ctx = new QOpenGLContext; + ctx->setFormat(QSurfaceFormat::defaultFormat()); + ctx->create(); + qt_gl_set_global_share_context(ctx); + ownGlobalShareContext = true; + } +#endif + QWindowSystemInterfacePrivate::eventTime.start(); is_app_running = true; @@ -1357,6 +1392,13 @@ QGuiApplicationPrivate::~QGuiApplicationPrivate() QPixmapCache::clear(); +#ifndef QT_NO_OPENGL + if (ownGlobalShareContext) { + delete qt_gl_global_share_context(); + qt_gl_set_global_share_context(0); + } +#endif + delete platform_theme; platform_theme = 0; delete platform_integration; @@ -1454,6 +1496,20 @@ QPlatformNativeInterface *QGuiApplication::platformNativeInterface() } /*! + Returns a function pointer from the platformplugin matching \a function +*/ +QFunctionPointer QGuiApplication::platformFunction(const QByteArray &function) +{ + QPlatformIntegration *pi = QGuiApplicationPrivate::platformIntegration(); + if (!pi) { + qWarning() << "QGuiApplication::platformFunction(): Must construct a QGuiApplication before accessing a platform function"; + return Q_NULLPTR; + } + + return pi->nativeInterface() ? pi->nativeInterface()->platformFunction(function) : Q_NULLPTR; +} + +/*! Enters the main event loop and waits until exit() is called, and then returns the value that was set to exit() (which is 0 if exit() is called via quit()). @@ -1576,8 +1632,9 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv case QWindowSystemInterfacePrivate::WindowScreenChanged: QGuiApplicationPrivate::processWindowScreenChangedEvent(static_cast<QWindowSystemInterfacePrivate::WindowScreenChangedEvent *>(e)); break; - case QWindowSystemInterfacePrivate::ApplicationStateChanged: - QGuiApplicationPrivate::setApplicationState(static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e)->newState); + case QWindowSystemInterfacePrivate::ApplicationStateChanged: { + QWindowSystemInterfacePrivate::ApplicationStateChangedEvent * changeEvent = static_cast<QWindowSystemInterfacePrivate::ApplicationStateChangedEvent *>(e); + QGuiApplicationPrivate::setApplicationState(changeEvent->newState, changeEvent->forcePropagate); } break; case QWindowSystemInterfacePrivate::FlushEvents: QWindowSystemInterface::deferredFlushWindowSystemEvents(); @@ -1594,10 +1651,6 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv QGuiApplicationPrivate::reportGeometryChange( static_cast<QWindowSystemInterfacePrivate::ScreenGeometryEvent *>(e)); break; - case QWindowSystemInterfacePrivate::ScreenAvailableGeometry: - QGuiApplicationPrivate::reportAvailableGeometryChange( - static_cast<QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *>(e)); - break; case QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInch: QGuiApplicationPrivate::reportLogicalDotsPerInchChange( static_cast<QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *>(e)); @@ -1664,7 +1717,8 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo // with the current event, we fake a move-only event that we recurse and process first. This // will update the global mouse position and cause the second event to be a button only event. QWindowSystemInterfacePrivate::MouseEvent moveEvent(e->window.data(), - e->timestamp, e->type, e->localPos, e->globalPos, buttons, e->modifiers); + e->timestamp, e->type, e->localPos, e->globalPos, buttons, e->modifiers, e->source); + moveEvent.synthetic = e->synthetic; processMouseEvent(&moveEvent); Q_ASSERT(e->globalPos == QGuiApplicationPrivate::lastCursorPosition); // continue with processing mouse button change event @@ -1854,13 +1908,17 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE ev.setAccepted(false); static bool backKeyPressAccepted = false; + static bool menuKeyPressAccepted = false; if (e->keyType == QEvent::KeyPress) { backKeyPressAccepted = e->key == Qt::Key_Back && ev.isAccepted(); - } else if (e->keyType == QEvent::KeyRelease && e->key == Qt::Key_Back && !backKeyPressAccepted && !ev.isAccepted()) { - if (!window) - qApp->quit(); - else - QWindowSystemInterface::handleCloseEvent(window); + menuKeyPressAccepted = e->key == Qt::Key_Menu && ev.isAccepted(); + } else if (e->keyType == QEvent::KeyRelease) { + if (e->key == Qt::Key_Back && !backKeyPressAccepted && !ev.isAccepted()) { + if (window) + QWindowSystemInterface::handleCloseEvent(window); + } else if (e->key == Qt::Key_Menu && !menuKeyPressAccepted && !ev.isAccepted()) { + platform_theme->showPlatformMenuBar(); + } } #endif } @@ -1972,7 +2030,7 @@ void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterf { if (QWindow *window = wse->window.data()) { if (QScreen *screen = wse->screen.data()) - window->d_func()->setScreen(screen, false /* recreate */); + window->d_func()->setTopLevelScreen(screen, false /* recreate */); else // Fall back to default behavior, and try to find some appropriate screen window->setScreen(0); } @@ -2058,10 +2116,8 @@ void QGuiApplicationPrivate::processTabletEvent(QWindowSystemInterfacePrivate::T { #ifndef QT_NO_TABLETEVENT QEvent::Type type = QEvent::TabletMove; - if (e->down != tabletState) { - type = e->down ? QEvent::TabletPress : QEvent::TabletRelease; - tabletState = e->down; - } + if (e->buttons != tabletState) + type = (e->buttons > tabletState) ? QEvent::TabletPress : QEvent::TabletRelease; QWindow *window = e->window.data(); modifier_buttons = e->modifiers; @@ -2093,12 +2149,21 @@ 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::MouseButton button = Qt::NoButton; + for (int check = Qt::LeftButton; check <= int(Qt::MaxMouseButton); check = check << 1) { + if (check & stateChange) { + button = Qt::MouseButton(check); + break; + } + } QTabletEvent ev(type, local, e->global, e->device, e->pointerType, e->pressure, e->xTilt, e->yTilt, e->tangentialPressure, e->rotation, e->z, - e->modifiers, e->uid); + e->modifiers, e->uid, button, e->buttons); ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(window, &ev); + tabletState = e->buttons; #else Q_UNUSED(e) #endif @@ -2110,7 +2175,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::NoModifier, e->uid, Qt::NoButton, tabletState); ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev); #else @@ -2124,7 +2189,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::NoModifier, e->uid, Qt::NoButton, tabletState); ev.setTimestamp(e->timestamp); QGuiApplication::sendSpontaneousEvent(qGuiApp, &ev); #else @@ -2213,7 +2278,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To e->timestamp, synthIt->pos, synthIt->screenPos, - Qt::NoButton, + buttons & ~Qt::LeftButton, e->modifiers, Qt::MouseEventSynthesizedByQt); fake.synthetic = true; @@ -2415,7 +2480,9 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To QWindowSystemInterfacePrivate::MouseEvent fake(w, e->timestamp, touchPoint.pos(), touchPoint.screenPos(), - b, e->modifiers); + b | (buttons & ~Qt::LeftButton), + e->modifiers, + Qt::MouseEventSynthesizedByQt); fake.synthetic = true; processMouseEvent(&fake); break; @@ -2483,40 +2550,36 @@ void QGuiApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate: return; QScreen *s = e->screen.data(); - s->d_func()->geometry = e->geometry; - Qt::ScreenOrientation primaryOrientation = s->primaryOrientation(); - s->d_func()->updatePrimaryOrientation(); + bool geometryChanged = e->geometry != s->d_func()->geometry; + s->d_func()->geometry = e->geometry; - emit s->geometryChanged(s->geometry()); - emit s->physicalSizeChanged(s->physicalSize()); - emit s->physicalDotsPerInchChanged(s->physicalDotsPerInch()); - emit s->logicalDotsPerInchChanged(s->logicalDotsPerInch()); - foreach (QScreen* sibling, s->virtualSiblings()) - emit sibling->virtualGeometryChanged(sibling->virtualGeometry()); + bool availableGeometryChanged = e->availableGeometry != s->d_func()->availableGeometry; + s->d_func()->availableGeometry = e->availableGeometry; - if (s->primaryOrientation() != primaryOrientation) - emit s->primaryOrientationChanged(s->primaryOrientation()); + if (geometryChanged) { + Qt::ScreenOrientation primaryOrientation = s->primaryOrientation(); + s->d_func()->updatePrimaryOrientation(); - if (s->d_func()->orientation == Qt::PrimaryOrientation) - updateFilteredScreenOrientation(s); -} + emit s->geometryChanged(s->geometry()); + emit s->physicalSizeChanged(s->physicalSize()); + emit s->physicalDotsPerInchChanged(s->physicalDotsPerInch()); + emit s->logicalDotsPerInchChanged(s->logicalDotsPerInch()); -void QGuiApplicationPrivate::reportAvailableGeometryChange( - QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e) -{ - // This operation only makes sense after the QGuiApplication constructor runs - if (QCoreApplication::startingUp()) - return; + if (s->primaryOrientation() != primaryOrientation) + emit s->primaryOrientationChanged(s->primaryOrientation()); - if (!e->screen) - return; + if (s->d_func()->orientation == Qt::PrimaryOrientation) + updateFilteredScreenOrientation(s); + } - QScreen *s = e->screen.data(); - s->d_func()->availableGeometry = e->availableGeometry; + if (availableGeometryChanged) + emit s->availableGeometryChanged(s->geometry()); - foreach (QScreen* sibling, s->virtualSiblings()) - emit sibling->virtualGeometryChanged(sibling->virtualGeometry()); + if (geometryChanged || availableGeometryChanged) { + foreach (QScreen* sibling, s->virtualSiblings()) + emit sibling->virtualGeometryChanged(sibling->virtualGeometry()); + } } void QGuiApplicationPrivate::reportLogicalDotsPerInchChange(QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e) @@ -2656,6 +2719,15 @@ QClipboard * QGuiApplication::clipboard() #endif /*! + \since 5.4 + \fn void QGuiApplication::paletteChanged(const QPalette &palette) + + This signal is emitted when the \a palette of the application changes. + + \sa palette() +*/ + +/*! Returns the default application palette. \sa setPalette() @@ -2681,6 +2753,7 @@ void QGuiApplication::setPalette(const QPalette &pal) else *QGuiApplicationPrivate::app_pal = pal; applicationResourceFlags |= ApplicationPaletteExplicitlySet; + emit qGuiApp->paletteChanged(*QGuiApplicationPrivate::app_pal); } QRect QGuiApplicationPrivate::applyWindowGeometrySpecification(const QRect &windowGeometry, const QWindow *window) @@ -2890,9 +2963,9 @@ Qt::ApplicationState QGuiApplication::applicationState() \sa applicationState() */ -void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state) +void QGuiApplicationPrivate::setApplicationState(Qt::ApplicationState state, bool forcePropagate) { - if (applicationState == state) + if ((applicationState == state) && !forcePropagate) return; applicationState = state; @@ -3093,6 +3166,8 @@ void QGuiApplicationPrivate::saveState() On system start-up, the default layout direction depends on the application's language. + The notifier signal was introduced in Qt 5.4. + \sa QWidget::layoutDirection, isLeftToRight(), isRightToLeft() */ @@ -3103,7 +3178,10 @@ void QGuiApplication::setLayoutDirection(Qt::LayoutDirection direction) layout_direction = direction; - QGuiApplicationPrivate::self->notifyLayoutDirectionChange(); + if (qGuiApp) { + emit qGuiApp->layoutDirectionChanged(direction); + QGuiApplicationPrivate::self->notifyLayoutDirectionChange(); + } } Qt::LayoutDirection QGuiApplication::layoutDirection() |