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

Reply via email to