Add a parent_window event to Plasma Window interface

Summary:
This change adds a parent_window event to Plasma Window. From server
side it's possible to specify that a window is a transient for another
window - that is it has a parent window.

On client side this is exposed respectively with a new change signal.

Reviewers: #plasma_on_wayland, hein

Subscribers: plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D1779
This commit is contained in:
Martin Gräßlin 2016-06-06 15:06:33 +02:00
parent 5ae8ac4327
commit d52485ffb7
3 changed files with 99 additions and 1 deletions

View file

@ -64,6 +64,7 @@ private Q_SLOTS:
void testShowingDesktop();
void testRequestShowingDesktop_data();
void testRequestShowingDesktop();
void testParentWindow();
void cleanup();
@ -470,5 +471,43 @@ void TestWindowManagement::testRequestShowingDesktop()
QTEST(requestSpy.first().first().value<PlasmaWindowManagementInterface::ShowingDesktopState>(), "expectedValue");
}
void TestWindowManagement::testParentWindow()
{
using namespace KWayland::Client;
// this test verifies the functionality of ParentWindows
QCOMPARE(m_windowManagement->windows().count(), 1);
auto parentWindow = m_windowManagement->windows().first();
QVERIFY(parentWindow);
QVERIFY(parentWindow->parentWindow().isNull());
// now let's create a second window
QSignalSpy windowAddedSpy(m_windowManagement, &PlasmaWindowManagement::windowCreated);
QVERIFY(windowAddedSpy.isValid());
auto serverTransient = m_windowManagementInterface->createWindow(this);
serverTransient->setParentWindow(m_windowInterface);
QVERIFY(windowAddedSpy.wait());
auto transient = windowAddedSpy.first().first().value<PlasmaWindow*>();
QCOMPARE(transient->parentWindow().data(), parentWindow);
// let's unset the parent
QSignalSpy parentWindowChangedSpy(transient, &PlasmaWindow::parentWindowChanged);
QVERIFY(parentWindowChangedSpy.isValid());
serverTransient->setParentWindow(nullptr);
QVERIFY(parentWindowChangedSpy.wait());
QVERIFY(transient->parentWindow().isNull());
// and set it again
serverTransient->setParentWindow(m_windowInterface);
QVERIFY(parentWindowChangedSpy.wait());
QCOMPARE(transient->parentWindow().data(), parentWindow);
// now let's try to unmap the parent
m_windowInterface->unmap();
m_window = nullptr;
m_windowInterface = nullptr;
QVERIFY(parentWindowChangedSpy.wait());
QVERIFY(transient->parentWindow().isNull());
}
QTEST_GUILESS_MAIN(TestWindowManagement)
#include "test_wayland_windowmanagement.moc"

View file

@ -73,6 +73,8 @@ public:
void setVirtualDesktop(quint32 desktop);
void unmap();
void setState(org_kde_plasma_window_management_state flag, bool set);
void setParentWindow(PlasmaWindowInterface *parent);
wl_resource *resourceForParent(PlasmaWindowInterface *parent, wl_resource *child) const;
QVector<wl_resource*> resources;
quint32 windowId = 0;
@ -80,6 +82,8 @@ public:
PlasmaWindowManagementInterface *wm;
bool unmapped = false;
PlasmaWindowInterface *parentWindow = nullptr;
QMetaObject::Connection parentWindowDestroyConnection;
private:
static void unbind(wl_resource *resource);
@ -105,7 +109,7 @@ private:
static const struct org_kde_plasma_window_interface s_interface;
};
const quint32 PlasmaWindowManagementInterface::Private::s_version = 4;
const quint32 PlasmaWindowManagementInterface::Private::s_version = 5;
PlasmaWindowManagementInterface::Private::Private(PlasmaWindowManagementInterface *q, Display *d)
: Global::Private(d, &org_kde_plasma_window_management_interface, s_version)
@ -321,6 +325,8 @@ void PlasmaWindowInterface::Private::createResource(wl_resource *parent, uint32_
org_kde_plasma_window_send_state_changed(resource, m_state);
org_kde_plasma_window_send_themed_icon_name_changed(resource, m_themedIconName.toUtf8().constData());
org_kde_plasma_window_send_parent_window(resource, resourceForParent(parentWindow, resource));
if (unmapped) {
org_kde_plasma_window_send_unmapped(resource);
}
@ -406,6 +412,46 @@ void PlasmaWindowInterface::Private::setState(org_kde_plasma_window_management_s
}
}
wl_resource *PlasmaWindowInterface::Private::resourceForParent(PlasmaWindowInterface *parent, wl_resource *child) const
{
if (!parent) {
return nullptr;
}
auto it = std::find_if(parent->d->resources.begin(), parent->d->resources.end(),
[child] (wl_resource *parentResource) {
return wl_resource_get_client(child) == wl_resource_get_client(parentResource);
}
);
if (it != parent->d->resources.end()) {
return *it;
}
return nullptr;
}
void PlasmaWindowInterface::Private::setParentWindow(PlasmaWindowInterface *window)
{
if (parentWindow == window) {
return;
}
QObject::disconnect(parentWindowDestroyConnection);
parentWindowDestroyConnection = QMetaObject::Connection();
parentWindow = window;
if (parentWindow) {
parentWindowDestroyConnection = QObject::connect(window, &QObject::destroyed, q,
[this] {
parentWindow = nullptr;
parentWindowDestroyConnection = QMetaObject::Connection();
for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
org_kde_plasma_window_send_parent_window(*it, nullptr);
}
}
);
}
for (auto it = resources.constBegin(); it != resources.constEnd(); ++it) {
org_kde_plasma_window_send_parent_window(*it, resourceForParent(window, *it));
}
}
void PlasmaWindowInterface::Private::closeCallback(wl_client *client, wl_resource *resource)
{
Q_UNUSED(client)
@ -658,5 +704,10 @@ void PlasmaWindowInterface::setVirtualDesktopChangeable(bool set)
d->setState(ORG_KDE_PLASMA_WINDOW_MANAGEMENT_STATE_VIRTUAL_DESKTOP_CHANGEABLE, set);
}
void PlasmaWindowInterface::setParentWindow(PlasmaWindowInterface *parentWindow)
{
d->setParentWindow(parentWindow);
}
}
}

View file

@ -139,6 +139,14 @@ public:
*/
QHash<SurfaceInterface*, QRect> minimizedGeometries() const;
/**
* Sets this PlasmaWindowInterface as a transient window to @p parentWindow.
* If @p parentWindow is @c nullptr, the PlasmaWindowInterface is a toplevel
* window and does not have a parent window.
* @since 5.24
**/
void setParentWindow(PlasmaWindowInterface *parentWindow);
Q_SIGNALS:
void closeRequested();
/**