[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:
Martin Gräßlin 2015-07-15 11:24:19 +02:00
parent 3beff66aca
commit df1146bfa6
4 changed files with 96 additions and 0 deletions

View file

@ -24,10 +24,19 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "composite.h" #include "composite.h"
#include "effects.h" #include "effects.h"
#include "toplevel.h" #include "toplevel.h"
#if HAVE_WAYLAND
#include "wayland_server.h"
#endif
#include <KDecoration2/Decoration> #include <KDecoration2/Decoration>
#include <KDecoration2/DecorationShadow> #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 namespace KWin
{ {
@ -49,6 +58,11 @@ Shadow *Shadow::createShadow(Toplevel *toplevel)
return NULL; return NULL;
} }
Shadow *shadow = crateShadowFromDecoration(toplevel); Shadow *shadow = crateShadowFromDecoration(toplevel);
#if HAVE_WAYLAND
if (!shadow && waylandServer()) {
shadow = createShadowFromWayland(toplevel);
}
#endif
if (!shadow) { if (!shadow) {
shadow = createShadowFromX11(toplevel); shadow = createShadowFromX11(toplevel);
} }
@ -98,6 +112,26 @@ Shadow *Shadow::crateShadowFromDecoration(Toplevel *toplevel)
return shadow; 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 > Shadow::readX11ShadowProperty(xcb_window_t id)
{ {
QVector<uint32_t> ret; QVector<uint32_t> ret;
@ -187,6 +221,36 @@ bool Shadow::init(KDecoration2::Decoration *decoration)
return true; 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() void Shadow::updateShadowRegion()
{ {
const QRect top(0, - m_topOffset, m_topLevel->width(), m_topOffset); const QRect top(0, - m_topOffset, m_topLevel->width(), m_topOffset);
@ -299,6 +363,20 @@ bool Shadow::updateShadow()
clear(); clear();
return false; 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()); auto data = Shadow::readX11ShadowProperty(m_topLevel->window());
if (data.isEmpty()) { if (data.isEmpty()) {
clear(); clear();

View file

@ -31,6 +31,14 @@ class Decoration;
class DecorationShadow; class DecorationShadow;
} }
namespace KWayland
{
namespace Server
{
class ShadowInterface;
}
}
namespace KWin { namespace KWin {
class Toplevel; class Toplevel;
@ -160,9 +168,11 @@ protected:
private: private:
static Shadow *createShadowFromX11(Toplevel *toplevel); static Shadow *createShadowFromX11(Toplevel *toplevel);
static Shadow *crateShadowFromDecoration(Toplevel *toplevel); static Shadow *crateShadowFromDecoration(Toplevel *toplevel);
static Shadow *createShadowFromWayland(Toplevel *toplevel);
static QVector<uint32_t> readX11ShadowProperty(xcb_window_t id); static QVector<uint32_t> readX11ShadowProperty(xcb_window_t id);
bool init(const QVector<uint32_t> &data); bool init(const QVector<uint32_t> &data);
bool init(KDecoration2::Decoration *decoration); bool init(KDecoration2::Decoration *decoration);
bool init(const QPointer<KWayland::Server::ShadowInterface> &shadow);
Toplevel *m_topLevel; Toplevel *m_topLevel;
// shadow pixmaps // shadow pixmaps
QPixmap m_shadowElements[ShadowElementsCount]; QPixmap m_shadowElements[ShadowElementsCount];

View file

@ -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/surface_interface.h>
#include <KWayland/Server/buffer_interface.h> #include <KWayland/Server/buffer_interface.h>
#include <KWayland/Server/plasmashell_interface.h> #include <KWayland/Server/plasmashell_interface.h>
#include <KWayland/Server/shadow_interface.h>
#include <KWayland/Server/qtsurfaceextension_interface.h> #include <KWayland/Server/qtsurfaceextension_interface.h>
#include <KDesktopFile> #include <KDesktopFile>
@ -88,6 +89,10 @@ ShellClient::ShellClient(ShellSurfaceInterface *surface)
); );
connect(surface, &ShellSurfaceInterface::windowClassChanged, this, &ShellClient::updateIcon); connect(surface, &ShellSurfaceInterface::windowClassChanged, this, &ShellClient::updateIcon);
updateIcon(); updateIcon();
// setup shadow integration
getShadow();
connect(surface->surface(), &SurfaceInterface::shadowChanged, this, &Toplevel::getShadow);
} }
ShellClient::~ShellClient() = default; ShellClient::~ShellClient() = default;

View file

@ -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/plasmawindowmanagement_interface.h>
#include <KWayland/Server/qtsurfaceextension_interface.h> #include <KWayland/Server/qtsurfaceextension_interface.h>
#include <KWayland/Server/seat_interface.h> #include <KWayland/Server/seat_interface.h>
#include <KWayland/Server/shadow_interface.h>
#include <KWayland/Server/shell_interface.h> #include <KWayland/Server/shell_interface.h>
// Qt // Qt
@ -186,6 +187,8 @@ void WaylandServer::init(const QByteArray &socketName)
workspace()->setShowingDesktop(set); workspace()->setShowingDesktop(set);
} }
); );
auto shadowManager = m_display->createShadowManager(m_display);
shadowManager->create();
} }
void WaylandServer::initWorkspace() void WaylandServer::initWorkspace()