2015-08-26 12:42:58 +00:00
|
|
|
/********************************************************************
|
|
|
|
Copyright 2015 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
Copyright 2015 Marco Martin <mart@kde.org>
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2.1 of the License, or (at your option) version 3, or any
|
|
|
|
later version accepted by the membership of KDE e.V. (or its
|
|
|
|
successor approved by the membership of KDE e.V.), which shall
|
|
|
|
act as a proxy defined in Section 6 of version 3 of the license.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Lesser General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*********************************************************************/
|
|
|
|
#include "blur_interface.h"
|
|
|
|
#include "region_interface.h"
|
|
|
|
#include "display.h"
|
|
|
|
#include "global_p.h"
|
|
|
|
#include "resource_p.h"
|
|
|
|
#include "surface_interface_p.h"
|
|
|
|
|
|
|
|
#include <wayland-server.h>
|
|
|
|
#include <wayland-blur-server-protocol.h>
|
|
|
|
|
|
|
|
namespace KWayland
|
|
|
|
{
|
|
|
|
namespace Server
|
|
|
|
{
|
|
|
|
|
|
|
|
class BlurManagerInterface::Private : public Global::Private
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Private(BlurManagerInterface *q, Display *d);
|
|
|
|
|
|
|
|
private:
|
|
|
|
void bind(wl_client *client, uint32_t version, uint32_t id) override;
|
|
|
|
void createBlur(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface);
|
|
|
|
|
|
|
|
static void createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface);
|
|
|
|
static void unsetCallback(wl_client *client, wl_resource *resource, wl_resource *surface);
|
|
|
|
static void unbind(wl_resource *resource);
|
|
|
|
static Private *cast(wl_resource *r) {
|
Don't crash if a client (legally) uses a deleted global
Summary:
There is a race condition in the following situation:
- Server creates a global
- Client binds to that global (making a new resource for that global)
Simultaneously:
- The client uses this resource
- The server deletes the global
We then process an event for a resource linked to a deleted global.
This is noted in the specification, the client documentation says:
"The object remains valid and requests to the object will be
ignored until the client destroys it, to avoid races between the global
going away and a client sending a request to it. "
KWayland does not handle this at all.
The global's user data refer to our C++ wrapper
The resource's user data refer to *the same* C++ wrapper
When the global is deleted the resource user data now refers to garbage.
To fix the issue, instead of setting the resource userdata to the
global, we set it to a smartpointer to the global stored on the heap.
We can then validate if our global is still valid.
Theoretically this applies to every global
Practically there are only 3 globals that don't have the lifespan of the
server. Output (which is read only and doesn't matter), Blur and
BackgroundContrast.
Blur resets it's global when a screen geometry changes.
Unfotunately this exactly at the same time that Plasmashell is
doing a lot of processing and creating some blurs.
Test Plan: See unit test
Reviewers: #plasma, graesslin
Reviewed By: #plasma, graesslin
Subscribers: graesslin, anthonyfieroni, plasma-devel, #frameworks
Tags: #frameworks, #plasma
Differential Revision: https://phabricator.kde.org/D7870
2017-09-19 12:50:16 +00:00
|
|
|
auto blurManager = reinterpret_cast<QPointer<BlurManagerInterface>*>(wl_resource_get_user_data(r))->data();
|
|
|
|
if (blurManager) {
|
|
|
|
return static_cast<Private*>(blurManager->d.data());
|
|
|
|
}
|
|
|
|
return nullptr;
|
2015-08-26 12:42:58 +00:00
|
|
|
}
|
|
|
|
BlurManagerInterface *q;
|
|
|
|
static const struct org_kde_kwin_blur_manager_interface s_interface;
|
2015-09-10 07:23:36 +00:00
|
|
|
static const quint32 s_version;
|
2015-08-26 12:42:58 +00:00
|
|
|
};
|
|
|
|
|
2015-09-10 07:23:36 +00:00
|
|
|
const quint32 BlurManagerInterface::Private::s_version = 1;
|
|
|
|
|
2020-01-23 11:20:45 +00:00
|
|
|
#ifndef K_DOXYGEN
|
2015-08-26 12:42:58 +00:00
|
|
|
const struct org_kde_kwin_blur_manager_interface BlurManagerInterface::Private::s_interface = {
|
|
|
|
createCallback,
|
|
|
|
unsetCallback
|
|
|
|
};
|
2015-09-09 14:39:50 +00:00
|
|
|
#endif
|
2015-08-26 12:42:58 +00:00
|
|
|
|
|
|
|
BlurManagerInterface::Private::Private(BlurManagerInterface *q, Display *d)
|
|
|
|
: Global::Private(d, &org_kde_kwin_blur_manager_interface, s_version)
|
|
|
|
, q(q)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlurManagerInterface::Private::bind(wl_client *client, uint32_t version, uint32_t id)
|
|
|
|
{
|
|
|
|
auto c = display->getConnection(client);
|
|
|
|
wl_resource *resource = c->createResource(&org_kde_kwin_blur_manager_interface, qMin(version, s_version), id);
|
|
|
|
if (!resource) {
|
|
|
|
wl_client_post_no_memory(client);
|
|
|
|
return;
|
|
|
|
}
|
Don't crash if a client (legally) uses a deleted global
Summary:
There is a race condition in the following situation:
- Server creates a global
- Client binds to that global (making a new resource for that global)
Simultaneously:
- The client uses this resource
- The server deletes the global
We then process an event for a resource linked to a deleted global.
This is noted in the specification, the client documentation says:
"The object remains valid and requests to the object will be
ignored until the client destroys it, to avoid races between the global
going away and a client sending a request to it. "
KWayland does not handle this at all.
The global's user data refer to our C++ wrapper
The resource's user data refer to *the same* C++ wrapper
When the global is deleted the resource user data now refers to garbage.
To fix the issue, instead of setting the resource userdata to the
global, we set it to a smartpointer to the global stored on the heap.
We can then validate if our global is still valid.
Theoretically this applies to every global
Practically there are only 3 globals that don't have the lifespan of the
server. Output (which is read only and doesn't matter), Blur and
BackgroundContrast.
Blur resets it's global when a screen geometry changes.
Unfotunately this exactly at the same time that Plasmashell is
doing a lot of processing and creating some blurs.
Test Plan: See unit test
Reviewers: #plasma, graesslin
Reviewed By: #plasma, graesslin
Subscribers: graesslin, anthonyfieroni, plasma-devel, #frameworks
Tags: #frameworks, #plasma
Differential Revision: https://phabricator.kde.org/D7870
2017-09-19 12:50:16 +00:00
|
|
|
auto ref = new QPointer<BlurManagerInterface>(q);//deleted in unbind
|
|
|
|
wl_resource_set_implementation(resource, &s_interface, ref, unbind);
|
2015-08-26 12:42:58 +00:00
|
|
|
}
|
|
|
|
|
Don't crash if a client (legally) uses a deleted global
Summary:
There is a race condition in the following situation:
- Server creates a global
- Client binds to that global (making a new resource for that global)
Simultaneously:
- The client uses this resource
- The server deletes the global
We then process an event for a resource linked to a deleted global.
This is noted in the specification, the client documentation says:
"The object remains valid and requests to the object will be
ignored until the client destroys it, to avoid races between the global
going away and a client sending a request to it. "
KWayland does not handle this at all.
The global's user data refer to our C++ wrapper
The resource's user data refer to *the same* C++ wrapper
When the global is deleted the resource user data now refers to garbage.
To fix the issue, instead of setting the resource userdata to the
global, we set it to a smartpointer to the global stored on the heap.
We can then validate if our global is still valid.
Theoretically this applies to every global
Practically there are only 3 globals that don't have the lifespan of the
server. Output (which is read only and doesn't matter), Blur and
BackgroundContrast.
Blur resets it's global when a screen geometry changes.
Unfotunately this exactly at the same time that Plasmashell is
doing a lot of processing and creating some blurs.
Test Plan: See unit test
Reviewers: #plasma, graesslin
Reviewed By: #plasma, graesslin
Subscribers: graesslin, anthonyfieroni, plasma-devel, #frameworks
Tags: #frameworks, #plasma
Differential Revision: https://phabricator.kde.org/D7870
2017-09-19 12:50:16 +00:00
|
|
|
void BlurManagerInterface::Private::unbind(wl_resource *r)
|
2015-08-26 12:42:58 +00:00
|
|
|
{
|
Don't crash if a client (legally) uses a deleted global
Summary:
There is a race condition in the following situation:
- Server creates a global
- Client binds to that global (making a new resource for that global)
Simultaneously:
- The client uses this resource
- The server deletes the global
We then process an event for a resource linked to a deleted global.
This is noted in the specification, the client documentation says:
"The object remains valid and requests to the object will be
ignored until the client destroys it, to avoid races between the global
going away and a client sending a request to it. "
KWayland does not handle this at all.
The global's user data refer to our C++ wrapper
The resource's user data refer to *the same* C++ wrapper
When the global is deleted the resource user data now refers to garbage.
To fix the issue, instead of setting the resource userdata to the
global, we set it to a smartpointer to the global stored on the heap.
We can then validate if our global is still valid.
Theoretically this applies to every global
Practically there are only 3 globals that don't have the lifespan of the
server. Output (which is read only and doesn't matter), Blur and
BackgroundContrast.
Blur resets it's global when a screen geometry changes.
Unfotunately this exactly at the same time that Plasmashell is
doing a lot of processing and creating some blurs.
Test Plan: See unit test
Reviewers: #plasma, graesslin
Reviewed By: #plasma, graesslin
Subscribers: graesslin, anthonyfieroni, plasma-devel, #frameworks
Tags: #frameworks, #plasma
Differential Revision: https://phabricator.kde.org/D7870
2017-09-19 12:50:16 +00:00
|
|
|
delete reinterpret_cast<QPointer<BlurManagerInterface>*>(wl_resource_get_user_data(r));
|
2015-08-26 12:42:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BlurManagerInterface::Private::createCallback(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface)
|
|
|
|
{
|
Don't crash if a client (legally) uses a deleted global
Summary:
There is a race condition in the following situation:
- Server creates a global
- Client binds to that global (making a new resource for that global)
Simultaneously:
- The client uses this resource
- The server deletes the global
We then process an event for a resource linked to a deleted global.
This is noted in the specification, the client documentation says:
"The object remains valid and requests to the object will be
ignored until the client destroys it, to avoid races between the global
going away and a client sending a request to it. "
KWayland does not handle this at all.
The global's user data refer to our C++ wrapper
The resource's user data refer to *the same* C++ wrapper
When the global is deleted the resource user data now refers to garbage.
To fix the issue, instead of setting the resource userdata to the
global, we set it to a smartpointer to the global stored on the heap.
We can then validate if our global is still valid.
Theoretically this applies to every global
Practically there are only 3 globals that don't have the lifespan of the
server. Output (which is read only and doesn't matter), Blur and
BackgroundContrast.
Blur resets it's global when a screen geometry changes.
Unfotunately this exactly at the same time that Plasmashell is
doing a lot of processing and creating some blurs.
Test Plan: See unit test
Reviewers: #plasma, graesslin
Reviewed By: #plasma, graesslin
Subscribers: graesslin, anthonyfieroni, plasma-devel, #frameworks
Tags: #frameworks, #plasma
Differential Revision: https://phabricator.kde.org/D7870
2017-09-19 12:50:16 +00:00
|
|
|
auto m = cast(resource);
|
|
|
|
if (!m) {
|
|
|
|
return;// will happen if global is deleted
|
|
|
|
}
|
|
|
|
m->createBlur(client, resource, id, surface);
|
2015-08-26 12:42:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void BlurManagerInterface::Private::createBlur(wl_client *client, wl_resource *resource, uint32_t id, wl_resource *surface)
|
|
|
|
{
|
|
|
|
SurfaceInterface *s = SurfaceInterface::get(surface);
|
|
|
|
if (!s) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlurInterface *blur = new BlurInterface(q, resource);
|
|
|
|
blur->create(display->getConnection(client), wl_resource_get_version(resource), id);
|
|
|
|
if (!blur->resource()) {
|
|
|
|
wl_resource_post_no_memory(resource);
|
|
|
|
delete blur;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
s->d_func()->setBlur(QPointer<BlurInterface>(blur));
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlurManagerInterface::Private::unsetCallback(wl_client *client, wl_resource *resource, wl_resource *surface)
|
|
|
|
{
|
|
|
|
Q_UNUSED(client)
|
|
|
|
Q_UNUSED(resource)
|
|
|
|
SurfaceInterface *s = SurfaceInterface::get(surface);
|
|
|
|
if (!s) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
s->d_func()->setBlur(QPointer<BlurInterface>());
|
|
|
|
}
|
|
|
|
|
|
|
|
BlurManagerInterface::BlurManagerInterface(Display *display, QObject *parent)
|
|
|
|
: Global(new Private(this, display), parent)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BlurManagerInterface::~BlurManagerInterface() = default;
|
|
|
|
|
|
|
|
class BlurInterface::Private : public Resource::Private
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Private(BlurInterface *q, BlurManagerInterface *c, wl_resource *parentResource);
|
|
|
|
~Private();
|
|
|
|
|
|
|
|
QRegion pendingRegion;
|
|
|
|
QRegion currentRegion;
|
|
|
|
|
|
|
|
private:
|
|
|
|
void commit();
|
|
|
|
//TODO
|
|
|
|
BlurInterface *q_func() {
|
|
|
|
return reinterpret_cast<BlurInterface *>(q);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void commitCallback(wl_client *client, wl_resource *resource);
|
|
|
|
static void setRegionCallback(wl_client *client, wl_resource *resource, wl_resource *region);
|
|
|
|
|
|
|
|
static const struct org_kde_kwin_blur_interface s_interface;
|
|
|
|
};
|
|
|
|
|
2020-01-23 11:20:45 +00:00
|
|
|
#ifndef K_DOXYGEN
|
2015-08-26 12:42:58 +00:00
|
|
|
const struct org_kde_kwin_blur_interface BlurInterface::Private::s_interface = {
|
|
|
|
commitCallback,
|
2015-09-09 07:41:25 +00:00
|
|
|
setRegionCallback,
|
2016-05-25 08:04:17 +00:00
|
|
|
resourceDestroyedCallback
|
2015-08-26 12:42:58 +00:00
|
|
|
};
|
2015-09-09 14:39:50 +00:00
|
|
|
#endif
|
2015-08-26 12:42:58 +00:00
|
|
|
|
|
|
|
void BlurInterface::Private::commitCallback(wl_client *client, wl_resource *resource)
|
|
|
|
{
|
|
|
|
Q_UNUSED(client)
|
|
|
|
cast<Private>(resource)->commit();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlurInterface::Private::commit()
|
|
|
|
{
|
|
|
|
currentRegion = pendingRegion;
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlurInterface::Private::setRegionCallback(wl_client *client, wl_resource *resource, wl_resource *region)
|
|
|
|
{
|
|
|
|
Q_UNUSED(client)
|
|
|
|
Private *p = cast<Private>(resource);
|
|
|
|
RegionInterface *r = RegionInterface::get(region);
|
|
|
|
if (r) {
|
|
|
|
p->pendingRegion = r->region();
|
|
|
|
} else {
|
|
|
|
p->pendingRegion = QRegion();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BlurInterface::Private::Private(BlurInterface *q, BlurManagerInterface *c, wl_resource *parentResource)
|
|
|
|
: Resource::Private(q, c, parentResource, &org_kde_kwin_blur_interface, &s_interface)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-05-25 08:33:43 +00:00
|
|
|
BlurInterface::Private::~Private() = default;
|
2015-08-26 12:42:58 +00:00
|
|
|
|
|
|
|
BlurInterface::BlurInterface(BlurManagerInterface *parent, wl_resource *parentResource)
|
|
|
|
: Resource(new Private(this, parent, parentResource))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
BlurInterface::~BlurInterface() = default;
|
|
|
|
|
|
|
|
QRegion BlurInterface::region()
|
|
|
|
{
|
|
|
|
Q_D();
|
|
|
|
return d->currentRegion;
|
|
|
|
}
|
|
|
|
|
|
|
|
BlurInterface::Private *BlurInterface::d_func() const
|
|
|
|
{
|
|
|
|
return reinterpret_cast<Private*>(d.data());
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|