50d9cd1be0
BUG: 165296 svn path=/trunk/KDE/kdebase/workspace/; revision=826357
885 lines
33 KiB
C++
885 lines
33 KiB
C++
/********************************************************************
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.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 "coverswitch.h"
|
|
|
|
#include <kwinconfig.h>
|
|
#include <QFont>
|
|
#include <QBitmap>
|
|
#include <klocale.h>
|
|
#include <kapplication.h>
|
|
#include <kcolorscheme.h>
|
|
#include <kconfiggroup.h>
|
|
|
|
#include <kwinglutils.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <GL/gl.h>
|
|
|
|
namespace KWin
|
|
{
|
|
|
|
KWIN_EFFECT( coverswitch, CoverSwitchEffect )
|
|
|
|
CoverSwitchEffect::CoverSwitchEffect()
|
|
: mActivated( 0 )
|
|
, angle( 60.0 )
|
|
, animation( false )
|
|
, start( false )
|
|
, stop( false )
|
|
, forward( true )
|
|
, rearrangeWindows( 0 )
|
|
, stopRequested( false )
|
|
, startRequested( false )
|
|
, twinview( false )
|
|
{
|
|
KConfigGroup conf = effects->effectConfig( "CoverSwitch" );
|
|
animationDuration = conf.readEntry( "Duration", 200 );
|
|
animateSwitch = conf.readEntry( "AnimateSwitch", true );
|
|
animateStart = conf.readEntry( "AnimateStart", true );
|
|
animateStop = conf.readEntry( "AnimateStop", true );
|
|
reflection = conf.readEntry( "Reflection", true );
|
|
timeLine.setCurveShape( TimeLine::EaseInOutCurve );
|
|
timeLine.setDuration( animationDuration );
|
|
}
|
|
|
|
CoverSwitchEffect::~CoverSwitchEffect()
|
|
{
|
|
}
|
|
|
|
void CoverSwitchEffect::prePaintScreen( ScreenPrePaintData& data, int time )
|
|
{
|
|
if( mActivated || stop || stopRequested )
|
|
{
|
|
data.mask |= Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
|
|
if( animation || start || stop )
|
|
{
|
|
timeLine.addTime( (double)time );
|
|
}
|
|
}
|
|
effects->prePaintScreen(data, time);
|
|
}
|
|
|
|
void CoverSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
|
|
{
|
|
effects->paintScreen( mask, region, data );
|
|
|
|
if( mActivated || stop || stopRequested )
|
|
{
|
|
glMatrixMode( GL_PROJECTION );
|
|
glPushMatrix();
|
|
glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT );
|
|
glLoadIdentity();
|
|
int viewport[4];
|
|
glGetIntegerv( GL_VIEWPORT, viewport );
|
|
int yPos = area.y();
|
|
QRect fullArea = effects->clientArea( FullArea, effects->activeScreen(), effects->currentDesktop());
|
|
if( twinview )
|
|
{
|
|
if( effects->clientArea( FullScreenArea, effects->activeScreen(), effects->currentDesktop()).x() == 0
|
|
&& effects->clientArea( FullScreenArea, effects->activeScreen()==0?1:0, effects->currentDesktop()).x() == 0 )
|
|
{
|
|
// top <-> bottom
|
|
// have to correct the yPos for top bottom constellation
|
|
yPos = area.height()-area.y();
|
|
if( ( area.height() * 2 != fullArea.height() ) ||
|
|
( effects->clientArea( FullScreenArea, effects->activeScreen(), effects->currentDesktop()).width() !=
|
|
effects->clientArea( FullScreenArea, effects->activeScreen()==0?1:0, effects->currentDesktop()).width() ) )
|
|
{
|
|
// different resolutions
|
|
if( area.y() > 0 )
|
|
yPos = 0;
|
|
else
|
|
yPos = fullArea.height() - area.height();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// left <-> right
|
|
if( ( area.width() * 2 != fullArea.width() ) ||
|
|
( effects->clientArea( FullScreenArea, effects->activeScreen(), effects->currentDesktop()).height() !=
|
|
effects->clientArea( FullScreenArea, effects->activeScreen()==0?1:0, effects->currentDesktop()).height() ) )
|
|
{
|
|
// different resolutions
|
|
yPos = area.y() + fullArea.height() - area.height();
|
|
}
|
|
}
|
|
}
|
|
float left, right, top, bottom;
|
|
left = -area.width() * 0.5f;
|
|
right = area.width() * 0.5f;
|
|
top = area.height()*0.5f;
|
|
bottom = -area.height()*0.5f;
|
|
if( twinview && ( start || stop ) )
|
|
{
|
|
// special handling for start and stop animation in twin view setup
|
|
glViewport( fullArea.x(), fullArea.y(), fullArea.width(), fullArea.height() );
|
|
left = -(area.x() + area.width() * 0.5f);
|
|
right = fullArea.width() + left;
|
|
bottom = -(area.y() + area.height() * 0.5f);
|
|
top = fullArea.height() + bottom;
|
|
}
|
|
else
|
|
{
|
|
glViewport( area.x(), yPos, area.width(), area.height() );
|
|
}
|
|
glFrustum( left, right, top, bottom, 10, 50 );
|
|
|
|
glMatrixMode( GL_MODELVIEW );
|
|
glLoadIdentity();
|
|
glPushMatrix();
|
|
glTranslatef(left, bottom, -7.5);
|
|
|
|
QList< EffectWindow* > tempList = effects->currentTabBoxWindowList();
|
|
int index = tempList.indexOf( effects->currentTabBoxWindow() );
|
|
if( animation || start || stop )
|
|
{
|
|
if( !start && !stop )
|
|
{
|
|
if( forward )
|
|
index--;
|
|
else
|
|
index++;
|
|
}
|
|
index += rearrangeWindows;
|
|
if( index < 0 )
|
|
index = tempList.count() + index;
|
|
if( index >= tempList.count() )
|
|
index = index % tempList.count();
|
|
}
|
|
int rightIndex = index -1;
|
|
if( rightIndex < 0 )
|
|
rightIndex = tempList.count() -1;
|
|
int leftIndex = index +1;
|
|
if( leftIndex == tempList.count() )
|
|
leftIndex = 0;
|
|
|
|
EffectWindow* frontWindow = tempList[ index ];
|
|
QList< EffectWindow* > leftWindows;
|
|
QList< EffectWindow* > rightWindows;
|
|
|
|
bool evenWindows = ( tempList.count() % 2 == 0 ) ? true : false;
|
|
int leftWindowCount = 0;
|
|
if( evenWindows )
|
|
leftWindowCount = tempList.count()/2;
|
|
else
|
|
leftWindowCount = ( tempList.count() - 1 )/2;
|
|
for( int i=0; i < leftWindowCount; i++ )
|
|
{
|
|
int tempIndex = ( leftIndex + i ) % tempList.count();
|
|
leftWindows.prepend( tempList[ tempIndex ] );
|
|
}
|
|
int rightWindowCount = 0;
|
|
if( evenWindows )
|
|
rightWindowCount = tempList.count()/2 - 1;
|
|
else
|
|
rightWindowCount = ( tempList.count() - 1 )/2;
|
|
for( int i=0; i < rightWindowCount; i++ )
|
|
{
|
|
int tempIndex = ( rightIndex - i );
|
|
if( tempIndex < 0 )
|
|
tempIndex = tempList.count() + tempIndex;
|
|
rightWindows.prepend( tempList[ tempIndex ] );
|
|
}
|
|
|
|
if( reflection )
|
|
{
|
|
// no reflections during start and stop animation
|
|
if( !start && !stop )
|
|
paintScene( frontWindow, &leftWindows, &rightWindows, true );
|
|
glEnable( GL_BLEND );
|
|
glBlendFunc( GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA );
|
|
glPolygonMode( GL_FRONT, GL_FILL );
|
|
glPushMatrix();
|
|
float leftVertex = 0.0;
|
|
if( twinview && ( start || stop ) )
|
|
{
|
|
leftVertex = area.x();
|
|
glTranslatef( 0.0, area.y() + area.height(), 7.5);
|
|
}
|
|
else
|
|
{
|
|
glTranslatef( 0.0, area.height(), 7.5);
|
|
}
|
|
float vertices[] = {
|
|
leftVertex, 0.0, -10.0,
|
|
leftVertex + area.width(), 0.0, -10.0,
|
|
leftVertex + area.width()*3, 0.0, -50.0,
|
|
leftVertex - area.width()*2, 0.0, -50.0 };
|
|
// foreground
|
|
float alpha = 1.0;
|
|
if( start )
|
|
alpha = timeLine.value();
|
|
else if( stop )
|
|
alpha = 1.0 - timeLine.value();
|
|
glColor4f( 0.0, 0.0, 0.0, alpha );
|
|
glBegin( GL_POLYGON );
|
|
glVertex3f( vertices[0], vertices[1], vertices[2] );
|
|
glVertex3f( vertices[3], vertices[4], vertices[5] );
|
|
// rearground
|
|
alpha = -1.0;
|
|
glColor4f( 0.0, 0.0, 0.0, alpha );
|
|
glVertex3f( vertices[6], vertices[7], vertices[8] );
|
|
glVertex3f( vertices[9], vertices[10], vertices[11] );
|
|
glEnd();
|
|
glPopMatrix();
|
|
glDisable( GL_BLEND );
|
|
}
|
|
paintScene( frontWindow, &leftWindows, &rightWindows );
|
|
|
|
glPopMatrix();
|
|
glPopAttrib();
|
|
glMatrixMode( GL_PROJECTION );
|
|
glPopMatrix();
|
|
glMatrixMode( GL_MODELVIEW );
|
|
glViewport( viewport[0], viewport[1], viewport[2], viewport[3] );
|
|
|
|
// caption of selected window
|
|
QColor color_frame;
|
|
QColor color_text;
|
|
color_frame = KColorScheme( QPalette::Active, KColorScheme::Window ).background().color();
|
|
color_frame.setAlphaF( 0.9 );
|
|
color_text = KColorScheme( QPalette::Active, KColorScheme::Window ).foreground().color();
|
|
if( start )
|
|
{
|
|
color_frame.setAlphaF( 0.9 * timeLine.value() );
|
|
color_text.setAlphaF( timeLine.value() );
|
|
}
|
|
else if( stop )
|
|
{
|
|
color_frame.setAlphaF( 0.9 - 0.9 * timeLine.value() );
|
|
color_text.setAlphaF( 1.0 - timeLine.value() );
|
|
}
|
|
QFont text_font;
|
|
text_font.setBold( true );
|
|
text_font.setPointSize( 20 );
|
|
glPushAttrib( GL_CURRENT_BIT );
|
|
glColor4f( color_frame.redF(), color_frame.greenF(), color_frame.blueF(), color_frame.alphaF());
|
|
QRect frameRect = QRect( area.width()*0.25f + area.x(),
|
|
area.height()*0.9f + area.y(),
|
|
area.width()*0.5f,
|
|
QFontMetrics( text_font ).height() * 1.2f );
|
|
renderRoundBoxWithEdge( frameRect );
|
|
effects->paintText( effects->currentTabBoxWindow()->caption(),
|
|
frameRect.center(),
|
|
frameRect.width() - 100,
|
|
color_text,
|
|
text_font );
|
|
glPopAttrib();
|
|
// icon of selected window
|
|
QPixmap iconPixmap = effects->currentTabBoxWindow()->icon();
|
|
if( start || stop )
|
|
{
|
|
int alpha = 255.0f * timeLine.value();
|
|
if( stop )
|
|
{
|
|
alpha = 255.0f - alpha;
|
|
}
|
|
QPixmap transparency = iconPixmap.copy( iconPixmap.rect() );
|
|
transparency.fill( QColor( 255, 255, 255, alpha ) );
|
|
iconPixmap.setAlphaChannel( transparency.alphaChannel() );
|
|
}
|
|
GLTexture* icon = new GLTexture( iconPixmap );
|
|
icon->bind();
|
|
glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT );
|
|
icon->bind();
|
|
glEnable( GL_BLEND );
|
|
glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
|
|
// icon takes 80 % of the height of the frame. So each 10 % space left on the top and botton
|
|
QRect iconRect = QRect( frameRect.x() + frameRect.height()*0.1f,
|
|
frameRect.y() + frameRect.height()*0.1f,
|
|
frameRect.height()*0.8f,
|
|
frameRect.height()*0.8f );
|
|
icon->render( region, iconRect);
|
|
icon->unbind();
|
|
delete icon;
|
|
glDisable( GL_BLEND );
|
|
glPopAttrib();
|
|
}
|
|
}
|
|
|
|
void CoverSwitchEffect::postPaintScreen()
|
|
{
|
|
if( ( mActivated && ( animation || start ) ) || stop || stopRequested )
|
|
{
|
|
if( timeLine.value() == 1.0 )
|
|
{
|
|
timeLine.setProgress(0.0);
|
|
if( stop )
|
|
{
|
|
stop = false;
|
|
effects->setActiveFullScreenEffect( 0 );
|
|
if( startRequested )
|
|
{
|
|
startRequested = false;
|
|
mActivated = true;
|
|
effects->refTabBox();
|
|
selectedWindow = effects->currentTabBoxWindowList().indexOf(effects->currentTabBoxWindow());
|
|
if( animateStart )
|
|
{
|
|
start = true;
|
|
}
|
|
}
|
|
}
|
|
else if( rearrangeWindows != 0 )
|
|
{
|
|
if( rearrangeWindows < 0 )
|
|
rearrangeWindows++;
|
|
else
|
|
rearrangeWindows--;
|
|
if( start )
|
|
{
|
|
animation = true;
|
|
start = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
animation = false;
|
|
start = false;
|
|
if( stopRequested )
|
|
{
|
|
stopRequested = false;
|
|
stop = true;
|
|
}
|
|
}
|
|
}
|
|
effects->addRepaintFull();
|
|
}
|
|
effects->postPaintScreen();
|
|
}
|
|
|
|
void CoverSwitchEffect::paintScene( EffectWindow* frontWindow, QList< EffectWindow* >* leftWindows,
|
|
QList< EffectWindow* >* rightWindows, bool reflectedWindows )
|
|
{
|
|
// LAYOUT
|
|
// one window in the front. Other windows left and right rotated
|
|
// for odd number of windows: left: (n-1)/2; front: 1; right: (n-1)/2
|
|
// for even number of windows: left: n/2; front: 1; right: n/2 -1
|
|
//
|
|
// ANIMATION
|
|
// forward (alt+tab)
|
|
// all left windows are moved to next position
|
|
// top most left window is rotated and moved to front window position
|
|
// front window is rotated and moved to next right window position
|
|
// right windows are moved to next position
|
|
// last right window becomes totally transparent in half the time
|
|
// appears transparent on left side and becomes totally opaque again
|
|
// backward (alt+shift+tab) same as forward but opposite direction
|
|
int width = area.width();
|
|
int height = area.height();
|
|
int leftWindowCount = leftWindows->count();
|
|
int rightWindowCount = rightWindows->count();
|
|
|
|
|
|
// Problem during animation: a window which is painted after another window
|
|
// appears in front of the other
|
|
// so during animation the painting order has to be rearreanged
|
|
// paint sequence no animation: left, right, front
|
|
// paint sequence forward animation: right, front, left
|
|
|
|
if( start || stop )
|
|
{
|
|
// start or stop animation
|
|
float radian = angle * timeLine.value() * ( 2 * M_PI / 360 );
|
|
if( stop )
|
|
radian = ( angle - angle * timeLine.value() ) * ( 2 * M_PI / 360 );
|
|
int x, y;
|
|
// left windows
|
|
for( int i=0; i< leftWindowCount; i++ )
|
|
{
|
|
EffectWindow* window = leftWindows->at( i );
|
|
if( window == NULL )
|
|
continue;
|
|
x = window->x();
|
|
y = window->y();
|
|
if( window->isMinimized() )
|
|
{
|
|
// use icon instead of window
|
|
x = window->iconGeometry().x();
|
|
y = window->iconGeometry().y();
|
|
}
|
|
glPushMatrix();
|
|
int windowHeight = window->geometry().height();
|
|
float distance = -width*0.25f + ( width * 0.25f * i )/leftWindowCount - x + area.x();
|
|
float distanceY = height - windowHeight - y + area.y();
|
|
if( start )
|
|
glTranslatef( distance*timeLine.value() + x, distanceY * timeLine.value() + y, -5 * timeLine.value() - 2.5);
|
|
else if( stop )
|
|
glTranslatef( distance*( 1.0 - timeLine.value() ) + x, distanceY * ( 1.0 -timeLine.value() ) + y, -5 * ( 1.0 - timeLine.value() ) - 2.5);
|
|
glRotatef( radian, 0.0, 1.0, 0.0 );
|
|
int windowWidth = window->geometry().width() * cos( radian );
|
|
QRect windowRect = QRect( 0, 0, windowWidth, windowHeight );
|
|
paintWindowCover( window, windowRect, reflectedWindows );
|
|
glPopMatrix();
|
|
}
|
|
|
|
// right windows
|
|
for( int i=0; i < rightWindowCount; i++ )
|
|
{
|
|
EffectWindow* window = rightWindows->at( i );
|
|
if( window == NULL )
|
|
continue;
|
|
x = window->x();
|
|
y = window->y();
|
|
if( window->isMinimized() )
|
|
{
|
|
// use icon instead of window
|
|
x = window->iconGeometry().x();
|
|
y = window->iconGeometry().y();
|
|
}
|
|
glPushMatrix();
|
|
int windowWidth = window->geometry().width() * cos( radian );
|
|
int windowHeight = window->geometry().height();
|
|
float distance = width*1.25f - ( width * 0.25f * i )/rightWindowCount - x - windowWidth + area.x();
|
|
float distanceY = height - windowHeight - y + area.y();
|
|
if( start )
|
|
glTranslatef( distance*timeLine.value() + x + windowWidth, distanceY * timeLine.value() + y, -5 * timeLine.value() - 2.5);
|
|
else if( stop )
|
|
glTranslatef( distance*( 1.0 - timeLine.value() ) + x + windowWidth, distanceY * ( 1.0 - timeLine.value() ) + y, -5 * ( 1.0 - timeLine.value() ) - 2.5);
|
|
glRotatef( -radian, 0.0, 1.0, 0.0 );
|
|
QRect windowRect = QRect( -windowWidth, 0, windowWidth, windowHeight );
|
|
paintWindowCover( window, windowRect, reflectedWindows );
|
|
glPopMatrix();
|
|
}
|
|
|
|
// front window
|
|
if( frontWindow == NULL )
|
|
return;
|
|
glPushMatrix();
|
|
x = frontWindow->x();
|
|
y = frontWindow->y();
|
|
if( frontWindow->isMinimized() )
|
|
{
|
|
// use icon instead of window
|
|
x = frontWindow->iconGeometry().x();
|
|
y = frontWindow->iconGeometry().y();
|
|
}
|
|
int windowHeight = frontWindow->geometry().height();
|
|
float distance = (width - frontWindow->geometry().width())*0.5f - x + area.x();
|
|
float distanceY = height - windowHeight - y + area.y();
|
|
if( start )
|
|
glTranslatef( distance * timeLine.value() + x, distanceY * timeLine.value() + y, -5*timeLine.value() - 2.5 );
|
|
else if( stop )
|
|
glTranslatef( distance * ( 1.0 - timeLine.value() ) + x, distanceY * ( 1.0 - timeLine.value() ) + y, -5 * ( 1.0 - timeLine.value() ) - 2.5 );
|
|
QRect windowRect = QRect( 0, 0, frontWindow->geometry().width(), windowHeight );
|
|
paintWindowCover( frontWindow, windowRect, reflectedWindows );
|
|
glPopMatrix();
|
|
}
|
|
else if( !animation )
|
|
{
|
|
paintWindows( leftWindows, true, reflectedWindows );
|
|
paintWindows( rightWindows, false, reflectedWindows );
|
|
paintFrontWindow( frontWindow, width, leftWindowCount, rightWindowCount, reflectedWindows );
|
|
}
|
|
else
|
|
{
|
|
if( forward )
|
|
{
|
|
if( timeLine.value() < 0.5 )
|
|
{
|
|
// paint in normal way
|
|
paintWindows( leftWindows, true, reflectedWindows );
|
|
paintWindows( rightWindows, false, reflectedWindows );
|
|
paintFrontWindow( frontWindow, width, leftWindowCount, rightWindowCount, reflectedWindows );
|
|
}
|
|
else
|
|
{
|
|
paintWindows( rightWindows, false, reflectedWindows );
|
|
EffectWindow* rightWindow;
|
|
if( rightWindowCount > 0)
|
|
{
|
|
rightWindow = rightWindows->at( 0 );
|
|
paintFrontWindow( frontWindow, width, leftWindowCount, rightWindowCount, reflectedWindows );
|
|
}
|
|
else
|
|
rightWindow = frontWindow;
|
|
paintWindows( leftWindows, true, reflectedWindows, rightWindow );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
paintWindows( leftWindows, true, reflectedWindows );
|
|
if( timeLine.value() < 0.5 )
|
|
{
|
|
paintWindows( rightWindows, false, reflectedWindows );
|
|
paintFrontWindow( frontWindow, width, leftWindowCount, rightWindowCount, reflectedWindows );
|
|
}
|
|
else
|
|
{
|
|
paintFrontWindow( frontWindow, width, leftWindowCount, rightWindowCount, reflectedWindows );
|
|
paintWindows( rightWindows, false, reflectedWindows, leftWindows->at( 0 ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CoverSwitchEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
|
|
{
|
|
if( mActivated || stop || stopRequested )
|
|
{
|
|
if( !( mask & PAINT_WINDOW_TRANSFORMED ) && !w->isDesktop() )
|
|
{
|
|
if( ( start || stop ) && w->isDock() )
|
|
{
|
|
data.opacity = 1.0 - timeLine.value();
|
|
if( stop )
|
|
data.opacity = timeLine.value();
|
|
}
|
|
else
|
|
return;
|
|
}
|
|
}
|
|
if ( ( start || stop ) && (!w->isOnCurrentDesktop() || w->isMinimized() ) )
|
|
{
|
|
if (stop) // Fade out windows not on the current desktop
|
|
data.opacity = (1.0 - timeLine.value());
|
|
else // Fade in Windows from other desktops when animation is started
|
|
data.opacity = timeLine.value();
|
|
}
|
|
effects->paintWindow( w, mask, region, data );
|
|
}
|
|
|
|
void CoverSwitchEffect::tabBoxAdded( int mode )
|
|
{
|
|
if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this )
|
|
return;
|
|
if( !mActivated )
|
|
{
|
|
// only for windows mode
|
|
if( mode == TabBoxWindowsMode && effects->currentTabBoxWindowList().count() > 0 )
|
|
{
|
|
if( !stop && !stopRequested )
|
|
{
|
|
effects->refTabBox();
|
|
effects->setActiveFullScreenEffect( this );
|
|
input = effects->createFullScreenInputWindow( this, Qt::BlankCursor );
|
|
selectedWindow = effects->currentTabBoxWindowList().indexOf(effects->currentTabBoxWindow());
|
|
mActivated = true;
|
|
if( animateStart )
|
|
{
|
|
start = true;
|
|
}
|
|
|
|
// Calculation of correct area
|
|
area = effects->clientArea( FullScreenArea, effects->activeScreen(), effects->currentDesktop());
|
|
QRect fullArea = effects->clientArea( FullArea, effects->activeScreen(), effects->currentDesktop());
|
|
// twinview?
|
|
if( area.height() != fullArea.height() || area.width() != fullArea.width() )
|
|
twinview = true;
|
|
else
|
|
twinview = false;
|
|
|
|
effects->addRepaintFull();
|
|
}
|
|
else
|
|
{
|
|
startRequested = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CoverSwitchEffect::tabBoxClosed()
|
|
{
|
|
if( mActivated )
|
|
{
|
|
if( animateStop )
|
|
{
|
|
if( !animation && !start )
|
|
{
|
|
stop = true;
|
|
}
|
|
else if( start && rearrangeWindows == 0 )
|
|
{
|
|
start = false;
|
|
stop = true;
|
|
timeLine.setProgress( 1.0 - timeLine.value() );
|
|
}
|
|
else
|
|
{
|
|
stopRequested = true;
|
|
}
|
|
}
|
|
else
|
|
effects->setActiveFullScreenEffect( 0 );
|
|
mActivated = false;
|
|
effects->unrefTabBox();
|
|
effects->destroyInputWindow( input );
|
|
effects->addRepaintFull();
|
|
}
|
|
}
|
|
|
|
void CoverSwitchEffect::tabBoxUpdated()
|
|
{
|
|
if( mActivated )
|
|
{
|
|
if( animateSwitch && effects->currentTabBoxWindowList().count() > 1)
|
|
{
|
|
// determine the switch direction
|
|
int index = effects->currentTabBoxWindowList().indexOf(effects->currentTabBoxWindow());
|
|
bool direction = false;
|
|
int windowCount = effects->currentTabBoxWindowList().count();
|
|
if( index > selectedWindow )
|
|
{
|
|
if( index == windowCount-1 && selectedWindow == 0 )
|
|
direction = false;
|
|
else
|
|
direction = true;
|
|
}
|
|
else if( index == 0 && ( selectedWindow == windowCount-1 ) )
|
|
{
|
|
direction = true;
|
|
}
|
|
else if( index == selectedWindow )
|
|
return; // nothing changed
|
|
else
|
|
{
|
|
direction = false;
|
|
}
|
|
|
|
// for two windows direction is always forward
|
|
if( windowCount == 2 )
|
|
direction = true;
|
|
selectedWindow = index;
|
|
if( !animation && !start )
|
|
{
|
|
forward = direction;
|
|
animation = true;
|
|
}
|
|
else
|
|
{
|
|
if( direction )
|
|
rearrangeWindows--;
|
|
else
|
|
rearrangeWindows++;
|
|
if( rearrangeWindows >= windowCount )
|
|
rearrangeWindows = rearrangeWindows % windowCount;
|
|
else if( (-1*rearrangeWindows) >= windowCount )
|
|
rearrangeWindows = -1*((-1*rearrangeWindows) % windowCount);
|
|
}
|
|
}
|
|
effects->addRepaintFull();
|
|
}
|
|
}
|
|
|
|
void CoverSwitchEffect::paintWindowCover( EffectWindow* w, QRect windowRect, bool reflectedWindow, float opacity )
|
|
{
|
|
WindowPaintData data( w );
|
|
|
|
data.opacity = opacity;
|
|
|
|
QRect thumbnail = infiniteRegion();
|
|
setPositionTransformations( data,
|
|
thumbnail, w,
|
|
windowRect,
|
|
Qt::IgnoreAspectRatio );
|
|
thumbnail = infiniteRegion();
|
|
|
|
if( reflectedWindow )
|
|
{
|
|
glPushMatrix();
|
|
glScalef( 1.0, -1.0, 1.0 );
|
|
glTranslatef( 0.0, - area.height() - windowRect.y() - windowRect.height(), 0.0 );
|
|
effects->paintWindow( w,
|
|
PAINT_WINDOW_TRANSFORMED,
|
|
thumbnail, data );
|
|
glPopMatrix();
|
|
}
|
|
else
|
|
{
|
|
effects->paintWindow( w,
|
|
PAINT_WINDOW_TRANSFORMED,
|
|
thumbnail, data );
|
|
}
|
|
}
|
|
|
|
void CoverSwitchEffect::paintFrontWindow( EffectWindow* frontWindow, int width, int leftWindows, int rightWindows, bool reflectedWindow )
|
|
{
|
|
if( frontWindow == NULL )
|
|
return;
|
|
glPushMatrix();
|
|
glTranslatef((width - frontWindow->geometry().width())*0.5f, 0.0, -7.5);
|
|
int windowWidth = frontWindow->geometry().width();
|
|
int windowHeight = frontWindow->geometry().height();;
|
|
float distance = 0.0;
|
|
int height = area.height();
|
|
int x = 0;
|
|
bool specialHandlingForward = false;
|
|
if( leftWindows == 0 )
|
|
leftWindows = 1;
|
|
if( rightWindows == 0 )
|
|
{
|
|
rightWindows = 1;
|
|
specialHandlingForward = true;
|
|
}
|
|
if( animation )
|
|
{
|
|
float radian = 0.0;
|
|
radian = angle * timeLine.value() * ( 2 * M_PI / 360 );
|
|
windowWidth = frontWindow->geometry().width() * cos( radian );
|
|
if( forward )
|
|
{
|
|
x = - windowWidth;
|
|
glTranslatef( frontWindow->geometry().width(), 0.0, 0.0 );
|
|
// move to right
|
|
// we are at: (width + frontWindow->geometry().width())*0.5f
|
|
// we want to: width*1.25 - ( width * 0.25 * (rightWindowCount -1) )/rightWindowCount
|
|
distance = width*1.25 - ( width * 0.25 * ( rightWindows - 1 ) )/rightWindows -
|
|
(width + frontWindow->geometry().width())*0.5f;
|
|
glTranslatef( distance * timeLine.value(), 0.0, 0.0 );
|
|
glRotatef(-radian, 0.0, 1.0, 0.0);
|
|
}
|
|
else
|
|
{
|
|
// move to left
|
|
// we are at: (width - frontWindow->geometry().width())*0.5f
|
|
// we want to: -width*0.25 + ( width * 0.25 * leftWindowCount - 1 )/leftWindowCount
|
|
distance = ( width - frontWindow->geometry().width() ) * 0.5f +
|
|
width*0.25 - ( width * 0.25 * ( leftWindows - 1 ) )/leftWindows;
|
|
glTranslatef( - distance * timeLine.value(), 0.0, 0.0 );
|
|
glRotatef(radian, 0.0, 1.0, 0.0);
|
|
}
|
|
}
|
|
QRect windowRect = QRect( x, height - windowHeight, windowWidth, windowHeight );
|
|
if( specialHandlingForward )
|
|
paintWindowCover( frontWindow, windowRect, reflectedWindow, 1.0 - timeLine.value() * 2 );
|
|
else
|
|
paintWindowCover( frontWindow, windowRect, reflectedWindow );
|
|
glPopMatrix();
|
|
}
|
|
|
|
void CoverSwitchEffect::paintWindows( QList< EffectWindow* >* windows, bool left, bool reflectedWindows, EffectWindow* additionalWindow )
|
|
{
|
|
int width = area.width();
|
|
int height = area.height();
|
|
float radian = angle * ( 2 * M_PI / 360 );
|
|
int windowCount = windows->count();
|
|
int windowWidth = 0;
|
|
int windowHeight = 0;
|
|
QRect windowRect;
|
|
EffectWindow* window;
|
|
|
|
int rotateFactor = 1;
|
|
float widthFactor = -0.25;
|
|
float widthFactorSingle = 0.25;
|
|
if( !left )
|
|
{
|
|
rotateFactor = -1;
|
|
widthFactor = 1.25;
|
|
widthFactorSingle = - 0.25;
|
|
}
|
|
|
|
glPushMatrix();
|
|
glTranslatef( width*widthFactor, 0.0, -7.5 );
|
|
// handling for additional window from other side
|
|
// has to appear on this side after half of the time
|
|
if( animation && timeLine.value() >= 0.5 && additionalWindow != NULL )
|
|
{
|
|
// window has to appear on left side
|
|
glPushMatrix();
|
|
glRotatef( radian * rotateFactor, 0.0, 1.0, 0.0 );
|
|
windowWidth = additionalWindow->geometry().width() * cos( radian );
|
|
windowHeight = additionalWindow->geometry().height();
|
|
int x = 0;
|
|
if( !left )
|
|
{
|
|
x = -windowWidth;
|
|
}
|
|
windowRect = QRect( x, height - windowHeight, windowWidth, windowHeight );
|
|
paintWindowCover( additionalWindow, windowRect, reflectedWindows, ( timeLine.value() - 0.5 ) * 2 );
|
|
glPopMatrix();
|
|
}
|
|
// normal behaviour
|
|
for( int i=0; i < windowCount; i++ )
|
|
{
|
|
window = windows->at( i );
|
|
if( window == NULL )
|
|
continue;
|
|
glPushMatrix();
|
|
glTranslatef( ( width * widthFactorSingle * i )/windowCount, 0.0, 0.0 );
|
|
if( animation )
|
|
{
|
|
if( forward )
|
|
{
|
|
if( ( i == windowCount - 1 ) && left )
|
|
{
|
|
// right most window on left side -> move to front
|
|
// we are at: -width*0.25 + ( width * 0.25 * i )/leftWindowCount
|
|
// we want to: (width - leftWindow->geometry().width())*0.5f
|
|
float distance = (width - window->geometry().width())*0.5f + width*(-widthFactor) - ( width * widthFactorSingle * i )/windowCount;
|
|
glTranslatef( distance * timeLine.value() , 0.0, 0.0 );
|
|
radian = ( angle - angle * timeLine.value() ) * ( 2 * M_PI / 360 );
|
|
}
|
|
// right most window does not have to be moved
|
|
else if( !left && ( i == 0 ) ); // do nothing
|
|
else
|
|
{
|
|
// all other windows - move to next position
|
|
glTranslatef( ( width * 0.25 * timeLine.value() )/windowCount, 0.0, 0.0 );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if( ( i == windowCount - 1 ) && !left )
|
|
{
|
|
// left most window on right side -> move to front
|
|
// we are at: width*1.25 - ( width * 0.25 * i )/rightWindowCount
|
|
// we want to: (width + rightWindow->geometry().width())*0.5f
|
|
float distance = width*1.25 - ( width * 0.25 * i )/windowCount -
|
|
(width + window->geometry().width())*0.5f;
|
|
glTranslatef( - distance * timeLine.value(), 0.0, 0.0 );
|
|
radian = ( angle - angle * timeLine.value() ) * ( 2 * M_PI / 360 );
|
|
}
|
|
// left most window does not have to be moved
|
|
else if( i==0 && left); // do nothing
|
|
else
|
|
{
|
|
// all other windows - move to next position
|
|
glTranslatef( - ( width * 0.25 * timeLine.value() )/windowCount, 0.0, 0.0 );
|
|
}
|
|
}
|
|
}
|
|
glRotatef( rotateFactor * radian, 0.0, 1.0, 0.0 );
|
|
windowWidth = window->geometry().width() * cos( radian );
|
|
windowHeight = window->geometry().height();
|
|
int x = 0;
|
|
if( !left )
|
|
{
|
|
x = -windowWidth;
|
|
}
|
|
windowRect = QRect( x, height - windowHeight, windowWidth, windowHeight );
|
|
// make window most to edge transparent if animation
|
|
if( animation && i == 0 && ( ( !forward && left ) || ( forward && !left ) ) )
|
|
{
|
|
// only for the first half of the animation
|
|
if( timeLine.value() < 0.5 )
|
|
paintWindowCover( window, windowRect, reflectedWindows, 1.0 - timeLine.value() * 2 );
|
|
}
|
|
else
|
|
paintWindowCover( window, windowRect, reflectedWindows );
|
|
glPopMatrix();
|
|
}
|
|
glPopMatrix();
|
|
}
|
|
|
|
} // namespace
|