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>
This commit is contained in:
parent
4d312f1ec7
commit
61b80576b0
@ -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")) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
if (!(window->flags() & Qt::BypassWindowManagerHint)) {
|
||||
QWaylandWindow::~QWaylandWindow()
|
||||
{
|
||||
delete mWindowDecoration;
|
||||
|
||||
if (isInitialized())
|
||||
reset();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user