File indexing completed on 2024-05-19 16:35:27

0001 /*
0002     SPDX-FileCopyrightText: 2015 Martin Gräßlin <mgraesslin@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #include "shadow_interface.h"
0007 #include "clientbuffer.h"
0008 #include "display.h"
0009 #include "surface_interface_p.h"
0010 
0011 #include <qwayland-server-shadow.h>
0012 
0013 namespace KWaylandServer
0014 {
0015 static const quint32 s_version = 2;
0016 
0017 class ShadowManagerInterfacePrivate : public QtWaylandServer::org_kde_kwin_shadow_manager
0018 {
0019 public:
0020     ShadowManagerInterfacePrivate(ShadowManagerInterface *_q, Display *display);
0021 
0022     ShadowManagerInterface *q;
0023     Display *display;
0024 
0025 protected:
0026     void org_kde_kwin_shadow_manager_create(Resource *resource, uint32_t id, wl_resource *surface) override;
0027     void org_kde_kwin_shadow_manager_unset(Resource *resource, wl_resource *surface) override;
0028     void org_kde_kwin_shadow_manager_destroy(Resource *resource) override;
0029 };
0030 
0031 ShadowManagerInterfacePrivate::ShadowManagerInterfacePrivate(ShadowManagerInterface *_q, Display *display)
0032     : QtWaylandServer::org_kde_kwin_shadow_manager(*display, s_version)
0033     , q(_q)
0034     , display(display)
0035 {
0036 }
0037 
0038 void ShadowManagerInterfacePrivate::org_kde_kwin_shadow_manager_destroy(Resource *resource)
0039 {
0040     wl_resource_destroy(resource->handle);
0041 }
0042 
0043 void ShadowManagerInterfacePrivate::org_kde_kwin_shadow_manager_create(Resource *resource, uint32_t id, wl_resource *surface)
0044 {
0045     SurfaceInterface *s = SurfaceInterface::get(surface);
0046     if (!s) {
0047         wl_resource_post_error(resource->handle, 0, "Invalid  surface");
0048         return;
0049     }
0050 
0051     wl_resource *shadow_resource = wl_resource_create(resource->client(), &org_kde_kwin_shadow_interface, resource->version(), id);
0052     if (!shadow_resource) {
0053         wl_client_post_no_memory(resource->client());
0054         return;
0055     }
0056 
0057     auto shadow = new ShadowInterface(q, shadow_resource);
0058 
0059     SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(s);
0060     surfacePrivate->setShadow(QPointer<ShadowInterface>(shadow));
0061 }
0062 
0063 void ShadowManagerInterfacePrivate::org_kde_kwin_shadow_manager_unset(Resource *resource, wl_resource *surface)
0064 {
0065     SurfaceInterface *s = SurfaceInterface::get(surface);
0066     if (!s) {
0067         wl_resource_post_error(resource->handle, 0, "Invalid  surface");
0068         return;
0069     }
0070     SurfaceInterfacePrivate *surfacePrivate = SurfaceInterfacePrivate::get(s);
0071     surfacePrivate->setShadow(QPointer<ShadowInterface>());
0072 }
0073 
0074 ShadowManagerInterface::ShadowManagerInterface(Display *display, QObject *parent)
0075     : QObject(parent)
0076     , d(new ShadowManagerInterfacePrivate(this, display))
0077 {
0078 }
0079 
0080 ShadowManagerInterface::~ShadowManagerInterface() = default;
0081 
0082 Display *ShadowManagerInterface::display() const
0083 {
0084     return d->display;
0085 }
0086 
0087 class ShadowInterfacePrivate : public QtWaylandServer::org_kde_kwin_shadow
0088 {
0089 public:
0090     ShadowInterfacePrivate(ShadowInterface *_q, wl_resource *resource);
0091     ~ShadowInterfacePrivate();
0092 
0093     struct State
0094     {
0095         enum Flags {
0096             None = 0,
0097             LeftBuffer = 1 << 0,
0098             TopLeftBuffer = 1 << 1,
0099             TopBuffer = 1 << 2,
0100             TopRightBuffer = 1 << 3,
0101             RightBuffer = 1 << 4,
0102             BottomRightBuffer = 1 << 5,
0103             BottomBuffer = 1 << 6,
0104             BottomLeftBuffer = 1 << 7,
0105             Offset = 1 << 8,
0106         };
0107         QPointer<ClientBuffer> left;
0108         QPointer<ClientBuffer> topLeft;
0109         QPointer<ClientBuffer> top;
0110         QPointer<ClientBuffer> topRight;
0111         QPointer<ClientBuffer> right;
0112         QPointer<ClientBuffer> bottomRight;
0113         QPointer<ClientBuffer> bottom;
0114         QPointer<ClientBuffer> bottomLeft;
0115         QMarginsF offset;
0116         Flags flags = Flags::None;
0117     };
0118 
0119     void commit();
0120     void attach(State::Flags flag, wl_resource *buffer);
0121 
0122     ShadowManagerInterface *manager;
0123     State current;
0124     State pending;
0125     ShadowInterface *q;
0126 
0127 protected:
0128     void org_kde_kwin_shadow_destroy_resource(Resource *resource) override;
0129     void org_kde_kwin_shadow_commit(Resource *resource) override;
0130     void org_kde_kwin_shadow_attach_left(Resource *resource, wl_resource *buffer) override;
0131     void org_kde_kwin_shadow_attach_top_left(Resource *resource, wl_resource *buffer) override;
0132     void org_kde_kwin_shadow_attach_top(Resource *resource, wl_resource *buffer) override;
0133     void org_kde_kwin_shadow_attach_top_right(Resource *resource, wl_resource *buffer) override;
0134     void org_kde_kwin_shadow_attach_right(Resource *resource, wl_resource *buffer) override;
0135     void org_kde_kwin_shadow_attach_bottom_right(Resource *resource, wl_resource *buffer) override;
0136     void org_kde_kwin_shadow_attach_bottom(Resource *resource, wl_resource *buffer) override;
0137     void org_kde_kwin_shadow_attach_bottom_left(Resource *resource, wl_resource *buffer) override;
0138     void org_kde_kwin_shadow_set_left_offset(Resource *resource, wl_fixed_t offset) override;
0139     void org_kde_kwin_shadow_set_top_offset(Resource *resource, wl_fixed_t offset) override;
0140     void org_kde_kwin_shadow_set_right_offset(Resource *resource, wl_fixed_t offset) override;
0141     void org_kde_kwin_shadow_set_bottom_offset(Resource *resource, wl_fixed_t offset) override;
0142     void org_kde_kwin_shadow_destroy(Resource *resource) override;
0143 };
0144 
0145 void ShadowInterfacePrivate::org_kde_kwin_shadow_commit(Resource *resource)
0146 {
0147 #define BUFFER(__FLAG__, __PART__)                        \
0148     if (pending.flags & State::Flags::__FLAG__##Buffer) { \
0149         if (current.__PART__) {                           \
0150             current.__PART__->unref();                    \
0151         }                                                 \
0152         if (pending.__PART__) {                           \
0153             pending.__PART__->ref();                      \
0154         }                                                 \
0155         current.__PART__ = pending.__PART__;              \
0156     }
0157     BUFFER(Left, left)
0158     BUFFER(TopLeft, topLeft)
0159     BUFFER(Top, top)
0160     BUFFER(TopRight, topRight)
0161     BUFFER(Right, right)
0162     BUFFER(BottomRight, bottomRight)
0163     BUFFER(Bottom, bottom)
0164     BUFFER(BottomLeft, bottomLeft)
0165 #undef BUFFER
0166 
0167     if (pending.flags & State::Offset) {
0168         current.offset = pending.offset;
0169     }
0170     pending = State();
0171 }
0172 
0173 void ShadowInterfacePrivate::attach(ShadowInterfacePrivate::State::Flags flag, wl_resource *buffer)
0174 {
0175     ClientBuffer *b = manager->display()->clientBufferForResource(buffer);
0176     switch (flag) {
0177     case State::LeftBuffer:
0178         pending.left = b;
0179         break;
0180     case State::TopLeftBuffer:
0181         pending.topLeft = b;
0182         break;
0183     case State::TopBuffer:
0184         pending.top = b;
0185         break;
0186     case State::TopRightBuffer:
0187         pending.topRight = b;
0188         break;
0189     case State::RightBuffer:
0190         pending.right = b;
0191         break;
0192     case State::BottomRightBuffer:
0193         pending.bottomRight = b;
0194         break;
0195     case State::BottomBuffer:
0196         pending.bottom = b;
0197         break;
0198     case State::BottomLeftBuffer:
0199         pending.bottomLeft = b;
0200         break;
0201     default:
0202         Q_UNREACHABLE();
0203         break;
0204     }
0205     pending.flags = State::Flags(pending.flags | flag);
0206 }
0207 
0208 void ShadowInterfacePrivate::org_kde_kwin_shadow_destroy(Resource *resource)
0209 {
0210     wl_resource_destroy(resource->handle);
0211 }
0212 
0213 void ShadowInterfacePrivate::org_kde_kwin_shadow_destroy_resource(Resource *resource)
0214 {
0215     delete q;
0216 }
0217 
0218 void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_left(Resource *resource, wl_resource *buffer)
0219 {
0220     attach(State::LeftBuffer, buffer);
0221 }
0222 
0223 void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_top_left(Resource *resource, wl_resource *buffer)
0224 {
0225     attach(State::TopLeftBuffer, buffer);
0226 }
0227 
0228 void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_top(Resource *resource, wl_resource *buffer)
0229 {
0230     attach(State::TopBuffer, buffer);
0231 }
0232 
0233 void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_top_right(Resource *resource, wl_resource *buffer)
0234 {
0235     attach(State::TopRightBuffer, buffer);
0236 }
0237 
0238 void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_right(Resource *resource, wl_resource *buffer)
0239 {
0240     attach(State::RightBuffer, buffer);
0241 }
0242 
0243 void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_bottom_right(Resource *resource, wl_resource *buffer)
0244 {
0245     attach(State::BottomRightBuffer, buffer);
0246 }
0247 
0248 void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_bottom(Resource *resource, wl_resource *buffer)
0249 {
0250     attach(State::BottomBuffer, buffer);
0251 }
0252 
0253 void ShadowInterfacePrivate::org_kde_kwin_shadow_attach_bottom_left(Resource *resource, wl_resource *buffer)
0254 {
0255     attach(State::BottomLeftBuffer, buffer);
0256 }
0257 
0258 void ShadowInterfacePrivate::org_kde_kwin_shadow_set_left_offset(Resource *resource, wl_fixed_t offset)
0259 {
0260     pending.flags = State::Flags(pending.flags | State::Offset);
0261     pending.offset.setLeft(wl_fixed_to_double(offset));
0262 }
0263 
0264 void ShadowInterfacePrivate::org_kde_kwin_shadow_set_top_offset(Resource *resource, wl_fixed_t offset)
0265 {
0266     pending.flags = State::Flags(pending.flags | State::Offset);
0267     pending.offset.setTop(wl_fixed_to_double(offset));
0268 }
0269 
0270 void ShadowInterfacePrivate::org_kde_kwin_shadow_set_right_offset(Resource *resource, wl_fixed_t offset)
0271 {
0272     pending.flags = State::Flags(pending.flags | State::Offset);
0273     pending.offset.setRight(wl_fixed_to_double(offset));
0274 }
0275 
0276 void ShadowInterfacePrivate::org_kde_kwin_shadow_set_bottom_offset(Resource *resource, wl_fixed_t offset)
0277 {
0278     pending.flags = State::Flags(pending.flags | State::Offset);
0279     pending.offset.setBottom(wl_fixed_to_double(offset));
0280 }
0281 
0282 ShadowInterfacePrivate::ShadowInterfacePrivate(ShadowInterface *_q, wl_resource *resource)
0283     : QtWaylandServer::org_kde_kwin_shadow(resource)
0284     , q(_q)
0285 {
0286 }
0287 
0288 ShadowInterfacePrivate::~ShadowInterfacePrivate()
0289 {
0290 #define CURRENT(__PART__)          \
0291     if (current.__PART__) {        \
0292         current.__PART__->unref(); \
0293     }
0294     CURRENT(left)
0295     CURRENT(topLeft)
0296     CURRENT(top)
0297     CURRENT(topRight)
0298     CURRENT(right)
0299     CURRENT(bottomRight)
0300     CURRENT(bottom)
0301     CURRENT(bottomLeft)
0302 #undef CURRENT
0303 }
0304 
0305 ShadowInterface::ShadowInterface(ShadowManagerInterface *manager, wl_resource *resource)
0306     : QObject()
0307     , d(new ShadowInterfacePrivate(this, resource))
0308 {
0309     d->manager = manager;
0310 }
0311 
0312 ShadowInterface::~ShadowInterface() = default;
0313 
0314 QMarginsF ShadowInterface::offset() const
0315 {
0316     return d->current.offset;
0317 }
0318 
0319 #define BUFFER(__PART__)                            \
0320     ClientBuffer *ShadowInterface::__PART__() const \
0321     {                                               \
0322         return d->current.__PART__;                 \
0323     }
0324 
0325 BUFFER(left)
0326 BUFFER(topLeft)
0327 BUFFER(top)
0328 BUFFER(topRight)
0329 BUFFER(right)
0330 BUFFER(bottomRight)
0331 BUFFER(bottom)
0332 BUFFER(bottomLeft)
0333 
0334 }