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 &region)
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 &region)
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"