[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.
icc-effect-5.14.5
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 "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();

View File

@ -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];

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/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;

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/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()