From 09b5b47b1ea5b964f8c3a72d9789f3de904a087e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lubo=C5=A1=20Lu=C5=88=C3=A1k?= Date: Mon, 16 Apr 2007 19:30:48 +0000 Subject: [PATCH] Integrate DesktopChangeSlide into DesktopGrid, so that they can co-exist without conflicting. svn path=/branches/work/kwin_composite/; revision=654687 --- effects/desktopchangeslide.cpp | 218 ----------------------------- effects/desktopchangeslide.desktop | 4 - effects/desktopchangeslide.h | 41 ------ effects/desktopgrid.cpp | 189 ++++++++++++++++++++++++- effects/desktopgrid.h | 6 + 5 files changed, 188 insertions(+), 270 deletions(-) delete mode 100644 effects/desktopchangeslide.cpp delete mode 100644 effects/desktopchangeslide.desktop delete mode 100644 effects/desktopchangeslide.h diff --git a/effects/desktopchangeslide.cpp b/effects/desktopchangeslide.cpp deleted file mode 100644 index 0ecb8d2286..0000000000 --- a/effects/desktopchangeslide.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/***************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - -Copyright (C) 2006 Lubos Lunak - -You can Freely distribute this program under the GNU General Public -License. See the file "COPYING" for the exact licensing terms. -******************************************************************/ - -#include "desktopchangeslide.h" - -namespace KWin -{ - -KWIN_EFFECT( DesktopChangeSlide, DesktopChangeSlideEffect ) - -const int MAX_PROGRESS = 500; // ms - -DesktopChangeSlideEffect::DesktopChangeSlideEffect() - : progress( MAX_PROGRESS ) - { - } - -void DesktopChangeSlideEffect::prePaintScreen( int* mask, QRegion* region, int time ) - { - progress = qBound( 0, progress + time, MAX_PROGRESS ); - // PAINT_SCREEN_BACKGROUND_FIRST is needed because screen will be actually painted more than once, - // so with normal screen painting second screen paint would erase parts of the first paint - if( progress != MAX_PROGRESS ) - *mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST; - effects->prePaintScreen( mask, region, time ); - } - -void DesktopChangeSlideEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time ) - { - if( progress != MAX_PROGRESS ) - { - if( w->isOnAllDesktops()) - { - if( painting_sticky ) - *mask |= PAINT_WINDOW_TRANSFORMED; - else - w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); - } - else if( w->isOnDesktop( painting_desktop )) - w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); - else - w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); - } - effects->prePaintWindow( w, mask, paint, clip, time ); - } - -void DesktopChangeSlideEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data ) - { - if( progress == MAX_PROGRESS ) - { - effects->paintScreen( mask, region, data ); - return; - } - /* - Transformations are done by remembering starting position of the change and the progress - of it, the destination is computed from the current desktop. Positions of desktops - are done using their topleft corner. - */ - QPoint destPos = desktopPos( effects->currentDesktop()); - QPoint diffPos = destPos - startPos; - int w = 0; - int h = 0; - if( effects->optionRollOverDesktops()) - { - int x, y; - Qt::Orientation orientation; - effects->calcDesktopLayout( &x, &y, &orientation ); - w = x * displayWidth(); - h = y * displayHeight(); - // wrap around if shorter - if( diffPos.x() > 0 && diffPos.x() > w / 2 ) - diffPos.setX( diffPos.x() - w ); - if( diffPos.x() < 0 && abs( diffPos.x()) > w / 2 ) - diffPos.setX( diffPos.x() + w ); - if( diffPos.y() > 0 && diffPos.y() > h / 2 ) - diffPos.setY( diffPos.y() - h ); - if( diffPos.y() < 0 && abs( diffPos.y()) > h / 2 ) - diffPos.setY( diffPos.y() + h ); - } - QPoint currentPos = startPos + progress * diffPos / MAX_PROGRESS; - QSize displaySize( displayWidth(), displayHeight()); - QRegion currentRegion = QRect( currentPos, displaySize ); - if( effects->optionRollOverDesktops()) - { - currentRegion |= ( currentRegion & QRect( -w, 0, w, h )).translated( w, 0 ); - currentRegion |= ( currentRegion & QRect( 0, -h, w, h )).translated( 0, h ); - currentRegion |= ( currentRegion & QRect( w, 0, w, h )).translated( -w, 0 ); - currentRegion |= ( currentRegion & QRect( 0, h, w, h )).translated( 0, -h ); - } - bool do_sticky = true; - for( int desktop = 1; - desktop <= effects->numberOfDesktops(); - ++desktop ) - { - QRect desktopRect( desktopPos( desktop ), displaySize ); - if( currentRegion.contains( desktopRect )) // part of the desktop needs painting - { - painting_desktop = desktop; - painting_sticky = do_sticky; - painting_diff = desktopRect.topLeft() - currentPos; - if( effects->optionRollOverDesktops()) - { - if( painting_diff.x() > displayWidth()) - painting_diff.setX( painting_diff.x() - w ); - if( painting_diff.x() < -displayWidth()) - painting_diff.setX( painting_diff.x() + w ); - if( painting_diff.y() > displayHeight()) - painting_diff.setY( painting_diff.y() - h ); - if( painting_diff.y() < -displayHeight()) - painting_diff.setY( painting_diff.y() + h ); - } - do_sticky = false; // paint on-all-desktop windows only once - ScreenPaintData d = data; - d.xTranslate += painting_diff.x(); - d.yTranslate += painting_diff.y(); - // TODO mask parts that are not visible? - effects->paintScreen( mask, region, d ); - } - } - } - -void DesktopChangeSlideEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) - { - if( progress != MAX_PROGRESS ) - { // don't move windows on all desktops (compensate screen transformation) - if( w->isOnAllDesktops()) // TODO also fix 'Workspace::movingClient' - { - data.xTranslate -= painting_diff.x(); - data.yTranslate -= painting_diff.y(); - } - } - effects->paintWindow( w, mask, region, data ); - } - -void DesktopChangeSlideEffect::postPaintScreen() - { - if( progress != MAX_PROGRESS ) - effects->addRepaintFull(); // trigger next animation repaint - effects->postPaintScreen(); - } - -// Gives a position of the given desktop when all desktops are arranged in a grid -QPoint DesktopChangeSlideEffect::desktopPos( int desktop ) - { - int x, y; - Qt::Orientation orientation; - effects->calcDesktopLayout( &x, &y, &orientation ); - --desktop; // make it start with 0 - if( orientation == Qt::Vertical ) - return QPoint(( desktop % x ) * displayWidth(), ( desktop / x ) * displayHeight()); - else - return QPoint(( desktop / y ) * displayWidth(), ( desktop % y ) * displayHeight()); - } - -void DesktopChangeSlideEffect::desktopChanged( int old ) - { - if( progress != MAX_PROGRESS ) // old slide still in progress - { - QPoint diffPos = desktopPos( old ) - startPos; - int w = 0; - int h = 0; - if( effects->optionRollOverDesktops()) - { - int x, y; - Qt::Orientation orientation; - effects->calcDesktopLayout( &x, &y, &orientation ); - w = x * displayWidth(); - h = y * displayHeight(); - // wrap around if shorter - if( diffPos.x() > 0 && diffPos.x() > w / 2 ) - diffPos.setX( diffPos.x() - w ); - if( diffPos.x() < 0 && abs( diffPos.x()) > w / 2 ) - diffPos.setX( diffPos.x() + w ); - if( diffPos.y() > 0 && diffPos.y() > h / 2 ) - diffPos.setY( diffPos.y() - h ); - if( diffPos.y() < 0 && abs( diffPos.y()) > h / 2 ) - diffPos.setY( diffPos.y() + h ); - } - QPoint currentPos = startPos + progress * diffPos / MAX_PROGRESS; - QRegion currentRegion = QRect( currentPos, QSize( displayWidth(), displayHeight())); - if( effects->optionRollOverDesktops()) - { - currentRegion |= ( currentRegion & QRect( -w, 0, w, h )).translated( w, 0 ); - currentRegion |= ( currentRegion & QRect( 0, -h, w, h )).translated( 0, h ); - currentRegion |= ( currentRegion & QRect( w, 0, w, h )).translated( -w, 0 ); - currentRegion |= ( currentRegion & QRect( 0, h, w, h )).translated( 0, -h ); - } - QRect desktopRect( desktopPos( effects->currentDesktop()), QSize( displayWidth(), displayHeight())); - if( currentRegion.contains( desktopRect )) - { // current position is in new current desktop (e.g. quickly changing back), - // don't do full progress - if( abs( currentPos.x() - desktopRect.x()) > abs( currentPos.y() - desktopRect.y())) - progress = MAX_PROGRESS - MAX_PROGRESS * abs( currentPos.x() - desktopRect.x()) / displayWidth(); - else - progress = MAX_PROGRESS - MAX_PROGRESS * abs( currentPos.y() - desktopRect.y()) / displayHeight(); - } - else // current position is not on current desktop, do full progress - progress = 0; - diffPos = desktopRect.topLeft() - currentPos; - // Compute starting point for this new move (given current and end positions) - startPos = desktopRect.topLeft() - diffPos * MAX_PROGRESS / ( MAX_PROGRESS - progress ); - } - else - { - progress = 0; - startPos = desktopPos( old ); - } - effects->addRepaintFull(); - } - -} // namespace diff --git a/effects/desktopchangeslide.desktop b/effects/desktopchangeslide.desktop deleted file mode 100644 index b83cf4905c..0000000000 --- a/effects/desktopchangeslide.desktop +++ /dev/null @@ -1,4 +0,0 @@ -[Desktop Entry] -Encoding=UTF-8 -Name=DesktopChangeSlide -X-KDE-Library=kwin4_effect_builtins diff --git a/effects/desktopchangeslide.h b/effects/desktopchangeslide.h deleted file mode 100644 index 73983cb4ad..0000000000 --- a/effects/desktopchangeslide.h +++ /dev/null @@ -1,41 +0,0 @@ -/***************************************************************** - KWin - the KDE window manager - This file is part of the KDE project. - -Copyright (C) 2006 Lubos Lunak - -You can Freely distribute this program under the GNU General Public -License. See the file "COPYING" for the exact licensing terms. -******************************************************************/ - -#ifndef KWIN_DESKTOPCHANGESLIDE_H -#define KWIN_DESKTOPCHANGESLIDE_H - -#include - -namespace KWin -{ - -class DesktopChangeSlideEffect - : public Effect - { - public: - DesktopChangeSlideEffect(); - virtual void prePaintScreen( int* mask, QRegion* region, int time ); - virtual void paintScreen( int mask, QRegion region, ScreenPaintData& data ); - virtual void postPaintScreen(); - virtual void prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time ); - virtual void paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ); - virtual void desktopChanged( int old ); - private: - QPoint desktopPos( int desktop ); - QPoint startPos; - int progress; - int painting_desktop; - bool painting_sticky; - QPoint painting_diff; - }; - -} // namespace - -#endif diff --git a/effects/desktopgrid.cpp b/effects/desktopgrid.cpp index 23e681ec97..57dee7db9d 100644 --- a/effects/desktopgrid.cpp +++ b/effects/desktopgrid.cpp @@ -20,10 +20,13 @@ namespace KWin KWIN_EFFECT( DesktopGrid, DesktopGridEffect ) +const int PROGRESS_TIME = 500; // ms + DesktopGridEffect::DesktopGridEffect() : progress( 0 ) , activated( false ) , keyboard_grab( false ) + , slide( false ) { KActionCollection* actionCollection = new KActionCollection( this ); KAction* a = static_cast< KAction* >( actionCollection->addAction( "ShowDesktopGrid" )); @@ -34,12 +37,25 @@ DesktopGridEffect::DesktopGridEffect() void DesktopGridEffect::prePaintScreen( int* mask, QRegion* region, int time ) { - if( progress != 0 || activated ) + if( slide ) + { + progress = qMin( 1.0, progress + time / double( PROGRESS_TIME )); + // PAINT_SCREEN_BACKGROUND_FIRST is needed because screen will be actually painted more than once, + // so with normal screen painting second screen paint would erase parts of the first paint + if( progress != 1 ) + *mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST; + else + { + slide = false; + progress = 0; + } + } + else if( progress != 0 || activated ) { if( activated ) - progress = qMin( 1.0, progress + time / 500. ); + progress = qMin( 1.0, progress + time / double( PROGRESS_TIME )); else - progress = qMax( 0.0, progress - time / 500. ); + progress = qMax( 0.0, progress - time / double( PROGRESS_TIME )); // PAINT_SCREEN_BACKGROUND_FIRST is needed because screen will be actually painted more than once, // so with normal screen painting second screen paint would erase parts of the first paint if( progress != 0 ) @@ -59,7 +75,21 @@ void DesktopGridEffect::prePaintScreen( int* mask, QRegion* region, int time ) void DesktopGridEffect::prePaintWindow( EffectWindow* w, int* mask, QRegion* paint, QRegion* clip, int time ) { - if( progress != 0 ) + if( slide ) + { + if( w->isOnAllDesktops()) + { + if( slide_painting_sticky ) + *mask |= PAINT_WINDOW_TRANSFORMED; + else + w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); + } + else if( w->isOnDesktop( painting_desktop )) + w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); + else + w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); + } + else if( progress != 0 ) { if( w->isOnDesktop( painting_desktop )) w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP ); @@ -76,6 +106,11 @@ void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData& effects->paintScreen( mask, region, data ); return; } + if( slide ) + { + paintSlide( mask, region, data ); + return; + } for( int desktop = 1; desktop <= effects->numberOfDesktops(); ++desktop ) @@ -96,9 +131,87 @@ void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData& } } +void DesktopGridEffect::paintSlide( int mask, QRegion region, const ScreenPaintData& data ) + { + /* + Transformations are done by remembering starting position of the change and the progress + of it, the destination is computed from the current desktop. Positions of desktops + are done using their topleft corner. + */ + QPoint destPos = desktopRect( effects->currentDesktop(), false ).topLeft(); + QPoint diffPos = destPos - slide_start_pos; + int w = 0; + int h = 0; + if( effects->optionRollOverDesktops()) + { + int x, y; + Qt::Orientation orientation; + effects->calcDesktopLayout( &x, &y, &orientation ); + w = x * displayWidth(); + h = y * displayHeight(); + // wrap around if shorter + if( diffPos.x() > 0 && diffPos.x() > w / 2 ) + diffPos.setX( diffPos.x() - w ); + if( diffPos.x() < 0 && abs( diffPos.x()) > w / 2 ) + diffPos.setX( diffPos.x() + w ); + if( diffPos.y() > 0 && diffPos.y() > h / 2 ) + diffPos.setY( diffPos.y() - h ); + if( diffPos.y() < 0 && abs( diffPos.y()) > h / 2 ) + diffPos.setY( diffPos.y() + h ); + } + QPoint currentPos = slide_start_pos + progress * diffPos; + QSize displaySize( displayWidth(), displayHeight()); + QRegion currentRegion = QRect( currentPos, displaySize ); + if( effects->optionRollOverDesktops()) + { + currentRegion |= ( currentRegion & QRect( -w, 0, w, h )).translated( w, 0 ); + currentRegion |= ( currentRegion & QRect( 0, -h, w, h )).translated( 0, h ); + currentRegion |= ( currentRegion & QRect( w, 0, w, h )).translated( -w, 0 ); + currentRegion |= ( currentRegion & QRect( 0, h, w, h )).translated( 0, -h ); + } + bool do_sticky = true; + for( int desktop = 1; + desktop <= effects->numberOfDesktops(); + ++desktop ) + { + QRect rect = desktopRect( desktop, false ); + if( currentRegion.contains( rect )) // part of the desktop needs painting + { + painting_desktop = desktop; + slide_painting_sticky = do_sticky; + slide_painting_diff = rect.topLeft() - currentPos; + if( effects->optionRollOverDesktops()) + { + if( slide_painting_diff.x() > displayWidth()) + slide_painting_diff.setX( slide_painting_diff.x() - w ); + if( slide_painting_diff.x() < -displayWidth()) + slide_painting_diff.setX( slide_painting_diff.x() + w ); + if( slide_painting_diff.y() > displayHeight()) + slide_painting_diff.setY( slide_painting_diff.y() - h ); + if( slide_painting_diff.y() < -displayHeight()) + slide_painting_diff.setY( slide_painting_diff.y() + h ); + } + do_sticky = false; // paint on-all-desktop windows only once + ScreenPaintData d = data; + d.xTranslate += slide_painting_diff.x(); + d.yTranslate += slide_painting_diff.y(); + // TODO mask parts that are not visible? + effects->paintScreen( mask, region, d ); + } + } + } + void DesktopGridEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data ) { - if( progress != 0 ) + if( slide ) + { // don't move windows on all desktops (compensate screen transformation) + if( w->isOnAllDesktops()) // TODO also fix 'Workspace::movingClient' + { + data.xTranslate -= slide_painting_diff.x(); + data.yTranslate -= slide_painting_diff.y(); + } + } + else if( progress != 0 ) { if( painting_desktop != hover_desktop ) data.brightness *= 0.7; @@ -108,6 +221,8 @@ void DesktopGridEffect::paintWindow( EffectWindow* w, int mask, QRegion region, void DesktopGridEffect::postPaintScreen() { + if( slide ) + effects->addRepaintFull(); if( activated ? progress != 1 : progress != 0 ) effects->addRepaintFull(); // trigger next animation repaint effects->postPaintScreen(); @@ -149,9 +264,69 @@ int DesktopGridEffect::posToDesktop( const QPoint& pos ) const return 0; } -void DesktopGridEffect::desktopChanged( int ) +void DesktopGridEffect::desktopChanged( int old ) { - setActive( false ); + if( activated ) + setActive( false ); + else + slideDesktopChanged( old ); + } + +void DesktopGridEffect::slideDesktopChanged( int old ) + { + if( slide ) // old slide still in progress + { + QPoint diffPos = desktopRect( old, false ).topLeft() - slide_start_pos; + int w = 0; + int h = 0; + if( effects->optionRollOverDesktops()) + { + int x, y; + Qt::Orientation orientation; + effects->calcDesktopLayout( &x, &y, &orientation ); + w = x * displayWidth(); + h = y * displayHeight(); + // wrap around if shorter + if( diffPos.x() > 0 && diffPos.x() > w / 2 ) + diffPos.setX( diffPos.x() - w ); + if( diffPos.x() < 0 && abs( diffPos.x()) > w / 2 ) + diffPos.setX( diffPos.x() + w ); + if( diffPos.y() > 0 && diffPos.y() > h / 2 ) + diffPos.setY( diffPos.y() - h ); + if( diffPos.y() < 0 && abs( diffPos.y()) > h / 2 ) + diffPos.setY( diffPos.y() + h ); + } + QPoint currentPos = slide_start_pos + progress * diffPos; + QRegion currentRegion = QRect( currentPos, QSize( displayWidth(), displayHeight())); + if( effects->optionRollOverDesktops()) + { + currentRegion |= ( currentRegion & QRect( -w, 0, w, h )).translated( w, 0 ); + currentRegion |= ( currentRegion & QRect( 0, -h, w, h )).translated( 0, h ); + currentRegion |= ( currentRegion & QRect( w, 0, w, h )).translated( -w, 0 ); + currentRegion |= ( currentRegion & QRect( 0, h, w, h )).translated( 0, -h ); + } + QRect rect = desktopRect( effects->currentDesktop(), false ); + if( currentRegion.contains( rect )) + { // current position is in new current desktop (e.g. quickly changing back), + // don't do full progress + if( abs( currentPos.x() - rect.x()) > abs( currentPos.y() - rect.y())) + progress = 1 - abs( currentPos.x() - rect.x()) / float( displayWidth()); + else + progress = 1 - abs( currentPos.y() - rect.y()) / float( displayHeight()); + } + else // current position is not on current desktop, do full progress + progress = 0; + diffPos = rect.topLeft() - currentPos; + // Compute starting point for this new move (given current and end positions) + slide_start_pos = rect.topLeft() - diffPos * 1 / ( 1 - progress ); + } + else + { + progress = 0; + slide_start_pos = desktopRect( old, false ).topLeft(); + slide = true; + } + effects->addRepaintFull(); } void DesktopGridEffect::toggle() diff --git a/effects/desktopgrid.h b/effects/desktopgrid.h index 4d95daa781..b12e33ebab 100644 --- a/effects/desktopgrid.h +++ b/effects/desktopgrid.h @@ -39,12 +39,18 @@ class DesktopGridEffect void setActive( bool active ); void setup(); void finish(); + void paintSlide( int mask, QRegion region, const ScreenPaintData& data ); + void slideDesktopChanged( int old ); float progress; bool activated; int painting_desktop; int hover_desktop; Window input; bool keyboard_grab; + bool slide; + QPoint slide_start_pos; + bool slide_painting_sticky; + QPoint slide_painting_diff; }; } // namespace