diff --git a/app/view/indicator/indicator.cpp b/app/view/indicator/indicator.cpp index defedde74..0e51983c0 100644 --- a/app/view/indicator/indicator.cpp +++ b/app/view/indicator/indicator.cpp @@ -329,7 +329,6 @@ void Indicator::configUiFor(QString type, QQuickItem *parent) delete m_lastCreatedConfigUi; m_lastCreatedConfigUi = nullptr; } - auto prevConfigUi = m_lastCreatedConfigUi; KPluginMetaData metadata; diff --git a/app/view/settings/CMakeLists.txt b/app/view/settings/CMakeLists.txt index 9b93441a8..2fb856d3b 100644 --- a/app/view/settings/CMakeLists.txt +++ b/app/view/settings/CMakeLists.txt @@ -2,5 +2,6 @@ set(lattedock-app_SRCS ${lattedock-app_SRCS} ${CMAKE_CURRENT_SOURCE_DIR}/primaryconfigview.cpp ${CMAKE_CURRENT_SOURCE_DIR}/secondaryconfigview.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/dialogshadows.cpp PARENT_SCOPE ) diff --git a/app/view/settings/dialogshadows.cpp b/app/view/settings/dialogshadows.cpp new file mode 100644 index 000000000..12ac35b28 --- /dev/null +++ b/app/view/settings/dialogshadows.cpp @@ -0,0 +1,747 @@ +/* +* Copyright 2011 by Aaron Seigo +* +* 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, +* or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include "dialogshadows_p.h" + +#include +#include +#include + +#include +#if HAVE_X11 +#include +#include +#include +#include +#include +#endif + +#if HAVE_KWAYLAND +#include +#include +#include +#include +#include +#include +#endif + +#include + +class DialogShadows::Private +{ +public: + Private(DialogShadows *shadows) + : q(shadows) +#if HAVE_X11 + , _connection(nullptr) + , _gc(0x0) + , m_isX11(KWindowSystem::isPlatformX11()) +#endif + { + setupWaylandIntegration(); + } + + ~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 updateShadows(); + void windowDestroyed(QObject *deletedObject); + void setupData(Plasma::FrameSvg::EnabledBorders enabledBorders); + + void setupWaylandIntegration(); + + DialogShadows *q; + QList 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 { + KWayland::Client::ShadowManager *manager = nullptr; + KWayland::Client::ShmPool *shmPool = nullptr; + KWayland::Client::PlasmaShell *plasmaShell = nullptr; + + QList shadowBuffers; + }; + Wayland m_wayland; +#endif + + QHash > data; + QHash m_windows; +}; + +class DialogShadowsSingleton +{ +public: + DialogShadowsSingleton() + { + } + + DialogShadows self; +}; + +Q_GLOBAL_STATIC(DialogShadowsSingleton, privateDialogShadowsSelf) + +DialogShadows::DialogShadows(QObject *parent, const QString &prefix) + : Plasma::Svg(parent), + d(new Private(this)) +{ + setImagePath(prefix); + connect(this, SIGNAL(repaintNeeded()), this, SLOT(updateShadows())); +} + +DialogShadows::~DialogShadows() +{ + delete d; +} + +DialogShadows *DialogShadows::self() +{ + return &privateDialogShadowsSelf->self; +} + +void DialogShadows::addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) +{ + if (!window) { + return; + } + + d->m_windows[window] = enabledBorders; + d->updateShadow(window, enabledBorders); + connect(window, SIGNAL(destroyed(QObject*)), + this, SLOT(windowDestroyed(QObject*)), Qt::UniqueConnection); +} + +void DialogShadows::removeWindow(const QWindow *window) +{ + if (!d->m_windows.contains(window)) { + return; + } + + d->m_windows.remove(window); + disconnect(window, nullptr, this, nullptr); + d->clearShadow(window); + + if (d->m_windows.isEmpty()) { + d->clearPixmaps(); + } +} + +void DialogShadows::setEnabledBorders(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) +{ + if (!window || !d->m_windows.contains(window)) { + return; + } + + d->updateShadow(window, enabledBorders); +} + + +void DialogShadows::Private::windowDestroyed(QObject *deletedObject) +{ + m_windows.remove(static_cast(deletedObject)); + + if (m_windows.isEmpty()) { + clearPixmaps(); + } +} + +void DialogShadows::Private::updateShadows() +{ + setupPixmaps(); + QHash::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) +{ + + // do nothing for invalid pixmaps + if (source.isNull()) { + return nullptr; + } + + /* + 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) +{ + m_shadowPixmaps << q->pixmap(element); +} + +QPixmap DialogShadows::Private::initEmptyPixmap(const QSize &size) +{ +#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 +} + +void DialogShadows::Private::setupPixmaps() +{ + 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 (m_wayland.shmPool) { + for (auto it = m_shadowPixmaps.constBegin(); it != m_shadowPixmaps.constEnd(); ++it) { + m_wayland.shadowBuffers << m_wayland.shmPool->createBuffer(it->toImage()); + } + } +#endif +} + +void DialogShadows::Private::setupData(Plasma::FrameSvg::EnabledBorders enabledBorders) +{ +#if HAVE_X11 + if (!m_isX11) { + return; + } + //shadow-top + if (enabledBorders & Plasma::FrameSvg::TopBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[0])); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyHorizontalPix)); + } + + //shadow-topright + if (enabledBorders & Plasma::FrameSvg::TopBorder && + enabledBorders & Plasma::FrameSvg::RightBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[1])); + } else if (enabledBorders & Plasma::FrameSvg::TopBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerTopPix)); + } else if (enabledBorders & Plasma::FrameSvg::RightBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerRightPix)); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerPix)); + } + + //shadow-right + if (enabledBorders & Plasma::FrameSvg::RightBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[2])); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyVerticalPix)); + } + + //shadow-bottomright + if (enabledBorders & Plasma::FrameSvg::BottomBorder && + enabledBorders & Plasma::FrameSvg::RightBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[3])); + } else if (enabledBorders & Plasma::FrameSvg::BottomBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerBottomPix)); + } else if (enabledBorders & Plasma::FrameSvg::RightBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerRightPix)); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerPix)); + } + + //shadow-bottom + if (enabledBorders & Plasma::FrameSvg::BottomBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[4])); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyHorizontalPix)); + } + + //shadow-bottomleft + if (enabledBorders & Plasma::FrameSvg::BottomBorder && + enabledBorders & Plasma::FrameSvg::LeftBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[5])); + } else if (enabledBorders & Plasma::FrameSvg::BottomBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerBottomPix)); + } else if (enabledBorders & Plasma::FrameSvg::LeftBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerLeftPix)); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerPix)); + } + + //shadow-left + if (enabledBorders & Plasma::FrameSvg::LeftBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[6])); + } else { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyVerticalPix)); + } + + //shadow-topleft + if (enabledBorders & Plasma::FrameSvg::TopBorder && + enabledBorders & Plasma::FrameSvg::LeftBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_shadowPixmaps[7])); + } else if (enabledBorders & Plasma::FrameSvg::TopBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerTopPix)); + } else if (enabledBorders & Plasma::FrameSvg::LeftBorder) { + data[enabledBorders] << reinterpret_cast(createPixmap(m_emptyCornerLeftPix)); + } else { + data[enabledBorders] << reinterpret_cast(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; + } + + if (enabledBorders & Plasma::FrameSvg::RightBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin")); + if (marginHint.isValid()) { + right = marginHint.width(); + } else { + right = m_shadowPixmaps[2].width(); // right + } + } else { + right = 1; + } + + if (enabledBorders & Plasma::FrameSvg::BottomBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin")); + if (marginHint.isValid()) { + bottom = marginHint.height(); + } else { + bottom = m_shadowPixmaps[4].height(); // bottom + } + } else { + bottom = 1; + } + + if (enabledBorders & Plasma::FrameSvg::LeftBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin")); + if (marginHint.isValid()) { + left = marginHint.width(); + } else { + left = m_shadowPixmaps[6].width(); // left + } + } else { + left = 1; + } + + data[enabledBorders] << top << right << bottom << left; +} + +void DialogShadows::Private::freeX11Pixmaps() +{ +#if HAVE_X11 + if (!m_isX11) { + return; + } + + auto *display = QX11Info::display(); + if (!display) { + return; + } + + foreach (const QPixmap &pixmap, m_shadowPixmaps) { + if (!pixmap.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(pixmap))); + } + } + + if (!m_emptyCornerPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyCornerPix))); + } + if (!m_emptyCornerBottomPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyCornerBottomPix))); + } + if (!m_emptyCornerLeftPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyCornerLeftPix))); + } + if (!m_emptyCornerRightPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyCornerRightPix))); + } + if (!m_emptyCornerTopPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyCornerTopPix))); + } + if (!m_emptyVerticalPix.isNull()) { + XFreePixmap(display, reinterpret_cast(createPixmap(m_emptyVerticalPix))); + } + if (!m_emptyHorizontalPix.isNull()) { + XFreePixmap(display, reinterpret_cast(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 (m_wayland.manager) { + 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(data[enabledBorders].constData()), data[enabledBorders].size()); +#endif +} + +void DialogShadows::Private::updateShadowWayland(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders) +{ +#if HAVE_KWAYLAND + if (!m_wayland.shmPool) { + 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(window)); + if (!surface) { + return; + } + auto shadow = m_wayland.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)); + } + + QSize marginHint; + QMarginsF margins; + if (enabledBorders & Plasma::FrameSvg::TopBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-top-margin")); + if (marginHint.isValid()) { + margins.setTop(marginHint.height()); + } else { + margins.setTop(m_shadowPixmaps[0].height()); + } + } + + if (enabledBorders & Plasma::FrameSvg::RightBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-right-margin")); + if (marginHint.isValid()) { + margins.setRight(marginHint.width()); + } else { + margins.setRight(m_shadowPixmaps[2].width()); + } + } + + if (enabledBorders & Plasma::FrameSvg::BottomBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-bottom-margin")); + if (marginHint.isValid()) { + margins.setBottom(marginHint.height()); + } else { + margins.setBottom(m_shadowPixmaps[4].height()); + } + } + + if (enabledBorders & Plasma::FrameSvg::LeftBorder) { + marginHint = q->elementSize(QStringLiteral("shadow-hint-left-margin")); + if (marginHint.isValid()) { + margins.setLeft(marginHint.width()); + } else { + margins.setLeft(m_shadowPixmaps[6].width()); + } + } + + shadow->setOffsets(margins); + shadow->commit(); + surface->commit(KWayland::Client::Surface::CommitFlag::None); +#endif +} + +void DialogShadows::Private::clearShadow(const QWindow *window) +{ + if (!static_cast(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 (m_wayland.manager) { + 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(window)); + if (!surface) { + return; + } + m_wayland.manager->removeShadow(surface); + surface->commit(KWayland::Client::Surface::CommitFlag::None); +#endif +} + +bool DialogShadows::enabled() const +{ + return hasElement(QStringLiteral("shadow-left")); +} + +KWayland::Client::PlasmaShell *DialogShadows::waylandPlasmaShellInterface() const +{ +#if HAVE_KWAYLAND + return d->m_wayland.plasmaShell; +#else + return nullptr; +#endif +} + +void DialogShadows::Private::setupWaylandIntegration() +{ +#if HAVE_KWAYLAND + if (!KWindowSystem::isPlatformWayland()) { + return; + } + using namespace KWayland::Client; + ConnectionThread *connection = ConnectionThread::fromApplication(q); + if (!connection) { + return; + } + Registry *registry = new Registry(q); + registry->create(connection); + connect(registry, &Registry::shadowAnnounced, q, + [this, registry] (quint32 name, quint32 version) { + m_wayland.manager = registry->createShadowManager(name, version, q); + updateShadows(); + }, Qt::QueuedConnection + ); + connect(registry, &Registry::shmAnnounced, q, + [this, registry] (quint32 name, quint32 version) { + m_wayland.shmPool = registry->createShmPool(name, version, q); + updateShadows(); + }, Qt::QueuedConnection + ); + connect(registry, &Registry::plasmaShellAnnounced, q, + [this, registry] (quint32 name, quint32 version) { + m_wayland.plasmaShell = registry->createPlasmaShell(name, version, q); + } + ); + registry->setup(); + connection->roundtrip(); +#endif +} + +#include "moc_dialogshadows_p.cpp" + + diff --git a/app/view/settings/dialogshadows_p.h b/app/view/settings/dialogshadows_p.h new file mode 100644 index 000000000..8d3703274 --- /dev/null +++ b/app/view/settings/dialogshadows_p.h @@ -0,0 +1,64 @@ +/* +* Copyright 2011 by Aaron Seigo +* +* 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, +* or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details +* +* You should have received a copy of the GNU Library General Public +* License along with this program; if not, write to the +* Free Software Foundation, Inc., +* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef PLASMA_DIALOGSHADOWS_H +#define PLASMA_DIALOGSHADOWS_H + +#include + +#include "plasma/framesvg.h" +#include "plasma/svg.h" + +namespace KWayland +{ + namespace Client + { + class PlasmaShell; + } +} + +class DialogShadows : public Plasma::Svg +{ + Q_OBJECT + +public: + explicit DialogShadows(QObject *parent = nullptr, const QString &prefix = QStringLiteral("dialogs/background")); + ~DialogShadows(); + + static DialogShadows *self(); + + void addWindow(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders); + void removeWindow(const QWindow *window); + + void setEnabledBorders(const QWindow *window, Plasma::FrameSvg::EnabledBorders enabledBorders = Plasma::FrameSvg::AllBorders); + + bool enabled() const; + + KWayland::Client::PlasmaShell *waylandPlasmaShellInterface() const; + +private: + class Private; + Private *const d; + + Q_PRIVATE_SLOT(d, void updateShadows()) + Q_PRIVATE_SLOT(d, void windowDestroyed(QObject *deletedObject)) +}; + +#endif + + diff --git a/app/view/settings/primaryconfigview.cpp b/app/view/settings/primaryconfigview.cpp index 9b3ea42fe..759bb8b52 100644 --- a/app/view/settings/primaryconfigview.cpp +++ b/app/view/settings/primaryconfigview.cpp @@ -23,8 +23,8 @@ // local #include #include "secondaryconfigview.h" +#include "dialogshadows_p.h" #include "../effects.h" -#include "../panelshadows_p.h" #include "../view.h" #include "../../lattecorona.h" #include "../../layouts/manager.h" @@ -124,6 +124,8 @@ PrimaryConfigView::~PrimaryConfigView() { qDebug() << "ConfigView deleting ..."; + DialogShadows::self()->removeWindow(this); + m_corona->wm()->unregisterIgnoredWindow(KWindowSystem::isPlatformX11() ? winId() : m_waylandWindowId); deleteSecondaryWindow(); @@ -143,7 +145,7 @@ void PrimaryConfigView::init() setDefaultAlphaBuffer(true); setColor(Qt::transparent); - PanelShadows::self()->addWindow(this); + DialogShadows::self()->addWindow(this); rootContext()->setContextProperty(QStringLiteral("latteView"), m_latteView); rootContext()->setContextProperty(QStringLiteral("shortcutsEngine"), m_corona->globalShortcuts()->shortcutsTracker()); rootContext()->setContextProperty(QStringLiteral("viewConfig"), this); @@ -683,7 +685,7 @@ void PrimaryConfigView::updateEnabledBorders() if (m_enabledBorders != borders) { m_enabledBorders = borders; - PanelShadows::self()->addWindow(this, m_enabledBorders); + DialogShadows::self()->addWindow(this, m_enabledBorders); emit enabledBordersChanged(); } diff --git a/app/view/settings/secondaryconfigview.cpp b/app/view/settings/secondaryconfigview.cpp index 46cebbc8f..3a62e7d83 100644 --- a/app/view/settings/secondaryconfigview.cpp +++ b/app/view/settings/secondaryconfigview.cpp @@ -21,8 +21,8 @@ // local #include +#include "dialogshadows_p.h" #include "primaryconfigview.h" -#include "../panelshadows_p.h" #include "../view.h" #include "../../lattecorona.h" #include "../../wm/abstractwindowinterface.h" @@ -106,6 +106,8 @@ SecondaryConfigView::~SecondaryConfigView() { qDebug() << "SecDockConfigView deleting ..."; + DialogShadows::self()->removeWindow(this); + m_corona->wm()->unregisterIgnoredWindow(KWindowSystem::isPlatformX11() ? winId() : m_waylandWindowId); for (const auto &var : connections) { @@ -119,7 +121,7 @@ void SecondaryConfigView::init() setDefaultAlphaBuffer(true); setColor(Qt::transparent); - PanelShadows::self()->addWindow(this); + DialogShadows::self()->addWindow(this); rootContext()->setContextProperty(QStringLiteral("latteView"), m_latteView); rootContext()->setContextProperty(QStringLiteral("viewConfig"), this); rootContext()->setContextProperty(QStringLiteral("plasmoid"), m_latteView->containment()->property("_plasma_graphicObject").value()); @@ -429,7 +431,7 @@ void SecondaryConfigView::updateEnabledBorders() if (m_enabledBorders != borders) { m_enabledBorders = borders; - PanelShadows::self()->addWindow(this, m_enabledBorders); + DialogShadows::self()->addWindow(this, m_enabledBorders); emit enabledBordersChanged(); }