File indexing completed on 2024-11-10 04:57:33

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