diff --git a/examples/wayland/pure-qml/qml/Chrome.qml b/examples/wayland/pure-qml/qml/Chrome.qml index d2ff5cc..dc3ad47 100644 --- a/examples/wayland/pure-qml/qml/Chrome.qml +++ b/examples/wayland/pure-qml/qml/Chrome.qml @@ -44,6 +44,8 @@ import QtWayland.Compositor 1.0 ShellSurfaceItem { id: rootChrome + property bool isChild: parent.shellSurface !== undefined + onSurfaceDestroyed: { bufferLocked = true; destroyAnimation.start(); @@ -67,6 +69,7 @@ ShellSurfaceItem { ParallelAnimation { NumberAnimation { target: scaleTransform; property: "yScale"; to: 2/height; duration: 150 } NumberAnimation { target: scaleTransform; property: "xScale"; to: 0.4; duration: 150 } + NumberAnimation { target: rootChrome; property: "opacity"; to: rootChrome.isChild ? 0 : 1; duration: 150 } } NumberAnimation { target: scaleTransform; property: "xScale"; to: 0; duration: 150 } ScriptAction { script: { rootChrome.destroy(); } } diff --git a/examples/wayland/pure-qml/qml/main.qml b/examples/wayland/pure-qml/qml/main.qml index 9bce7bc..5eece07 100644 --- a/examples/wayland/pure-qml/qml/main.qml +++ b/examples/wayland/pure-qml/qml/main.qml @@ -81,7 +81,8 @@ WaylandCompositor { } onXdgPopupCreated: { var parentView = viewsBySurface[xdgPopup.parentSurface]; - chromeComponent.createObject(parentView, { "shellSurface": xdgPopup } ); + var item = chromeComponent.createObject(parentView, { "shellSurface": xdgPopup } ); + viewsBySurface[xdgPopup.surface] = item; } } diff --git a/src/client/client.pro b/src/client/client.pro index 34955df..5ae01c0 100644 --- a/src/client/client.pro +++ b/src/client/client.pro @@ -66,7 +66,7 @@ SOURCES += qwaylandintegration.cpp \ qwaylandwlshellintegration.cpp \ qwaylandxdgshell.cpp \ qwaylandxdgsurface.cpp \ - qwaylandxdgpopup_p.cpp \ + qwaylandxdgpopup.cpp \ qwaylandxdgshellintegration.cpp \ qwaylandextendedsurface.cpp \ qwaylandsubsurface.cpp \ diff --git a/src/client/qwaylandclipboard.cpp b/src/client/qwaylandclipboard.cpp index 2e3c204..409abaa 100644 --- a/src/client/qwaylandclipboard.cpp +++ b/src/client/qwaylandclipboard.cpp @@ -44,6 +44,8 @@ #include "qwaylanddatasource_p.h" #include "qwaylanddatadevice_p.h" +#ifndef QT_NO_DRAGANDDROP + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -60,11 +62,11 @@ QWaylandClipboard::~QWaylandClipboard() QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode) { if (mode != QClipboard::Clipboard) - return 0; + return &m_emptyData; QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice(); if (!inputDevice || !inputDevice->dataDevice()) - return 0; + return &m_emptyData; QWaylandDataSource *source = inputDevice->dataDevice()->selectionSource(); if (source) { @@ -74,7 +76,7 @@ QMimeData *QWaylandClipboard::mimeData(QClipboard::Mode mode) if (inputDevice->dataDevice()->selectionOffer()) return inputDevice->dataDevice()->selectionOffer()->mimeData(); - return 0; + return &m_emptyData; } void QWaylandClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) @@ -115,3 +117,5 @@ bool QWaylandClipboard::ownsMode(QClipboard::Mode mode) const } QT_END_NAMESPACE + +#endif // QT_NO_DRAGANDDROP diff --git a/src/client/qwaylandclipboard_p.h b/src/client/qwaylandclipboard_p.h index aa008ee..6468613 100644 --- a/src/client/qwaylandclipboard_p.h +++ b/src/client/qwaylandclipboard_p.h @@ -53,9 +53,11 @@ #include #include +#include #include +#ifndef QT_NO_DRAGANDDROP QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -76,10 +78,13 @@ public: private: QWaylandDisplay *mDisplay; + QMimeData m_emptyData; }; } QT_END_NAMESPACE +#endif // QT_NO_DRAGANDDROP + #endif // QWAYLANDCLIPBOARD_H diff --git a/src/client/qwaylanddatadevice.cpp b/src/client/qwaylanddatadevice.cpp index d04c20b..f1a1ba6 100644 --- a/src/client/qwaylanddatadevice.cpp +++ b/src/client/qwaylanddatadevice.cpp @@ -56,6 +56,8 @@ #include #include +#ifndef QT_NO_DRAGANDDROP + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -268,3 +270,5 @@ QPoint QWaylandDataDevice::calculateDragPosition(int x, int y, QWindow *wnd) con } QT_END_NAMESPACE + +#endif // QT_NO_DRAGANDDROP diff --git a/src/client/qwaylanddatadevice_p.h b/src/client/qwaylanddatadevice_p.h index 7daa9f0..318636d 100644 --- a/src/client/qwaylanddatadevice_p.h +++ b/src/client/qwaylanddatadevice_p.h @@ -58,6 +58,8 @@ #include +#ifndef QT_NO_DRAGANDDROP + QT_BEGIN_NAMESPACE class QMimeData; @@ -120,4 +122,6 @@ private: QT_END_NAMESPACE +#endif // QT_NO_DRAGANDDROP + #endif // QWAYLANDDATADEVICE_H diff --git a/src/client/qwaylanddatadevicemanager.cpp b/src/client/qwaylanddatadevicemanager.cpp index 35d6730..5c6f741 100644 --- a/src/client/qwaylanddatadevicemanager.cpp +++ b/src/client/qwaylanddatadevicemanager.cpp @@ -46,6 +46,8 @@ #include +#ifndef QT_NO_DRAGANDDROP + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -80,3 +82,5 @@ QWaylandDisplay *QWaylandDataDeviceManager::display() const } QT_END_NAMESPACE + +#endif // QT_NO_DRAGANDDROP diff --git a/src/client/qwaylanddatadevicemanager_p.h b/src/client/qwaylanddatadevicemanager_p.h index 0c1d95d..90ca301 100644 --- a/src/client/qwaylanddatadevicemanager_p.h +++ b/src/client/qwaylanddatadevicemanager_p.h @@ -54,6 +54,8 @@ #include #include +#ifndef QT_NO_DRAGANDDROP + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -81,4 +83,6 @@ private: QT_END_NAMESPACE +#endif // QT_NO_DRAGANDDROP + #endif // QWAYLANDDATADEVICEMANAGER_H diff --git a/src/client/qwaylanddataoffer.cpp b/src/client/qwaylanddataoffer.cpp index 2491c65..b33a98e 100644 --- a/src/client/qwaylanddataoffer.cpp +++ b/src/client/qwaylanddataoffer.cpp @@ -47,6 +47,8 @@ #include +#ifndef QT_NO_DRAGANDDROP + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -181,3 +183,5 @@ int QWaylandMimeData::readData(int fd, QByteArray &data) const } QT_END_NAMESPACE + +#endif // QT_NO_DRAGANDDROP diff --git a/src/client/qwaylanddataoffer_p.h b/src/client/qwaylanddataoffer_p.h index 5e635c1..6368bff 100644 --- a/src/client/qwaylanddataoffer_p.h +++ b/src/client/qwaylanddataoffer_p.h @@ -56,6 +56,7 @@ #include #include +#ifndef QT_NO_DRAGANDDROP QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -105,5 +106,5 @@ private: } QT_END_NAMESPACE - +#endif // QT_NO_DRAGANDDROP #endif diff --git a/src/client/qwaylanddatasource.cpp b/src/client/qwaylanddatasource.cpp index 40beea3..bada694 100644 --- a/src/client/qwaylanddatasource.cpp +++ b/src/client/qwaylanddatasource.cpp @@ -49,6 +49,8 @@ #include +#ifndef QT_NO_DRAGANDDROP + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -96,3 +98,5 @@ void QWaylandDataSource::data_source_target(const QString &mime_type) } QT_END_NAMESPACE + +#endif // QT_NO_DRAGANDDROP diff --git a/src/client/qwaylanddatasource_p.h b/src/client/qwaylanddatasource_p.h index c099ff6..9e29ae8 100644 --- a/src/client/qwaylanddatasource_p.h +++ b/src/client/qwaylanddatasource_p.h @@ -56,6 +56,8 @@ #include #include +#ifndef QT_NO_DRAGANDDROP + QT_BEGIN_NAMESPACE class QMimeData; @@ -92,4 +94,6 @@ private: QT_END_NAMESPACE +#endif // QT_NO_DRAGANDDROP + #endif // QWAYLANDDATASOURCE_H diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp index 3fd2aa5..de38e3f 100644 --- a/src/client/qwaylanddisplay.cpp +++ b/src/client/qwaylanddisplay.cpp @@ -120,7 +120,9 @@ QWaylandWindowManagerIntegration *QWaylandDisplay::windowManagerIntegration() co QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration) : mWaylandIntegration(waylandIntegration) +#ifndef QT_NO_DRAGANDDROP , mDndSelectionHandler(0) +#endif , mWindowExtension(0) , mSubCompositor(0) , mTouchExtension(0) @@ -158,7 +160,9 @@ QWaylandDisplay::~QWaylandDisplay(void) mWaylandIntegration->destroyScreen(screen); } mScreens.clear(); +#ifndef QT_NO_DRAGANDDROP delete mDndSelectionHandler.take(); +#endif wl_display_disconnect(mDisplay); } @@ -251,8 +255,10 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin } else if (interface == QStringLiteral("wl_seat")) { QWaylandInputDevice *inputDevice = mWaylandIntegration->createInputDevice(this, version, id); mInputDevices.append(inputDevice); +#ifndef QT_NO_DRAGANDDROP } else if (interface == QStringLiteral("wl_data_device_manager")) { mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id)); +#endif } else if (interface == QStringLiteral("qt_surface_extension")) { mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1)); } else if (interface == QStringLiteral("wl_subcompositor")) { @@ -413,11 +419,7 @@ void QWaylandDisplay::handleKeyboardFocusChanged(QWaylandInputDevice *inputDevic if (mLastKeyboardFocus == keyboardFocus) return; - if (keyboardFocus && !keyboardFocus->shellManagesActiveState()) - handleWindowActivated(keyboardFocus); - - if (mLastKeyboardFocus && !mLastKeyboardFocus->shellManagesActiveState()) - handleWindowDeactivated(mLastKeyboardFocus); + mWaylandIntegration->mShellIntegration->handleKeyboardFocusChanged(keyboardFocus, mLastKeyboardFocus); mLastKeyboardFocus = keyboardFocus; } diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h index 2864b35..fae17d5 100644 --- a/src/client/qwaylanddisplay_p.h +++ b/src/client/qwaylanddisplay_p.h @@ -137,9 +137,9 @@ public: QList inputDevices() const { return mInputDevices; } QWaylandInputDevice *defaultInputDevice() const; QWaylandInputDevice *currentInputDevice() const { return defaultInputDevice(); } - +#ifndef QT_NO_DRAGANDDROP QWaylandDataDeviceManager *dndSelectionHandler() const { return mDndSelectionHandler.data(); } - +#endif QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); } QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); } QtWayland::zwp_text_input_manager_v2 *textInputManager() const { return mTextInputManager.data(); } @@ -202,7 +202,9 @@ private: QList mInputDevices; QList mRegistryListeners; QWaylandIntegration *mWaylandIntegration; +#ifndef QT_NO_DRAGANDDROP QScopedPointer mDndSelectionHandler; +#endif QScopedPointer mWindowExtension; QScopedPointer mSubCompositor; QScopedPointer mTouchExtension; diff --git a/src/client/qwaylanddnd.cpp b/src/client/qwaylanddnd.cpp index b59ac6d..e29267f 100644 --- a/src/client/qwaylanddnd.cpp +++ b/src/client/qwaylanddnd.cpp @@ -50,7 +50,7 @@ #include QT_BEGIN_NAMESPACE - +#ifndef QT_NO_DRAGANDDROP namespace QtWaylandClient { QWaylandDrag::QWaylandDrag(QWaylandDisplay *display) @@ -98,7 +98,7 @@ void QWaylandDrag::drop(const QPoint &globalPos) void QWaylandDrag::endDrag() { - // Do nothing + m_display->currentInputDevice()->handleEndDrag(); } void QWaylandDrag::updateTarget(const QString &mimeType) @@ -131,5 +131,5 @@ void QWaylandDrag::finishDrag(const QPlatformDropQtResponse &response) } } - +#endif // QT_NO_DRAGANDDROP QT_END_NAMESPACE diff --git a/src/client/qwaylanddnd_p.h b/src/client/qwaylanddnd_p.h index 2ff00b9..464b983 100644 --- a/src/client/qwaylanddnd_p.h +++ b/src/client/qwaylanddnd_p.h @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE namespace QtWaylandClient { class QWaylandDisplay; - +#ifndef QT_NO_DRAGANDDROP class Q_WAYLAND_CLIENT_EXPORT QWaylandDrag : public QBasicDrag { public: @@ -88,7 +88,7 @@ protected: private: QWaylandDisplay *m_display; }; - +#endif } QT_END_NAMESPACE diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index f490f07..94316ba 100644 --- a/src/client/qwaylandinputdevice.cpp +++ b/src/client/qwaylandinputdevice.cpp @@ -188,9 +188,11 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version, , mSerial(0) , mTouchDevice(0) { +#ifndef QT_NO_DRAGANDDROP if (mQDisplay->dndSelectionHandler()) { mDataDevice = mQDisplay->dndSelectionHandler()->getDataDevice(this); } +#endif if (mQDisplay->textInputManager()) { mTextInput = new QWaylandTextInput(mQDisplay, mQDisplay->textInputManager()->get_text_input(wl_seat())); @@ -268,6 +270,14 @@ void QWaylandInputDevice::handleWindowDestroyed(QWaylandWindow *window) mTouch->mFocus = 0; } +void QWaylandInputDevice::handleEndDrag() +{ + if (mTouch) + mTouch->releasePoints(); + if (mPointer) + mPointer->releaseButtons(); +} + void QWaylandInputDevice::setDataDevice(QWaylandDataDevice *device) { mDataDevice = device; @@ -532,6 +542,14 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time } } +void QWaylandInputDevice::Pointer::releaseButtons() +{ + mButtons = Qt::NoButton; + MotionEvent e(mParent->mTime, mSurfacePos, mGlobalPos, mButtons, mParent->modifiers()); + if (mFocus) + mFocus->handleMouse(mParent, e); +} + class WheelEvent : public QWaylandPointerEvent { public: @@ -845,6 +863,16 @@ bool QWaylandInputDevice::Touch::allTouchPointsReleased() return true; } +void QWaylandInputDevice::Touch::releasePoints() +{ + Q_FOREACH (const QWindowSystemInterface::TouchPoint &previousPoint, mPrevTouchPoints) { + QWindowSystemInterface::TouchPoint tp = previousPoint; + tp.state = Qt::TouchPointReleased; + mTouchPoints.append(tp); + } + touch_frame(); +} + void QWaylandInputDevice::Touch::touch_frame() { // Copy all points, that are in the previous but not in the current list, as stationary. diff --git a/src/client/qwaylandinputdevice_p.h b/src/client/qwaylandinputdevice_p.h index ea68522..2f39bc5 100644 --- a/src/client/qwaylandinputdevice_p.h +++ b/src/client/qwaylandinputdevice_p.h @@ -105,6 +105,7 @@ public: void setCursor(struct wl_buffer *buffer, const QPoint &hotSpot, const QSize &size); void setCursor(const QSharedPointer &buffer, const QPoint &hotSpot); void handleWindowDestroyed(QWaylandWindow *window); + void handleEndDrag(); void setDataDevice(QWaylandDataDevice *device); QWaylandDataDevice *dataDevice() const; @@ -239,6 +240,8 @@ public: uint32_t axis, wl_fixed_t value) Q_DECL_OVERRIDE; + void releaseButtons(); + QWaylandInputDevice *mParent; QWaylandWindow *mFocus; uint32_t mEnterSerial; @@ -271,6 +274,7 @@ public: void touch_cancel() Q_DECL_OVERRIDE; bool allTouchPointsReleased(); + void releasePoints(); QWaylandInputDevice *mParent; QWaylandWindow *mFocus; diff --git a/src/client/qwaylandintegration.cpp b/src/client/qwaylandintegration.cpp index 48517fc..32b4b89 100644 --- a/src/client/qwaylandintegration.cpp +++ b/src/client/qwaylandintegration.cpp @@ -119,7 +119,6 @@ public: QWaylandIntegration::QWaylandIntegration() : mClientBufferIntegration(0) - , mShellIntegration(Q_NULLPTR) , mInputDeviceIntegration(Q_NULLPTR) , mFontDb(new QGenericUnixFontDatabase()) , mNativeInterface(new QWaylandNativeInterface(this)) @@ -131,16 +130,17 @@ QWaylandIntegration::QWaylandIntegration() , mShellIntegrationInitialized(false) { initializeInputDeviceIntegration(); - mDisplay = new QWaylandDisplay(this); - mClipboard = new QWaylandClipboard(mDisplay); - mDrag = new QWaylandDrag(mDisplay); - + mDisplay.reset(new QWaylandDisplay(this)); +#ifndef QT_NO_DRAGANDDROP + mClipboard.reset(new QWaylandClipboard(mDisplay.data())); + mDrag.reset(new QWaylandDrag(mDisplay.data())); +#endif QString icStr = QPlatformInputContextFactory::requested(); if (!icStr.isNull()) { mInputContext.reset(QPlatformInputContextFactory::create(icStr)); } else { //try to use the input context using the wl_text_input interface - QPlatformInputContext *ctx = new QWaylandInputContext(mDisplay); + QPlatformInputContext *ctx = new QWaylandInputContext(mDisplay.data()); mInputContext.reset(ctx); //use the traditional way for on screen keyboards for now @@ -153,18 +153,11 @@ QWaylandIntegration::QWaylandIntegration() QWaylandIntegration::~QWaylandIntegration() { - delete mDrag; - delete mClipboard; -#ifndef QT_NO_ACCESSIBILITY - delete mAccessibility; -#endif - delete mNativeInterface; - delete mDisplay; } QPlatformNativeInterface * QWaylandIntegration::nativeInterface() const { - return mNativeInterface; + return mNativeInterface.data(); } bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) const @@ -217,28 +210,30 @@ QAbstractEventDispatcher *QWaylandIntegration::createEventDispatcher() const void QWaylandIntegration::initialize() { QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; - QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay, SLOT(flushRequests())); - QObject::connect(dispatcher, SIGNAL(awake()), mDisplay, SLOT(flushRequests())); + QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay.data(), SLOT(flushRequests())); + QObject::connect(dispatcher, SIGNAL(awake()), mDisplay.data(), SLOT(flushRequests())); int fd = wl_display_get_fd(mDisplay->wl_display()); - QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay); - QObject::connect(sn, SIGNAL(activated(int)), mDisplay, SLOT(flushRequests())); + QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay.data()); + QObject::connect(sn, SIGNAL(activated(int)), mDisplay.data(), SLOT(flushRequests())); } QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const { - return mFontDb; + return mFontDb.data(); } +#ifndef QT_NO_DRAGANDDROP QPlatformClipboard *QWaylandIntegration::clipboard() const { - return mClipboard; + return mClipboard.data(); } QPlatformDrag *QWaylandIntegration::drag() const { - return mDrag; + return mDrag.data(); } +#endif // QT_NO_DRAGANDDROP QPlatformInputContext *QWaylandIntegration::inputContext() const { @@ -263,7 +258,7 @@ QVariant QWaylandIntegration::styleHint(StyleHint hint) const #ifndef QT_NO_ACCESSIBILITY QPlatformAccessibility *QWaylandIntegration::accessibility() const { - return mAccessibility; + return mAccessibility.data(); } #endif @@ -274,7 +269,7 @@ QPlatformServices *QWaylandIntegration::services() const QWaylandDisplay *QWaylandIntegration::display() const { - return mDisplay; + return mDisplay.data(); } QStringList QWaylandIntegration::themeNames() const @@ -292,7 +287,7 @@ QWaylandClientBufferIntegration *QWaylandIntegration::clientBufferIntegration() if (!mClientBufferIntegrationInitialized) const_cast(this)->initializeClientBufferIntegration(); - return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration : 0; + return mClientBufferIntegration && mClientBufferIntegration->isValid() ? mClientBufferIntegration.data() : nullptr; } QWaylandServerBufferIntegration *QWaylandIntegration::serverBufferIntegration() const @@ -300,7 +295,7 @@ QWaylandServerBufferIntegration *QWaylandIntegration::serverBufferIntegration() if (!mServerBufferIntegrationInitialized) const_cast(this)->initializeServerBufferIntegration(); - return mServerBufferIntegration; + return mServerBufferIntegration.data(); } QWaylandShellIntegration *QWaylandIntegration::shellIntegration() const @@ -308,7 +303,7 @@ QWaylandShellIntegration *QWaylandIntegration::shellIntegration() const if (!mShellIntegrationInitialized) const_cast(this)->initializeShellIntegration(); - return mShellIntegration; + return mShellIntegration.data(); } void QWaylandIntegration::initializeClientBufferIntegration() @@ -334,10 +329,10 @@ void QWaylandIntegration::initializeClientBufferIntegration() QStringList keys = QWaylandClientBufferIntegrationFactory::keys(); if (keys.contains(targetKey)) { - mClientBufferIntegration = QWaylandClientBufferIntegrationFactory::create(targetKey, QStringList()); + mClientBufferIntegration.reset(QWaylandClientBufferIntegrationFactory::create(targetKey, QStringList())); } if (mClientBufferIntegration) - mClientBufferIntegration->initialize(mDisplay); + mClientBufferIntegration->initialize(mDisplay.data()); else qWarning("Failed to load client buffer integration: %s\n", qPrintable(targetKey)); } @@ -364,10 +359,10 @@ void QWaylandIntegration::initializeServerBufferIntegration() QStringList keys = QWaylandServerBufferIntegrationFactory::keys(); if (keys.contains(targetKey)) { - mServerBufferIntegration = QWaylandServerBufferIntegrationFactory::create(targetKey, QStringList()); + mServerBufferIntegration.reset(QWaylandServerBufferIntegrationFactory::create(targetKey, QStringList())); } if (mServerBufferIntegration) - mServerBufferIntegration->initialize(mDisplay); + mServerBufferIntegration->initialize(mDisplay.data()); else qWarning("Failed to load server buffer integration %s\n", qPrintable(targetKey)); } @@ -383,7 +378,7 @@ void QWaylandIntegration::initializeShellIntegration() QStringList keys = QWaylandShellIntegrationFactory::keys(); if (keys.contains(targetKey)) { qDebug("Using the '%s' shell integration", qPrintable(targetKey)); - mShellIntegration = QWaylandShellIntegrationFactory::create(targetKey, QStringList()); + mShellIntegration.reset(QWaylandShellIntegrationFactory::create(targetKey, QStringList())); } } else { QStringList preferredShells; @@ -393,15 +388,14 @@ void QWaylandIntegration::initializeShellIntegration() Q_FOREACH (QString preferredShell, preferredShells) { if (mDisplay->hasRegistryGlobal(preferredShell)) { - mShellIntegration = createShellIntegration(preferredShell); + mShellIntegration.reset(createShellIntegration(preferredShell)); break; } } } - if (!mShellIntegration || !mShellIntegration->initialize(mDisplay)) { - delete mShellIntegration; - mShellIntegration = Q_NULLPTR; + if (!mShellIntegration || !mShellIntegration->initialize(mDisplay.data())) { + mShellIntegration.reset(); qWarning("Failed to load shell integration %s", qPrintable(targetKey)); } } @@ -425,7 +419,7 @@ void QWaylandIntegration::initializeInputDeviceIntegration() QStringList keys = QWaylandInputDeviceIntegrationFactory::keys(); if (keys.contains(targetKey)) { - mInputDeviceIntegration = QWaylandInputDeviceIntegrationFactory::create(targetKey, QStringList()); + mInputDeviceIntegration.reset(QWaylandInputDeviceIntegrationFactory::create(targetKey, QStringList())); qDebug("Using the '%s' input device integration", qPrintable(targetKey)); } else { qWarning("Wayland inputdevice integration '%s' not found, using default", qPrintable(targetKey)); @@ -435,9 +429,9 @@ void QWaylandIntegration::initializeInputDeviceIntegration() QWaylandShellIntegration *QWaylandIntegration::createShellIntegration(const QString &interfaceName) { if (interfaceName == QLatin1Literal("wl_shell")) { - return new QWaylandWlShellIntegration(mDisplay); + return new QWaylandWlShellIntegration(mDisplay.data()); } else if (interfaceName == QLatin1Literal("xdg_shell")) { - return new QWaylandXdgShellIntegration(mDisplay); + return new QWaylandXdgShellIntegration(mDisplay.data()); } else { return Q_NULLPTR; } diff --git a/src/client/qwaylandintegration_p.h b/src/client/qwaylandintegration_p.h index 9a49902..3b91313 100644 --- a/src/client/qwaylandintegration_p.h +++ b/src/client/qwaylandintegration_p.h @@ -54,6 +54,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -85,11 +87,10 @@ public: QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; QPlatformNativeInterface *nativeInterface() const Q_DECL_OVERRIDE; - +#ifndef QT_NO_DRAGANDDROP QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE; - QPlatformDrag *drag() const Q_DECL_OVERRIDE; - +#endif QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE; QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE; @@ -113,10 +114,10 @@ public: virtual QWaylandShellIntegration *shellIntegration() const; protected: - QWaylandClientBufferIntegration *mClientBufferIntegration; - QWaylandServerBufferIntegration *mServerBufferIntegration; - QWaylandShellIntegration *mShellIntegration; - QWaylandInputDeviceIntegration *mInputDeviceIntegration; + QScopedPointer mClientBufferIntegration; + QScopedPointer mServerBufferIntegration; + QScopedPointer mShellIntegration; + QScopedPointer mInputDeviceIntegration; private: void initializeClientBufferIntegration(); @@ -125,14 +126,16 @@ private: void initializeInputDeviceIntegration(); QWaylandShellIntegration *createShellIntegration(const QString& interfaceName); - QPlatformFontDatabase *mFontDb; - QPlatformClipboard *mClipboard; - QPlatformDrag *mDrag; - QWaylandDisplay *mDisplay; - QPlatformNativeInterface *mNativeInterface; + QScopedPointer mFontDb; +#ifndef QT_NO_DRAGANDDROP + QScopedPointer mClipboard; + QScopedPointer mDrag; +#endif + QScopedPointer mDisplay; + QScopedPointer mNativeInterface; QScopedPointer mInputContext; #ifndef QT_NO_ACCESSIBILITY - QPlatformAccessibility *mAccessibility; + QScopedPointer mAccessibility; #endif bool mClientBufferIntegrationInitialized; bool mServerBufferIntegrationInitialized; diff --git a/src/client/qwaylandnativeinterface.cpp b/src/client/qwaylandnativeinterface.cpp index 4a79fb5..52c61ee 100644 --- a/src/client/qwaylandnativeinterface.cpp +++ b/src/client/qwaylandnativeinterface.cpp @@ -116,6 +116,7 @@ void *QWaylandNativeInterface::nativeResourceForScreen(const QByteArray &resourc return nullptr; } +#ifndef QT_NO_OPENGL void *QWaylandNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) { #ifdef QT_WAYLAND_GL_SUPPORT @@ -133,6 +134,7 @@ void *QWaylandNativeInterface::nativeResourceForContext(const QByteArray &resour return nullptr; } +#endif // QT_NO_OPENGL QVariantMap QWaylandNativeInterface::windowProperties(QPlatformWindow *window) const { diff --git a/src/client/qwaylandnativeinterface_p.h b/src/client/qwaylandnativeinterface_p.h index 83e3fe5..49e52cd 100644 --- a/src/client/qwaylandnativeinterface_p.h +++ b/src/client/qwaylandnativeinterface_p.h @@ -72,8 +72,9 @@ public: QWindow *window) Q_DECL_OVERRIDE; void *nativeResourceForScreen(const QByteArray &resourceString, QScreen *screen) Q_DECL_OVERRIDE; +#ifndef QT_NO_OPENGL void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) Q_DECL_OVERRIDE; - +#endif QVariantMap windowProperties(QPlatformWindow *window) const Q_DECL_OVERRIDE; QVariant windowProperty(QPlatformWindow *window, const QString &name) const Q_DECL_OVERRIDE; QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const Q_DECL_OVERRIDE; diff --git a/src/client/qwaylandshellsurface_p.h b/src/client/qwaylandshellsurface_p.h index 79f65b1..b51c252 100644 --- a/src/client/qwaylandshellsurface_p.h +++ b/src/client/qwaylandshellsurface_p.h @@ -91,19 +91,17 @@ public: virtual void setContentOrientationMask(Qt::ScreenOrientations orientation) { Q_UNUSED(orientation) } virtual void sendProperty(const QString &name, const QVariant &value); - virtual bool shellManagesActiveState() const { return false; } inline QWaylandWindow *window() { return m_window; } + virtual void setType(Qt::WindowType type, QWaylandWindow *transientParent) = 0; + protected: virtual void setMaximized() {} virtual void setFullscreen() {} virtual void setNormal() {} virtual void setMinimized() {} - virtual void setTopLevel() {} - virtual void updateTransientParent(QWindow * /*parent*/) {} - private: QWaylandWindow *m_window; friend class QWaylandWindow; diff --git a/src/client/qwaylandshmbackingstore.cpp b/src/client/qwaylandshmbackingstore.cpp index 13f823e..d0d6cfd 100644 --- a/src/client/qwaylandshmbackingstore.cpp +++ b/src/client/qwaylandshmbackingstore.cpp @@ -185,10 +185,6 @@ void QWaylandShmBackingStore::endPaint() waylandWindow()->setCanResize(true); } -void QWaylandShmBackingStore::hidden() -{ -} - void QWaylandShmBackingStore::ensureSize() { waylandWindow()->setBackingStore(this); @@ -215,13 +211,7 @@ void QWaylandShmBackingStore::flush(QWindow *window, const QRegion ®ion, cons QMargins margins = windowDecorationMargins(); - waylandWindow()->attachOffset(mFrontBuffer); - mFrontBuffer->setBusy(); - - QVector rects = region.rects(); - foreach (const QRect &rect, rects) - waylandWindow()->damage(rect.translated(margins.left(), margins.top())); - waylandWindow()->commit(); + waylandWindow()->commit(mFrontBuffer, region.translated(margins.left(), margins.top())); } void QWaylandShmBackingStore::resize(const QSize &size, const QRegion &) diff --git a/src/client/qwaylandshmbackingstore_p.h b/src/client/qwaylandshmbackingstore_p.h index c3e7635..5068519 100644 --- a/src/client/qwaylandshmbackingstore_p.h +++ b/src/client/qwaylandshmbackingstore_p.h @@ -96,7 +96,6 @@ public: void resize(const QSize &size); void beginPaint(const QRegion &) Q_DECL_OVERRIDE; void endPaint() Q_DECL_OVERRIDE; - void hidden(); QWaylandAbstractDecoration *windowDecoration() const; diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index 2b7d81f..1ff6686 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -96,8 +96,6 @@ QWaylandWindow::QWaylandWindow(QWindow *window) { static WId id = 1; mWindowId = id++; - if (window->type() != Qt::Desktop) - initWindow(); } QWaylandWindow::~QWaylandWindow() @@ -126,20 +124,30 @@ QWaylandWindow::~QWaylandWindow() void QWaylandWindow::initWindow() { - init(mDisplay->createSurface(static_cast(this))); + if (window()->type() == Qt::Desktop) + return; + + if (!isInitialized()) + init(mDisplay->createSurface(static_cast(this))); if (shouldCreateSubSurface()) { + Q_ASSERT(!mSubSurfaceWindow); + QWaylandWindow *p = static_cast(QPlatformWindow::parent()); if (::wl_subsurface *ss = mDisplay->createSubSurface(this, p)) { mSubSurfaceWindow = new QWaylandSubSurface(this, p, ss); } } else if (shouldCreateShellSurface()) { + Q_ASSERT(!mShellSurface); + mShellSurface = mDisplay->createShellSurface(this); - } + if (!mShellSurface) + qFatal("Could not create a shell surface object."); + + mShellSurface->setType(window()->type(), transientParent()); - if (mShellSurface) { // Set initial surface title - mShellSurface->setTitle(window()->title()); + setWindowTitle(window()->title()); // The appId is the desktop entry identifier that should follow the // reverse DNS convention (see http://standards.freedesktop.org/desktop-entry-spec/latest/ar01s02.html). @@ -171,17 +179,6 @@ void QWaylandWindow::initWindow() } } - if (mShellSurface) { - if (window()->transientParent()) { - if (window()->type() != Qt::Popup) { - mShellSurface->updateTransientParent(window()->transientParent()); - } - } else { - if (window()->type() != Qt::ToolTip) - mShellSurface->setTopLevel(); - } - } - // Enable high-dpi rendering. Scale() returns the screen scale factor and will // typically be integer 1 (normal-dpi) or 2 (high-dpi). Call set_buffer_scale() // to inform the compositor that high-resolution buffers will be provided. @@ -244,6 +241,9 @@ WId QWaylandWindow::winId() const void QWaylandWindow::setParent(const QPlatformWindow *parent) { + if (!window()->isVisible()) + return; + QWaylandWindow *oldparent = mSubSurfaceWindow ? mSubSurfaceWindow->parent() : 0; if (oldparent == parent) return; @@ -261,7 +261,8 @@ void QWaylandWindow::setParent(const QPlatformWindow *parent) void QWaylandWindow::setWindowTitle(const QString &title) { if (mShellSurface) { - mShellSurface->setTitle(title); + const QString separator = QString::fromUtf8(" \xe2\x80\x94 "); // unicode character U+2014, EM DASH + mShellSurface->setTitle(formatWindowTitle(title, separator)); } if (mWindowDecoration && window()->isVisible()) @@ -285,8 +286,8 @@ void QWaylandWindow::setGeometry_helper(const QRect &rect) if (mSubSurfaceWindow) { QMargins m = QPlatformWindow::parent()->frameMargins(); mSubSurfaceWindow->set_position(rect.x() + m.left(), rect.y() + m.top()); - } else if (shellSurface() && window()->transientParent() && window()->type() != Qt::Popup) - shellSurface()->updateTransientParent(window()->transientParent()); + mSubSurfaceWindow->parent()->window()->requestUpdate(); + } } void QWaylandWindow::setGeometry(const QRect &rect) @@ -311,20 +312,8 @@ void QWaylandWindow::setGeometry(const QRect &rect) void QWaylandWindow::setVisible(bool visible) { if (visible) { - if (mShellSurface) { - if (window()->type() == Qt::Popup) { - QWaylandWindow *parent = transientParent(); - if (parent) { - QWaylandWlShellSurface *wlshellSurface = qobject_cast(mShellSurface); - if (wlshellSurface) - wlshellSurface->setPopup(parent, mDisplay->lastInputDevice(), mDisplay->lastInputSerial()); - } - } else if (window()->type() == Qt::ToolTip) { - if (QWaylandWindow *parent = transientParent()) { - mShellSurface->updateTransientParent(parent->window()); - } - } - } + initWindow(); + mDisplay->flushRequests(); setGeometry(window()->geometry()); // Don't flush the events here, or else the newly visible window may start drawing, but since @@ -336,13 +325,8 @@ void QWaylandWindow::setVisible(bool visible) // case 'this' will be deleted. When that happens, we must abort right away. QPointer deleteGuard(this); QWindowSystemInterface::flushWindowSystemEvents(); - if (!deleteGuard.isNull()) { - attach(static_cast(0), 0, 0); - commit(); - if (mBackingStore) { - mBackingStore->hidden(); - } - } + if (!deleteGuard.isNull()) + reset(); } } @@ -375,7 +359,7 @@ void QWaylandWindow::setMask(const QRegion &mask) wl_region_destroy(region); } - commit(); + wl_surface::commit(); } void QWaylandWindow::configure(uint32_t edges, int32_t width, int32_t height) @@ -462,6 +446,7 @@ void QWaylandWindow::attach(QWaylandBuffer *buffer, int x, int y) wl_callback_add_listener(callback, &QWaylandWindow::callbackListener, this); mFrameCallback = callback; mWaitingForFrameSync = true; + buffer->setBusy(); attach(buffer->buffer(), x, y); } else { @@ -480,6 +465,18 @@ void QWaylandWindow::damage(const QRect &rect) damage(rect.x(), rect.y(), rect.width(), rect.height()); } +void QWaylandWindow::commit(QWaylandBuffer *buffer, const QRegion &damage) +{ + if (!isInitialized()) + return; + + attachOffset(buffer); + const QVector rects = damage.rects(); + for (const QRect &rect: rects) + wl_surface::damage(rect.x(), rect.y(), rect.width(), rect.height()); + wl_surface::commit(); +} + const wl_callback_listener QWaylandWindow::callbackListener = { QWaylandWindow::frameCallback }; @@ -528,11 +525,6 @@ QWaylandSubSurface *QWaylandWindow::subSurfaceWindow() const return mSubSurfaceWindow; } -bool QWaylandWindow::shellManagesActiveState() const -{ - return mShellSurface && mShellSurface->shellManagesActiveState(); -} - void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation) { if (mDisplay->compositorVersion() < 2) @@ -561,7 +553,7 @@ void QWaylandWindow::handleContentOrientationChange(Qt::ScreenOrientation orient } set_buffer_transform(transform); // set_buffer_transform is double buffered, we need to commit. - commit(); + wl_surface::commit(); } void QWaylandWindow::setOrientationMask(Qt::ScreenOrientations mask) @@ -687,15 +679,13 @@ static QWindow *topLevelWindow(QWindow *window) QWaylandWindow *QWaylandWindow::transientParent() const { - if (window()->transientParent()) { - // Take the top level window here, since the transient parent may be a QWidgetWindow - // or some other window without a shell surface, which is then not able to get mouse - // events. - return static_cast(topLevelWindow(window()->transientParent())->handle()); - } - // Try with the current focus window. It should be the right one and anyway - // better than having no parent at all. - return mDisplay->lastInputWindow(); + // Take the top level window here, since the transient parent may be a QWidgetWindow + // or some other window without a shell surface, which is then not able to get mouse + // events. + if (auto transientParent = window()->transientParent()) + return static_cast(topLevelWindow(transientParent)->handle()); + + return nullptr; } void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e) @@ -809,10 +799,12 @@ void QWaylandWindow::requestActivateWindow() void QWaylandWindow::unfocus() { +#ifndef QT_NO_DRAGANDDROP QWaylandInputDevice *inputDevice = mDisplay->currentInputDevice(); if (inputDevice && inputDevice->dataDevice()) { inputDevice->dataDevice()->invalidateSelectionOffer(); } +#endif } bool QWaylandWindow::isExposed() const diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index e0c42ac..7e7078f 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -132,6 +132,8 @@ public: using QtWayland::wl_surface::damage; void damage(const QRect &rect); + void commit(QWaylandBuffer *buffer, const QRegion &damage); + void waitForFrameSync(); QMargins frameMargins() const Q_DECL_OVERRIDE; @@ -143,8 +145,6 @@ public: QWaylandSubSurface *subSurfaceWindow() const; QWaylandScreen *screen() const { return mScreen; } - bool shellManagesActiveState() const; - void handleContentOrientationChange(Qt::ScreenOrientation orientation) Q_DECL_OVERRIDE; void setOrientationMask(Qt::ScreenOrientations mask); diff --git a/src/client/qwaylandwlshellintegration.cpp b/src/client/qwaylandwlshellintegration.cpp index 6a9220d..ce7c783 100644 --- a/src/client/qwaylandwlshellintegration.cpp +++ b/src/client/qwaylandwlshellintegration.cpp @@ -52,6 +52,12 @@ QWaylandWlShellIntegration::QWaylandWlShellIntegration(QWaylandDisplay *display) } } +bool QWaylandWlShellIntegration::initialize(QWaylandDisplay *display) +{ + QWaylandShellIntegration::initialize(display); + return m_wlShell != nullptr; +}; + QWaylandShellSurface *QWaylandWlShellIntegration::createShellSurface(QWaylandWindow *window) { return new QWaylandWlShellSurface(m_wlShell->get_shell_surface(window->object()), window); diff --git a/src/client/qwaylandwlshellintegration_p.h b/src/client/qwaylandwlshellintegration_p.h index 8531eb3..9082c76 100644 --- a/src/client/qwaylandwlshellintegration_p.h +++ b/src/client/qwaylandwlshellintegration_p.h @@ -58,7 +58,7 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandWlShellIntegration : public QWaylandShellI { public: QWaylandWlShellIntegration(QWaylandDisplay* display); - bool initialize(QWaylandDisplay *) Q_DECL_OVERRIDE { return m_wlShell != Q_NULLPTR; } + bool initialize(QWaylandDisplay *) Q_DECL_OVERRIDE; QWaylandShellSurface *createShellSurface(QWaylandWindow *window) Q_DECL_OVERRIDE; private: diff --git a/src/client/qwaylandwlshellsurface.cpp b/src/client/qwaylandwlshellsurface.cpp index 3527015..77434e9 100644 --- a/src/client/qwaylandwlshellsurface.cpp +++ b/src/client/qwaylandwlshellsurface.cpp @@ -215,6 +215,16 @@ void QWaylandWlShellSurface::setPopup(QWaylandWindow *parent, QWaylandInputDevic transientPos.x(), transientPos.y(), 0); } +void QWaylandWlShellSurface::setType(Qt::WindowType type, QWaylandWindow *transientParent) +{ + if (type == Qt::Popup && transientParent) + setPopup(transientParent, m_window->display()->lastInputDevice(), m_window->display()->lastInputSerial()); + else if (transientParent) + updateTransientParent(transientParent->window()); + else + setTopLevel(); +} + void QWaylandWlShellSurface::shell_surface_ping(uint32_t serial) { pong(serial); diff --git a/src/client/qwaylandwlshellsurface_p.h b/src/client/qwaylandwlshellsurface_p.h index ef732ef..af86276 100644 --- a/src/client/qwaylandwlshellsurface_p.h +++ b/src/client/qwaylandwlshellsurface_p.h @@ -92,14 +92,16 @@ public: void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE; void sendProperty(const QString &name, const QVariant &value) Q_DECL_OVERRIDE; + void setType(Qt::WindowType type, QWaylandWindow *transientParent) override; + private: void setMaximized() Q_DECL_OVERRIDE; void setFullscreen() Q_DECL_OVERRIDE; void setNormal() Q_DECL_OVERRIDE; void setMinimized() Q_DECL_OVERRIDE; - void setTopLevel() Q_DECL_OVERRIDE; - void updateTransientParent(QWindow *parent) Q_DECL_OVERRIDE; + void setTopLevel(); + void updateTransientParent(QWindow *parent); void setPopup(QWaylandWindow *parent, QWaylandInputDevice *device, int serial); QWaylandWindow *m_window; diff --git a/src/client/qwaylandxdgpopup_p.cpp b/src/client/qwaylandxdgpopup.cpp similarity index 93% rename from src/client/qwaylandxdgpopup_p.cpp rename to src/client/qwaylandxdgpopup.cpp index abc2527..57800f1 100644 --- a/src/client/qwaylandxdgpopup_p.cpp +++ b/src/client/qwaylandxdgpopup.cpp @@ -56,6 +56,12 @@ QWaylandXdgPopup::~QWaylandXdgPopup() delete m_extendedWindow; } +void QWaylandXdgPopup::setType(Qt::WindowType type, QWaylandWindow *transientParent) +{ + Q_UNUSED(type); + Q_UNUSED(transientParent); +} + } QT_END_NAMESPACE diff --git a/src/client/qwaylandxdgpopup_p.h b/src/client/qwaylandxdgpopup_p.h index ff58041..64bb4d9 100644 --- a/src/client/qwaylandxdgpopup_p.h +++ b/src/client/qwaylandxdgpopup_p.h @@ -68,6 +68,8 @@ public: QWaylandXdgPopup(struct ::xdg_popup *popup, QWaylandWindow *window); virtual ~QWaylandXdgPopup(); + void setType(Qt::WindowType type, QWaylandWindow *transientParent) override; + private: QWaylandExtendedSurface *m_extendedWindow; }; diff --git a/src/client/qwaylandxdgshell.cpp b/src/client/qwaylandxdgshell.cpp index 6a378b8..6a99306 100644 --- a/src/client/qwaylandxdgshell.cpp +++ b/src/client/qwaylandxdgshell.cpp @@ -54,11 +54,13 @@ namespace QtWaylandClient { QWaylandXdgShell::QWaylandXdgShell(struct ::xdg_shell *shell) : QtWayland::xdg_shell(shell) + , m_popupSerial(0) { } QWaylandXdgShell::QWaylandXdgShell(struct ::wl_registry *registry, uint32_t id) : QtWayland::xdg_shell(registry, id, 1) + , m_popupSerial(0) { use_unstable_version(QtWayland::xdg_shell::version_current); } @@ -75,15 +77,26 @@ QWaylandXdgSurface *QWaylandXdgShell::createXdgSurface(QWaylandWindow *window) QWaylandXdgPopup *QWaylandXdgShell::createXdgPopup(QWaylandWindow *window) { - QWaylandWindow *parentWindow = window->transientParent(); + QWaylandWindow *parentWindow = m_popups.empty() ? window->transientParent() : m_popups.last(); ::wl_surface *parentSurface = parentWindow->object(); + QWaylandInputDevice *inputDevice = window->display()->lastInputDevice(); + if (m_popupSerial == 0) + m_popupSerial = inputDevice->serial(); ::wl_seat *seat = inputDevice->wl_seat(); - uint serial = inputDevice->serial(); - QPoint position = window->geometry().topLeft(); + + QPoint position = window->geometry().topLeft() - parentWindow->geometry().topLeft(); int x = position.x() + parentWindow->frameMargins().left(); int y = position.y() + parentWindow->frameMargins().top(); - return new QWaylandXdgPopup(get_xdg_popup(window->object(), parentSurface, seat, serial, x, y), window); + + auto popup = new QWaylandXdgPopup(get_xdg_popup(window->object(), parentSurface, seat, m_popupSerial, x, y), window); + m_popups.append(window); + QObject::connect(popup, &QWaylandXdgPopup::destroyed, [this, window](){ + m_popups.removeOne(window); + if (m_popups.empty()) + m_popupSerial = 0; + }); + return popup; } void QWaylandXdgShell::xdg_shell_ping(uint32_t serial) diff --git a/src/client/qwaylandxdgshell_p.h b/src/client/qwaylandxdgshell_p.h index c04a9ce..8b35e36 100644 --- a/src/client/qwaylandxdgshell_p.h +++ b/src/client/qwaylandxdgshell_p.h @@ -52,6 +52,7 @@ // #include +#include #include @@ -82,6 +83,9 @@ public: private: void xdg_shell_ping(uint32_t serial) Q_DECL_OVERRIDE; + + QVector m_popups; + uint m_popupSerial; }; QT_END_NAMESPACE diff --git a/src/client/qwaylandxdgshellintegration.cpp b/src/client/qwaylandxdgshellintegration.cpp index b6b1d9d..a48157d 100644 --- a/src/client/qwaylandxdgshellintegration.cpp +++ b/src/client/qwaylandxdgshellintegration.cpp @@ -54,6 +54,12 @@ QWaylandXdgShellIntegration::QWaylandXdgShellIntegration(QWaylandDisplay *displa } } +bool QWaylandXdgShellIntegration::initialize(QWaylandDisplay *display) +{ + QWaylandShellIntegration::initialize(display); + return m_xdgShell != nullptr; +} + QWaylandShellSurface *QWaylandXdgShellIntegration::createShellSurface(QWaylandWindow *window) { if (window->window()->type() == Qt::WindowType::Popup) @@ -62,6 +68,13 @@ QWaylandShellSurface *QWaylandXdgShellIntegration::createShellSurface(QWaylandWi return m_xdgShell->createXdgSurface(window); } +void QWaylandXdgShellIntegration::handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) { + if (newFocus && qobject_cast(newFocus->shellSurface())) + m_display->handleWindowActivated(newFocus); + if (oldFocus && qobject_cast(oldFocus->shellSurface())) + m_display->handleWindowDeactivated(oldFocus); +} + } QT_END_NAMESPACE diff --git a/src/client/qwaylandxdgshellintegration_p.h b/src/client/qwaylandxdgshellintegration_p.h index 29374ff..e0e6bda 100644 --- a/src/client/qwaylandxdgshellintegration_p.h +++ b/src/client/qwaylandxdgshellintegration_p.h @@ -59,8 +59,9 @@ class Q_WAYLAND_CLIENT_EXPORT QWaylandXdgShellIntegration : public QWaylandShell { public: QWaylandXdgShellIntegration(QWaylandDisplay *display); - bool initialize(QWaylandDisplay *) Q_DECL_OVERRIDE { return m_xdgShell != Q_NULLPTR; } + bool initialize(QWaylandDisplay *display) Q_DECL_OVERRIDE; QWaylandShellSurface *createShellSurface(QWaylandWindow *window) Q_DECL_OVERRIDE; + void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) Q_DECL_OVERRIDE; private: QWaylandXdgShell *m_xdgShell; diff --git a/src/client/qwaylandxdgsurface.cpp b/src/client/qwaylandxdgsurface.cpp index 4f9d8cf..fe8761e 100644 --- a/src/client/qwaylandxdgsurface.cpp +++ b/src/client/qwaylandxdgsurface.cpp @@ -128,17 +128,13 @@ void QWaylandXdgSurface::setMinimized() set_minimized(); } -void QWaylandXdgSurface::setTopLevel() +void QWaylandXdgSurface::updateTransientParent(QWaylandWindow *parent) { - // There's no xdg_shell_surface API for this, ignoring -} - -void QWaylandXdgSurface::updateTransientParent(QWindow *parent) -{ - QWaylandWindow *parent_wayland_window = static_cast(parent->handle()); - if (!parent_wayland_window) + if (!parent) return; - set_parent(m_shell->get_xdg_surface(parent_wayland_window->object())); + auto parentXdgSurface = qobject_cast(parent->shellSurface()); + Q_ASSERT(parentXdgSurface); + set_parent(parentXdgSurface->object()); } void QWaylandXdgSurface::setTitle(const QString & title) @@ -181,6 +177,13 @@ void QWaylandXdgSurface::sendProperty(const QString &name, const QVariant &value m_extendedWindow->updateGenericProperty(name, value); } +void QWaylandXdgSurface::setType(Qt::WindowType type, QWaylandWindow *transientParent) +{ + Q_UNUSED(type) + if (transientParent) + updateTransientParent(transientParent); +} + void QWaylandXdgSurface::xdg_surface_configure(int32_t width, int32_t height, struct wl_array *states,uint32_t serial) { uint32_t *state = reinterpret_cast(states->data); diff --git a/src/client/qwaylandxdgsurface_p.h b/src/client/qwaylandxdgsurface_p.h index 27decab..265d3ba 100644 --- a/src/client/qwaylandxdgsurface_p.h +++ b/src/client/qwaylandxdgsurface_p.h @@ -96,19 +96,18 @@ public: void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE; void sendProperty(const QString &name, const QVariant &value) Q_DECL_OVERRIDE; - bool shellManagesActiveState() const Q_DECL_OVERRIDE { return true; } - bool isFullscreen() const { return m_fullscreen; } bool isMaximized() const { return m_maximized; } + void setType(Qt::WindowType type, QWaylandWindow *transientParent) override; + private: void setMaximized() Q_DECL_OVERRIDE; void setFullscreen() Q_DECL_OVERRIDE; void setNormal() Q_DECL_OVERRIDE; void setMinimized() Q_DECL_OVERRIDE; - void setTopLevel() Q_DECL_OVERRIDE; - void updateTransientParent(QWindow *parent) Q_DECL_OVERRIDE; + void updateTransientParent(QWaylandWindow *parent); private: QWaylandWindow *m_window; diff --git a/src/client/shellintegration/qwaylandshellintegration_p.h b/src/client/shellintegration/qwaylandshellintegration_p.h index e8e46ec..144e583 100644 --- a/src/client/shellintegration/qwaylandshellintegration_p.h +++ b/src/client/shellintegration/qwaylandshellintegration_p.h @@ -53,6 +53,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -68,8 +69,20 @@ public: QWaylandShellIntegration() {} virtual ~QWaylandShellIntegration() {} - virtual bool initialize(QWaylandDisplay *display) = 0; + virtual bool initialize(QWaylandDisplay *display) { + m_display = display; + return true; + } virtual QWaylandShellSurface *createShellSurface(QWaylandWindow *window) = 0; + virtual void handleKeyboardFocusChanged(QWaylandWindow *newFocus, QWaylandWindow *oldFocus) { + if (newFocus) + m_display->handleWindowActivated(newFocus); + if (oldFocus) + m_display->handleWindowDeactivated(oldFocus); + } + +protected: + QWaylandDisplay *m_display; }; } diff --git a/src/compositor/compositor_api/qwaylandoutputmode.h b/src/compositor/compositor_api/qwaylandoutputmode.h index 4ef57f2..aa44be9 100644 --- a/src/compositor/compositor_api/qwaylandoutputmode.h +++ b/src/compositor/compositor_api/qwaylandoutputmode.h @@ -66,6 +66,7 @@ private: void setWidth(int width); void setHeight(int height); }; +Q_DECLARE_TYPEINFO(QWaylandOutputMode, Q_MOVABLE_TYPE); QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp index f0454b7..d57cbb4 100644 --- a/src/compositor/compositor_api/qwaylandquickitem.cpp +++ b/src/compositor/compositor_api/qwaylandquickitem.cpp @@ -653,6 +653,9 @@ void QWaylandQuickItem::touchEvent(QTouchEvent *event) seat->sendMouseMoveEvent(d->view.data(), pointPos, mapToScene(pointPos)); } seat->sendFullTouchEvent(surface(), event); + + if (event->type() == QEvent::TouchBegin && d->focusOnClick) + takeFocus(seat); } else { event->ignore(); } @@ -921,7 +924,7 @@ void QWaylandQuickItem::updateSize() * \qmlproperty bool QtWaylandCompositor::WaylandQuickItem::focusOnClick * * This property specifies whether the WaylandQuickItem should take focus when - * it is clicked. + * it is clicked or touched. * * The default is \c true. */ @@ -930,7 +933,7 @@ void QWaylandQuickItem::updateSize() * \property QWaylandQuickItem::focusOnClick * * This property specifies whether the QWaylandQuickItem should take focus when - * it is clicked. + * it is clicked or touched. * * The default is \c true. */ @@ -1071,11 +1074,16 @@ void QWaylandQuickItem::updateBuffer(bool hasBuffer) void QWaylandQuickItem::updateWindow() { Q_D(QWaylandQuickItem); + + QQuickWindow *newWindow = window(); + if (newWindow == d->connectedWindow) + return; + if (d->connectedWindow) { disconnect(d->connectedWindow, &QQuickWindow::beforeSynchronizing, this, &QWaylandQuickItem::beforeSync); } - d->connectedWindow = window(); + d->connectedWindow = newWindow; if (d->connectedWindow) { connect(d->connectedWindow, &QQuickWindow::beforeSynchronizing, this, &QWaylandQuickItem::beforeSync, Qt::DirectConnection); diff --git a/src/compositor/compositor_api/qwaylandquickitem_p.h b/src/compositor/compositor_api/qwaylandquickitem_p.h index c308299..441ac97 100644 --- a/src/compositor/compositor_api/qwaylandquickitem_p.h +++ b/src/compositor/compositor_api/qwaylandquickitem_p.h @@ -110,7 +110,7 @@ public: , oldSurface(Q_NULLPTR) , provider(Q_NULLPTR) , paintEnabled(true) - , touchEventsEnabled(false) + , touchEventsEnabled(true) , inputEventsEnabled(true) , isDragging(false) , newTexture(false) @@ -142,6 +142,8 @@ public: QObject::connect(view.data(), &QWaylandView::outputChanged, q, &QWaylandQuickItem::outputChanged); QObject::connect(view.data(), &QWaylandView::bufferLockedChanged, q, &QWaylandQuickItem::bufferLockedChanged); QObject::connect(view.data(), &QWaylandView::allowDiscardFrontBufferChanged, q, &QWaylandQuickItem::allowDiscardFrontBuffer); + + q->updateWindow(); } void setInputEventsEnabled(bool enable) diff --git a/src/compositor/compositor_api/qwaylandseat.cpp b/src/compositor/compositor_api/qwaylandseat.cpp index 169d5de..f6a5276 100644 --- a/src/compositor/compositor_api/qwaylandseat.cpp +++ b/src/compositor/compositor_api/qwaylandseat.cpp @@ -257,8 +257,8 @@ void QWaylandSeat::sendKeyReleaseEvent(uint code) } /*! - * Sends a touch point event with the given \a id and \a state to the touch device. The position - * of the touch point is given by \a point. + * Sends a touch point event to the \a surface on a touch device with the given + * \a id, \a point and \a state. * * Returns the serial for the touch up or touch down event. */ @@ -273,7 +273,7 @@ uint QWaylandSeat::sendTouchPointEvent(QWaylandSurface *surface, int id, const Q } /*! - * Sends a frame event to the touch device. + * Sends a frame event to the touch device of a \a client. */ void QWaylandSeat::sendTouchFrameEvent(QWaylandClient *client) { @@ -283,7 +283,7 @@ void QWaylandSeat::sendTouchFrameEvent(QWaylandClient *client) } /*! - * Sends a cancel event to the touch device. + * Sends a cancel event to the touch device of a \a client. */ void QWaylandSeat::sendTouchCancelEvent(QWaylandClient *client) { @@ -293,7 +293,7 @@ void QWaylandSeat::sendTouchCancelEvent(QWaylandClient *client) } /*! - * Sends the \a event to the touch device. + * Sends the \a event to the specified \a surface on the touch device. */ void QWaylandSeat::sendFullTouchEvent(QWaylandSurface *surface, QTouchEvent *event) { diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index 80e8715..f79fd57 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -269,7 +269,7 @@ void QWaylandSurfacePrivate::surface_commit(Resource *) { Q_Q(QWaylandSurface); - if (pending.buffer.hasBuffer()) + if (pending.buffer.hasBuffer() || pending.newlyAttached) bufferRef = pending.buffer; auto buffer = bufferRef.buffer(); @@ -872,13 +872,13 @@ void QWaylandSurfacePrivate::Subsurface::subsurface_set_desync(wl_subsurface::Re /*! * \qmlsignal void QtWaylandCompositor::WaylandSurface::dragStarted(object drag) * - * This signal is emitted when a drag has started from this surface. + * This signal is emitted when a \a drag has started from this surface. */ /*! * \fn void QWaylandSurface::dragStarted(QWaylandDrag *drag) * - * This signal is emitted when a drag has started from this surface. + * This signal is emitted when a \a drag has started from this surface. */ QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandtouch.cpp b/src/compositor/compositor_api/qwaylandtouch.cpp index 168edc4..92a8f5c 100644 --- a/src/compositor/compositor_api/qwaylandtouch.cpp +++ b/src/compositor/compositor_api/qwaylandtouch.cpp @@ -133,7 +133,7 @@ QWaylandCompositor *QWaylandTouch::compositor() const } /*! - * Sends a touch point event for the touch device with the given \a id, + * Sends a touch point event to the touch device of \a surface with the given \a id, * \a position, and \a state. * * Returns the serial of the down or up event if sent, otherwise 0. @@ -162,7 +162,7 @@ uint QWaylandTouch::sendTouchPointEvent(QWaylandSurface *surface, int id, const } /*! - * Sends a touch frame event for the touch device. This indicates the end of a + * Sends a touch frame event to the touch device of a \a client. This indicates the end of a * contact point list. */ void QWaylandTouch::sendFrameEvent(QWaylandClient *client) @@ -174,7 +174,7 @@ void QWaylandTouch::sendFrameEvent(QWaylandClient *client) } /*! - * Sends a touch cancel event for the touch device. + * Sends a touch cancel event to the touch device of a \a client. */ void QWaylandTouch::sendCancelEvent(QWaylandClient *client) { @@ -185,8 +185,8 @@ void QWaylandTouch::sendCancelEvent(QWaylandClient *client) } /*! - * Sends all the touch points in \a event for this touch device, followed - * by a touch frame event. + * Sends all touch points in \a event to the specified \a surface, + * followed by a touch frame event. * * \sa sendTouchPointEvent(), sendFrameEvent() */ diff --git a/src/compositor/extensions/qwaylandivisurface.cpp b/src/compositor/extensions/qwaylandivisurface.cpp index fc3102d..06e12a5 100644 --- a/src/compositor/extensions/qwaylandivisurface.cpp +++ b/src/compositor/extensions/qwaylandivisurface.cpp @@ -68,7 +68,7 @@ QWaylandIviSurface::QWaylandIviSurface() /*! * Constructs a QWaylandIviSurface for \a surface and initializes it with the - * given \a application, \a surface, \a iviId, and resource \a res. + * given \a application, \a surface, \a iviId, and \a resource. */ QWaylandIviSurface::QWaylandIviSurface(QWaylandIviApplication *application, QWaylandSurface *surface, uint iviId, const QWaylandResource &resource) : QWaylandShellSurfaceTemplate(*new QWaylandIviSurfacePrivate()) @@ -129,7 +129,7 @@ QWaylandSurface *QWaylandIviSurface::surface() const */ /*! - * \property QWaylandClient::iviId + * \property QWaylandIviSurface::iviId * * This property holds the ivi id of this QWaylandIviSurface. */ diff --git a/src/compositor/extensions/qwaylandivisurface.h b/src/compositor/extensions/qwaylandivisurface.h index 37c37c0..ec53650 100644 --- a/src/compositor/extensions/qwaylandivisurface.h +++ b/src/compositor/extensions/qwaylandivisurface.h @@ -81,7 +81,7 @@ Q_SIGNALS: void iviIdChanged(); private: - void initialize(); + void initialize() Q_DECL_OVERRIDE; }; QT_END_NAMESPACE diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp index f6a88e4..91f9d77 100644 --- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp +++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp @@ -208,7 +208,7 @@ bool QWaylandQuickShellEventFilter::eventFilter(QObject *receiver, QEvent *e) QMouseEvent *event = static_cast(e); QWaylandQuickShellSurfaceItem *shellSurfaceItem = qobject_cast(item); bool finalRelease = (event->type() == QEvent::MouseButtonRelease) && (event->buttons() == Qt::NoButton); - bool popupClient = shellSurfaceItem && shellSurfaceItem->surface()->client() == client; + bool popupClient = shellSurfaceItem && shellSurfaceItem->surface() && shellSurfaceItem->surface()->client() == client; if (waitForRelease) { // We are eating events until all mouse buttons are released diff --git a/src/compositor/extensions/qwaylandwlshell.cpp b/src/compositor/extensions/qwaylandwlshell.cpp index 3145c66..9b43467 100644 --- a/src/compositor/extensions/qwaylandwlshell.cpp +++ b/src/compositor/extensions/qwaylandwlshell.cpp @@ -335,7 +335,7 @@ QList QWaylandWlShell::shellSurfacesForClient(QWayland Q_D(const QWaylandWlShell); QList surfsForClient; Q_FOREACH (QWaylandWlShellSurface *shellSurface, d->m_shellSurfaces) { - if (shellSurface->surface()->client() == client) + if (shellSurface->surface() && shellSurface->surface()->client() == client) surfsForClient.append(shellSurface); } return surfsForClient; @@ -347,7 +347,7 @@ QList QWaylandWlShell::mappedPopups() const QList popupSurfaces; Q_FOREACH (QWaylandWlShellSurface *shellSurface, d->m_shellSurfaces) { if (shellSurface->windowType() == Qt::WindowType::Popup - && shellSurface->surface()->hasContent()) { + && shellSurface->surface() && shellSurface->surface()->hasContent()) { popupSurfaces.append(shellSurface); } } @@ -359,7 +359,7 @@ QWaylandClient *QWaylandWlShell::popupClient() const Q_D(const QWaylandWlShell); Q_FOREACH (QWaylandWlShellSurface *shellSurface, d->m_shellSurfaces) { if (shellSurface->windowType() == Qt::WindowType::Popup - && shellSurface->surface()->hasContent()) { + && shellSurface->surface() && shellSurface->surface()->hasContent()) { return shellSurface->surface()->client(); } } diff --git a/src/compositor/extensions/qwaylandwlshell_p.h b/src/compositor/extensions/qwaylandwlshell_p.h index 5e89030..a087f6f 100644 --- a/src/compositor/extensions/qwaylandwlshell_p.h +++ b/src/compositor/extensions/qwaylandwlshell_p.h @@ -98,7 +98,7 @@ public: private: QWaylandWlShell *m_shell; - QWaylandSurface *m_surface; + QPointer m_surface; QSet m_pings; diff --git a/src/compositor/extensions/qwaylandwlshellintegration.cpp b/src/compositor/extensions/qwaylandwlshellintegration.cpp index 30e4704..761a902 100644 --- a/src/compositor/extensions/qwaylandwlshellintegration.cpp +++ b/src/compositor/extensions/qwaylandwlshellintegration.cpp @@ -55,17 +55,17 @@ WlShellIntegration::WlShellIntegration(QWaylandQuickShellSurfaceItem *item) , nextState(State::Windowed) { m_item->setSurface(m_shellSurface->surface()); - connect(m_shellSurface, &QWaylandWlShellSurface::startMove, this, &WlShellIntegration::handleStartMove); - connect(m_shellSurface, &QWaylandWlShellSurface::startResize, this, &WlShellIntegration::handleStartResize); + connect(m_shellSurface.data(), &QWaylandWlShellSurface::startMove, this, &WlShellIntegration::handleStartMove); + connect(m_shellSurface.data(), &QWaylandWlShellSurface::startResize, this, &WlShellIntegration::handleStartResize); connect(m_shellSurface->surface(), &QWaylandSurface::redraw, this, &WlShellIntegration::handleRedraw); connect(m_shellSurface->surface(), &QWaylandSurface::offsetForNextFrame, this, &WlShellIntegration::adjustOffsetForNextFrame); connect(m_shellSurface->surface(), &QWaylandSurface::hasContentChanged, this, &WlShellIntegration::handleSurfaceHasContentChanged); - connect(m_shellSurface, &QWaylandWlShellSurface::setDefaultToplevel, this, &WlShellIntegration::handleSetDefaultTopLevel); - connect(m_shellSurface, &QWaylandWlShellSurface::setTransient, this, &WlShellIntegration::handleSetTransient); - connect(m_shellSurface, &QWaylandWlShellSurface::setMaximized, this, &WlShellIntegration::handleSetMaximized); - connect(m_shellSurface, &QWaylandWlShellSurface::setFullScreen, this, &WlShellIntegration::handleSetFullScreen); - connect(m_shellSurface, &QWaylandWlShellSurface::setPopup, this, &WlShellIntegration::handleSetPopup); - connect(m_shellSurface, &QWaylandWlShellSurface::destroyed, this, &WlShellIntegration::handleShellSurfaceDestroyed); + connect(m_shellSurface.data(), &QWaylandWlShellSurface::setDefaultToplevel, this, &WlShellIntegration::handleSetDefaultTopLevel); + connect(m_shellSurface.data(), &QWaylandWlShellSurface::setTransient, this, &WlShellIntegration::handleSetTransient); + connect(m_shellSurface.data(), &QWaylandWlShellSurface::setMaximized, this, &WlShellIntegration::handleSetMaximized); + connect(m_shellSurface.data(), &QWaylandWlShellSurface::setFullScreen, this, &WlShellIntegration::handleSetFullScreen); + connect(m_shellSurface.data(), &QWaylandWlShellSurface::setPopup, this, &WlShellIntegration::handleSetPopup); + connect(m_shellSurface.data(), &QWaylandWlShellSurface::destroyed, this, &WlShellIntegration::handleShellSurfaceDestroyed); } void WlShellIntegration::handleStartMove(QWaylandSeat *seat) @@ -182,8 +182,9 @@ void WlShellIntegration::handleSetPopup(QWaylandSeat *seat, QWaylandSurface *par } isPopup = true; - QWaylandQuickShellEventFilter::startFilter(m_shellSurface->surface()->client(), [&]() { - m_shellSurface->shell()->closeAllPopups(); + auto shell = m_shellSurface->shell(); + QWaylandQuickShellEventFilter::startFilter(m_shellSurface->surface()->client(), [shell]() { + shell->closeAllPopups(); }); QObject::connect(m_shellSurface->surface(), &QWaylandSurface::hasContentChanged, diff --git a/src/compositor/extensions/qwaylandwlshellintegration_p.h b/src/compositor/extensions/qwaylandwlshellintegration_p.h index bbdfbd7..c0bbcfd 100644 --- a/src/compositor/extensions/qwaylandwlshellintegration_p.h +++ b/src/compositor/extensions/qwaylandwlshellintegration_p.h @@ -88,7 +88,7 @@ private: void handlePopupRemoved(); QWaylandQuickShellSurfaceItem *m_item; - QWaylandWlShellSurface *m_shellSurface; + QPointer m_shellSurface; GrabberState grabberState; struct { QWaylandSeat *seat; diff --git a/src/compositor/extensions/qwaylandxdgshellv5.cpp b/src/compositor/extensions/qwaylandxdgshellv5.cpp index b73b84d..fd23865 100644 --- a/src/compositor/extensions/qwaylandxdgshellv5.cpp +++ b/src/compositor/extensions/qwaylandxdgshellv5.cpp @@ -912,13 +912,15 @@ QSize QWaylandXdgSurfaceV5::sizeForResize(const QSizeF &size, const QPointF &del } /*! - * \qmlmethod int QtWaylandCompositor::XdgSurface::sendConfigure(size size, List) + * \qmlmethod int QtWaylandCompositor::XdgSurface::sendConfigure(size size, list states) * - * Sends a configure event to the client. Known states are enumerated in XdgSurface::State + * Sends a configure event to the client. \a size contains the pixel size of the surface. + * Known \a states are enumerated in XdgSurface::State. */ /*! - * Sends a configure event to the client. Known states are enumerated in QWaylandXdgSurfaceV5::State + * Sends a configure event to the client. Parameter \a size contains the pixel size + * of the surface. Known \a states are enumerated in QWaylandXdgSurfaceV5::State. */ uint QWaylandXdgSurfaceV5::sendConfigure(const QSize &size, const QVector &states) { @@ -1038,8 +1040,8 @@ QWaylandXdgPopupV5::QWaylandXdgPopupV5() } /*! - * Constructs a QWaylandXdgPopupV5 for \a surface and initializes it with the - * given \a parentSurface and \a resource. + * Constructs a QWaylandXdgPopupV5, associating it with \a xdgShell at the specified \a position + * for \a surface and initializes it with the given \a parentSurface and \a resource. */ QWaylandXdgPopupV5::QWaylandXdgPopupV5(QWaylandXdgShellV5 *xdgShell, QWaylandSurface *surface, QWaylandSurface *parentSurface, const QPoint &position, const QWaylandResource &resource) diff --git a/src/compositor/extensions/qwaylandxdgshellv5integration.cpp b/src/compositor/extensions/qwaylandxdgshellv5integration.cpp index b317033..e2aa6b3 100644 --- a/src/compositor/extensions/qwaylandxdgshellv5integration.cpp +++ b/src/compositor/extensions/qwaylandxdgshellv5integration.cpp @@ -194,10 +194,14 @@ XdgPopupV5Integration::XdgPopupV5Integration(QWaylandQuickShellSurfaceItem *item , m_xdgShell(QWaylandXdgPopupV5Private::get(m_xdgPopup)->m_xdgShell) { item->setSurface(m_xdgPopup->surface()); - item->moveItem()->setPosition(QPointF(m_xdgPopup->position() * item->view()->output()->scaleFactor())); + if (item->view()->output()) + item->moveItem()->setPosition(QPointF(m_xdgPopup->position() * item->view()->output()->scaleFactor())); + else + qWarning() << "XdgPopupV5Integration popup item without output" << item; QWaylandClient *client = m_xdgPopup->surface()->client(); - QWaylandQuickShellEventFilter::startFilter(client, [&]() { m_xdgShell->closeAllPopups(); }); + auto shell = m_xdgShell; + QWaylandQuickShellEventFilter::startFilter(client, [shell]() { shell->closeAllPopups(); }); connect(m_xdgPopup, &QWaylandXdgPopupV5::destroyed, this, &XdgPopupV5Integration::handlePopupDestroyed); } diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp index 236218e..6b5c532 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.cpp @@ -159,6 +159,12 @@ void QWaylandEglWindow::setVisible(bool visible) { QWaylandWindow::setVisible(visible); if (!visible) + QMetaObject::invokeMethod(this, "doInvalidateSurface", Qt::QueuedConnection); +} + +void QWaylandEglWindow::doInvalidateSurface() +{ + if (!window()->isVisible()) invalidateSurface(); } @@ -168,6 +174,10 @@ void QWaylandEglWindow::invalidateSurface() eglDestroySurface(m_clientBufferIntegration->eglDisplay(), m_eglSurface); m_eglSurface = 0; } + if (m_waylandEglWindow) { + wl_egl_window_destroy(m_waylandEglWindow); + m_waylandEglWindow = nullptr; + } } EGLSurface QWaylandEglWindow::eglSurface() const diff --git a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h index 556ed68..bf65668 100644 --- a/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h +++ b/src/hardwareintegration/client/wayland-egl/qwaylandeglwindow.h @@ -54,6 +54,7 @@ class QWaylandGLContext; class QWaylandEglWindow : public QWaylandWindow { + Q_OBJECT public: QWaylandEglWindow(QWindow *window); ~QWaylandEglWindow(); @@ -75,6 +76,9 @@ public: void invalidateSurface() Q_DECL_OVERRIDE; void setVisible(bool visible) Q_DECL_OVERRIDE; +private Q_SLOTS: + void doInvalidateSurface(); + private: QWaylandEglClientBufferIntegration *m_clientBufferIntegration; struct wl_egl_window *m_waylandEglWindow; diff --git a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp index e2e2f55..c07ad53 100644 --- a/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp +++ b/src/hardwareintegration/client/xcomposite-egl/qwaylandxcompositeeglcontext.cpp @@ -64,9 +64,7 @@ void QWaylandXCompositeEGLContext::swapBuffers(QPlatformSurface *surface) QSize size = w->geometry().size(); - w->attach(w->buffer(), 0, 0); - w->damage(QRect(QPoint(), size)); - w->commit(); + w->commit(w->buffer(), QRegion(0, 0, size.width(), size.height())); w->waitForFrameSync(); } diff --git a/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.cpp b/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.cpp index bc6e94f..439acc0 100644 --- a/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.cpp +++ b/src/hardwareintegration/client/xcomposite-glx/qwaylandxcompositeglxcontext.cpp @@ -90,9 +90,7 @@ void QWaylandXCompositeGLXContext::swapBuffers(QPlatformSurface *surface) glXSwapBuffers(m_display, w->xWindow()); - w->attach(w->buffer(), 0, 0); - w->damage(QRect(QPoint(), size)); - w->commit(); + w->commit(w->buffer(), QRegion(0, 0, size.width(), size.height())); w->waitForFrameSync(); } diff --git a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp index 6876385..6103e6b 100644 --- a/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp +++ b/src/plugins/shellintegration/ivi-shell/qwaylandivishellintegration.cpp @@ -66,6 +66,7 @@ QWaylandIviShellIntegration::~QWaylandIviShellIntegration() bool QWaylandIviShellIntegration::initialize(QWaylandDisplay *display) { + QWaylandShellIntegration::initialize(display); display->addRegistryListener(registryIvi, this); return true; diff --git a/src/plugins/shellintegration/ivi-shell/qwaylandivisurface.cpp b/src/plugins/shellintegration/ivi-shell/qwaylandivisurface.cpp index f8871fa..ecc47e0 100644 --- a/src/plugins/shellintegration/ivi-shell/qwaylandivisurface.cpp +++ b/src/plugins/shellintegration/ivi-shell/qwaylandivisurface.cpp @@ -71,6 +71,13 @@ QWaylandIviSurface::~QWaylandIviSurface() delete m_extendedWindow; } +void QWaylandIviSurface::setType(Qt::WindowType type, QWaylandWindow *transientParent) +{ + + Q_UNUSED(type) + Q_UNUSED(transientParent) +} + void QWaylandIviSurface::createExtendedSurface(QWaylandWindow *window) { if (window->display()->windowExtension()) diff --git a/src/plugins/shellintegration/ivi-shell/qwaylandivisurface_p.h b/src/plugins/shellintegration/ivi-shell/qwaylandivisurface_p.h index 96978e2..9ac81ad 100644 --- a/src/plugins/shellintegration/ivi-shell/qwaylandivisurface_p.h +++ b/src/plugins/shellintegration/ivi-shell/qwaylandivisurface_p.h @@ -56,6 +56,8 @@ public: struct ::ivi_controller_surface *iviControllerSurface); virtual ~QWaylandIviSurface(); + void setType(Qt::WindowType type, QWaylandWindow *transientParent) override; + private: void createExtendedSurface(QWaylandWindow *window); virtual void ivi_surface_configure(int32_t width, int32_t height) Q_DECL_OVERRIDE; diff --git a/sync.profile b/sync.profile index 6fee67e..1276df0 100644 --- a/sync.profile +++ b/sync.profile @@ -8,18 +8,6 @@ ); %deprecatedheaders = ( ); -# Module dependencies. -# Every module that is required to build this module should have one entry. -# Each of the module version specifiers can take one of the following values: -# - A specific Git revision. -# - any git symbolic ref resolvable from the module's repository (e.g. "refs/heads/master" to track master branch) -# - an empty string to use the same branch under test (dependencies will become "refs/heads/master" if we are in the master branch) -# -%dependencies = ( - "qtbase" => "", - "qtdeclarative" => "", -); - %classnames = ( "qwaylandquickextension.h" => "QWaylandQuickExtension", ); diff --git a/tests/auto/client/client/tst_client.cpp b/tests/auto/client/client/tst_client.cpp index 74363ef..6aad25b 100644 --- a/tests/auto/client/client/tst_client.cpp +++ b/tests/auto/client/client/tst_client.cpp @@ -248,8 +248,8 @@ void tst_WaylandClient::backingStore() window.hide(); - // hiding the window should detach the buffer - QTRY_VERIFY(surface->image.isNull()); + // hiding the window should destroy the surface + QTRY_VERIFY(!compositor->surface()); } class DndWindow : public QWindow diff --git a/tests/manual/qmlclient/main.cpp b/tests/manual/qmlclient/main.cpp new file mode 100644 index 0000000..cb2044c --- /dev/null +++ b/tests/manual/qmlclient/main.cpp @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pier Luigi Fiorini +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +int main(int argc, char* argv[]) +{ + setenv("QT_QPA_PLATFORM", "wayland", 1); + + QGuiApplication app(argc, argv); + QQmlApplicationEngine engine(QUrl("qrc:/main.qml")); + return app.exec(); +} diff --git a/tests/manual/qmlclient/main.qml b/tests/manual/qmlclient/main.qml new file mode 100644 index 0000000..a1fe241 --- /dev/null +++ b/tests/manual/qmlclient/main.qml @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Pier Luigi Fiorini +** Contact: http://www.qt-project.org/legal +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtQuick.Window 2.2 + +Window { + id: window + width: 400 + height: 400 + color: "blue" + visible: true + + Column { + spacing: 8 + + Row { + spacing: 8 + + Repeater { + model: ListModel { + ListElement { label: "Windowed"; value: Window.Windowed } + ListElement { label: "Maximized"; value: Window.Maximized } + ListElement { label: "FullScreen"; value: Window.FullScreen } + } + + Rectangle { + width: 96 + height: 40 + color: "gainsboro" + + MouseArea { + anchors.fill: parent + onClicked: window.visibility = model.value + + Text { + anchors.centerIn: parent + text: model.label + } + } + } + } + } + + Text { + color: "white" + text: { + switch (window.visibility) { + case Window.Windowed: + return "windowed"; + case Window.Maximized: + return "maximized"; + case Window.FullScreen: + return "fullscreen"; + case Window.Minimized: + return "minimized"; + case Window.AutomaticVisibility: + return "automatic"; + case Window.Hidden: + return "hidden"; + default: + break; + } + return "unknown"; + } + } + } +} diff --git a/tests/manual/qmlclient/qml.qrc b/tests/manual/qmlclient/qml.qrc new file mode 100644 index 0000000..6b2d0a7 --- /dev/null +++ b/tests/manual/qmlclient/qml.qrc @@ -0,0 +1,5 @@ + + + main.qml + + diff --git a/tests/manual/qmlclient/qmlclient.pro b/tests/manual/qmlclient/qmlclient.pro new file mode 100644 index 0000000..dcf66db --- /dev/null +++ b/tests/manual/qmlclient/qmlclient.pro @@ -0,0 +1,12 @@ +TEMPLATE = app + +QT += \ + gui gui-private core-private \ + quick \ + waylandclient \ + +SOURCES += \ + main.cpp + +RESOURCES += \ + qml.qrc