summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiulio Camuffo <giulio.camuffo@jollamobile.com>2015-07-05 17:58:23 +0300
committerSimon Hausmann <simon.hausmann@theqtcompany.com>2015-07-22 07:42:07 +0000
commit2e3cddf8b28cf6ce2b4db9c9a21f0a2427bdf756 (patch)
treed61f67f2468431379df438052e701d803c7f1c40
parent6c47babc1a3566c7186e3196e7975df2be9b575b (diff)
Use standard wl_subsurface interface to set a window as a child of another one
Change-Id: I52628f87dbea5383db06468f9748a9bacdec3179 Reviewed-by: Robin Burchell <robin.burchell@viroteck.net>
-rw-r--r--src/client/qwaylanddisplay.cpp15
-rw-r--r--src/client/qwaylanddisplay_p.h4
-rw-r--r--src/client/qwaylandsubsurface.cpp41
-rw-r--r--src/client/qwaylandsubsurface_p.h14
-rw-r--r--src/client/qwaylandwindow.cpp126
-rw-r--r--src/client/qwaylandwindow_p.h5
6 files changed, 113 insertions, 92 deletions
diff --git a/src/client/qwaylanddisplay.cpp b/src/client/qwaylanddisplay.cpp
index 5b6f2cbf6..ab69bca32 100644
--- a/src/client/qwaylanddisplay.cpp
+++ b/src/client/qwaylanddisplay.cpp
@@ -100,6 +100,15 @@ struct ::wl_region *QWaylandDisplay::createRegion(const QRegion &qregion)
return region;
}
+::wl_subsurface *QWaylandDisplay::createSubSurface(QWaylandWindow *window, QWaylandWindow *parent)
+{
+ if (!mSubCompositor) {
+ return NULL;
+ }
+
+ return mSubCompositor->get_subsurface(window->object(), parent->object());
+}
+
QWaylandClientBufferIntegration * QWaylandDisplay::clientBufferIntegration() const
{
return mWaylandIntegration->clientBufferIntegration();
@@ -125,7 +134,7 @@ QWaylandDisplay::QWaylandDisplay(QWaylandIntegration *waylandIntegration)
, mLastKeyboardFocusInputDevice(0)
, mDndSelectionHandler(0)
, mWindowExtension(0)
- , mSubSurfaceExtension(0)
+ , mSubCompositor(0)
, mTouchExtension(0)
, mQtKeyExtension(0)
, mTextInputManager(0)
@@ -259,8 +268,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
mDndSelectionHandler.reset(new QWaylandDataDeviceManager(this, id));
} else if (interface == QStringLiteral("qt_surface_extension")) {
mWindowExtension.reset(new QtWayland::qt_surface_extension(registry, id, 1));
- } else if (interface == QStringLiteral("qt_sub_surface_extension")) {
- mSubSurfaceExtension.reset(new QtWayland::qt_sub_surface_extension(registry, id, 1));
+ } else if (interface == QStringLiteral("wl_subcompositor")) {
+ mSubCompositor.reset(new QtWayland::wl_subcompositor(registry, id, 1));
} else if (interface == QStringLiteral("qt_touch_extension")) {
mTouchExtension.reset(new QWaylandTouchExtension(this, id));
} else if (interface == QStringLiteral("qt_key_extension")) {
diff --git a/src/client/qwaylanddisplay_p.h b/src/client/qwaylanddisplay_p.h
index 9a7ad39ce..96d79ddbd 100644
--- a/src/client/qwaylanddisplay_p.h
+++ b/src/client/qwaylanddisplay_p.h
@@ -100,6 +100,7 @@ public:
struct wl_surface *createSurface(void *handle);
QWaylandShellSurface *createShellSurface(QWaylandWindow *window);
struct ::wl_region *createRegion(const QRegion &qregion);
+ struct ::wl_subsurface *createSubSurface(QWaylandWindow *window, QWaylandWindow *parent);
QWaylandClientBufferIntegration *clientBufferIntegration() const;
@@ -128,7 +129,6 @@ public:
QWaylandDataDeviceManager *dndSelectionHandler() const { return mDndSelectionHandler.data(); }
QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); }
- QtWayland::qt_sub_surface_extension *subSurfaceExtension() const { return mSubSurfaceExtension.data(); }
QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); }
QtWayland::wl_text_input_manager *textInputManager() const { return mTextInputManager.data(); }
QWaylandHardwareIntegration *hardwareIntegration() const { return mHardwareIntegration.data(); }
@@ -188,7 +188,7 @@ private:
QWaylandInputDevice *mLastKeyboardFocusInputDevice;
QScopedPointer<QWaylandDataDeviceManager> mDndSelectionHandler;
QScopedPointer<QtWayland::qt_surface_extension> mWindowExtension;
- QScopedPointer<QtWayland::qt_sub_surface_extension> mSubSurfaceExtension;
+ QScopedPointer<QtWayland::wl_subcompositor> mSubCompositor;
QScopedPointer<QWaylandTouchExtension> mTouchExtension;
QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension;
QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration;
diff --git a/src/client/qwaylandsubsurface.cpp b/src/client/qwaylandsubsurface.cpp
index 81cfef254..ec813609f 100644
--- a/src/client/qwaylandsubsurface.cpp
+++ b/src/client/qwaylandsubsurface.cpp
@@ -41,45 +41,18 @@ QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
-QWaylandSubSurface::QWaylandSubSurface(QWaylandWindow *window, struct ::qt_sub_surface *sub_surface)
- : QtWayland::qt_sub_surface(sub_surface)
+QWaylandSubSurface::QWaylandSubSurface(QWaylandWindow *window, QWaylandWindow *parent, ::wl_subsurface *sub_surface)
+ : QtWayland::wl_subsurface(sub_surface)
, m_window(window)
+ , m_parent(parent)
{
+ m_parent->mChildren << this;
+ set_desync();
}
-void QWaylandSubSurface::setParent(const QWaylandWindow *parent)
+QWaylandSubSurface::~QWaylandSubSurface()
{
- QWaylandSubSurface *parentSurface = parent ? parent->subSurfaceWindow() : 0;
- if (parentSurface) {
- int x = m_window->geometry().x() + parent->frameMargins().left();
- int y = m_window->geometry().y() + parent->frameMargins().top();
- parentSurface->attach_sub_surface(object(), x, y);
- }
-}
-
-static void setPositionToParent(QWaylandWindow *parentWaylandWindow)
-{
- QObjectList children = parentWaylandWindow->window()->children();
- for (int i = 0; i < children.size(); i++) {
- QWindow *childWindow = qobject_cast<QWindow *>(children.at(i));
- if (!childWindow)
- continue;
-
- if (childWindow->handle()) {
- QWaylandWindow *waylandWindow = static_cast<QWaylandWindow *>(childWindow->handle());
- waylandWindow->subSurfaceWindow()->setParent(parentWaylandWindow);
- setPositionToParent(waylandWindow);
- }
- }
-}
-
-void QWaylandSubSurface::adjustPositionOfChildren()
-{
- QWindow *window = m_window->window();
- if (window->parent()) {
- qDebug() << "QWaylandSubSurface::adjustPositionOfChildren not called for toplevel window";
- }
- setPositionToParent(m_window);
+ m_parent->mChildren.removeOne(this);
}
}
diff --git a/src/client/qwaylandsubsurface_p.h b/src/client/qwaylandsubsurface_p.h
index 232330855..75d8cf6a0 100644
--- a/src/client/qwaylandsubsurface_p.h
+++ b/src/client/qwaylandsubsurface_p.h
@@ -39,8 +39,7 @@
#include <QtCore/qglobal.h>
#include <QtWaylandClient/private/qwaylandclientexport_p.h>
-
-#include <QtWaylandClient/private/qwayland-sub-surface-extension.h>
+#include <QtWaylandClient/private/qwayland-wayland.h>
QT_BEGIN_NAMESPACE
@@ -48,18 +47,19 @@ namespace QtWaylandClient {
class QWaylandDisplay;
class QWaylandWindow;
-class QWaylandSubSurface;
-class Q_WAYLAND_CLIENT_EXPORT QWaylandSubSurface : public QtWayland::qt_sub_surface
+class Q_WAYLAND_CLIENT_EXPORT QWaylandSubSurface : public QtWayland::wl_subsurface
{
public:
- QWaylandSubSurface(QWaylandWindow *window, struct ::qt_sub_surface *sub_surface);
+ QWaylandSubSurface(QWaylandWindow *window, QWaylandWindow *parent, ::wl_subsurface *subsurface);
+ ~QWaylandSubSurface();
- void setParent(const QWaylandWindow *parent);
- void adjustPositionOfChildren();
+ QWaylandWindow *window() const { return m_window; }
+ QWaylandWindow *parent() const { return m_parent; }
private:
QWaylandWindow *m_window;
+ QWaylandWindow *m_parent;
};
QT_END_NAMESPACE
diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp
index 922b1ee00..a54979a2f 100644
--- a/src/client/qwaylandwindow.cpp
+++ b/src/client/qwaylandwindow.cpp
@@ -86,21 +86,49 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
, mMask()
, mBackingStore(Q_NULLPTR)
{
- init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this)));
-
static WId id = 1;
mWindowId = id++;
- if (mDisplay->subSurfaceExtension())
- mSubSurfaceWindow = new QWaylandSubSurface(this, mDisplay->subSurfaceExtension()->get_sub_surface_aware_surface(object()));
+ initWindow();
+}
+
+QWaylandWindow::~QWaylandWindow()
+{
+ delete mWindowDecoration;
+
+ if (isInitialized())
+ reset();
- if (!(window->flags() & Qt::BypassWindowManagerHint)) {
+ QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices();
+ for (int i = 0; i < inputDevices.size(); ++i)
+ inputDevices.at(i)->handleWindowDestroyed(this);
+
+ const QWindow *parent = window();
+ foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
+ if (w->transientParent() == parent)
+ QWindowSystemInterface::handleCloseEvent(w);
+ }
+
+ if (mMouseGrab == this) {
+ mMouseGrab = 0;
+ }
+}
+
+void QWaylandWindow::initWindow()
+{
+ init(mDisplay->createSurface(static_cast<QtWayland::wl_surface *>(this)));
+ if (QPlatformWindow::parent()) {
+ QWaylandWindow *p = static_cast<QWaylandWindow *>(QPlatformWindow::parent());
+ if (::wl_subsurface *ss = mDisplay->createSubSurface(this, p)) {
+ mSubSurfaceWindow = new QWaylandSubSurface(this, p, ss);
+ }
+ } else if (!(window()->flags() & Qt::BypassWindowManagerHint)) {
mShellSurface = mDisplay->createShellSurface(this);
}
if (mShellSurface) {
// Set initial surface title
- mShellSurface->setTitle(window->title());
+ mShellSurface->setTitle(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),
@@ -122,14 +150,14 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
}
}
- if (QPlatformWindow::parent() && mSubSurfaceWindow) {
- mSubSurfaceWindow->setParent(static_cast<const QWaylandWindow *>(QPlatformWindow::parent()));
- } else if (window->transientParent() && mShellSurface) {
- if (window->type() != Qt::Popup) {
- mShellSurface->updateTransientParent(window->transientParent());
+ if (mShellSurface) {
+ if (window()->transientParent()) {
+ if (window()->type() != Qt::Popup) {
+ mShellSurface->updateTransientParent(window()->transientParent());
+ }
+ } else {
+ mShellSurface->setTopLevel();
}
- } else if (mShellSurface) {
- mShellSurface->setTopLevel();
}
// Enable high-dpi rendering. Scale() returns the screen scale factor and will
@@ -138,38 +166,25 @@ QWaylandWindow::QWaylandWindow(QWindow *window)
if (mDisplay->compositorVersion() >= 3)
set_buffer_scale(scale());
- setOrientationMask(window->screen()->orientationUpdateMask());
- setWindowFlags(window->flags());
- setGeometry_helper(window->geometry());
- setMask(window->mask());
- setWindowStateInternal(window->windowState());
- handleContentOrientationChange(window->contentOrientation());
+ if (QScreen *s = window()->screen())
+ setOrientationMask(s->orientationUpdateMask());
+ setWindowFlags(window()->flags());
+ setGeometry_helper(window()->geometry());
+ setMask(window()->mask());
+ setWindowStateInternal(window()->windowState());
+ handleContentOrientationChange(window()->contentOrientation());
}
-QWaylandWindow::~QWaylandWindow()
+void QWaylandWindow::reset()
{
- delete mWindowDecoration;
+ delete mShellSurface;
+ mShellSurface = 0;
+ delete mSubSurfaceWindow;
+ mSubSurfaceWindow = 0;
+ destroy();
- if (isInitialized()) {
- delete mShellSurface;
- destroy();
- }
if (mFrameCallback)
wl_callback_destroy(mFrameCallback);
-
- QList<QWaylandInputDevice *> inputDevices = mDisplay->inputDevices();
- for (int i = 0; i < inputDevices.size(); ++i)
- inputDevices.at(i)->handleWindowDestroyed(this);
-
- const QWindow *parent = window();
- foreach (QWindow *w, QGuiApplication::topLevelWindows()) {
- if (w->transientParent() == parent)
- QWindowSystemInterface::handleCloseEvent(w);
- }
-
- if (mMouseGrab == this) {
- mMouseGrab = 0;
- }
}
QWaylandWindow *QWaylandWindow::fromWlSurface(::wl_surface *surface)
@@ -184,9 +199,17 @@ WId QWaylandWindow::winId() const
void QWaylandWindow::setParent(const QPlatformWindow *parent)
{
- const QWaylandWindow *parentWaylandWindow = static_cast<const QWaylandWindow *>(parent);
- if (subSurfaceWindow()) {
- subSurfaceWindow()->setParent(parentWaylandWindow);
+ QWaylandWindow *oldparent = mSubSurfaceWindow ? mSubSurfaceWindow->parent() : 0;
+ if (oldparent == parent)
+ return;
+
+ if (mSubSurfaceWindow && parent) { // new parent, but we were a subsurface already
+ delete mSubSurfaceWindow;
+ QWaylandWindow *p = const_cast<QWaylandWindow *>(static_cast<const QWaylandWindow *>(parent));
+ mSubSurfaceWindow = new QWaylandSubSurface(this, p, mDisplay->createSubSurface(this, p));
+ } else { // we're changing role, need to make a new wl_surface
+ reset();
+ initWindow();
}
}
@@ -214,7 +237,10 @@ void QWaylandWindow::setGeometry_helper(const QRect &rect)
qBound(window()->minimumWidth(), rect.width(), window()->maximumWidth()),
qBound(window()->minimumHeight(), rect.height(), window()->maximumHeight())));
- if (shellSurface() && window()->transientParent() && window()->type() != Qt::Popup)
+ 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());
}
@@ -546,7 +572,10 @@ bool QWaylandWindow::createDecoration()
decoration = false;
if (window()->flags() & Qt::BypassWindowManagerHint)
decoration = false;
+ if (mSubSurfaceWindow)
+ decoration = false;
+ bool hadDecoration = mWindowDecoration;
if (decoration && !decorationPluginFailed) {
if (!mWindowDecoration) {
QStringList decorations = QWaylandDecorationFactory::keys();
@@ -577,15 +606,20 @@ bool QWaylandWindow::createDecoration()
return false;
}
mWindowDecoration->setWaylandWindow(this);
- if (subSurfaceWindow()) {
- subSurfaceWindow()->adjustPositionOfChildren();
- }
}
} else {
delete mWindowDecoration;
mWindowDecoration = 0;
}
+ if (hadDecoration != (bool)mWindowDecoration) {
+ foreach (QWaylandSubSurface *subsurf, mChildren) {
+ QPoint pos = subsurf->window()->geometry().topLeft();
+ QMargins m = frameMargins();
+ subsurf->set_position(pos.x() + m.left(), pos.y() + m.top());
+ }
+ }
+
return mWindowDecoration;
}
diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h
index 1898c4953..6b9af1031 100644
--- a/src/client/qwaylandwindow_p.h
+++ b/src/client/qwaylandwindow_p.h
@@ -190,6 +190,7 @@ protected:
QWaylandDisplay *mDisplay;
QWaylandShellSurface *mShellSurface;
QWaylandSubSurface *mSubSurfaceWindow;
+ QVector<QWaylandSubSurface *> mChildren;
QWaylandAbstractDecoration *mWindowDecoration;
bool mMouseEventsInContentArea;
@@ -223,6 +224,8 @@ protected:
private:
bool setWindowStateInternal(Qt::WindowState flags);
void setGeometry_helper(const QRect &rect);
+ void initWindow();
+ void reset();
void handleMouseEventWithDecoration(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
@@ -231,6 +234,8 @@ private:
static QMutex mFrameSyncMutex;
static QWaylandWindow *mMouseGrab;
+
+ friend class QWaylandSubSurface;
};
inline QIcon QWaylandWindow::windowIcon() const