2021-02-04 09:07:20 +00:00
|
|
|
/*
|
|
|
|
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
|
|
|
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "surfaceitem_wayland.h"
|
2021-04-09 07:06:04 +00:00
|
|
|
#include "composite.h"
|
|
|
|
#include "scene.h"
|
2021-02-04 09:07:20 +00:00
|
|
|
|
2021-07-20 19:37:03 +00:00
|
|
|
#include <KWaylandServer/clientbuffer.h>
|
2021-02-04 09:07:20 +00:00
|
|
|
#include <KWaylandServer/subcompositor_interface.h>
|
|
|
|
#include <KWaylandServer/surface_interface.h>
|
|
|
|
|
|
|
|
namespace KWin
|
|
|
|
{
|
|
|
|
|
|
|
|
SurfaceItemWayland::SurfaceItemWayland(KWaylandServer::SurfaceInterface *surface,
|
|
|
|
Scene::Window *window, Item *parent)
|
|
|
|
: SurfaceItem(window, parent)
|
|
|
|
, m_surface(surface)
|
|
|
|
{
|
|
|
|
connect(surface, &KWaylandServer::SurfaceInterface::surfaceToBufferMatrixChanged,
|
2021-07-21 19:25:42 +00:00
|
|
|
this, &SurfaceItemWayland::handleSurfaceToBufferMatrixChanged);
|
2021-02-04 09:07:20 +00:00
|
|
|
|
|
|
|
connect(surface, &KWaylandServer::SurfaceInterface::sizeChanged,
|
|
|
|
this, &SurfaceItemWayland::handleSurfaceSizeChanged);
|
|
|
|
connect(surface, &KWaylandServer::SurfaceInterface::bufferSizeChanged,
|
|
|
|
this, &SurfaceItemWayland::discardPixmap);
|
|
|
|
|
|
|
|
connect(surface, &KWaylandServer::SurfaceInterface::childSubSurfacesChanged,
|
|
|
|
this, &SurfaceItemWayland::handleChildSubSurfacesChanged);
|
|
|
|
connect(surface, &KWaylandServer::SurfaceInterface::committed,
|
|
|
|
this, &SurfaceItemWayland::handleSurfaceCommitted);
|
|
|
|
connect(surface, &KWaylandServer::SurfaceInterface::damaged,
|
|
|
|
this, &SurfaceItemWayland::addDamage);
|
|
|
|
connect(surface, &KWaylandServer::SurfaceInterface::childSubSurfaceRemoved,
|
|
|
|
this, &SurfaceItemWayland::handleChildSubSurfaceRemoved);
|
|
|
|
|
|
|
|
KWaylandServer::SubSurfaceInterface *subsurface = surface->subSurface();
|
|
|
|
if (subsurface) {
|
|
|
|
connect(subsurface, &KWaylandServer::SubSurfaceInterface::positionChanged,
|
|
|
|
this, &SurfaceItemWayland::handleSubSurfacePositionChanged);
|
|
|
|
setPosition(subsurface->position());
|
|
|
|
}
|
|
|
|
|
2021-06-19 14:01:12 +00:00
|
|
|
handleChildSubSurfacesChanged();
|
2021-02-04 09:07:20 +00:00
|
|
|
setSize(surface->size());
|
2021-07-21 19:25:42 +00:00
|
|
|
setSurfaceToBufferMatrix(surface->surfaceToBufferMatrix());
|
2021-02-04 09:07:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QRegion SurfaceItemWayland::shape() const
|
|
|
|
{
|
2021-07-05 17:40:47 +00:00
|
|
|
return QRegion(rect());
|
2021-02-04 09:07:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QRegion SurfaceItemWayland::opaque() const
|
|
|
|
{
|
|
|
|
if (m_surface) {
|
|
|
|
return m_surface->opaque();
|
|
|
|
}
|
|
|
|
return QRegion();
|
|
|
|
}
|
|
|
|
|
|
|
|
KWaylandServer::SurfaceInterface *SurfaceItemWayland::surface() const
|
|
|
|
{
|
|
|
|
return m_surface;
|
|
|
|
}
|
|
|
|
|
2021-07-21 19:25:42 +00:00
|
|
|
void SurfaceItemWayland::handleSurfaceToBufferMatrixChanged()
|
|
|
|
{
|
|
|
|
setSurfaceToBufferMatrix(m_surface->surfaceToBufferMatrix());
|
|
|
|
discardQuads();
|
|
|
|
discardPixmap();
|
|
|
|
}
|
|
|
|
|
2021-02-04 09:07:20 +00:00
|
|
|
void SurfaceItemWayland::handleSurfaceSizeChanged()
|
|
|
|
{
|
|
|
|
setSize(m_surface->size());
|
|
|
|
}
|
|
|
|
|
|
|
|
void SurfaceItemWayland::handleSurfaceCommitted()
|
|
|
|
{
|
|
|
|
if (m_surface->hasFrameCallbacks()) {
|
2021-05-19 06:35:42 +00:00
|
|
|
scheduleFrame();
|
2021-02-04 09:07:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-19 14:01:12 +00:00
|
|
|
SurfaceItemWayland *SurfaceItemWayland::getOrCreateSubSurfaceItem(KWaylandServer::SubSurfaceInterface *child)
|
2021-02-04 09:07:20 +00:00
|
|
|
{
|
2021-06-19 14:01:12 +00:00
|
|
|
SurfaceItemWayland *&item = m_subsurfaces[child];
|
|
|
|
if (!item) {
|
|
|
|
item = new SurfaceItemWayland(child->surface(), window());
|
|
|
|
item->setParent(this);
|
|
|
|
item->setParentItem(this);
|
|
|
|
}
|
|
|
|
return item;
|
2021-02-04 09:07:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void SurfaceItemWayland::handleChildSubSurfaceRemoved(KWaylandServer::SubSurfaceInterface *child)
|
|
|
|
{
|
|
|
|
delete m_subsurfaces.take(child);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SurfaceItemWayland::handleChildSubSurfacesChanged()
|
|
|
|
{
|
2021-06-19 12:59:07 +00:00
|
|
|
const QList<KWaylandServer::SubSurfaceInterface *> below = m_surface->below();
|
|
|
|
const QList<KWaylandServer::SubSurfaceInterface *> above = m_surface->above();
|
|
|
|
|
2021-06-19 14:01:12 +00:00
|
|
|
for (int i = 0; i < below.count(); ++i) {
|
|
|
|
SurfaceItemWayland *subsurfaceItem = getOrCreateSubSurfaceItem(below[i]);
|
|
|
|
subsurfaceItem->setZ(i - below.count());
|
2021-06-19 12:59:07 +00:00
|
|
|
}
|
2021-07-20 19:37:03 +00:00
|
|
|
|
2021-06-19 14:01:12 +00:00
|
|
|
for (int i = 0; i < above.count(); ++i) {
|
|
|
|
SurfaceItemWayland *subsurfaceItem = getOrCreateSubSurfaceItem(above[i]);
|
|
|
|
subsurfaceItem->setZ(i);
|
2021-02-04 09:07:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SurfaceItemWayland::handleSubSurfacePositionChanged()
|
|
|
|
{
|
|
|
|
setPosition(m_surface->subSurface()->position());
|
|
|
|
}
|
|
|
|
|
2021-04-09 07:06:04 +00:00
|
|
|
SurfacePixmap *SurfaceItemWayland::createPixmap()
|
2021-02-04 09:07:20 +00:00
|
|
|
{
|
2021-04-09 07:06:04 +00:00
|
|
|
return new SurfacePixmapWayland(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
SurfacePixmapWayland::SurfacePixmapWayland(SurfaceItemWayland *item, QObject *parent)
|
|
|
|
: SurfacePixmap(Compositor::self()->scene()->createPlatformSurfaceTextureWayland(this), parent)
|
|
|
|
, m_item(item)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
SurfacePixmapWayland::~SurfacePixmapWayland()
|
|
|
|
{
|
|
|
|
setBuffer(nullptr);
|
|
|
|
}
|
|
|
|
|
2021-07-21 19:25:42 +00:00
|
|
|
SurfaceItemWayland *SurfacePixmapWayland::item() const
|
|
|
|
{
|
|
|
|
return m_item;
|
|
|
|
}
|
|
|
|
|
2021-04-09 07:06:04 +00:00
|
|
|
KWaylandServer::SurfaceInterface *SurfacePixmapWayland::surface() const
|
|
|
|
{
|
|
|
|
return m_item->surface();
|
|
|
|
}
|
|
|
|
|
2021-07-20 19:37:03 +00:00
|
|
|
KWaylandServer::ClientBuffer *SurfacePixmapWayland::buffer() const
|
2021-04-09 07:06:04 +00:00
|
|
|
{
|
|
|
|
return m_buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void SurfacePixmapWayland::create()
|
|
|
|
{
|
|
|
|
update();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SurfacePixmapWayland::update()
|
|
|
|
{
|
|
|
|
KWaylandServer::SurfaceInterface *surface = m_item->surface();
|
|
|
|
if (surface) {
|
|
|
|
setBuffer(surface->buffer());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool SurfacePixmapWayland::isValid() const
|
|
|
|
{
|
2021-07-20 19:37:03 +00:00
|
|
|
return m_buffer;
|
2021-04-09 07:06:04 +00:00
|
|
|
}
|
|
|
|
|
2021-07-20 19:37:03 +00:00
|
|
|
void SurfacePixmapWayland::setBuffer(KWaylandServer::ClientBuffer *buffer)
|
2021-04-09 07:06:04 +00:00
|
|
|
{
|
|
|
|
if (m_buffer == buffer) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (m_buffer) {
|
|
|
|
m_buffer->unref();
|
|
|
|
}
|
|
|
|
m_buffer = buffer;
|
|
|
|
if (m_buffer) {
|
|
|
|
m_buffer->ref();
|
|
|
|
m_hasAlphaChannel = m_buffer->hasAlphaChannel();
|
|
|
|
}
|
2021-02-04 09:07:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SurfaceItemXwayland::SurfaceItemXwayland(Scene::Window *window, Item *parent)
|
|
|
|
: SurfaceItemWayland(window->window()->surface(), window, parent)
|
|
|
|
{
|
2021-05-26 08:19:09 +00:00
|
|
|
const Toplevel *toplevel = window->window();
|
|
|
|
connect(toplevel, &Toplevel::geometryShapeChanged, this, &SurfaceItemXwayland::discardQuads);
|
2021-02-04 09:07:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QRegion SurfaceItemXwayland::shape() const
|
|
|
|
{
|
|
|
|
const Toplevel *toplevel = window()->window();
|
2021-07-19 06:28:50 +00:00
|
|
|
const QRect clipRect = rect() & toplevel->clientGeometry().translated(-toplevel->bufferGeometry().topLeft());
|
2021-02-04 09:07:20 +00:00
|
|
|
const QRegion shape = toplevel->shapeRegion();
|
|
|
|
|
|
|
|
return shape & clipRect;
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace KWin
|