On Tuesday 21 July 2009, Lucas Murray wrote: > On Tue, Jul 21, 2009 at 11:59 AM, Lucas Murray<lmur...@undefinedfire.com> wrote: > > The property would look something like: _KDE_SLIDE = {x1, y1, x2, y2, > > direction} where the two coordinates must be either exactly horizontal > > or vertical and the direction is 0 for coming from the top/left and 1 > > is for coming from the bottom/right when the window appears. When the > > window is closed it goes back the way it came (Changing the property > > while the window is mapped allows you to make the window slide to a > > different location on close). The coordinates specify the clipping > > geometry--it starts at the coords and ends at the (Xinerama) screen > > edge in the direction that the window specified. > > Two coordinates are not required, it's possible with just one value. > Thus the property would be {coord, direction} where `direction` is 0 = > left, 1 = right, 2 = top, 3 = bottom and `coord` specifies either the > starting X or Y position, depending on the direction.
Here we go, now the direction and the starting points are specified by the _KDE_SLIDE atom. and plasma::dialog sets it, it seems to work quite good. for plasma side: is the custom anim code in Dialog and Panel to be removed? or should be there some kind of fallback for Compiz/Windows/whatever? Cheers, Marco Martin
Index: slidingpopups/slidingpopups.cpp =================================================================== --- slidingpopups/slidingpopups.cpp (revision 0) +++ slidingpopups/slidingpopups.cpp (revision 0) @@ -0,0 +1,180 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2009 Marco Martin notm...@gmail.com + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, 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 General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*********************************************************************/ + +#include "slidingpopups.h" + +#include <kdebug.h> + +namespace KWin +{ + +KWIN_EFFECT( slidingpopups, SlidingPopupsEffect ) + +SlidingPopupsEffect::SlidingPopupsEffect() + { + mAtom = XInternAtom( display(), "_KDE_SLIDE", False ); + effects->registerPropertyType( mAtom, true ); + // TODO hackish way to announce support, make better after 4.0 + unsigned char dummy = 0; + XChangeProperty( display(), rootWindow(), mAtom, mAtom, 8, PropModeReplace, &dummy, 1 ); + } + +SlidingPopupsEffect::~SlidingPopupsEffect() + { + XDeleteProperty( display(), rootWindow(), mAtom ); + effects->registerPropertyType( mAtom, false ); + } + +void SlidingPopupsEffect::prePaintScreen( ScreenPrePaintData& data, int time ) + { + if( !mAppearingWindows.isEmpty() || !mDisappearingWindows.isEmpty() ) + data.mask |= PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS; + effects->prePaintScreen( data, time ); + } + +void SlidingPopupsEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ) + { + if( mAppearingWindows.contains( w ) ) + { + mAppearingWindows[ w ].addTime( time ); + if( mAppearingWindows[ w ].value() < 1 ) + data.setTransformed(); + else + mAppearingWindows.remove( w ); + } + else if( mDisappearingWindows.contains( w ) ) + { + mDisappearingWindows[ w ].addTime( time ); + if( mDisappearingWindows[ w ].value() < 1 ) + data.setTransformed(); + else + { + mDisappearingWindows.remove( w ); + w->unrefWindow(); + } + } + effects->prePaintWindow( w, data, time ); + } + +void SlidingPopupsEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) + { + bool animating = false; + bool appearing = false; + QRegion clippedRegion = region; + + if( mAppearingWindows.contains( w ) ) + { + appearing = true; + animating = true; + } + else if( mDisappearingWindows.contains( w ) ) + { + appearing = false; + animating = true; + } + + + if( animating ) + { + const qreal progress = appearing?(1 - mAppearingWindows[ w ].value()):mDisappearingWindows[ w ].value(); + const int start = mWindowsData[ w ].start; + + switch (mWindowsData[ w ].from) + { + case West: + data.xTranslate += (start - w->width()) * progress; + clippedRegion = clippedRegion.subtracted(QRegion(start - w->width(), w->y(), w->width(), w->height())); + break; + case North: + data.yTranslate += (start - w->height()) * progress; + clippedRegion = clippedRegion.subtracted(QRegion(w->x(), start - w->height(), w->width(), w->height())); + break; + case East: + data.xTranslate += (start - w->x()) * progress; + clippedRegion = clippedRegion.subtracted(QRegion(w->x()+w->width(), w->y(), w->width(), w->height())); + break; + case South: + default: + data.yTranslate += (start - w->y()) * progress; + clippedRegion = clippedRegion.subtracted(QRegion(w->x(), start, w->width(), w->height())); + } + } + + effects->paintWindow( w, mask, clippedRegion, data ); + } + +void SlidingPopupsEffect::postPaintWindow( EffectWindow* w ) + { + if( mAppearingWindows.contains( w ) || mDisappearingWindows.contains( w ) ) + w->addRepaintFull(); // trigger next animation repaint + effects->postPaintWindow( w ); + } + +void SlidingPopupsEffect::windowAdded( EffectWindow* w ) + { + propertyNotify( w, mAtom ); + if( w->isOnCurrentDesktop() && mWindowsData.contains( w ) ) + { + mAppearingWindows[ w ].setDuration( animationTime( 250 )); + mAppearingWindows[ w ].setProgress( 0.0 ); + mAppearingWindows[ w ].setCurveShape( TimeLine::EaseOutCurve ); + + w->addRepaintFull(); + } + } + +void SlidingPopupsEffect::windowClosed( EffectWindow* w ) + { + propertyNotify( w, mAtom ); + if( w->isOnCurrentDesktop() && !w->isMinimized() && mWindowsData.contains( w ) ) + { + w->refWindow(); + propertyNotify( w, mAtom ); + mAppearingWindows.remove( w ); + mDisappearingWindows[ w ].setDuration( animationTime( 250 )); + mDisappearingWindows[ w ].setProgress( 0.0 ); + mDisappearingWindows[ w ].setCurveShape( TimeLine::EaseOutCurve ); + + w->addRepaintFull(); + } + } + +void SlidingPopupsEffect::windowDeleted( EffectWindow* w ) + { + mAppearingWindows.remove( w ); + mDisappearingWindows.remove( w ); + mWindowsData.remove( w ); + } + +void SlidingPopupsEffect::propertyNotify( EffectWindow* w, long a ) + { + if( a != mAtom ) + return; + + QByteArray data = w->readProperty( mAtom, mAtom, 32 ); + if( data.length() < 1 ) + return; + long* d = reinterpret_cast< long* >( data.data()); + Data animData; + animData.start = d[ 0 ]; + animData.from = (Position)d[ 1 ]; + mWindowsData[ w ] = animData; + } +} // namespace Index: slidingpopups/slidingpopups.h =================================================================== --- slidingpopups/slidingpopups.h (revision 0) +++ slidingpopups/slidingpopups.h (revision 0) @@ -0,0 +1,67 @@ +/******************************************************************** + KWin - the KDE window manager + This file is part of the KDE project. + +Copyright (C) 2009 Marco Martin notm...@gmail.com + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, 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 General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. +*********************************************************************/ + +#ifndef KWIN_SLIDEBACK_H +#define KWIN_SLIDEBACK_H + +// Include with base class for effects. +#include <kwineffects.h> + +namespace KWin +{ + +class SlidingPopupsEffect + : public Effect + { + public: + SlidingPopupsEffect(); + ~SlidingPopupsEffect(); + virtual void prePaintScreen( ScreenPrePaintData& data, int time ); + virtual void prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time ); + virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); + virtual void postPaintWindow( EffectWindow* w ); + // TODO react also on virtual desktop changes + virtual void windowAdded( EffectWindow* c ); + virtual void windowClosed( EffectWindow* c ); + virtual void windowDeleted( EffectWindow* c ); + virtual void propertyNotify( EffectWindow* w, long a ); + private: + enum Position + { + West = 0, + North = 1, + East = 2, + South = 3 + }; + struct Data + { + int start; //point in screen coordinates where the window starts + //to animate, from decides if this point is an x or an y + Position from; + }; + long mAtom; + QHash< const EffectWindow*, TimeLine > mAppearingWindows; + QHash< const EffectWindow*, TimeLine > mDisappearingWindows; + QHash< const EffectWindow*, Data > mWindowsData; + }; + +} // namespace + +#endif Index: slidingpopups/slidingpopups.desktop =================================================================== --- slidingpopups/slidingpopups.desktop (revision 0) +++ slidingpopups/slidingpopups.desktop (revision 0) @@ -0,0 +1,18 @@ +[Desktop Entry] +Name=Sliding popups + +Type=Service +Comment=Sliding animation for Plasma popups + +Icon=preferences-system-windows-effect-slidingpopups +X-KDE-ServiceTypes=KWin/Effect +X-KDE-PluginInfo-Author=Marco Martin +x-kde-plugininfo-email=notm...@gmail.com +X-KDE-PluginInfo-Name=kwin4_effect_slidingpopups +X-KDE-PluginInfo-Version=0.1 +X-KDE-PluginInfo-Category=Appearance +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-Library=kwin4_effect_builtins +X-KDE-Ordering=50 Index: slidingpopups/CMakeLists.txt =================================================================== --- slidingpopups/CMakeLists.txt (revision 0) +++ slidingpopups/CMakeLists.txt (revision 0) @@ -0,0 +1,12 @@ +####################################### +# Effect + +# Source files +set( kwin4_effect_builtins_sources ${kwin4_effect_builtins_sources} + slidingpopups/slidingpopups.cpp + ) + +# .desktop files +install( FILES + slidingpopups/slidingpopups.desktop + DESTINATION ${SERVICES_INSTALL_DIR}/kwin ) Index: CMakeLists.txt =================================================================== --- CMakeLists.txt (revision 1000423) +++ CMakeLists.txt (working copy) @@ -71,6 +71,7 @@ include( showpaint/CMakeLists.txt ) include( slide/CMakeLists.txt ) include( slideback/CMakeLists.txt ) +include( slidingpopups/CMakeLists.txt ) include( taskbarthumbnail/CMakeLists.txt ) include( thumbnailaside/CMakeLists.txt ) include( zoom/CMakeLists.txt )
Index: dialog.cpp =================================================================== --- dialog.cpp (revision 1000396) +++ dialog.cpp (working copy) @@ -37,6 +37,7 @@ #include <QtGui/QGraphicsWidget> #include <QApplication> #include <QDesktopWidget> +#include <QVarLengthArray> #include <kdebug.h> #include <kwindowsystem.h> @@ -553,36 +554,80 @@ void Dialog::animatedHide(Plasma::Direction direction) { - if (d->hideAnimId) { - // already hiding/showing + if (!KWindowSystem::compositingActive()) { + hide(); return; } - if (KWindowSystem::compositingActive() && d->view) { - //TODO: implement for the QWidget scenario too - d->hideDirection = direction; - d->hideAnimId = Animator::self()->customAnimation(20, 200, Animator::EaseOutCurve, - this, "progressHide"); - } else { - hide(); + //set again the atom, the location could have changed + QDesktopWidget *desktop = QApplication::desktop(); + QRect avail = desktop->availableGeometry(desktop->screenNumber(pos())); + + Display *dpy = QX11Info::display(); + Atom atom = XInternAtom( dpy, "_KDE_SLIDE", False ); + QVarLengthArray<long, 1024> data(2); + + switch (direction) { + case Left: + data[0] = avail.left(); + data[1] = 0; + break; + case Up: + data[0] = avail.top(); + data[1] = 1; + break; + case Right: + data[0] = avail.right(); + data[1] = 2; + break; + case Down: + default: + data[0] = avail.bottom(); + data[1] = 3; } + + XChangeProperty(dpy, winId(), atom, atom, 32, PropModeReplace, + reinterpret_cast<unsigned char *>(data.data()), data.size()); + hide(); } void Dialog::animatedShow(Plasma::Direction direction) { - if (d->hideAnimId) { - // already hiding/showing + if (!KWindowSystem::compositingActive()) { + show(); return; } - if (KWindowSystem::compositingActive() && d->view) { - //TODO: implement for the QWidget scenario too - d->hideDirection = direction; - d->hideAnimId = Animator::self()->customAnimation(5, 100, Animator::EaseInCurve, - this, "progressShow"); - } else { - show(); + QDesktopWidget *desktop = QApplication::desktop(); + QRect avail = desktop->availableGeometry(desktop->screenNumber(pos())); + + Display *dpy = QX11Info::display(); + Atom atom = XInternAtom( dpy, "_KDE_SLIDE", False ); + QVarLengthArray<long, 1024> data(2); + + switch (direction) { + case Right: + data[0] = avail.left(); + data[1] = 0; + break; + case Down: + data[0] = avail.top(); + data[1] = 1; + break; + case Left: + data[0] = avail.right(); + data[1] = 2; + break; + case Up: + default: + data[0] = avail.bottom(); + data[1] = 3; } + + XChangeProperty(dpy, winId(), atom, atom, 32, PropModeReplace, + reinterpret_cast<unsigned char *>(data.data()), data.size()); + show(); + } void DialogPrivate::progressShow(qreal amount)
_______________________________________________ Plasma-devel mailing list Plasma-devel@kde.org https://mail.kde.org/mailman/listinfo/plasma-devel