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"