[Dialog Shadows] Port to KWindowSystem shadows API
Summary: BUG: 416640 Test Plan: Run `qmlscene tests/dialog.qml` Reviewers: #plasma, davidedmundson Reviewed By: #plasma, davidedmundson Subscribers: kde-frameworks-devel Tags: #frameworks Maniphest Tasks: T12496 Differential Revision: https://phabricator.kde.org/D26503
This commit is contained in:
parent
5be495b4d7
commit
4ddf0d9944
@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright 2011 by Aaron Seigo <aseigo@kde.org>
|
||||
* Copyright 2020 by Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Library General Public License version 2,
|
||||
@ -17,95 +18,35 @@
|
||||
*/
|
||||
|
||||
#include "dialogshadows_p.h"
|
||||
#include "debug_p.h"
|
||||
|
||||
#include <QWindow>
|
||||
#include <QPainter>
|
||||
#include <config-plasma.h>
|
||||
|
||||
#include <KWindowSystem>
|
||||
#if HAVE_X11
|
||||
#include <QX11Info>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <fixx11h.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_KWAYLAND
|
||||
#include "waylandintegration_p.h"
|
||||
#include <KWayland/Client/shadow.h>
|
||||
#include <KWayland/Client/shm_pool.h>
|
||||
#include <KWayland/Client/surface.h>
|
||||
#endif
|
||||
|
||||
#include <qdebug.h>
|
||||
#include <KWindowShadow>
|
||||
|
||||
class DialogShadows::Private
|
||||
{
|
||||
public:
|
||||
Private(DialogShadows *shadows)
|
||||
: q(shadows)
|
||||
#if HAVE_X11
|
||||
, _connection(nullptr)
|
||||
, _gc(0x0)
|
||||
, m_isX11(KWindowSystem::isPlatformX11())
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
~Private()
|
||||
{
|
||||
// Do not call clearPixmaps() from here: it creates new QPixmap(),
|
||||
// which causes a crash when application is stopping.
|
||||
freeX11Pixmaps();
|
||||
}
|
||||
|
||||
void freeX11Pixmaps();
|
||||
void freeWaylandBuffers();
|
||||
void clearPixmaps();
|
||||
void setupPixmaps();
|
||||
Qt::HANDLE createPixmap(const QPixmap &source);
|
||||
void initPixmap(const QString &element);
|
||||
QPixmap initEmptyPixmap(const QSize &size);
|
||||
void updateShadow(const QWindow *window, Plasma::FrameSvg::EnabledBorders);
|
||||
void updateShadowX11(const QWindow *window, Plasma::FrameSvg::EnabledBorders);
|
||||
void updateShadowWayland(const QWindow *window, Plasma::FrameSvg::EnabledBorders);
|
||||
void clearShadow(const QWindow *window);
|
||||
void clearShadowX11(const QWindow *window);
|
||||
void clearShadowWayland(const QWindow *window);
|
||||
void clearTiles();
|
||||
void setupTiles();
|
||||
void initTile(const QString &element);
|
||||
void updateShadow(QWindow *window, Plasma::FrameSvg::EnabledBorders);
|
||||
void clearShadow(QWindow *window);
|
||||
void updateShadows();
|
||||
void windowDestroyed(QObject *deletedObject);
|
||||
void setupData(Plasma::FrameSvg::EnabledBorders enabledBorders);
|
||||
|
||||
DialogShadows *q;
|
||||
QList<QPixmap> m_shadowPixmaps;
|
||||
|
||||
QPixmap m_emptyCornerPix;
|
||||
QPixmap m_emptyCornerLeftPix;
|
||||
QPixmap m_emptyCornerTopPix;
|
||||
QPixmap m_emptyCornerRightPix;
|
||||
QPixmap m_emptyCornerBottomPix;
|
||||
QPixmap m_emptyVerticalPix;
|
||||
QPixmap m_emptyHorizontalPix;
|
||||
|
||||
#if HAVE_X11
|
||||
//! xcb connection
|
||||
xcb_connection_t *_connection;
|
||||
|
||||
//! graphical context
|
||||
xcb_gcontext_t _gc;
|
||||
bool m_isX11;
|
||||
#endif
|
||||
|
||||
#if HAVE_KWAYLAND
|
||||
struct Wayland {
|
||||
QList<KWayland::Client::Buffer::Ptr> shadowBuffers;
|
||||
};
|
||||
Wayland m_wayland;
|
||||
#endif
|
||||
|
||||
QHash<Plasma::FrameSvg::EnabledBorders, QVector<unsigned long> > data;
|
||||
QHash<const QWindow *, Plasma::FrameSvg::EnabledBorders> m_windows;
|
||||
QHash<QWindow *, Plasma::FrameSvg::EnabledBorders> m_windows;
|
||||
QHash<QWindow *, KWindowShadow *> m_shadows;
|
||||
QVector<KWindowShadowTile::Ptr> m_tiles;
|
||||
};
|
||||
|
||||
class DialogShadowsSingleton
|
||||
@ -138,7 +79,7 @@ DialogShadows *DialogShadows::self()
|
||||
return &privateDialogShadowsSelf->self;
|
||||
}
|
||||
|
||||
void DialogShadows::addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
void DialogShadows::addWindow(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
if (!window) {
|
||||
return;
|
||||
@ -150,7 +91,7 @@ void DialogShadows::addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBo
|
||||
this, SLOT(windowDestroyed(QObject*)), Qt::UniqueConnection);
|
||||
}
|
||||
|
||||
void DialogShadows::removeWindow(const QWindow *window)
|
||||
void DialogShadows::removeWindow(QWindow *window)
|
||||
{
|
||||
if (!d->m_windows.contains(window)) {
|
||||
return;
|
||||
@ -161,11 +102,11 @@ void DialogShadows::removeWindow(const QWindow *window)
|
||||
d->clearShadow(window);
|
||||
|
||||
if (d->m_windows.isEmpty()) {
|
||||
d->clearPixmaps();
|
||||
d->clearTiles();
|
||||
}
|
||||
}
|
||||
|
||||
void DialogShadows::setEnabledBorders(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
void DialogShadows::setEnabledBorders(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
if (!window || !d->m_windows.contains(window)) {
|
||||
return;
|
||||
@ -177,513 +118,171 @@ void DialogShadows::setEnabledBorders(const QWindow *window, Plasma::FrameSvg::E
|
||||
|
||||
void DialogShadows::Private::windowDestroyed(QObject *deletedObject)
|
||||
{
|
||||
m_windows.remove(static_cast<QWindow *>(deletedObject));
|
||||
QWindow *window = static_cast<QWindow *>(deletedObject);
|
||||
|
||||
m_windows.remove(window);
|
||||
clearShadow(window);
|
||||
|
||||
if (m_windows.isEmpty()) {
|
||||
clearPixmaps();
|
||||
clearTiles();
|
||||
}
|
||||
}
|
||||
|
||||
void DialogShadows::Private::updateShadows()
|
||||
{
|
||||
setupPixmaps();
|
||||
QHash<const QWindow *, Plasma::FrameSvg::EnabledBorders>::const_iterator i;
|
||||
setupTiles();
|
||||
QHash<QWindow *, Plasma::FrameSvg::EnabledBorders>::const_iterator i;
|
||||
for (i = m_windows.constBegin(); i != m_windows.constEnd(); ++i) {
|
||||
updateShadow(i.key(), i.value());
|
||||
}
|
||||
}
|
||||
|
||||
Qt::HANDLE DialogShadows::Private::createPixmap(const QPixmap &source)
|
||||
void DialogShadows::Private::initTile(const QString &element)
|
||||
{
|
||||
const QImage image = q->pixmap(element).toImage();
|
||||
|
||||
// do nothing for invalid pixmaps
|
||||
if (source.isNull()) {
|
||||
return nullptr;
|
||||
KWindowShadowTile::Ptr tile = KWindowShadowTile::Ptr::create();
|
||||
tile->setImage(image);
|
||||
|
||||
m_tiles << tile;
|
||||
}
|
||||
|
||||
/*
|
||||
in some cases, pixmap handle is invalid. This is the case notably
|
||||
when Qt uses to RasterEngine. In this case, we create an X11 Pixmap
|
||||
explicitly and draw the source pixmap on it.
|
||||
*/
|
||||
|
||||
#if HAVE_X11
|
||||
if (!m_isX11) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// check connection
|
||||
if (!_connection) {
|
||||
_connection = QX11Info::connection();
|
||||
}
|
||||
|
||||
const int width(source.width());
|
||||
const int height(source.height());
|
||||
|
||||
// create X11 pixmap
|
||||
Pixmap pixmap = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), width, height, 32);
|
||||
|
||||
// check gc
|
||||
if (!_gc) {
|
||||
_gc = xcb_generate_id(_connection);
|
||||
xcb_create_gc(_connection, _gc, pixmap, 0, nullptr);
|
||||
}
|
||||
|
||||
// // create explicitly shared QPixmap from it
|
||||
// QPixmap dest( QPixmap::fromX11Pixmap( pixmap, QPixmap::ExplicitlyShared ) );
|
||||
//
|
||||
// // create surface for pixmap
|
||||
// {
|
||||
// QPainter painter( &dest );
|
||||
// painter.setCompositionMode( QPainter::CompositionMode_Source );
|
||||
// painter.drawPixmap( 0, 0, source );
|
||||
// }
|
||||
//
|
||||
//
|
||||
// return pixmap;
|
||||
QImage image(source.toImage());
|
||||
xcb_put_image(
|
||||
_connection, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap, _gc,
|
||||
image.width(), image.height(), 0, 0,
|
||||
0, 32,
|
||||
image.sizeInBytes(), image.constBits());
|
||||
|
||||
return (Qt::HANDLE)pixmap;
|
||||
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void DialogShadows::Private::initPixmap(const QString &element)
|
||||
void DialogShadows::Private::setupTiles()
|
||||
{
|
||||
m_shadowPixmaps << q->pixmap(element);
|
||||
clearTiles();
|
||||
|
||||
initTile(QStringLiteral("shadow-top"));
|
||||
initTile(QStringLiteral("shadow-topright"));
|
||||
initTile(QStringLiteral("shadow-right"));
|
||||
initTile(QStringLiteral("shadow-bottomright"));
|
||||
initTile(QStringLiteral("shadow-bottom"));
|
||||
initTile(QStringLiteral("shadow-bottomleft"));
|
||||
initTile(QStringLiteral("shadow-left"));
|
||||
initTile(QStringLiteral("shadow-topleft"));
|
||||
}
|
||||
|
||||
QPixmap DialogShadows::Private::initEmptyPixmap(const QSize &size)
|
||||
void DialogShadows::Private::clearTiles()
|
||||
{
|
||||
#if HAVE_X11
|
||||
if (!m_isX11) {
|
||||
return QPixmap();
|
||||
}
|
||||
QPixmap tempEmptyPix(size);
|
||||
if (!size.isEmpty()) {
|
||||
tempEmptyPix.fill(Qt::transparent);
|
||||
}
|
||||
return tempEmptyPix;
|
||||
#else
|
||||
Q_UNUSED(size)
|
||||
return QPixmap();
|
||||
#endif
|
||||
m_tiles.clear();
|
||||
}
|
||||
|
||||
void DialogShadows::Private::setupPixmaps()
|
||||
void DialogShadows::Private::updateShadow(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
clearPixmaps();
|
||||
initPixmap(QStringLiteral("shadow-top"));
|
||||
initPixmap(QStringLiteral("shadow-topright"));
|
||||
initPixmap(QStringLiteral("shadow-right"));
|
||||
initPixmap(QStringLiteral("shadow-bottomright"));
|
||||
initPixmap(QStringLiteral("shadow-bottom"));
|
||||
initPixmap(QStringLiteral("shadow-bottomleft"));
|
||||
initPixmap(QStringLiteral("shadow-left"));
|
||||
initPixmap(QStringLiteral("shadow-topleft"));
|
||||
|
||||
m_emptyCornerPix = initEmptyPixmap(QSize(1, 1));
|
||||
m_emptyCornerLeftPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-topleft")).width(), 1));
|
||||
m_emptyCornerTopPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-topleft")).height()));
|
||||
m_emptyCornerRightPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-bottomright")).width(), 1));
|
||||
m_emptyCornerBottomPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-bottomright")).height()));
|
||||
m_emptyVerticalPix = initEmptyPixmap(QSize(1, q->elementSize(QStringLiteral("shadow-left")).height()));
|
||||
m_emptyHorizontalPix = initEmptyPixmap(QSize(q->elementSize(QStringLiteral("shadow-top")).width(), 1));
|
||||
|
||||
#if HAVE_KWAYLAND
|
||||
if (KWayland::Client::ShmPool *shmPool = WaylandIntegration::self()->waylandShmPool()) {
|
||||
for (auto it = m_shadowPixmaps.constBegin(); it != m_shadowPixmaps.constEnd(); ++it) {
|
||||
m_wayland.shadowBuffers << shmPool->createBuffer(it->toImage());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (m_tiles.isEmpty()) {
|
||||
setupTiles();
|
||||
}
|
||||
|
||||
void DialogShadows::Private::setupData(Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
#if HAVE_X11
|
||||
if (!m_isX11) {
|
||||
return;
|
||||
KWindowShadow *&shadow = m_shadows[window];
|
||||
|
||||
if (!shadow) {
|
||||
shadow = new KWindowShadow(q);
|
||||
}
|
||||
//shadow-top
|
||||
|
||||
if (shadow->isCreated()) {
|
||||
shadow->destroy();
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[0]));
|
||||
shadow->setTopTile(m_tiles.at(0));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyHorizontalPix));
|
||||
shadow->setTopTile(nullptr);
|
||||
}
|
||||
|
||||
//shadow-topright
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[1]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix));
|
||||
shadow->setTopRightTile(m_tiles.at(1));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
|
||||
}
|
||||
|
||||
//shadow-right
|
||||
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[2]));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix));
|
||||
}
|
||||
|
||||
//shadow-bottomright
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[3]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
|
||||
}
|
||||
|
||||
//shadow-bottom
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[4]));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyHorizontalPix));
|
||||
}
|
||||
|
||||
//shadow-bottomleft
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[5]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
|
||||
}
|
||||
|
||||
//shadow-left
|
||||
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[6]));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix));
|
||||
}
|
||||
|
||||
//shadow-topleft
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_shadowPixmaps[7]));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix));
|
||||
} else if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix));
|
||||
} else {
|
||||
data[enabledBorders] << reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix));
|
||||
}
|
||||
#endif
|
||||
|
||||
int left, top, right, bottom = 0;
|
||||
|
||||
QSize marginHint;
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
top = marginHint.height();
|
||||
} else {
|
||||
top = m_shadowPixmaps[0].height(); // top
|
||||
}
|
||||
} else {
|
||||
top = 1;
|
||||
shadow->setTopRightTile(nullptr);
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
right = marginHint.width();
|
||||
shadow->setRightTile(m_tiles.at(2));
|
||||
} else {
|
||||
right = m_shadowPixmaps[2].width(); // right
|
||||
shadow->setRightTile(nullptr);
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
shadow->setBottomRightTile(m_tiles.at(3));
|
||||
} else {
|
||||
right = 1;
|
||||
shadow->setBottomRightTile(nullptr);
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
bottom = marginHint.height();
|
||||
shadow->setBottomTile(m_tiles.at(4));
|
||||
} else {
|
||||
bottom = m_shadowPixmaps[4].height(); // bottom
|
||||
shadow->setBottomTile(nullptr);
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
shadow->setBottomLeftTile(m_tiles.at(5));
|
||||
} else {
|
||||
bottom = 1;
|
||||
shadow->setBottomLeftTile(nullptr);
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
left = marginHint.width();
|
||||
shadow->setLeftTile(m_tiles.at(6));
|
||||
} else {
|
||||
left = m_shadowPixmaps[6].width(); // left
|
||||
}
|
||||
} else {
|
||||
left = 1;
|
||||
shadow->setLeftTile(nullptr);
|
||||
}
|
||||
|
||||
data[enabledBorders] << top << right << bottom << left;
|
||||
}
|
||||
|
||||
void DialogShadows::Private::freeX11Pixmaps()
|
||||
{
|
||||
#if HAVE_X11
|
||||
if (!m_isX11) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto *display = QX11Info::display();
|
||||
if (!display) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const QPixmap &pixmap : qAsConst(m_shadowPixmaps)) {
|
||||
if (!pixmap.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(pixmap)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_emptyCornerPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerPix)));
|
||||
}
|
||||
if (!m_emptyCornerBottomPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerBottomPix)));
|
||||
}
|
||||
if (!m_emptyCornerLeftPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerLeftPix)));
|
||||
}
|
||||
if (!m_emptyCornerRightPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerRightPix)));
|
||||
}
|
||||
if (!m_emptyCornerTopPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyCornerTopPix)));
|
||||
}
|
||||
if (!m_emptyVerticalPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyVerticalPix)));
|
||||
}
|
||||
if (!m_emptyHorizontalPix.isNull()) {
|
||||
XFreePixmap(display, reinterpret_cast<unsigned long>(createPixmap(m_emptyHorizontalPix)));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DialogShadows::Private::clearPixmaps()
|
||||
{
|
||||
#if HAVE_X11
|
||||
freeX11Pixmaps();
|
||||
|
||||
m_emptyCornerPix = QPixmap();
|
||||
m_emptyCornerBottomPix = QPixmap();
|
||||
m_emptyCornerLeftPix = QPixmap();
|
||||
m_emptyCornerRightPix = QPixmap();
|
||||
m_emptyCornerTopPix = QPixmap();
|
||||
m_emptyVerticalPix = QPixmap();
|
||||
m_emptyHorizontalPix = QPixmap();
|
||||
#endif
|
||||
freeWaylandBuffers();
|
||||
m_shadowPixmaps.clear();
|
||||
data.clear();
|
||||
}
|
||||
|
||||
void DialogShadows::Private::freeWaylandBuffers()
|
||||
{
|
||||
#if HAVE_KWAYLAND
|
||||
m_wayland.shadowBuffers.clear();
|
||||
#endif
|
||||
}
|
||||
|
||||
void DialogShadows::Private::updateShadow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
#if HAVE_X11
|
||||
if (m_isX11) {
|
||||
updateShadowX11(window, enabledBorders);
|
||||
}
|
||||
#endif
|
||||
#if HAVE_KWAYLAND
|
||||
if (WaylandIntegration::self()->waylandShadowManager()) {
|
||||
updateShadowWayland(window, enabledBorders);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DialogShadows::Private::updateShadowX11(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
#if HAVE_X11
|
||||
if (m_shadowPixmaps.isEmpty()) {
|
||||
setupPixmaps();
|
||||
}
|
||||
|
||||
if (!data.contains(enabledBorders)) {
|
||||
setupData(enabledBorders);
|
||||
}
|
||||
|
||||
Display *dpy = QX11Info::display();
|
||||
Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False);
|
||||
|
||||
//qDebug() << "going to set the shadow of" << window->winId() << "to" << data;
|
||||
XChangeProperty(dpy, window->winId(), atom, XA_CARDINAL, 32, PropModeReplace,
|
||||
reinterpret_cast<const unsigned char *>(data[enabledBorders].constData()), data[enabledBorders].size());
|
||||
#endif
|
||||
}
|
||||
|
||||
void DialogShadows::Private::updateShadowWayland(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders)
|
||||
{
|
||||
#if HAVE_KWAYLAND
|
||||
if (!WaylandIntegration::self()->waylandShmPool()) {
|
||||
return;
|
||||
}
|
||||
if (m_wayland.shadowBuffers.isEmpty()) {
|
||||
setupPixmaps();
|
||||
}
|
||||
// TODO: check whether the surface already has a shadow
|
||||
KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(const_cast<QWindow*>(window));
|
||||
if (!surface) {
|
||||
return;
|
||||
}
|
||||
KWayland::Client::ShadowManager *manager = WaylandIntegration::self()->waylandShadowManager();
|
||||
auto shadow = manager->createShadow(surface, surface);
|
||||
|
||||
//shadow-top
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
shadow->attachTop(m_wayland.shadowBuffers.at(0));
|
||||
}
|
||||
|
||||
//shadow-topright
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
shadow->attachTopRight(m_wayland.shadowBuffers.at(1));
|
||||
}
|
||||
|
||||
//shadow-right
|
||||
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
shadow->attachRight(m_wayland.shadowBuffers.at(2));
|
||||
}
|
||||
|
||||
//shadow-bottomright
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
shadow->attachBottomRight(m_wayland.shadowBuffers.at(3));
|
||||
}
|
||||
|
||||
//shadow-bottom
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
shadow->attachBottom(m_wayland.shadowBuffers.at(4));
|
||||
}
|
||||
|
||||
//shadow-bottomleft
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
shadow->attachBottomLeft(m_wayland.shadowBuffers.at(5));
|
||||
}
|
||||
|
||||
//shadow-left
|
||||
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
shadow->attachLeft(m_wayland.shadowBuffers.at(6));
|
||||
}
|
||||
|
||||
//shadow-topleft
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder &&
|
||||
enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
shadow->attachTopLeft(m_wayland.shadowBuffers.at(7));
|
||||
shadow->setTopLeftTile(m_tiles.at(7));
|
||||
} else {
|
||||
shadow->setTopLeftTile(nullptr);
|
||||
}
|
||||
|
||||
QSize marginHint;
|
||||
QMarginsF margins;
|
||||
QMargins padding;
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::TopBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin"));
|
||||
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
margins.setTop(marginHint.height());
|
||||
padding.setTop(marginHint.height());
|
||||
} else {
|
||||
margins.setTop(m_shadowPixmaps[0].height());
|
||||
padding.setTop(m_tiles[0]->image().height());
|
||||
}
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::RightBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin"));
|
||||
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
margins.setRight(marginHint.width());
|
||||
padding.setRight(marginHint.width());
|
||||
} else {
|
||||
margins.setRight(m_shadowPixmaps[2].width());
|
||||
padding.setRight(m_tiles[2]->image().width());
|
||||
}
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::BottomBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin"));
|
||||
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
margins.setBottom(marginHint.height());
|
||||
padding.setBottom(marginHint.height());
|
||||
} else {
|
||||
margins.setBottom(m_shadowPixmaps[4].height());
|
||||
padding.setBottom(m_tiles[4]->image().height());
|
||||
}
|
||||
}
|
||||
|
||||
if (enabledBorders & Plasma::FrameSvg::LeftBorder) {
|
||||
marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin"));
|
||||
const QSize marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin"));
|
||||
if (marginHint.isValid()) {
|
||||
margins.setLeft(marginHint.width());
|
||||
padding.setLeft(marginHint.width());
|
||||
} else {
|
||||
margins.setLeft(m_shadowPixmaps[6].width());
|
||||
padding.setLeft(m_tiles[6]->image().width());
|
||||
}
|
||||
}
|
||||
|
||||
shadow->setOffsets(margins);
|
||||
shadow->commit();
|
||||
surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
#endif
|
||||
shadow->setPadding(padding);
|
||||
shadow->setWindow(window);
|
||||
|
||||
if (!shadow->create()) {
|
||||
qCWarning(LOG_PLASMAQUICK) << "Couldn't create KWindowShadow for" << window;
|
||||
}
|
||||
}
|
||||
|
||||
void DialogShadows::Private::clearShadow(const QWindow *window)
|
||||
void DialogShadows::Private::clearShadow(QWindow *window)
|
||||
{
|
||||
if (!static_cast<const QSurface*>(window)->surfaceHandle()) {
|
||||
qWarning() << "Cannot clear shadow from window without native surface!";
|
||||
return;
|
||||
}
|
||||
#if HAVE_X11
|
||||
if (m_isX11) {
|
||||
clearShadowX11(window);
|
||||
}
|
||||
#endif
|
||||
#if HAVE_KWAYLAND
|
||||
if (WaylandIntegration::self()->waylandShadowManager()) {
|
||||
clearShadowWayland(window);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DialogShadows::Private::clearShadowX11(const QWindow* window)
|
||||
{
|
||||
#if HAVE_X11
|
||||
Display *dpy = QX11Info::display();
|
||||
Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False);
|
||||
XDeleteProperty(dpy, window->winId(), atom);
|
||||
#endif
|
||||
}
|
||||
|
||||
void DialogShadows::Private::clearShadowWayland(const QWindow *window)
|
||||
{
|
||||
#if HAVE_KWAYLAND
|
||||
KWayland::Client::Surface *surface = KWayland::Client::Surface::fromWindow(const_cast<QWindow*>(window));
|
||||
if (!surface) {
|
||||
return;
|
||||
}
|
||||
KWayland::Client::ShadowManager *manager = WaylandIntegration::self()->waylandShadowManager();
|
||||
manager->removeShadow(surface);
|
||||
surface->commit(KWayland::Client::Surface::CommitFlag::None);
|
||||
#endif
|
||||
delete m_shadows.take(window);
|
||||
}
|
||||
|
||||
bool DialogShadows::enabled() const
|
||||
|
@ -34,10 +34,10 @@ public:
|
||||
|
||||
static DialogShadows *self();
|
||||
|
||||
void addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
|
||||
void removeWindow(const QWindow *window);
|
||||
void addWindow(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
|
||||
void removeWindow(QWindow *window);
|
||||
|
||||
void setEnabledBorders(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
|
||||
void setEnabledBorders(QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders);
|
||||
|
||||
bool enabled() const;
|
||||
|
||||
|
@ -27,8 +27,6 @@
|
||||
#include <KWayland/Client/connection_thread.h>
|
||||
#include <KWayland/Client/plasmashell.h>
|
||||
#include <KWayland/Client/registry.h>
|
||||
#include <KWayland/Client/shadow.h>
|
||||
#include <KWayland/Client/shm_pool.h>
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
@ -71,47 +69,6 @@ KWayland::Client::PlasmaShell *WaylandIntegration::waylandPlasmaShell()
|
||||
return m_waylandPlasmaShell;
|
||||
}
|
||||
|
||||
KWayland::Client::ShadowManager *WaylandIntegration::waylandShadowManager()
|
||||
{
|
||||
if (!m_waylandShadowManager && m_registry) {
|
||||
const KWayland::Client::Registry::AnnouncedInterface interface =
|
||||
m_registry->interface(KWayland::Client::Registry::Interface::Shadow);
|
||||
|
||||
if (interface.name == 0) {
|
||||
qCWarning(LOG_PLASMAQUICK) << "The compositor does not support the shadow protocol";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_waylandShadowManager = m_registry->createShadowManager(interface.name, interface.version, qApp);
|
||||
|
||||
connect(m_waylandShadowManager, &KWayland::Client::ShadowManager::removed, this, [this]() {
|
||||
m_waylandShadowManager->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
return m_waylandShadowManager;
|
||||
}
|
||||
|
||||
KWayland::Client::ShmPool *WaylandIntegration::waylandShmPool()
|
||||
{
|
||||
if (!m_waylandShmPool && m_registry) {
|
||||
const KWayland::Client::Registry::AnnouncedInterface interface =
|
||||
m_registry->interface(KWayland::Client::Registry::Interface::Shm);
|
||||
|
||||
if (interface.name == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
m_waylandShmPool = m_registry->createShmPool(interface.name, interface.version, qApp);
|
||||
|
||||
connect(m_waylandShmPool, &KWayland::Client::ShmPool::removed, this, [this]() {
|
||||
m_waylandShmPool->deleteLater();
|
||||
});
|
||||
}
|
||||
|
||||
return m_waylandShmPool;
|
||||
}
|
||||
|
||||
WaylandIntegration *WaylandIntegration::self()
|
||||
{
|
||||
return &privateWaylandIntegrationSelf()->self;
|
||||
|
@ -28,8 +28,6 @@ namespace Client
|
||||
{
|
||||
class PlasmaShell;
|
||||
class Registry;
|
||||
class ShadowManager;
|
||||
class ShmPool;
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,8 +40,6 @@ public:
|
||||
~WaylandIntegration() override;
|
||||
|
||||
KWayland::Client::PlasmaShell *waylandPlasmaShell();
|
||||
KWayland::Client::ShadowManager *waylandShadowManager();
|
||||
KWayland::Client::ShmPool *waylandShmPool();
|
||||
|
||||
static WaylandIntegration *self();
|
||||
|
||||
@ -52,8 +48,6 @@ private:
|
||||
|
||||
QPointer<KWayland::Client::Registry> m_registry;
|
||||
QPointer<KWayland::Client::PlasmaShell> m_waylandPlasmaShell;
|
||||
QPointer<KWayland::Client::ShadowManager> m_waylandShadowManager;
|
||||
QPointer<KWayland::Client::ShmPool> m_waylandShmPool;
|
||||
|
||||
Q_DISABLE_COPY(WaylandIntegration)
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user