File indexing completed on 2024-12-22 05:09:24
0001 /* 0002 SPDX-FileCopyrightText: 2014 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 "surface.h" 0007 #include "output.h" 0008 #include "region.h" 0009 #include "surface_p.h" 0010 #include "wayland_pointer_p.h" 0011 0012 #include <QGuiApplication> 0013 #include <QList> 0014 #include <QRegion> 0015 // Wayland 0016 #include <wayland-client-protocol.h> 0017 0018 namespace KWayland 0019 { 0020 namespace Client 0021 { 0022 0023 QList<Surface *> Surface::Private::s_surfaces = QList<Surface *>(); 0024 0025 Surface::Private::Private(Surface *q) 0026 : q(q) 0027 { 0028 } 0029 0030 Surface::Surface(QObject *parent) 0031 : QObject(parent) 0032 , d(new Private(this)) 0033 { 0034 Private::s_surfaces << this; 0035 } 0036 0037 Surface::~Surface() 0038 { 0039 Private::s_surfaces.removeAll(this); 0040 release(); 0041 } 0042 0043 0044 void Surface::release() 0045 { 0046 d->surface.release(); 0047 } 0048 0049 void Surface::destroy() 0050 { 0051 d->surface.destroy(); 0052 } 0053 0054 void Surface::setup(wl_surface *surface) 0055 { 0056 d->setup(surface); 0057 } 0058 0059 void Surface::Private::setup(wl_surface *s) 0060 { 0061 Q_ASSERT(s); 0062 Q_ASSERT(!surface); 0063 surface.setup(s); 0064 wl_surface_add_listener(s, &s_surfaceListener, this); 0065 } 0066 0067 void Surface::Private::frameCallback(void *data, wl_callback *callback, uint32_t time) 0068 { 0069 Q_UNUSED(time) 0070 auto s = reinterpret_cast<Surface::Private *>(data); 0071 if (callback) { 0072 wl_callback_destroy(callback); 0073 } 0074 s->handleFrameCallback(); 0075 } 0076 0077 void Surface::Private::handleFrameCallback() 0078 { 0079 frameCallbackInstalled = false; 0080 Q_EMIT q->frameRendered(); 0081 } 0082 0083 #ifndef K_DOXYGEN 0084 const struct wl_callback_listener Surface::Private::s_listener = {frameCallback}; 0085 0086 const struct wl_surface_listener Surface::Private::s_surfaceListener = {enterCallback, leaveCallback}; 0087 #endif 0088 0089 void Surface::Private::removeOutput(Output *o) 0090 { 0091 if (o && outputs.removeOne(o)) { 0092 Q_EMIT q->outputLeft(o); 0093 } 0094 } 0095 0096 void Surface::Private::enterCallback(void *data, wl_surface *surface, wl_output *output) 0097 { 0098 Q_UNUSED(surface); 0099 auto s = reinterpret_cast<Surface::Private *>(data); 0100 Output *o = Output::get(output); 0101 if (!o) { 0102 return; 0103 } 0104 s->outputs << o; 0105 QObject::connect(o, &Output::removed, s->q, [s, o]() { 0106 s->removeOutput(o); 0107 }); 0108 Q_EMIT s->q->outputEntered(o); 0109 } 0110 0111 void Surface::Private::leaveCallback(void *data, wl_surface *surface, wl_output *output) 0112 { 0113 Q_UNUSED(surface); 0114 auto s = reinterpret_cast<Surface::Private *>(data); 0115 s->removeOutput(Output::get(output)); 0116 } 0117 0118 void Surface::Private::setupFrameCallback() 0119 { 0120 Q_ASSERT(!frameCallbackInstalled); 0121 wl_callback *callback = wl_surface_frame(surface); 0122 wl_callback_add_listener(callback, &s_listener, this); 0123 frameCallbackInstalled = true; 0124 } 0125 0126 void Surface::setupFrameCallback() 0127 { 0128 Q_ASSERT(isValid()); 0129 d->setupFrameCallback(); 0130 } 0131 0132 void Surface::commit(Surface::CommitFlag flag) 0133 { 0134 Q_ASSERT(isValid()); 0135 if (flag == CommitFlag::FrameCallback) { 0136 setupFrameCallback(); 0137 } 0138 wl_surface_commit(d->surface); 0139 } 0140 0141 void Surface::damage(const QRegion ®ion) 0142 { 0143 for (const QRect &rect : region) { 0144 damage(rect); 0145 } 0146 } 0147 0148 void Surface::damage(const QRect &rect) 0149 { 0150 Q_ASSERT(isValid()); 0151 wl_surface_damage(d->surface, rect.x(), rect.y(), rect.width(), rect.height()); 0152 } 0153 0154 void Surface::damageBuffer(const QRegion ®ion) 0155 { 0156 for (const QRect &r : region) { 0157 damageBuffer(r); 0158 } 0159 } 0160 0161 void Surface::damageBuffer(const QRect &rect) 0162 { 0163 Q_ASSERT(isValid()); 0164 wl_surface_damage_buffer(d->surface, rect.x(), rect.y(), rect.width(), rect.height()); 0165 } 0166 0167 void Surface::attachBuffer(wl_buffer *buffer, const QPoint &offset) 0168 { 0169 Q_ASSERT(isValid()); 0170 wl_surface_attach(d->surface, buffer, offset.x(), offset.y()); 0171 } 0172 0173 void Surface::attachBuffer(Buffer *buffer, const QPoint &offset) 0174 { 0175 attachBuffer(buffer ? buffer->buffer() : nullptr, offset); 0176 } 0177 0178 void Surface::attachBuffer(Buffer::Ptr buffer, const QPoint &offset) 0179 { 0180 attachBuffer(buffer.toStrongRef().data(), offset); 0181 } 0182 0183 void Surface::setInputRegion(const Region *region) 0184 { 0185 Q_ASSERT(isValid()); 0186 if (region) { 0187 wl_surface_set_input_region(d->surface, *region); 0188 } else { 0189 wl_surface_set_input_region(d->surface, nullptr); 0190 } 0191 } 0192 0193 void Surface::setOpaqueRegion(const Region *region) 0194 { 0195 Q_ASSERT(isValid()); 0196 if (region) { 0197 wl_surface_set_opaque_region(d->surface, *region); 0198 } else { 0199 wl_surface_set_opaque_region(d->surface, nullptr); 0200 } 0201 } 0202 0203 void Surface::setSize(const QSize &size) 0204 { 0205 if (d->size == size) { 0206 return; 0207 } 0208 d->size = size; 0209 Q_EMIT sizeChanged(d->size); 0210 } 0211 0212 Surface *Surface::get(wl_surface *native) 0213 { 0214 auto it = std::find_if(Private::s_surfaces.constBegin(), Private::s_surfaces.constEnd(), [native](Surface *s) { 0215 return s->d->surface == native; 0216 }); 0217 if (it != Private::s_surfaces.constEnd()) { 0218 return *(it); 0219 } 0220 return nullptr; 0221 } 0222 0223 const QList<Surface *> &Surface::all() 0224 { 0225 return Private::s_surfaces; 0226 } 0227 0228 bool Surface::isValid() const 0229 { 0230 return d->surface.isValid(); 0231 } 0232 0233 QSize Surface::size() const 0234 { 0235 return d->size; 0236 } 0237 0238 Surface::operator wl_surface *() 0239 { 0240 return d->surface; 0241 } 0242 0243 Surface::operator wl_surface *() const 0244 { 0245 return d->surface; 0246 } 0247 0248 quint32 Surface::id() const 0249 { 0250 wl_surface *s = *this; 0251 return wl_proxy_get_id(reinterpret_cast<wl_proxy *>(s)); 0252 } 0253 0254 qint32 Surface::scale() const 0255 { 0256 return d->scale; 0257 } 0258 0259 void Surface::setScale(qint32 scale) 0260 { 0261 d->scale = scale; 0262 wl_surface_set_buffer_scale(d->surface, scale); 0263 } 0264 0265 QList<Output *> Surface::outputs() const 0266 { 0267 return d->outputs; 0268 } 0269 0270 } 0271 } 0272 0273 #include "moc_surface.cpp"