diff --git a/CMakeLists.txt b/CMakeLists.txt index b4ab273c3..5338f5f85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -128,6 +128,7 @@ set(plasma_LIB_SRCS private/tooltip.cpp private/wallpaperrenderthread.cpp private/windowpreview.cpp + private/windowshadows.cpp private/kineticscroll.cpp private/effects/halopainter.cpp private/effects/ripple.cpp diff --git a/data/services/plasma.protocol b/data/services/plasma.protocol index df0a941e7..7b9d10e32 100644 --- a/data/services/plasma.protocol +++ b/data/services/plasma.protocol @@ -9,6 +9,7 @@ Icon=plasma Description=A protocol for Plasma services Description[bs]=Protokol Plazma usluga Description[ca]=Un protocol pels serveis del Plasma +Description[ca@valencia]=Un protocol pels serveis del Plasma Description[da]=En protokol til Plasma-tjenester Description[es]=Un protocolo para los servicios de Plasma Description[et]=Plasma teenuste protokoll diff --git a/dialog.cpp b/dialog.cpp index a61acc893..ca4dbb056 100644 --- a/dialog.cpp +++ b/dialog.cpp @@ -55,6 +55,7 @@ #include "plasma/theme.h" #include "plasma/widgets/scrollwidget.h" #include "plasma/windoweffects.h" +#include "plasma/private/windowshadows_p.h" #ifdef Q_WS_X11 #include @@ -94,6 +95,11 @@ void DialogPrivate::scheduleBorderCheck(bool triggeredByResize) void DialogPrivate::themeChanged() { checkBorders(false); + if (background->hasElement("shadow-top")) { + WindowShadows::self()->addWindow(q); + } else { + WindowShadows::self()->removeWindow(q); + } const bool translucency = Plasma::Theme::defaultTheme()->windowTranslucencyEnabled(); // WA_NoSystemBackground is going to fail combined with sliding popups, but is needed diff --git a/private/windowshadows.cpp b/private/windowshadows.cpp new file mode 100644 index 000000000..28b1d40be --- /dev/null +++ b/private/windowshadows.cpp @@ -0,0 +1,235 @@ +/* +* 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 "windowshadows_p.h" + +#include +#include + +#ifdef Q_WS_X11 +#include +#include +#include +#include +#endif + +#include + +namespace Plasma +{ + +class WindowShadows::Private +{ +public: + Private(WindowShadows *shadows) + : q(shadows), + m_managePixmaps(false) + { + } + ~Private() + { + clearPixmaps(); + } + + void clearPixmaps(); + void setupPixmaps(); + void initPixmap(const QString &element); + void updateShadow(const QWidget *window); + void clearShadow(const QWidget *window); + void updateShadows(); + void windowDestroyed(QObject *deletedObject); + + WindowShadows *q; + QList m_shadowPixmaps; + QVector m_data; + QSet m_windows; + bool m_managePixmaps; +}; + +class WindowShadowsSingleton +{ + public: + WindowShadows self; +}; + +K_GLOBAL_STATIC(WindowShadowsSingleton, privateWindowShadowsSelf) + +WindowShadows *WindowShadows::self() +{ + return &privateWindowShadowsSelf->self; +} + +WindowShadows::WindowShadows(QObject *parent) + : Plasma::Svg(parent), + d(new Private(this)) +{ + setImagePath("dialogs/background"); + connect(this, SIGNAL(repaintNeeded()), this, SLOT(updateShadows())); +} + +void WindowShadows::addWindow(const QWidget *window) +{ + if (!window || !window->isWindow()) { + return; + } + + d->m_windows << window; + d->updateShadow(window); + connect(window, SIGNAL(destroyed(QObject*)), this, SLOT(windowDestroyed(QObject*))); +} + +void WindowShadows::removeWindow(const QWidget *window) +{ + if (!d->m_windows.contains(window)) { + return; + } + + d->m_windows.remove(window); + disconnect(window, 0, this, 0); + d->clearShadow(window); + + if (d->m_windows.isEmpty()) { + d->clearPixmaps(); + } +} + +void WindowShadows::Private::windowDestroyed(QObject *deletedObject) +{ + m_windows.remove(static_cast(deletedObject)); + + if (m_windows.isEmpty()) { + clearPixmaps(); + } +} + +void WindowShadows::Private::updateShadows() +{ + setupPixmaps(); + foreach (const QWidget *window, m_windows) { + updateShadow(window); + } +} + +void WindowShadows::Private::initPixmap(const QString &element) +{ +#ifdef Q_WS_X11 + QPixmap pix = q->pixmap(element); + if (pix.handle() == 0) { + Pixmap xPix = XCreatePixmap(QX11Info::display(), QX11Info::appRootWindow(), pix.width(), pix.height(), 32); + QPixmap tempPix = QPixmap::fromX11Pixmap(xPix, QPixmap::ExplicitlyShared); + tempPix.fill(Qt::transparent); + QPainter p(&tempPix); + p.drawPixmap(QPoint(0, 0), pix); + m_shadowPixmaps << tempPix; + m_managePixmaps = true; + } else { + m_shadowPixmaps << pix; + } +#endif +} + +void WindowShadows::Private::setupPixmaps() +{ + clearPixmaps(); + initPixmap("shadow-top"); + initPixmap("shadow-topright"); + initPixmap("shadow-right"); + initPixmap("shadow-bottomright"); + initPixmap("shadow-bottom"); + initPixmap("shadow-bottomleft"); + initPixmap("shadow-left"); + initPixmap("shadow-topleft"); + +#ifdef Q_WS_X11 + foreach (const QPixmap &pixmap, m_shadowPixmaps) { + m_data << pixmap.handle(); + } +#endif + + QSize marginHint = q->elementSize("shadow-hint-top-margin"); + if (marginHint.isValid()) { + m_data << marginHint.height(); + } else { + m_data << m_shadowPixmaps[0].height(); // top + } + + marginHint = q->elementSize("shadow-hint-right-margin"); + if (marginHint.isValid()) { + m_data << marginHint.width(); + } else { + m_data << m_shadowPixmaps[2].width(); // right + } + + marginHint = q->elementSize("shadow-hint-bottom-margin"); + if (marginHint.isValid()) { + m_data << marginHint.height(); + } else { + m_data << m_shadowPixmaps[4].height(); // bottom + } + + marginHint = q->elementSize("shadow-hint-left-margin"); + if (marginHint.isValid()) { + m_data << marginHint.width(); + } else { + m_data << m_shadowPixmaps[6].width(); // left + } +} + +void WindowShadows::Private::clearPixmaps() +{ +#ifdef Q_WS_X11 + if (m_managePixmaps) { + foreach (const QPixmap &pixmap, m_shadowPixmaps) { + XFreePixmap(QX11Info::display(), pixmap.handle()); + } + m_managePixmaps = false; + } +#endif + m_shadowPixmaps.clear(); + m_data.clear(); +} + +void WindowShadows::Private::updateShadow(const QWidget *window) +{ +#ifdef Q_WS_X11 + if (m_data.isEmpty()) { + setupPixmaps(); + } + + Display *dpy = QX11Info::display(); + Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False); + + //kDebug() << "going to set the shadow of" << winId() << "to" << data; + XChangeProperty(dpy, window->winId(), atom, XA_CARDINAL, 32, PropModeReplace, + reinterpret_cast(m_data.constData()), m_data.size()); +#endif +} + +void WindowShadows::Private::clearShadow(const QWidget *window) +{ +#ifdef Q_WS_X11 + Display *dpy = QX11Info::display(); + Atom atom = XInternAtom(dpy, "_KDE_NET_WM_SHADOW", False); + XDeleteProperty(dpy, window->winId(), atom); +#endif +} + +} // namespace Plasma + +#include "windowshadows_p.moc" + diff --git a/private/windowshadows_p.h b/private/windowshadows_p.h new file mode 100644 index 000000000..0b8d5b036 --- /dev/null +++ b/private/windowshadows_p.h @@ -0,0 +1,54 @@ +/* +* 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_WINDOWSHADOWS_H +#define PLASMA_WINDOWSHADOWS_H + +#include + +#include + +namespace Plasma +{ + +class WindowShadows : Plasma::Svg +{ + Q_OBJECT + +public: + static WindowShadows *self(); + + explicit WindowShadows(QObject *parent = 0); + + void addWindow(const QWidget *window); + void removeWindow(const QWidget *window); + +private Q_SLOTS: + +private: + class Private; + Private * const d; + + Q_PRIVATE_SLOT(d, void updateShadows()) + Q_PRIVATE_SLOT(d, void windowDestroyed(QObject *deletedObject)) +}; + +} // namespace Plasma + +#endif + diff --git a/widgets/itembackground.cpp b/widgets/itembackground.cpp index 3a26c3b48..960578daf 100644 --- a/widgets/itembackground.cpp +++ b/widgets/itembackground.cpp @@ -251,7 +251,7 @@ QVariant ItemBackground::itemChange(GraphicsItemChange change, const QVariant &v d->anim->stop(); } - d->anim->setDuration(250); + d->anim->setDuration(100); d->anim->start(); return retVisible;