/* SPDX-FileCopyrightText: 2014 Martin Gräßlin SPDX-FileCopyrightText: 2020 Vlad Zahorodnii SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #pragma once #include "output_interface.h" #include #include #include #include #include namespace KWaylandServer { class BlurInterface; class BufferInterface; class ConfinedPointerV1Interface; class ContrastInterface; class CompositorInterface; class LockedPointerV1Interface; class ShadowInterface; class SlideInterface; class SubSurfaceInterface; class SurfaceInterfacePrivate; /** * @brief Resource representing a wl_surface. * * The SurfaceInterface gets created by the CompositorInterface. A SurfaceInterface normally * takes up a role by being "attached" to either a ShellSurfaceInterface, a SubSurfaceInterface * or a Cursor. * * The implementation of the SurfaceInterface does not only wrap the features exposed by wl_surface, * but goes further by integrating the information added to a SurfaceInterface by other interfaces. * This should make interacting from the server easier, it only needs to monitor the SurfaceInterface * and does not need to track each specific interface. * * The SurfaceInterface takes care of reference/unreferencing the BufferInterface attached to it. * As long as a BufferInterface is attached, the released signal won't be sent. If the BufferInterface * is no longer needed by the SurfaceInterface, it will get unreferenced and might be automatically * deleted (if it's no longer referenced). * * @see CompositorInterface * @see BufferInterface * @see SubSurfaceInterface * @see BlurInterface * @see ContrastInterface * @see ShadowInterface * @see SlideInterface */ class KWAYLANDSERVER_EXPORT SurfaceInterface : public QObject { Q_OBJECT /** * The current damage region. */ Q_PROPERTY(QRegion damage READ damage NOTIFY damaged) /** * The opaque region for a translucent buffer. */ Q_PROPERTY(QRegion opaque READ opaque NOTIFY opaqueChanged) /** * The current input region. */ Q_PROPERTY(QRegion input READ input NOTIFY inputChanged) Q_PROPERTY(qint32 bufferScale READ bufferScale NOTIFY bufferScaleChanged) Q_PROPERTY(KWaylandServer::OutputInterface::Transform bufferTransform READ bufferTransform NOTIFY bufferTransformChanged) Q_PROPERTY(QSize size READ size NOTIFY sizeChanged) public: explicit SurfaceInterface(CompositorInterface *compositor, wl_resource *resource); ~SurfaceInterface() override; /** * Returns the object id for this Wayland surface. */ uint32_t id() const; /** * Returns the Wayland client that owns this SurfaceInterface. */ ClientConnection *client() const; /** * Returns the Wayland resource corresponding to this SurfaceInterface. */ wl_resource *resource() const; /** * Returns the compositor for this SurfaceInterface. */ CompositorInterface *compositor() const; /** * Returns a list with all created Wayland surfaces. */ static QList surfaces(); /** * Maps the specified @a point from the surface-local coordinates to buffer pixel coordinates. * * Note that there is no direct connection between points in the surface-local coordinates * and points in the buffer pixel coordinates. In order to map points between the two spaces, * one has to use mapToBuffer() and mapFromBuffer(). * * The returned value will become invalid when the surfaceToBufferMatrixChanged() signal is emitted. * * @see surfaceToBufferMatrix(), surfaceToBufferMatrixChanged() */ QPointF mapToBuffer(const QPointF &point) const; /** * Maps the specified @a point from the buffer pixel coordinates to surface-local coordinates. * * Note that there is no direct connection between points in the surface-local coordinates * and points in the buffer pixel coordinates. In order to map points between the two spaces, * one has to use mapToBuffer() and mapFromBuffer(). * * The returned value will become invalid when the surfaceToBufferMatrixChanged() signal is emitted. * * @see surfaceToBufferMatrix(), surfaceToBufferMatrixChanged() */ QPointF mapFromBuffer(const QPointF &point) const; /** * Maps the specified @a region from the surface-local coordinates to buffer pixel coordinates. * * Note that there is no direct connection between regions in the surface-local coordinates * and regions in the buffer pixel coordinates. In order to map regions between the two spaces, * one has to use mapToBuffer() and mapFromBuffer(). * * The returned value will become invalid when the surfaceToBufferMatrixChanged() signal is emitted. * * @see surfaceToBufferMatrix(), surfaceToBufferMatrixChanged() */ QRegion mapToBuffer(const QRegion ®ion) const; /** * Maps the specified @a region from the buffer pixel coordinates to surface-local coordinates. * * Note that there is no direct connection between regions in the surface-local coordinates * and regions in the buffer pixel coordinates. In order to map regions between the two spaces, * one has to use mapToBuffer() and mapFromBuffer(). * * The returned value will become invalid when the surfaceToBufferMatrixChanged() signal is emitted. * * @see surfaceToBufferMatrix(), surfaceToBufferMatrixChanged() */ QRegion mapFromBuffer(const QRegion ®ion) const; /** * Returns the projection matrix from the surface-local coordinates to buffer coordinates. * * @see surfaceToBufferMatrixChanged() */ QMatrix4x4 surfaceToBufferMatrix() const; /** * Maps the specified @a point in this surface's coordinate system to the equivalent point * within the @a child's coordinate system, and returns the mapped point. * * If this surface is not an ancestor of the @a child, a null point is returned. */ QPointF mapToChild(SurfaceInterface *child, const QPointF &point) const; void frameRendered(quint32 msec); bool hasFrameCallbacks() const; QRegion damage() const; QRegion opaque() const; QRegion input() const; qint32 bufferScale() const; /** * Returns the buffer transform that had been applied to the buffer to compensate for * output rotation. * * If the surface is on an output that is rotated 90 degrees clockwise, the buffer will * be rotated 90 degrees counter clockwise. */ OutputInterface::Transform bufferTransform() const; /** * @returns the current BufferInterface, might be @c nullptr. */ BufferInterface *buffer(); QPoint offset() const; /** * Returns the current size of the surface, in surface coordinates. * * Note that there is no direct relationship between the surface size and the buffer size. * In order to determine the size of the currently attached buffer, use buffer()->size(). */ QSize size() const; /** * Returns the rectangle that bounds this surface and all of its sub-surfaces. * * QPoint(0, 0) corresponds to the upper left corner of this surface. */ QRect boundingRect() const; /** * Returns the size of the attached buffer, in device pixels. * * If no buffer is attached to this surface, an invalid QSize will be returned. */ QSize bufferSize() const; /** * @returns The SubSurface for this Surface in case there is one. */ SubSurfaceInterface *subSurface() const; /** * @returns Children in stacking order from bottom (first) to top (last). */ QList childSubSurfaces() const; /** * @returns The Shadow for this Surface. */ QPointer shadow() const; /** * @returns The Blur for this Surface. */ QPointer blur() const; /** * @returns The Slide for this Surface. */ QPointer slideOnShowHide() const; /** * @returns The Contrast for this Surface. */ QPointer contrast() const; /** * Whether the SurfaceInterface is currently considered to be mapped. * A SurfaceInterface is mapped if it has a non-null BufferInterface attached. * If the SurfaceInterface references a SubSurfaceInterface it is only considered * mapped if it has a BufferInterface attached and the parent SurfaceInterface is mapped. * * @returns Whether the SurfaceInterface is currently mapped */ bool isMapped() const; /** * Returns the tracked damage since the last call to {@link resetTrackedDamage}. * In contrast to {@link damage} this method does not reset the damage when * a new BufferInterface gets committed. This allows a compositor to properly * track the damage over multiple commits even if it didn't render each new * BufferInterface. * * The damage gets reset whenever {@link resetTrackedDamage} is called. * This allows a compositor to properly track the change in its rendering scene * for this SurfaceInterface. After it updates its internal state (e.g. by creating * an OpenGL texture from the BufferInterface) it can invoke {@link resetTrackedDamage} * and the damage tracker will start to track further damage changes. * * @returns Combined damage since last call to resetTrackedDamage * @see damage * @see resetTrackedDamage */ QRegion trackedDamage() const; /** * Reset the damage tracking. The compositor should invoke this method once it updated * it's internal state and processed the current damage. * @see trackedDamage */ void resetTrackedDamage(); /** * Finds the SurfaceInterface at the given @p position in surface-local coordinates. * This can be either a descendant SurfaceInterface honoring the stacking order or * the SurfaceInterface itself if its geometry contains the given @p position. * * If no such SurfaceInterface is found, e.g. because the SurfaceInterface is unmapped, * @c nullptr is returned. * * @param position The position in surface-local coordinates * @returns Child surface at the given @p position or surface itself at the position, might be @c nullptr */ SurfaceInterface *surfaceAt(const QPointF &position); /** * Finds the input receiving SurfaceInterface at the given @p position in surface-local coordinates. * This can be either a descendant SurfaceInterface honoring the stacking order or * the SurfaceInterface itself if its geometry contains the given @p position. * * If no such SurfaceInterface is found, e.g. because the SurfaceInterface is unmapped or there is no * input region containing the position, * @c nullptr is returned. * * @param position The position in surface-local coordinates * @returns Input receiving child surface at the given @p position or surface itself at the position, might be @c nullptr */ SurfaceInterface *inputSurfaceAt(const QPointF &position); /** * Sets the @p outputs this SurfaceInterface overlaps with, may be empty. * * The compositor should update whenever the SurfaceInterface becomes visible on * an OutputInterface by e.g. getting (un)mapped, resized, moved, etc. * * @see outputs */ void setOutputs(const QVector &outputs); /** * @returns All OutputInterfaces the SurfaceInterface is on. * @see setOutputs */ QVector outputs() const; /** * Pointer confinement installed on this SurfaceInterface. * @see pointerConstraintsChanged */ ConfinedPointerV1Interface *confinedPointer() const; /** * Pointer lock installed on this SurfaceInterface. * @see pointerConstraintsChanged */ LockedPointerV1Interface *lockedPointer() const; /** * @returns Whether this SurfaceInterface wants idle to be inhibited on the Output it is shown * @see inhibitsIdleChanged */ bool inhibitsIdle() const; /** * @returns The SurfaceInterface for the @p native resource. */ static SurfaceInterface *get(wl_resource *native); /** * @returns The SurfaceInterface with given @p id for @p client, if it exists, otherwise @c nullptr. */ static SurfaceInterface *get(quint32 id, const ClientConnection *client); /** * Set @p surface as a data proxy for this SurfaceInterface. This enables * the proxy to conduct drags on the surface's client behalf. * * Setting a data proxy is only allowed when the client owning this surface * has not created a data device itself. */ void setDataProxy(SurfaceInterface *surface); /** * Returns the data proxy of this SurfaceInterface or null if there * is none set. */ SurfaceInterface* dataProxy() const; Q_SIGNALS: /** * This signal is emitted when the underlying wl_surface resource is about to be freed. * * The unbound() signal is emitted either when the client that owns the surface has been * destroyed or if the surface has been destroyed due to a destructor request. * * The SurfaceInterface object and the associated wl_surface resource are valid when this * signal is emitted. */ void aboutToBeDestroyed(); /** * This signal is emitted when the projection matrix from the surface-local coordinate space * to the buffer coordinate space has been changed. * * Note that the compositor will most likely need to re-compute the texture coordinates after * the surface-to-buffer matrix has been changed. */ void surfaceToBufferMatrixChanged(); /** * Emitted whenever the SurfaceInterface got damaged. * The signal is only emitted during the commit of state. * A damage means that a new BufferInterface got attached. * * @see buffer * @see damage */ void damaged(const QRegion&); void opaqueChanged(const QRegion&); void inputChanged(const QRegion&); /** * This signal is emitted when the scale of the attached buffer has changed. */ void bufferScaleChanged(qint32); /** * This signal is emitted when the buffer transform has changed. */ void bufferTransformChanged(KWaylandServer::OutputInterface::Transform); /** * This signal is emitted when the size of the attached buffer has changed. */ void bufferSizeChanged(); /** * Emitted when the Surface becomes visible, i.e. a non-null buffer has been attached. */ void mapped(); /** * Emitted when the Surface removes its content */ void unmapped(); /** * This signal is emitted when the surface size has changed. */ void sizeChanged(); void shadowChanged(); void blurChanged(); void slideOnShowHideChanged(); void contrastChanged(); /** * Emitted whenever the tree of sub-surfaces changes in a way which requires a repaint. */ void subSurfaceTreeChanged(); /** * Emitted whenever a new child sub-surface @p subSurface is added. */ void childSubSurfaceAdded(SubSurfaceInterface *subSurface); /** * Emitted whenver the child sub-surface @p subSurface is removed. */ void childSubSurfaceRemoved(SubSurfaceInterface *subSurface); /** * Emitted whenever a pointer constraint get (un)installed on this SurfaceInterface. * * The pointer constraint does not get activated, the compositor needs to activate * the lock/confinement. * * @see confinedPointer * @see lockedPointer */ void pointerConstraintsChanged(); /** * Emitted whenever the SurfaceInterface starts/ends to inhibit idle. * @see inhibitsIdle */ void inhibitsIdleChanged(); /** * Emitted when the Surface has been committed. * * This signal is emitted after all the relevant damage and xyzChanged signals * for this commit are emitted. */ void committed(); private: void handleBufferRemoved(BufferInterface *buffer); QScopedPointer d; friend class SurfaceInterfacePrivate; }; } Q_DECLARE_METATYPE(KWaylandServer::SurfaceInterface*)