2020-08-02 22:22:19 +00:00
|
|
|
/*
|
|
|
|
KWin - the KDE window manager
|
|
|
|
This file is part of the KDE project.
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-FileCopyrightText: 2018 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2020-08-02 22:22:19 +00:00
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
#include "kwin_wayland_test.h"
|
|
|
|
|
|
|
|
#include "atoms.h"
|
|
|
|
#include "main.h"
|
|
|
|
#include "wayland_server.h"
|
2022-04-22 17:39:12 +00:00
|
|
|
#include "window.h"
|
2018-10-02 05:39:31 +00:00
|
|
|
#include "workspace.h"
|
2022-04-22 17:54:31 +00:00
|
|
|
#include "x11window.h"
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
#include <KWayland/Client/compositor.h>
|
|
|
|
#include <KWayland/Client/surface.h>
|
|
|
|
|
|
|
|
#include <xcb/xcb.h>
|
|
|
|
#include <xcb/xcb_icccm.h>
|
|
|
|
|
|
|
|
using namespace KWin;
|
|
|
|
|
|
|
|
static const QString s_socketName = QStringLiteral("wayland_test_kwin_stacking_order-0");
|
|
|
|
|
|
|
|
class StackingOrderTest : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
private Q_SLOTS:
|
|
|
|
void initTestCase();
|
|
|
|
void init();
|
|
|
|
void cleanup();
|
|
|
|
|
|
|
|
void testTransientIsAboveParent();
|
|
|
|
void testRaiseTransient();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
void testDeletedTransient();
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
void testGroupTransientIsAboveWindowGroup();
|
|
|
|
void testRaiseGroupTransient();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
void testDeletedGroupTransient();
|
2018-10-02 05:39:31 +00:00
|
|
|
void testDontKeepAboveNonModalDialogGroupTransients();
|
|
|
|
|
2018-10-16 16:19:17 +00:00
|
|
|
void testKeepAbove();
|
|
|
|
void testKeepBelow();
|
2023-11-16 01:53:17 +00:00
|
|
|
|
|
|
|
void testPreserveRelativeWindowStacking();
|
2018-10-02 05:39:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void StackingOrderTest::initTestCase()
|
|
|
|
{
|
2022-04-22 17:39:12 +00:00
|
|
|
qRegisterMetaType<KWin::Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2020-07-07 09:32:29 +00:00
|
|
|
QSignalSpy applicationStartedSpy(kwinApp(), &Application::started);
|
2020-12-09 13:06:15 +00:00
|
|
|
QVERIFY(waylandServer()->init(s_socketName));
|
2023-05-08 10:16:00 +00:00
|
|
|
Test::setOutputConfig({
|
|
|
|
QRect(0, 0, 1280, 1024),
|
|
|
|
QRect(1280, 0, 1280, 1024),
|
|
|
|
});
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
kwinApp()->setConfig(KSharedConfig::openConfig(QString(), KConfig::SimpleConfig));
|
|
|
|
|
|
|
|
kwinApp()->start();
|
2020-07-07 09:32:29 +00:00
|
|
|
QVERIFY(applicationStartedSpy.wait());
|
2018-10-02 05:39:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void StackingOrderTest::init()
|
|
|
|
{
|
|
|
|
QVERIFY(Test::setupWaylandConnection());
|
|
|
|
}
|
|
|
|
|
|
|
|
void StackingOrderTest::cleanup()
|
|
|
|
{
|
|
|
|
Test::destroyWaylandConnection();
|
|
|
|
}
|
|
|
|
|
|
|
|
void StackingOrderTest::testTransientIsAboveParent()
|
|
|
|
{
|
|
|
|
// This test verifies that transients are always above their parents.
|
|
|
|
|
|
|
|
// Create the parent.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> parentSurface = Test::createSurface();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(parentSurface);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> parentShellSurface(Test::createXdgToplevelSurface(parentSurface.get()));
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(parentShellSurface);
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *parent = Test::renderAndWaitForShown(parentSurface.get(), QSize(256, 256), Qt::blue);
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(parent);
|
|
|
|
QVERIFY(parent->isActive());
|
|
|
|
QVERIFY(!parent->isTransient());
|
|
|
|
|
|
|
|
// Initially, the stacking order should contain only the parent window.
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{parent}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create the transient.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> transientSurface = Test::createSurface();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(transientSurface);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> transientShellSurface(Test::createXdgToplevelSurface(transientSurface.get()));
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(transientShellSurface);
|
2021-05-11 05:26:51 +00:00
|
|
|
transientShellSurface->set_parent(parentShellSurface->object());
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *transient = Test::renderAndWaitForShown(transientSurface.get(), QSize(128, 128), Qt::red);
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(transient);
|
|
|
|
QVERIFY(transient->isActive());
|
|
|
|
QVERIFY(transient->isTransient());
|
|
|
|
|
|
|
|
// The transient should be above the parent.
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{parent, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// The transient still stays above the parent if we activate the latter.
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(parent);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(parent->isActive());
|
|
|
|
QTRY_VERIFY(!transient->isActive());
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{parent, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void StackingOrderTest::testRaiseTransient()
|
|
|
|
{
|
|
|
|
// This test verifies that both the parent and the transient will be
|
|
|
|
// raised if either one of them is activated.
|
|
|
|
|
|
|
|
// Create the parent.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> parentSurface = Test::createSurface();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(parentSurface);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> parentShellSurface(Test::createXdgToplevelSurface(parentSurface.get()));
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(parentShellSurface);
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *parent = Test::renderAndWaitForShown(parentSurface.get(), QSize(256, 256), Qt::blue);
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(parent);
|
|
|
|
QVERIFY(parent->isActive());
|
|
|
|
QVERIFY(!parent->isTransient());
|
|
|
|
|
|
|
|
// Initially, the stacking order should contain only the parent window.
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{parent}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create the transient.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> transientSurface = Test::createSurface();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(transientSurface);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> transientShellSurface(Test::createXdgToplevelSurface(transientSurface.get()));
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(transientShellSurface);
|
2021-05-11 05:26:51 +00:00
|
|
|
transientShellSurface->set_parent(parentShellSurface->object());
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *transient = Test::renderAndWaitForShown(transientSurface.get(), QSize(128, 128), Qt::red);
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(transient);
|
|
|
|
QTRY_VERIFY(transient->isActive());
|
|
|
|
QVERIFY(transient->isTransient());
|
|
|
|
|
|
|
|
// The transient should be above the parent.
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{parent, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create a window that doesn't have any relationship to the parent or the transient.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> anotherSurface = Test::createSurface();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(anotherSurface);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> anotherShellSurface(Test::createXdgToplevelSurface(anotherSurface.get()));
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(anotherShellSurface);
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *anotherWindow = Test::renderAndWaitForShown(anotherSurface.get(), QSize(128, 128), Qt::green);
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(anotherWindow);
|
|
|
|
QVERIFY(anotherWindow->isActive());
|
|
|
|
QVERIFY(!anotherWindow->isTransient());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// The newly created surface has to be above both the parent and the transient.
|
2022-04-23 19:51:16 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{parent, transient, anotherWindow}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// If we activate the parent, the transient should be raised too.
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(parent);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(parent->isActive());
|
|
|
|
QTRY_VERIFY(!transient->isActive());
|
2022-04-23 19:51:16 +00:00
|
|
|
QTRY_VERIFY(!anotherWindow->isActive());
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{anotherWindow, parent, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Go back to the initial setup.
|
2022-04-23 19:51:16 +00:00
|
|
|
workspace()->activateWindow(anotherWindow);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(!parent->isActive());
|
|
|
|
QTRY_VERIFY(!transient->isActive());
|
2022-04-23 19:51:16 +00:00
|
|
|
QTRY_VERIFY(anotherWindow->isActive());
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{parent, transient, anotherWindow}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// If we activate the transient, the parent should be raised too.
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(transient);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(!parent->isActive());
|
|
|
|
QTRY_VERIFY(transient->isActive());
|
2022-04-23 19:51:16 +00:00
|
|
|
QTRY_VERIFY(!anotherWindow->isActive());
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{anotherWindow, parent, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
}
|
|
|
|
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
struct WindowUnrefDeleter
|
|
|
|
{
|
2023-03-02 21:08:15 +00:00
|
|
|
void operator()(Window *d)
|
2022-03-23 10:13:38 +00:00
|
|
|
{
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
if (d != nullptr) {
|
2023-03-02 20:51:46 +00:00
|
|
|
d->unref();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
void StackingOrderTest::testDeletedTransient()
|
|
|
|
{
|
|
|
|
// This test verifies that deleted transients are kept above their
|
|
|
|
// old parents.
|
|
|
|
|
|
|
|
// Create the parent.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> parentSurface = Test::createSurface();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(parentSurface);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> parentShellSurface(Test::createXdgToplevelSurface(parentSurface.get()));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(parentShellSurface);
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *parent = Test::renderAndWaitForShown(parentSurface.get(), QSize(256, 256), Qt::blue);
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(parent);
|
|
|
|
QVERIFY(parent->isActive());
|
|
|
|
QVERIFY(!parent->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{parent}));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
// Create the first transient.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> transient1Surface = Test::createSurface();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(transient1Surface);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> transient1ShellSurface(Test::createXdgToplevelSurface(transient1Surface.get()));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(transient1ShellSurface);
|
2021-05-11 05:26:51 +00:00
|
|
|
transient1ShellSurface->set_parent(parentShellSurface->object());
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *transient1 = Test::renderAndWaitForShown(transient1Surface.get(), QSize(128, 128), Qt::red);
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(transient1);
|
|
|
|
QTRY_VERIFY(transient1->isActive());
|
|
|
|
QVERIFY(transient1->isTransient());
|
|
|
|
QCOMPARE(transient1->transientFor(), parent);
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{parent, transient1}));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
// Create the second transient.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> transient2Surface = Test::createSurface();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(transient2Surface);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> transient2ShellSurface(Test::createXdgToplevelSurface(transient2Surface.get()));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(transient2ShellSurface);
|
2021-05-11 05:26:51 +00:00
|
|
|
transient2ShellSurface->set_parent(transient1ShellSurface->object());
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *transient2 = Test::renderAndWaitForShown(transient2Surface.get(), QSize(128, 128), Qt::red);
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(transient2);
|
|
|
|
QTRY_VERIFY(transient2->isActive());
|
|
|
|
QVERIFY(transient2->isTransient());
|
|
|
|
QCOMPARE(transient2->transientFor(), transient1);
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{parent, transient1, transient2}));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
// Activate the parent, both transients have to be above it.
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(parent);
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QTRY_VERIFY(parent->isActive());
|
|
|
|
QTRY_VERIFY(!transient1->isActive());
|
|
|
|
QTRY_VERIFY(!transient2->isActive());
|
|
|
|
|
|
|
|
// Close the top-most transient.
|
Drop Deleted
Currently, the normal window lifecycle looks as follows: create Window,
wait until it's shown, add it to Workspace, wait until it's closed,
create a Deleted, copy properties from the original window to the
deleted one, destroy the original window, wait until the last deleted
window reference is dropped.
There are a couple of issues with this design: we can't nicely
encapsulate X11 or Wayland specific implementation details if they need
to be accessed for closed windows; manual copying of properties is
cumbersome and error prone and we've had a dozen of cases where effects
worked incorrectly because some properties had not been copied.
The goal of this patch is to drop Deleted and extend the lifetime of the
original window, but with a special state set: Window::isDeleted().
The main danger is that somebody can try to do something with deleted
windows that they should not do, but on the other hand, such code needs
to be guarded with relevant checks too.
2023-03-14 09:45:18 +00:00
|
|
|
connect(transient2, &Window::closed, transient2, &Window::ref);
|
|
|
|
auto cleanup = qScopeGuard([transient2]() {
|
|
|
|
transient2->unref();
|
2022-04-28 07:44:11 +00:00
|
|
|
});
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
2023-03-13 19:21:11 +00:00
|
|
|
QSignalSpy windowClosedSpy(transient2, &Window::closed);
|
2023-11-21 22:21:34 +00:00
|
|
|
transient2ShellSurface.reset();
|
2022-08-16 11:43:33 +00:00
|
|
|
transient2Surface.reset();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(windowClosedSpy.wait());
|
|
|
|
|
|
|
|
// The deleted transient still has to be above its old parent (transient1).
|
|
|
|
QTRY_VERIFY(parent->isActive());
|
|
|
|
QTRY_VERIFY(!transient1->isActive());
|
Drop Deleted
Currently, the normal window lifecycle looks as follows: create Window,
wait until it's shown, add it to Workspace, wait until it's closed,
create a Deleted, copy properties from the original window to the
deleted one, destroy the original window, wait until the last deleted
window reference is dropped.
There are a couple of issues with this design: we can't nicely
encapsulate X11 or Wayland specific implementation details if they need
to be accessed for closed windows; manual copying of properties is
cumbersome and error prone and we've had a dozen of cases where effects
worked incorrectly because some properties had not been copied.
The goal of this patch is to drop Deleted and extend the lifetime of the
original window, but with a special state set: Window::isDeleted().
The main danger is that somebody can try to do something with deleted
windows that they should not do, but on the other hand, such code needs
to be guarded with relevant checks too.
2023-03-14 09:45:18 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{parent, transient1, transient2}));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
}
|
|
|
|
|
2018-10-02 05:39:31 +00:00
|
|
|
static xcb_window_t createGroupWindow(xcb_connection_t *conn,
|
|
|
|
const QRect &geometry,
|
|
|
|
xcb_window_t leaderWid = XCB_WINDOW_NONE)
|
|
|
|
{
|
|
|
|
xcb_window_t wid = xcb_generate_id(conn);
|
|
|
|
xcb_create_window(
|
2022-03-23 10:13:38 +00:00
|
|
|
conn, // c
|
|
|
|
XCB_COPY_FROM_PARENT, // depth
|
|
|
|
wid, // wid
|
|
|
|
rootWindow(), // parent
|
|
|
|
geometry.x(), // x
|
|
|
|
geometry.y(), // y
|
|
|
|
geometry.width(), // width
|
|
|
|
geometry.height(), // height
|
|
|
|
0, // border_width
|
2018-10-02 05:39:31 +00:00
|
|
|
XCB_WINDOW_CLASS_INPUT_OUTPUT, // _class
|
2022-03-23 10:13:38 +00:00
|
|
|
XCB_COPY_FROM_PARENT, // visual
|
|
|
|
0, // value_mask
|
|
|
|
nullptr // value_list
|
2018-10-02 05:39:31 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
xcb_size_hints_t sizeHints = {};
|
|
|
|
xcb_icccm_size_hints_set_position(&sizeHints, 1, geometry.x(), geometry.y());
|
|
|
|
xcb_icccm_size_hints_set_size(&sizeHints, 1, geometry.width(), geometry.height());
|
|
|
|
xcb_icccm_set_wm_normal_hints(conn, wid, &sizeHints);
|
|
|
|
|
|
|
|
if (leaderWid == XCB_WINDOW_NONE) {
|
|
|
|
leaderWid = wid;
|
|
|
|
}
|
|
|
|
|
|
|
|
xcb_change_property(
|
2022-03-23 10:13:38 +00:00
|
|
|
conn, // c
|
|
|
|
XCB_PROP_MODE_REPLACE, // mode
|
|
|
|
wid, // window
|
2018-10-02 05:39:31 +00:00
|
|
|
atoms->wm_client_leader, // property
|
2022-03-23 10:13:38 +00:00
|
|
|
XCB_ATOM_WINDOW, // type
|
|
|
|
32, // format
|
|
|
|
1, // data_len
|
|
|
|
&leaderWid // data
|
2018-10-02 05:39:31 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
return wid;
|
|
|
|
}
|
|
|
|
|
|
|
|
void StackingOrderTest::testGroupTransientIsAboveWindowGroup()
|
|
|
|
{
|
|
|
|
// This test verifies that group transients are always above other
|
|
|
|
// window group members.
|
|
|
|
|
|
|
|
const QRect geometry = QRect(0, 0, 128, 128);
|
|
|
|
|
2023-02-03 13:29:21 +00:00
|
|
|
Test::XcbConnectionPtr conn = Test::createX11Connection();
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create the group leader.
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t leaderWid = createGroupWindow(conn.get(), geometry);
|
|
|
|
xcb_map_window(conn.get(), leaderWid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *leader = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(leader);
|
|
|
|
QVERIFY(leader->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(leader->window(), leaderWid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(!leader->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create another group member.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t member1Wid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_map_window(conn.get(), member1Wid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *member1 = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(member1);
|
|
|
|
QVERIFY(member1->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(member1->window(), member1Wid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QCOMPARE(member1->group(), leader->group());
|
|
|
|
QVERIFY(!member1->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create yet another group member.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t member2Wid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_map_window(conn.get(), member2Wid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *member2 = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(member2);
|
|
|
|
QVERIFY(member2->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(member2->window(), member2Wid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QCOMPARE(member2->group(), leader->group());
|
|
|
|
QVERIFY(!member2->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create a group transient.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t transientWid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_icccm_set_wm_transient_for(conn.get(), transientWid, rootWindow());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Currently, we have some weird bug workaround: if a group transient
|
|
|
|
// is a non-modal dialog, then it won't be kept above its window group.
|
|
|
|
// We need to explicitly specify window type, otherwise the window type
|
|
|
|
// will be deduced to _NET_WM_WINDOW_TYPE_DIALOG because we set transient
|
|
|
|
// for before (the EWMH spec says to do that).
|
|
|
|
xcb_atom_t net_wm_window_type = Xcb::Atom(
|
2022-08-01 21:29:02 +00:00
|
|
|
QByteArrayLiteral("_NET_WM_WINDOW_TYPE"), false, conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
xcb_atom_t net_wm_window_type_normal = Xcb::Atom(
|
2022-08-01 21:29:02 +00:00
|
|
|
QByteArrayLiteral("_NET_WM_WINDOW_TYPE_NORMAL"), false, conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
xcb_change_property(
|
2022-08-01 21:29:02 +00:00
|
|
|
conn.get(), // c
|
2022-03-23 10:13:38 +00:00
|
|
|
XCB_PROP_MODE_REPLACE, // mode
|
|
|
|
transientWid, // window
|
|
|
|
net_wm_window_type, // property
|
|
|
|
XCB_ATOM_ATOM, // type
|
|
|
|
32, // format
|
|
|
|
1, // data_len
|
2018-10-02 05:39:31 +00:00
|
|
|
&net_wm_window_type_normal // data
|
|
|
|
);
|
|
|
|
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_map_window(conn.get(), transientWid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *transient = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(transient);
|
|
|
|
QVERIFY(transient->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(transient->window(), transientWid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QCOMPARE(transient->group(), leader->group());
|
|
|
|
QVERIFY(transient->isTransient());
|
|
|
|
QVERIFY(transient->groupTransient());
|
|
|
|
QVERIFY(!transient->isDialog()); // See above why
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// If we activate any member of the window group, the transient will be above it.
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(leader);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(leader->isActive());
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{member1, member2, leader, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(member1);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(member1->isActive());
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{member2, leader, member1, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(member2);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(member2->isActive());
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(transient);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(transient->isActive());
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void StackingOrderTest::testRaiseGroupTransient()
|
|
|
|
{
|
|
|
|
const QRect geometry = QRect(0, 0, 128, 128);
|
|
|
|
|
2023-02-03 13:29:21 +00:00
|
|
|
Test::XcbConnectionPtr conn = Test::createX11Connection();
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create the group leader.
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t leaderWid = createGroupWindow(conn.get(), geometry);
|
|
|
|
xcb_map_window(conn.get(), leaderWid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *leader = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(leader);
|
|
|
|
QVERIFY(leader->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(leader->window(), leaderWid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(!leader->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create another group member.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t member1Wid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_map_window(conn.get(), member1Wid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *member1 = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(member1);
|
|
|
|
QVERIFY(member1->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(member1->window(), member1Wid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QCOMPARE(member1->group(), leader->group());
|
|
|
|
QVERIFY(!member1->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create yet another group member.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t member2Wid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_map_window(conn.get(), member2Wid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *member2 = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(member2);
|
|
|
|
QVERIFY(member2->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(member2->window(), member2Wid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QCOMPARE(member2->group(), leader->group());
|
|
|
|
QVERIFY(!member2->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create a group transient.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t transientWid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_icccm_set_wm_transient_for(conn.get(), transientWid, rootWindow());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Currently, we have some weird bug workaround: if a group transient
|
|
|
|
// is a non-modal dialog, then it won't be kept above its window group.
|
|
|
|
// We need to explicitly specify window type, otherwise the window type
|
|
|
|
// will be deduced to _NET_WM_WINDOW_TYPE_DIALOG because we set transient
|
|
|
|
// for before (the EWMH spec says to do that).
|
|
|
|
xcb_atom_t net_wm_window_type = Xcb::Atom(
|
2022-08-01 21:29:02 +00:00
|
|
|
QByteArrayLiteral("_NET_WM_WINDOW_TYPE"), false, conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
xcb_atom_t net_wm_window_type_normal = Xcb::Atom(
|
2022-08-01 21:29:02 +00:00
|
|
|
QByteArrayLiteral("_NET_WM_WINDOW_TYPE_NORMAL"), false, conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
xcb_change_property(
|
2022-08-01 21:29:02 +00:00
|
|
|
conn.get(), // c
|
2022-03-23 10:13:38 +00:00
|
|
|
XCB_PROP_MODE_REPLACE, // mode
|
|
|
|
transientWid, // window
|
|
|
|
net_wm_window_type, // property
|
|
|
|
XCB_ATOM_ATOM, // type
|
|
|
|
32, // format
|
|
|
|
1, // data_len
|
2018-10-02 05:39:31 +00:00
|
|
|
&net_wm_window_type_normal // data
|
|
|
|
);
|
|
|
|
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_map_window(conn.get(), transientWid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *transient = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(transient);
|
|
|
|
QVERIFY(transient->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(transient->window(), transientWid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QCOMPARE(transient->group(), leader->group());
|
|
|
|
QVERIFY(transient->isTransient());
|
|
|
|
QVERIFY(transient->groupTransient());
|
|
|
|
QVERIFY(!transient->isDialog()); // See above why
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 19:51:16 +00:00
|
|
|
// Create a Wayland window that is not a member of the window group.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> anotherSurface = Test::createSurface();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(anotherSurface);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> anotherShellSurface(Test::createXdgToplevelSurface(anotherSurface.get()));
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(anotherShellSurface);
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *anotherWindow = Test::renderAndWaitForShown(anotherSurface.get(), QSize(128, 128), Qt::green);
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(anotherWindow);
|
|
|
|
QVERIFY(anotherWindow->isActive());
|
|
|
|
QVERIFY(!anotherWindow->isTransient());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 19:51:16 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2, transient, anotherWindow}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// If we activate the leader, then only it and the transient have to be raised.
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(leader);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(leader->isActive());
|
2022-04-23 19:51:16 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{member1, member2, anotherWindow, leader, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// If another member of the window group is activated, then the transient will
|
|
|
|
// be above that member and the leader.
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(member2);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(member2->isActive());
|
2022-04-23 19:51:16 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{member1, anotherWindow, leader, member2, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// FIXME: If we activate the transient, only it will be raised.
|
2022-04-23 19:51:16 +00:00
|
|
|
workspace()->activateWindow(anotherWindow);
|
|
|
|
QTRY_VERIFY(anotherWindow->isActive());
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{member1, leader, member2, transient, anotherWindow}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(transient);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(transient->isActive());
|
2022-04-23 19:51:16 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{member1, leader, member2, anotherWindow, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
}
|
|
|
|
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
void StackingOrderTest::testDeletedGroupTransient()
|
|
|
|
{
|
|
|
|
// This test verifies that deleted group transients are kept above their
|
|
|
|
// old window groups.
|
|
|
|
|
|
|
|
const QRect geometry = QRect(0, 0, 128, 128);
|
|
|
|
|
2023-02-03 13:29:21 +00:00
|
|
|
Test::XcbConnectionPtr conn = Test::createX11Connection();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
// Create the group leader.
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t leaderWid = createGroupWindow(conn.get(), geometry);
|
|
|
|
xcb_map_window(conn.get(), leaderWid);
|
|
|
|
xcb_flush(conn.get());
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *leader = windowCreatedSpy.first().first().value<X11Window *>();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(leader);
|
|
|
|
QVERIFY(leader->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(leader->window(), leaderWid);
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(!leader->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader}));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
// Create another group member.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t member1Wid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_map_window(conn.get(), member1Wid);
|
|
|
|
xcb_flush(conn.get());
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *member1 = windowCreatedSpy.first().first().value<X11Window *>();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(member1);
|
|
|
|
QVERIFY(member1->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(member1->window(), member1Wid);
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QCOMPARE(member1->group(), leader->group());
|
|
|
|
QVERIFY(!member1->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1}));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
// Create yet another group member.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t member2Wid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_map_window(conn.get(), member2Wid);
|
|
|
|
xcb_flush(conn.get());
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *member2 = windowCreatedSpy.first().first().value<X11Window *>();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(member2);
|
|
|
|
QVERIFY(member2->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(member2->window(), member2Wid);
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QCOMPARE(member2->group(), leader->group());
|
|
|
|
QVERIFY(!member2->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2}));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
// Create a group transient.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t transientWid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_icccm_set_wm_transient_for(conn.get(), transientWid, rootWindow());
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
// Currently, we have some weird bug workaround: if a group transient
|
|
|
|
// is a non-modal dialog, then it won't be kept above its window group.
|
|
|
|
// We need to explicitly specify window type, otherwise the window type
|
|
|
|
// will be deduced to _NET_WM_WINDOW_TYPE_DIALOG because we set transient
|
|
|
|
// for before (the EWMH spec says to do that).
|
|
|
|
xcb_atom_t net_wm_window_type = Xcb::Atom(
|
2022-08-01 21:29:02 +00:00
|
|
|
QByteArrayLiteral("_NET_WM_WINDOW_TYPE"), false, conn.get());
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
xcb_atom_t net_wm_window_type_normal = Xcb::Atom(
|
2022-08-01 21:29:02 +00:00
|
|
|
QByteArrayLiteral("_NET_WM_WINDOW_TYPE_NORMAL"), false, conn.get());
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
xcb_change_property(
|
2022-08-01 21:29:02 +00:00
|
|
|
conn.get(), // c
|
2022-03-23 10:13:38 +00:00
|
|
|
XCB_PROP_MODE_REPLACE, // mode
|
|
|
|
transientWid, // window
|
|
|
|
net_wm_window_type, // property
|
|
|
|
XCB_ATOM_ATOM, // type
|
|
|
|
32, // format
|
|
|
|
1, // data_len
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
&net_wm_window_type_normal // data
|
|
|
|
);
|
|
|
|
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_map_window(conn.get(), transientWid);
|
|
|
|
xcb_flush(conn.get());
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *transient = windowCreatedSpy.first().first().value<X11Window *>();
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(transient);
|
|
|
|
QVERIFY(transient->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(transient->window(), transientWid);
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QCOMPARE(transient->group(), leader->group());
|
|
|
|
QVERIFY(transient->isTransient());
|
|
|
|
QVERIFY(transient->groupTransient());
|
|
|
|
QVERIFY(!transient->isDialog()); // See above why
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2, transient}));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
|
|
|
// Unmap the transient.
|
Drop Deleted
Currently, the normal window lifecycle looks as follows: create Window,
wait until it's shown, add it to Workspace, wait until it's closed,
create a Deleted, copy properties from the original window to the
deleted one, destroy the original window, wait until the last deleted
window reference is dropped.
There are a couple of issues with this design: we can't nicely
encapsulate X11 or Wayland specific implementation details if they need
to be accessed for closed windows; manual copying of properties is
cumbersome and error prone and we've had a dozen of cases where effects
worked incorrectly because some properties had not been copied.
The goal of this patch is to drop Deleted and extend the lifetime of the
original window, but with a special state set: Window::isDeleted().
The main danger is that somebody can try to do something with deleted
windows that they should not do, but on the other hand, such code needs
to be guarded with relevant checks too.
2023-03-14 09:45:18 +00:00
|
|
|
connect(transient, &Window::closed, transient, &Window::ref);
|
|
|
|
auto cleanup = qScopeGuard([transient]() {
|
|
|
|
transient->unref();
|
2022-04-28 07:44:11 +00:00
|
|
|
});
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
|
2023-03-13 19:21:11 +00:00
|
|
|
QSignalSpy windowClosedSpy(transient, &X11Window::closed);
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_unmap_window(conn.get(), transientWid);
|
|
|
|
xcb_flush(conn.get());
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
QVERIFY(windowClosedSpy.wait());
|
|
|
|
|
|
|
|
// The transient has to be above each member of the window group.
|
Drop Deleted
Currently, the normal window lifecycle looks as follows: create Window,
wait until it's shown, add it to Workspace, wait until it's closed,
create a Deleted, copy properties from the original window to the
deleted one, destroy the original window, wait until the last deleted
window reference is dropped.
There are a couple of issues with this design: we can't nicely
encapsulate X11 or Wayland specific implementation details if they need
to be accessed for closed windows; manual copying of properties is
cumbersome and error prone and we've had a dozen of cases where effects
worked incorrectly because some properties had not been copied.
The goal of this patch is to drop Deleted and extend the lifetime of the
original window, but with a special state set: Window::isDeleted().
The main danger is that somebody can try to do something with deleted
windows that they should not do, but on the other hand, such code needs
to be guarded with relevant checks too.
2023-03-14 09:45:18 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2, transient}));
|
Keep Deleted transients above old parents
Summary:
If a modal window is closed, usually, it will go behind its parent. The
reason for this is that Workspace::constrainedStackingOrder() puts only
AbstractClient transients above parents, not Deleted transients.
So, if fade/glide/scale effect animates the disappearing of a transient,
unfortunately, one can't see that animation.
BUG: 397448
FIXED-IN: 5.15.0
Test Plan:
=== Closing of a transient and parent window
Before:
https://www.youtube.com/watch?v=XiLq7EAVCp0
After:
https://www.youtube.com/watch?v=cH_Ki-sqY8M
=== Scale effect
Before:
https://www.youtube.com/watch?v=Eb2a3U7R10I
After:
https://www.youtube.com/watch?v=4AKu3fdrnYQ
=== Sheet effect
Before:
https://www.youtube.com/watch?v=xPPSnR5FUU0
After:
https://www.youtube.com/watch?v=o_hxTNT-5Hg
=== Popup menus on Wayland
Before:
https://www.youtube.com/watch?v=5DnrY8p3F5A
After:
https://www.youtube.com/watch?v=7XEo8n_CrCc
Reviewers: #kwin, davidedmundson
Reviewed By: #kwin, davidedmundson
Subscribers: abetts, davidedmundson, kwin
Tags: #kwin
Differential Revision: https://phabricator.kde.org/D14868
2018-10-15 13:04:05 +00:00
|
|
|
}
|
|
|
|
|
2018-10-02 05:39:31 +00:00
|
|
|
void StackingOrderTest::testDontKeepAboveNonModalDialogGroupTransients()
|
|
|
|
{
|
|
|
|
// Bug 76026
|
|
|
|
|
|
|
|
const QRect geometry = QRect(0, 0, 128, 128);
|
|
|
|
|
2023-02-03 13:29:21 +00:00
|
|
|
Test::XcbConnectionPtr conn = Test::createX11Connection();
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
QSignalSpy windowCreatedSpy(workspace(), &Workspace::windowAdded);
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create the group leader.
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t leaderWid = createGroupWindow(conn.get(), geometry);
|
|
|
|
xcb_map_window(conn.get(), leaderWid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *leader = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(leader);
|
|
|
|
QVERIFY(leader->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(leader->window(), leaderWid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(!leader->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create another group member.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t member1Wid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_map_window(conn.get(), member1Wid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *member1 = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(member1);
|
|
|
|
QVERIFY(member1->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(member1->window(), member1Wid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QCOMPARE(member1->group(), leader->group());
|
|
|
|
QVERIFY(!member1->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create yet another group member.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t member2Wid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_map_window(conn.get(), member2Wid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *member2 = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(member2);
|
|
|
|
QVERIFY(member2->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(member2->window(), member2Wid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QCOMPARE(member2->group(), leader->group());
|
|
|
|
QVERIFY(!member2->isTransient());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
// Create a group transient.
|
|
|
|
windowCreatedSpy.clear();
|
2022-08-01 21:29:02 +00:00
|
|
|
xcb_window_t transientWid = createGroupWindow(conn.get(), geometry, leaderWid);
|
|
|
|
xcb_icccm_set_wm_transient_for(conn.get(), transientWid, rootWindow());
|
|
|
|
xcb_map_window(conn.get(), transientWid);
|
|
|
|
xcb_flush(conn.get());
|
2018-10-02 05:39:31 +00:00
|
|
|
|
|
|
|
QVERIFY(windowCreatedSpy.wait());
|
2022-04-22 17:54:31 +00:00
|
|
|
X11Window *transient = windowCreatedSpy.first().first().value<X11Window *>();
|
2018-10-02 05:39:31 +00:00
|
|
|
QVERIFY(transient);
|
|
|
|
QVERIFY(transient->isActive());
|
2020-11-04 15:49:10 +00:00
|
|
|
QCOMPARE(transient->window(), transientWid);
|
2018-10-02 05:39:31 +00:00
|
|
|
QCOMPARE(transient->group(), leader->group());
|
|
|
|
QVERIFY(transient->isTransient());
|
|
|
|
QVERIFY(transient->groupTransient());
|
|
|
|
QVERIFY(transient->isDialog());
|
|
|
|
QVERIFY(!transient->isModal());
|
|
|
|
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(leader);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(leader->isActive());
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{member1, member2, transient, leader}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(member1);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(member1->isActive());
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{member2, transient, leader, member1}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(member2);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(member2->isActive());
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{transient, leader, member1, member2}));
|
2018-10-02 05:39:31 +00:00
|
|
|
|
2022-04-23 08:33:23 +00:00
|
|
|
workspace()->activateWindow(transient);
|
2018-10-02 05:39:31 +00:00
|
|
|
QTRY_VERIFY(transient->isActive());
|
2022-04-22 17:39:12 +00:00
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{leader, member1, member2, transient}));
|
2018-10-02 05:39:31 +00:00
|
|
|
}
|
|
|
|
|
2018-10-16 16:19:17 +00:00
|
|
|
void StackingOrderTest::testKeepAbove()
|
|
|
|
{
|
|
|
|
// This test verifies that "keep-above" windows are kept above other windows.
|
|
|
|
|
2022-04-23 19:51:16 +00:00
|
|
|
// Create the first window.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> surface1 = Test::createSurface();
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(surface1);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(shellSurface1);
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(128, 128), Qt::green);
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(window1);
|
|
|
|
QVERIFY(window1->isActive());
|
|
|
|
QVERIFY(!window1->keepAbove());
|
|
|
|
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{window1}));
|
|
|
|
|
|
|
|
// Create the second window.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> surface2 = Test::createSurface();
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(surface2);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(shellSurface2);
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(128, 128), Qt::green);
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(window2);
|
|
|
|
QVERIFY(window2->isActive());
|
|
|
|
QVERIFY(!window2->keepAbove());
|
|
|
|
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{window1, window2}));
|
2018-10-16 16:19:17 +00:00
|
|
|
|
|
|
|
// Go to the initial test position.
|
2022-04-23 19:51:16 +00:00
|
|
|
workspace()->activateWindow(window1);
|
|
|
|
QTRY_VERIFY(window1->isActive());
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{window2, window1}));
|
2018-10-16 16:19:17 +00:00
|
|
|
|
2022-04-23 19:51:16 +00:00
|
|
|
// Set the "keep-above" flag on the window2, it should go above other windows.
|
2018-10-16 16:19:17 +00:00
|
|
|
{
|
|
|
|
StackingUpdatesBlocker blocker(workspace());
|
2022-04-23 19:51:16 +00:00
|
|
|
window2->setKeepAbove(true);
|
2018-10-16 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(window2->keepAbove());
|
|
|
|
QVERIFY(!window2->isActive());
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{window1, window2}));
|
2018-10-16 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void StackingOrderTest::testKeepBelow()
|
|
|
|
{
|
|
|
|
// This test verifies that "keep-below" windows are kept below other windows.
|
|
|
|
|
2022-04-23 19:51:16 +00:00
|
|
|
// Create the first window.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> surface1 = Test::createSurface();
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(surface1);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> shellSurface1(Test::createXdgToplevelSurface(surface1.get()));
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(shellSurface1);
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *window1 = Test::renderAndWaitForShown(surface1.get(), QSize(128, 128), Qt::green);
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(window1);
|
|
|
|
QVERIFY(window1->isActive());
|
|
|
|
QVERIFY(!window1->keepBelow());
|
|
|
|
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{window1}));
|
|
|
|
|
|
|
|
// Create the second window.
|
2022-08-16 11:43:33 +00:00
|
|
|
std::unique_ptr<KWayland::Client::Surface> surface2 = Test::createSurface();
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(surface2);
|
2024-03-10 14:32:54 +00:00
|
|
|
std::unique_ptr<Test::XdgToplevel> shellSurface2(Test::createXdgToplevelSurface(surface2.get()));
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(shellSurface2);
|
2022-08-16 11:43:33 +00:00
|
|
|
Window *window2 = Test::renderAndWaitForShown(surface2.get(), QSize(128, 128), Qt::green);
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(window2);
|
|
|
|
QVERIFY(window2->isActive());
|
|
|
|
QVERIFY(!window2->keepBelow());
|
|
|
|
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{window1, window2}));
|
|
|
|
|
|
|
|
// Set the "keep-below" flag on the window2, it should go below other windows.
|
2018-10-16 16:19:17 +00:00
|
|
|
{
|
|
|
|
StackingUpdatesBlocker blocker(workspace());
|
2022-04-23 19:51:16 +00:00
|
|
|
window2->setKeepBelow(true);
|
2018-10-16 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
2022-04-23 19:51:16 +00:00
|
|
|
QVERIFY(window2->isActive());
|
|
|
|
QVERIFY(window2->keepBelow());
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{window2, window1}));
|
2018-10-16 16:19:17 +00:00
|
|
|
}
|
|
|
|
|
2023-11-16 01:53:17 +00:00
|
|
|
void StackingOrderTest::testPreserveRelativeWindowStacking()
|
|
|
|
{
|
|
|
|
// This test verifies that raising a window doesn't affect the order of transient windows that are constrained
|
|
|
|
// to be above it, see BUG: 477262
|
|
|
|
|
|
|
|
const int windowsQuantity = 5;
|
|
|
|
|
|
|
|
std::unique_ptr<KWayland::Client::Surface> surfaces[windowsQuantity];
|
|
|
|
std::unique_ptr<Test::XdgToplevel> shellSurfaces[windowsQuantity];
|
|
|
|
Window *windows[windowsQuantity];
|
|
|
|
|
|
|
|
// Create 5 windows.
|
|
|
|
for (int i = 0; i < windowsQuantity; i++) {
|
|
|
|
surfaces[i] = Test::createSurface();
|
|
|
|
QVERIFY(surfaces[i]);
|
2024-03-10 14:32:54 +00:00
|
|
|
shellSurfaces[i] = Test::createXdgToplevelSurface(surfaces[i].get());
|
2023-11-16 01:53:17 +00:00
|
|
|
QVERIFY(shellSurfaces[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// link them into the following hierarchy:
|
|
|
|
// * 0 - parent to all
|
|
|
|
// * 1, 2, 3 - children of 0
|
|
|
|
// * 4 - child of 3
|
|
|
|
shellSurfaces[1]->set_parent(shellSurfaces[0]->object());
|
|
|
|
shellSurfaces[2]->set_parent(shellSurfaces[0]->object());
|
|
|
|
shellSurfaces[3]->set_parent(shellSurfaces[0]->object());
|
|
|
|
shellSurfaces[4]->set_parent(shellSurfaces[3]->object());
|
|
|
|
|
|
|
|
for (int i = 0; i < windowsQuantity; i++) {
|
|
|
|
windows[i] = Test::renderAndWaitForShown(surfaces[i].get(), QSize(128, 128), Qt::green);
|
|
|
|
QVERIFY(windows[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
// verify initial windows order
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{windows[0], windows[1], windows[2], windows[3], windows[4]}));
|
|
|
|
|
|
|
|
// activate parent
|
|
|
|
workspace()->activateWindow(windows[0]);
|
|
|
|
// verify that order hasn't changed
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{windows[0], windows[1], windows[2], windows[3], windows[4]}));
|
|
|
|
|
|
|
|
// change stacking order
|
|
|
|
workspace()->activateWindow(windows[2]);
|
|
|
|
workspace()->activateWindow(windows[1]);
|
|
|
|
// verify order
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{windows[0], windows[3], windows[4], windows[2], windows[1]}));
|
|
|
|
|
|
|
|
// activate parent
|
|
|
|
workspace()->activateWindow(windows[0]);
|
|
|
|
// verify that order hasn't changed
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{windows[0], windows[3], windows[4], windows[2], windows[1]}));
|
|
|
|
|
|
|
|
// activate child 3
|
|
|
|
workspace()->activateWindow(windows[3]);
|
|
|
|
// verify that both child 3 and 4 have been raised
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{windows[0], windows[2], windows[1], windows[3], windows[4]}));
|
|
|
|
|
|
|
|
// activate parent
|
|
|
|
workspace()->activateWindow(windows[0]);
|
|
|
|
// verify that order hasn't changed
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{windows[0], windows[2], windows[1], windows[3], windows[4]}));
|
|
|
|
|
|
|
|
// yet another check - add KeepAbove attribute to parent window (see BUG: 477262)
|
|
|
|
windows[0]->setKeepAbove(true);
|
|
|
|
// verify that order hasn't changed
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{windows[0], windows[2], windows[1], windows[3], windows[4]}));
|
|
|
|
// verify that child windows can still be restacked freely
|
|
|
|
workspace()->activateWindow(windows[1]);
|
|
|
|
workspace()->activateWindow(windows[2]);
|
|
|
|
QCOMPARE(workspace()->stackingOrder(), (QList<Window *>{windows[0], windows[3], windows[4], windows[1], windows[2]}));
|
|
|
|
}
|
|
|
|
|
2018-10-02 05:39:31 +00:00
|
|
|
WAYLANDTEST_MAIN(StackingOrderTest)
|
|
|
|
#include "stacking_order_test.moc"
|