[wayland] Shadow gains support for a Wayland protocol
For Wayland clients we now are able to get shadows. Internally this reuses large parts of the X11 implementation. This could be improved to make the Scene's better aware of the Wayland shadow, so that less memory is needed.
This commit is contained in:
parent
3beff66aca
commit
df1146bfa6
4 changed files with 96 additions and 0 deletions
78
shadow.cpp
78
shadow.cpp
|
@ -24,10 +24,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include "composite.h"
|
||||
#include "effects.h"
|
||||
#include "toplevel.h"
|
||||
#if HAVE_WAYLAND
|
||||
#include "wayland_server.h"
|
||||
#endif
|
||||
|
||||
#include <KDecoration2/Decoration>
|
||||
#include <KDecoration2/DecorationShadow>
|
||||
|
||||
#if HAVE_WAYLAND
|
||||
#include <KWayland/Server/buffer_interface.h>
|
||||
#include <KWayland/Server/shadow_interface.h>
|
||||
#include <KWayland/Server/surface_interface.h>
|
||||
#endif
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
|
@ -49,6 +58,11 @@ Shadow *Shadow::createShadow(Toplevel *toplevel)
|
|||
return NULL;
|
||||
}
|
||||
Shadow *shadow = crateShadowFromDecoration(toplevel);
|
||||
#if HAVE_WAYLAND
|
||||
if (!shadow && waylandServer()) {
|
||||
shadow = createShadowFromWayland(toplevel);
|
||||
}
|
||||
#endif
|
||||
if (!shadow) {
|
||||
shadow = createShadowFromX11(toplevel);
|
||||
}
|
||||
|
@ -98,6 +112,26 @@ Shadow *Shadow::crateShadowFromDecoration(Toplevel *toplevel)
|
|||
return shadow;
|
||||
}
|
||||
|
||||
Shadow *Shadow::createShadowFromWayland(Toplevel *toplevel)
|
||||
{
|
||||
#if HAVE_WAYLAND
|
||||
auto surface = toplevel->surface();
|
||||
if (!surface) {
|
||||
return nullptr;
|
||||
}
|
||||
const auto s = surface->shadow();
|
||||
if (!s) {
|
||||
return nullptr;
|
||||
}
|
||||
Shadow *shadow = Compositor::self()->scene()->createShadow(toplevel);
|
||||
if (!shadow->init(s)) {
|
||||
delete shadow;
|
||||
return nullptr;
|
||||
}
|
||||
return shadow;
|
||||
#endif
|
||||
}
|
||||
|
||||
QVector< uint32_t > Shadow::readX11ShadowProperty(xcb_window_t id)
|
||||
{
|
||||
QVector<uint32_t> ret;
|
||||
|
@ -187,6 +221,36 @@ bool Shadow::init(KDecoration2::Decoration *decoration)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Shadow::init(const QPointer< KWayland::Server::ShadowInterface > &shadow)
|
||||
{
|
||||
#if HAVE_WAYLAND
|
||||
if (!shadow) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_shadowElements[ShadowElementTop] = shadow->top() ? QPixmap::fromImage(shadow->top()->data().copy()) : QPixmap();
|
||||
m_shadowElements[ShadowElementTopRight] = shadow->topRight() ? QPixmap::fromImage(shadow->topRight()->data().copy()) : QPixmap();
|
||||
m_shadowElements[ShadowElementRight] = shadow->right() ? QPixmap::fromImage(shadow->right()->data().copy()) : QPixmap();
|
||||
m_shadowElements[ShadowElementBottomRight] = shadow->bottomRight() ? QPixmap::fromImage(shadow->bottomRight()->data().copy()) : QPixmap();
|
||||
m_shadowElements[ShadowElementBottom] = shadow->bottom() ? QPixmap::fromImage(shadow->bottom()->data().copy()) : QPixmap();
|
||||
m_shadowElements[ShadowElementBottomLeft] = shadow->bottomLeft() ? QPixmap::fromImage(shadow->bottomLeft()->data().copy()) : QPixmap();
|
||||
m_shadowElements[ShadowElementLeft] = shadow->left() ? QPixmap::fromImage(shadow->left()->data().copy()) : QPixmap();
|
||||
m_shadowElements[ShadowElementTopLeft] = shadow->topLeft() ? QPixmap::fromImage(shadow->topLeft()->data().copy()) : QPixmap();
|
||||
|
||||
const QMarginsF &p = shadow->offset();
|
||||
m_topOffset = p.top();
|
||||
m_rightOffset = p.right();
|
||||
m_bottomOffset = p.bottom();
|
||||
m_leftOffset = p.left();
|
||||
updateShadowRegion();
|
||||
if (!prepareBackend()) {
|
||||
return false;
|
||||
}
|
||||
buildQuads();
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Shadow::updateShadowRegion()
|
||||
{
|
||||
const QRect top(0, - m_topOffset, m_topLevel->width(), m_topOffset);
|
||||
|
@ -299,6 +363,20 @@ bool Shadow::updateShadow()
|
|||
clear();
|
||||
return false;
|
||||
}
|
||||
#if HAVE_WAYLAND
|
||||
if (waylandServer()) {
|
||||
if (m_topLevel && m_topLevel->surface()) {
|
||||
if (const auto &s = m_topLevel->surface()->shadow()) {
|
||||
if (init(s)) {
|
||||
if (m_topLevel->effectWindow()) {
|
||||
m_topLevel->effectWindow()->buildQuads(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
auto data = Shadow::readX11ShadowProperty(m_topLevel->window());
|
||||
if (data.isEmpty()) {
|
||||
clear();
|
||||
|
|
10
shadow.h
10
shadow.h
|
@ -31,6 +31,14 @@ class Decoration;
|
|||
class DecorationShadow;
|
||||
}
|
||||
|
||||
namespace KWayland
|
||||
{
|
||||
namespace Server
|
||||
{
|
||||
class ShadowInterface;
|
||||
}
|
||||
}
|
||||
|
||||
namespace KWin {
|
||||
|
||||
class Toplevel;
|
||||
|
@ -160,9 +168,11 @@ protected:
|
|||
private:
|
||||
static Shadow *createShadowFromX11(Toplevel *toplevel);
|
||||
static Shadow *crateShadowFromDecoration(Toplevel *toplevel);
|
||||
static Shadow *createShadowFromWayland(Toplevel *toplevel);
|
||||
static QVector<uint32_t> readX11ShadowProperty(xcb_window_t id);
|
||||
bool init(const QVector<uint32_t> &data);
|
||||
bool init(KDecoration2::Decoration *decoration);
|
||||
bool init(const QPointer<KWayland::Server::ShadowInterface> &shadow);
|
||||
Toplevel *m_topLevel;
|
||||
// shadow pixmaps
|
||||
QPixmap m_shadowElements[ShadowElementsCount];
|
||||
|
|
|
@ -31,6 +31,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KWayland/Server/surface_interface.h>
|
||||
#include <KWayland/Server/buffer_interface.h>
|
||||
#include <KWayland/Server/plasmashell_interface.h>
|
||||
#include <KWayland/Server/shadow_interface.h>
|
||||
#include <KWayland/Server/qtsurfaceextension_interface.h>
|
||||
|
||||
#include <KDesktopFile>
|
||||
|
@ -88,6 +89,10 @@ ShellClient::ShellClient(ShellSurfaceInterface *surface)
|
|||
);
|
||||
connect(surface, &ShellSurfaceInterface::windowClassChanged, this, &ShellClient::updateIcon);
|
||||
updateIcon();
|
||||
|
||||
// setup shadow integration
|
||||
getShadow();
|
||||
connect(surface->surface(), &SurfaceInterface::shadowChanged, this, &Toplevel::getShadow);
|
||||
}
|
||||
|
||||
ShellClient::~ShellClient() = default;
|
||||
|
|
|
@ -39,6 +39,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||
#include <KWayland/Server/plasmawindowmanagement_interface.h>
|
||||
#include <KWayland/Server/qtsurfaceextension_interface.h>
|
||||
#include <KWayland/Server/seat_interface.h>
|
||||
#include <KWayland/Server/shadow_interface.h>
|
||||
#include <KWayland/Server/shell_interface.h>
|
||||
|
||||
// Qt
|
||||
|
@ -186,6 +187,8 @@ void WaylandServer::init(const QByteArray &socketName)
|
|||
workspace()->setShowingDesktop(set);
|
||||
}
|
||||
);
|
||||
auto shadowManager = m_display->createShadowManager(m_display);
|
||||
shadowManager->create();
|
||||
}
|
||||
|
||||
void WaylandServer::initWorkspace()
|
||||
|
|
Loading…
Reference in a new issue