kwin/src/wayland/shadow_interface.cpp

350 lines
11 KiB
C++
Raw Normal View History

/*
SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "shadow_interface.h"
#include "clientbuffer.h"
#include "display.h"
#include "surface_interface_p.h"
2020-07-27 18:05:04 +00:00
#include <qwayland-server-shadow.h>
2020-04-29 14:56:38 +00:00
namespace KWaylandServer
{
static const quint32 s_version = 2;
2020-07-27 18:05:04 +00:00
class ShadowManagerInterfacePrivate : public QtWaylandServer::org_kde_kwin_shadow_manager
{
public:
2020-07-27 18:05:04 +00:00
ShadowManagerInterfacePrivate(ShadowManagerInterface *_q, Display *display);
ShadowManagerInterface *q;
Display *display;
2020-07-27 18:05:04 +00:00
protected:
void org_kde_kwin_shadow_manager_create(Resource *resource, uint32_t id, wl_resource *surface) override;
void org_kde_kwin_shadow_manager_unset(Resource *resource, wl_resource *surface) override;
void org_kde_kwin_shadow_manager_destroy(Resource *resource) override;
};
2020-07-27 18:05:04 +00:00
ShadowManagerInterfacePrivate::ShadowManagerInterfacePrivate(ShadowManagerInterface *_q, Display *display)
: QtWaylandServer::org_kde_kwin_shadow_manager(*display, s_version)
, q(_q)
, display(display)
{
}
2020-07-27 18:05:04 +00:00
void ShadowManagerInterfacePrivate::org_kde_kwin_shadow_manager_destroy(Resource *resource)
{
2020-07-27 18:05:04 +00:00
wl_resource_destroy(resource->handle);
}
2020-07-27 18:05:04 +00:00
void ShadowManagerInterfacePrivate::org_kde_kwin_shadow_manager_create(Resource *resource, uint32_t id, wl_resource *surface)
{
2020-07-28 13:30:54 +00:00
SurfaceInterface *s = SurfaceInterface::get(surface);
if (!s) {
2020-07-27 18:05:04 +00:00
wl_resource_post_error(resource->handle, 0, "Invalid surface");
return;
}
2020-07-27 18:05:04 +00:00
wl_resource *shadow_resource = wl_resource_create(resource->client(), &org_kde_kwin_shadow_interface, resource->version(), id);
if (!shadow_resource) {
wl_client_post_no_memory(resource->client());
return;
}
2020-07-27 18:05:04 +00:00
auto shadow = new ShadowInterface(q, shadow_resource);
2020-07-27 18:05:04 +00:00
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(s);
surfacePrivate->setShadow(QPointer<ShadowInterface>(shadow));
}
2020-07-27 18:05:04 +00:00
void ShadowManagerInterfacePrivate::org_kde_kwin_shadow_manager_unset(Resource *resource, wl_resource *surface)
{
Q_UNUSED(resource)
SurfaceInterface *s = SurfaceInterface::get(surface);
if (!s) {
2020-07-27 18:05:04 +00:00
wl_resource_post_error(resource->handle, 0, "Invalid surface");
return;
}
SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(s);
surfacePrivate->setShadow(QPointer<ShadowInterface>());
}
ShadowManagerInterface::ShadowManagerInterface(Display *display, QObject *parent)
2020-07-27 18:05:04 +00:00
: QObject(parent)
, d(new ShadowManagerInterfacePrivate(this, display))
{
}
ShadowManagerInterface::~ShadowManagerInterface() = default;
Display *ShadowManagerInterface::display() const
{
return d->display;
}
2020-07-27 18:05:04 +00:00
class ShadowInterfacePrivate : public QtWaylandServer::org_kde_kwin_shadow
{
public:
2020-07-27 18:05:04 +00:00
ShadowInterfacePrivate(ShadowInterface *_q, wl_resource *resource);
2020-07-28 14:46:06 +00:00
~ShadowInterfacePrivate();
2022-04-19 10:14:26 +00:00
struct State
{
enum Flags {
None = 0,
LeftBuffer = 1 << 0,
TopLeftBuffer = 1 << 1,
TopBuffer = 1 << 2,
TopRightBuffer = 1 << 3,
RightBuffer = 1 << 4,
BottomRightBuffer = 1 << 5,
BottomBuffer = 1 << 6,
BottomLeftBuffer = 1 << 7,
2021-04-29 09:45:00 +00:00
Offset = 1 << 8,
};
QPointer<ClientBuffer> left;
QPointer<ClientBuffer> topLeft;
QPointer<ClientBuffer> top;
QPointer<ClientBuffer> topRight;
QPointer<ClientBuffer> right;
QPointer<ClientBuffer> bottomRight;
QPointer<ClientBuffer> bottom;
QPointer<ClientBuffer> bottomLeft;
QMarginsF offset;
Flags flags = Flags::None;
};
2020-07-28 14:46:06 +00:00
void commit();
void attach(State::Flags flag, wl_resource *buffer);
ShadowManagerInterface *manager;
State current;
State pending;
2020-07-27 18:05:04 +00:00
ShadowInterface *q;
protected:
void org_kde_kwin_shadow_destroy_resource(Resource *resource) override;
void org_kde_kwin_shadow_commit(Resource *resource) override;
void org_kde_kwin_shadow_attach_left(Resource *resource, wl_resource *buffer) override;
void org_kde_kwin_shadow_attach_top_left(Resource *resource, wl_resource *buffer) override;
void org_kde_kwin_shadow_attach_top(Resource *resource, wl_resource *buffer) override;
void org_kde_kwin_shadow_attach_top_right(Resource *resource, wl_resource *buffer) override;
void org_kde_kwin_shadow_attach_right(Resource *resource, wl_resource *buffer) override;
void org_kde_kwin_shadow_attach_bottom_right(Resource *resource, wl_resource *buffer) override;
void org_kde_kwin_shadow_attach_bottom(Resource *resource, wl_resource *buffer) override;
void org_kde_kwin_shadow_attach_bottom_left(Resource *resource, wl_resource *buffer) override;
void org_kde_kwin_shadow_set_left_offset(Resource *resource, wl_fixed_t offset) override;
void org_kde_kwin_shadow_set_top_offset(Resource *resource, wl_fixed_t offset) override;
void org_kde_kwin_shadow_set_right_offset(Resource *resource, wl_fixed_t offset) override;
void org_kde_kwin_shadow_set_bottom_offset(Resource *resource, wl_fixed_t offset) override;
void org_kde_kwin_shadow_destroy(Resource *resource) override;
};
2020-07-27 18:05:04 +00:00
void ShadowInterfacePrivate::org_kde_kwin_shadow_commit(Resource *resource)
{
2020-07-27 18:05:04 +00:00
Q_UNUSED(resource)
2022-04-19 10:14:26 +00:00
#define BUFFER(__FLAG__, __PART__) \
if (pending.flags & State::Flags::__FLAG__##Buffer) { \
if (current.__PART__) { \
current.__PART__->unref(); \
} \
if (pending.__PART__) { \
pending.__PART__->ref(); \
} \
current.__PART__ = pending.__PART__; \
}
BUFFER(Left, left)
BUFFER(TopLeft, topLeft)
BUFFER(Top, top)
BUFFER(TopRight, topRight)
BUFFER(Right, right)
BUFFER(BottomRight, bottomRight)
BUFFER(Bottom, bottom)
BUFFER(BottomLeft, bottomLeft)
#undef BUFFER
if (pending.flags & State::Offset) {
current.offset = pending.offset;
}
pending = State();
}
2020-07-27 18:05:04 +00:00
void ShadowInterfacePrivate::attach(ShadowInterfacePrivate::State::Flags flag, wl_resource *buffer)
{
ClientBuffer *b = manager->display()->clientBufferForResource(buffer);
switch (flag) {
case State::LeftBuffer:
pending.left = b;
break;
case State::TopLeftBuffer:
pending.topLeft = b;
break;
case State::TopBuffer:
pending.top = b;
break;
case State::TopRightBuffer:
pending.topRight = b;
break;
case State::RightBuffer:
pending.right = b;
break;
case State::BottomRightBuffer:
pending.bottomRight = b;
break;
case State::BottomBuffer:
pending.bottom = b;
break;
case State::BottomLeftBuffer:
pending.bottomLeft = b;
break;
default:
Q_UNREACHABLE();
break;
}
pending.flags = State::Flags(pending.flags | flag);
}
2020-07-27 18:05:04 +00:00
void ShadowInterfacePrivate::org_kde_kwin_shadow_destroy(Resource *resource)
{
wl_resource_destroy(resource->handle);
}
2020-07-27 18:05:04 +00:00
void ShadowInterfacePrivate::org_kde_kwin_shadow_destroy_resource(Resource *resource)
{
Q_UNUSED(resource)
delete q;
}
2020-07-27 18:05:04 +00:00
void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_left(Resource *resource, wl_resource *buffer)
{
Q_UNUSED(resource)
attach(State::LeftBuffer, buffer);
}
2020-07-27 18:05:04 +00:00
void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_top_left(Resource *resource, wl_resource *buffer)
{
Q_UNUSED(resource)
attach(State::TopLeftBuffer, buffer);
}
2020-07-27 18:05:04 +00:00
void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_top(Resource *resource, wl_resource *buffer)
{
Q_UNUSED(resource)
attach(State::TopBuffer, buffer);
}
void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_top_right(Resource *resource, wl_resource *buffer)
{
Q_UNUSED(resource)
attach(State::TopRightBuffer, buffer);
}
void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_right(Resource *resource, wl_resource *buffer)
{
Q_UNUSED(resource)
attach(State::RightBuffer, buffer);
}
void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_bottom_right(Resource *resource, wl_resource *buffer)
{
Q_UNUSED(resource)
attach(State::BottomRightBuffer, buffer);
}
void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_bottom(Resource *resource, wl_resource *buffer)
{
Q_UNUSED(resource)
attach(State::BottomBuffer, buffer);
}
void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_bottom_left(Resource *resource, wl_resource *buffer)
{
Q_UNUSED(resource)
attach(State::BottomLeftBuffer, buffer);
}
void ShadowInterfacePrivate::org_kde_kwin_shadow_set_left_offset(Resource *resource, wl_fixed_t offset)
{
Q_UNUSED(resource)
pending.flags = State::Flags(pending.flags | State::Offset);
pending.offset.setLeft(wl_fixed_to_double(offset));
}
void ShadowInterfacePrivate::org_kde_kwin_shadow_set_top_offset(Resource *resource, wl_fixed_t offset)
{
Q_UNUSED(resource)
pending.flags = State::Flags(pending.flags | State::Offset);
pending.offset.setTop(wl_fixed_to_double(offset));
}
void ShadowInterfacePrivate::org_kde_kwin_shadow_set_right_offset(Resource *resource, wl_fixed_t offset)
{
Q_UNUSED(resource)
pending.flags = State::Flags(pending.flags | State::Offset);
pending.offset.setRight(wl_fixed_to_double(offset));
}
2020-07-27 18:05:04 +00:00
void ShadowInterfacePrivate::org_kde_kwin_shadow_set_bottom_offset(Resource *resource, wl_fixed_t offset)
{
Q_UNUSED(resource)
pending.flags = State::Flags(pending.flags | State::Offset);
pending.offset.setBottom(wl_fixed_to_double(offset));
}
2020-07-27 18:05:04 +00:00
ShadowInterfacePrivate::ShadowInterfacePrivate(ShadowInterface *_q, wl_resource *resource)
: QtWaylandServer::org_kde_kwin_shadow(resource)
, q(_q)
{
}
2020-07-27 18:05:04 +00:00
ShadowInterfacePrivate::~ShadowInterfacePrivate()
{
2022-04-19 10:14:26 +00:00
#define CURRENT(__PART__) \
if (current.__PART__) { \
current.__PART__->unref(); \
}
CURRENT(left)
CURRENT(topLeft)
CURRENT(top)
CURRENT(topRight)
CURRENT(right)
CURRENT(bottomRight)
CURRENT(bottom)
CURRENT(bottomLeft)
#undef CURRENT
}
ShadowInterface::ShadowInterface(ShadowManagerInterface *manager, wl_resource *resource)
2020-07-27 18:05:04 +00:00
: QObject()
, d(new ShadowInterfacePrivate(this, resource))
{
d->manager = manager;
}
ShadowInterface::~ShadowInterface() = default;
QMarginsF ShadowInterface::offset() const
{
return d->current.offset;
}
2022-04-19 10:14:26 +00:00
#define BUFFER(__PART__) \
ClientBuffer *ShadowInterface::__PART__() const \
{ \
return d->current.__PART__; \
}
BUFFER(left)
BUFFER(topLeft)
BUFFER(top)
BUFFER(topRight)
BUFFER(right)
BUFFER(bottomRight)
BUFFER(bottom)
BUFFER(bottomLeft)
}