/******************************************************************** KWin - the KDE window manager This file is part of the KDE project. Copyright (C) 2008 Martin Gräßlin 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 . *********************************************************************/ #include "coverswitch.h" #include #include #include #include #include #include #include #include #include #include #include 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(); 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() ) { 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 ); 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->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