On Tuesday 21 July 2009, Lucas Murray wrote:
> On Tue, Jul 21, 2009 at 11:59 AM, Lucas Murray<[email protected]>
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 [email protected]
+
+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 [email protected]
+
+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
[email protected]
+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
[email protected]
https://mail.kde.org/mailman/listinfo/plasma-devel