Client: Track parent-popup relationship in QWaylandWindow

This reduces the amount of boilerplate code that goes in shell
integration plugins providing popups.

The main motivation behind this change though is to ensure that
QWaylandWindow::addChildPopup() gets called outside the
QWaylandShellSurface constructor so one could use the popup's shell
surface object to customize parent-child relationship.

    mShellSurface = mShellIntegration->createShellSurface(this);

when this code executes, addChildPopup() will be called before the
return value of createShellSurface() is assigned to mShellSurface.

Change-Id: I9ccfb21f46febb451bdd7b4aa7851a99f3a03655
Reviewed-by: David Edmundson <davidedmundson@kde.org>
This commit is contained in:
Vlad Zahorodnii 2023-03-27 14:27:21 +03:00
parent eabe2a039b
commit e1ef4a7f89
3 changed files with 27 additions and 14 deletions

View File

@ -211,10 +211,8 @@ QWaylandXdgSurface::Popup::Popup(QWaylandXdgSurface *xdgSurface, QWaylandWindow
, m_parent(parent)
{
init(xdgSurface->get_popup(m_parentXdgSurface ? m_parentXdgSurface->object() : nullptr, positioner->object()));
if (m_parent) {
m_parent->addChildPopup(m_xdgSurface->window());
}
init(xdgSurface->get_popup(m_parentXdgSurface ? m_parentXdgSurface->object() : nullptr,
positioner->object()));
}
QWaylandXdgSurface::Popup::~Popup()
@ -222,10 +220,6 @@ QWaylandXdgSurface::Popup::~Popup()
if (isInitialized())
destroy();
if (m_parent) {
m_parent->removeChildPopup(m_xdgSurface->window());
}
if (m_grabbing) {
auto *shell = m_xdgSurface->m_shell;
Q_ASSERT(shell->m_topmostGrabbingPopup == this);

View File

@ -137,9 +137,15 @@ void QWaylandWindow::initWindow()
} else if (shouldCreateShellSurface()) {
Q_ASSERT(!mShellSurface);
Q_ASSERT(mShellIntegration);
mTransientParent = closestTransientParent();
mShellSurface = mShellIntegration->createShellSurface(this);
if (mShellSurface) {
if (mTransientParent) {
if (window()->type() == Qt::ToolTip || window()->type() == Qt::Popup)
mTransientParent->addChildPopup(this);
}
// Set initial surface title
setWindowTitle(window()->title());
@ -272,10 +278,13 @@ void QWaylandWindow::reset()
emit wlSurfaceDestroyed();
QWriteLocker lock(&mSurfaceLock);
invalidateSurface();
if (mTransientParent)
mTransientParent->removeChildPopup(this);
delete mShellSurface;
mShellSurface = nullptr;
delete mSubSurfaceWindow;
mSubSurfaceWindow = nullptr;
mTransientParent = nullptr;
mSurface.reset();
mViewport.reset();
mFractionalScale.reset();
@ -1050,6 +1059,11 @@ static QWaylandWindow *closestShellSurfaceWindow(QWindow *window)
}
QWaylandWindow *QWaylandWindow::transientParent() const
{
return mTransientParent;
}
QWaylandWindow *QWaylandWindow::closestTransientParent() const
{
// Take the closest window with a shell surface, since the transient parent may be a
// QWidgetWindow or some other window without a shell surface, which is then not able to
@ -1619,12 +1633,14 @@ void QWaylandWindow::setXdgActivationToken(const QString &token)
mShellSurface->setXdgActivationToken(token);
}
void QWaylandWindow::addChildPopup(QWaylandWindow *surface) {
mChildPopups.append(surface);
void QWaylandWindow::addChildPopup(QWaylandWindow *child)
{
mChildPopups.append(child);
}
void QWaylandWindow::removeChildPopup(QWaylandWindow *surface) {
mChildPopups.removeAll(surface);
void QWaylandWindow::removeChildPopup(QWaylandWindow *child)
{
mChildPopups.removeAll(child);
}
void QWaylandWindow::closeChildPopups() {

View File

@ -225,8 +225,6 @@ public:
void beginFrame();
void endFrame();
void addChildPopup(QWaylandWindow* child);
void removeChildPopup(QWaylandWindow* child);
void closeChildPopups();
virtual void reinit();
@ -320,6 +318,7 @@ protected:
QMargins mCustomMargins;
QPointer<QWaylandWindow> mTransientParent;
QList<QPointer<QWaylandWindow>> mChildPopups;
private:
@ -337,6 +336,10 @@ private:
void handleScreensChanged();
void sendRecursiveExposeEvent();
QWaylandWindow *closestTransientParent() const;
void addChildPopup(QWaylandWindow *child);
void removeChildPopup(QWaylandWindow *child);
bool mInResizeFromApplyConfigure = false;
bool lastVisible = false;
QRect mLastExposeGeometry;