1 /********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 2008 Martin Gräßlin <ubuntu@martin-graesslin.com>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *********************************************************************/
23 #include <kactioncollection.h>
25 #include <kwinconfig.h>
26 #include <kconfiggroup.h>
27 #include <kcolorscheme.h>
29 #include <kstandarddirs.h>
44 KWIN_EFFECT( cube
, CubeEffect
)
45 KWIN_EFFECT_SUPPORTED( cube
, CubeEffect::supported() )
47 CubeEffect::CubeEffect()
49 , cube_painting( false )
50 , keyboard_grab( false )
51 , schedule_close( false )
52 , borderActivate( ElectricNone
)
55 , displayDesktopName( true )
58 , desktopChangedWhileRotating( false )
60 , rotationDirection( Left
)
61 , verticalRotationDirection( Upwards
)
62 , verticalPosition( Normal
)
64 , texturedCaps( true )
67 , manualVerticalAngle( 0.0 )
68 , currentShape( TimeLine::EaseInOutCurve
)
71 , reflectionPainting( false )
75 , animateDesktopChange( false )
78 , closeOnMouseRelease( false )
81 , useForTabBox( false )
83 , capListCreated( false )
86 reconfigure( ReconfigureAll
);
88 KActionCollection
* actionCollection
= new KActionCollection( this );
89 KAction
* a
= static_cast< KAction
* >( actionCollection
->addAction( "Cube" ));
90 a
->setText( i18n("Desktop Cube" ));
91 a
->setGlobalShortcut( KShortcut( Qt::CTRL
+ Qt::Key_F11
));
92 connect( a
, SIGNAL( triggered( bool )), this, SLOT( toggle()));
95 bool CubeEffect::supported()
97 return effects
->compositingType() == OpenGLCompositing
;
100 void CubeEffect::reconfigure( ReconfigureFlags
)
102 loadConfig( "Cube" );
105 void CubeEffect::loadConfig( QString config
)
107 KConfigGroup conf
= effects
->effectConfig( config
);
108 effects
->unreserveElectricBorder( borderActivate
);
109 borderActivate
= (ElectricBorder
)conf
.readEntry( "BorderActivate", (int)ElectricNone
);
110 effects
->reserveElectricBorder( borderActivate
);
112 cubeOpacity
= (float)conf
.readEntry( "Opacity", 80 )/100.0f
;
113 displayDesktopName
= conf
.readEntry( "DisplayDesktopName", true );
114 reflection
= conf
.readEntry( "Reflection", true );
115 rotationDuration
= animationTime( conf
, "RotationDuration", 500 );
116 backgroundColor
= conf
.readEntry( "BackgroundColor", QColor( Qt::black
) );
117 animateDesktopChange
= conf
.readEntry( "AnimateDesktopChange", false );
118 bigCube
= conf
.readEntry( "BigCube", false );
119 capColor
= conf
.readEntry( "CapColor", KColorScheme( QPalette::Active
, KColorScheme::Window
).background().color() );
120 paintCaps
= conf
.readEntry( "Caps", true );
121 closeOnMouseRelease
= conf
.readEntry( "CloseOnMouseRelease", false );
122 zPosition
= conf
.readEntry( "ZPosition", 100.0 );
123 useForTabBox
= conf
.readEntry( "TabBox", false );
124 QString file
= conf
.readEntry( "Wallpaper", QString("") );
127 if( !file
.isEmpty() )
129 QImage img
= QImage( file
);
132 wallpaper
= new GLTexture( img
);
137 texturedCaps
= conf
.readEntry( "TexturedCaps", true );
140 QString capPath
= conf
.readEntry( "CapPath", KGlobal::dirs()->findResource( "appdata", "cubecap.png" ) );
141 QImage img
= QImage( capPath
);
144 // change the alpha value of each pixel
145 for( int x
=0; x
<img
.width(); x
++ )
147 for( int y
=0; y
<img
.height(); y
++ )
149 QRgb pixel
= img
.pixel( x
, y
);
150 if( x
== 0 || x
== img
.width()-1 || y
== 0 || y
== img
.height()-1 )
151 img
.setPixel( x
, y
, qRgba( capColor
.red(), capColor
.green(), capColor
.blue(), 255*cubeOpacity
) );
154 if( qAlpha(pixel
) < 255 )
156 // Pixel is transparent - has to be blended with cap color
157 int red
= (qAlpha(pixel
)/255)*(qRed(pixel
)/255) + (1 - qAlpha(pixel
)/255 )*capColor
.red();
158 int green
= (qAlpha(pixel
)/255)*(qGreen(pixel
)/255) + (1 - qAlpha(pixel
)/255 )*capColor
.green();
159 int blue
= (qAlpha(pixel
)/255)*(qBlue(pixel
)/255) + (1 - qAlpha(pixel
)/255 )*capColor
.blue();
160 int alpha
= qAlpha(pixel
) + (255 - qAlpha(pixel
))*cubeOpacity
;
161 img
.setPixel( x
, y
, qRgba( red
, green
, blue
, alpha
) );
165 img
.setPixel( x
, y
, qRgba( qRed(pixel
), qGreen(pixel
), qBlue(pixel
), ((float)qAlpha(pixel
))*cubeOpacity
) );
170 capTexture
= new GLTexture( img
);
171 capTexture
->setFilter( GL_LINEAR
);
172 capTexture
->setWrapMode( GL_CLAMP_TO_EDGE
);
176 timeLine
.setCurveShape( TimeLine::EaseInOutCurve
);
177 timeLine
.setDuration( rotationDuration
);
179 verticalTimeLine
.setCurveShape( TimeLine::EaseInOutCurve
);
180 verticalTimeLine
.setDuration( rotationDuration
);
183 CubeEffect::~CubeEffect()
185 effects
->unreserveElectricBorder( borderActivate
);
190 void CubeEffect::prePaintScreen( ScreenPrePaintData
& data
, int time
)
194 data
.mask
|= PAINT_SCREEN_TRANSFORMED
| Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS
| PAINT_SCREEN_BACKGROUND_FIRST
;
196 if( rotating
|| start
|| stop
)
198 timeLine
.addTime( time
);
200 if( verticalRotating
)
202 verticalTimeLine
.addTime( time
);
205 effects
->prePaintScreen( data
, time
);
208 void CubeEffect::paintScreen( int mask
, QRegion region
, ScreenPaintData
& data
)
212 QRect rect
= effects
->clientArea( FullScreenArea
, activeScreen
, effects
->currentDesktop());
213 if( effects
->numScreens() > 1 && (slide
|| bigCube
) )
214 rect
= effects
->clientArea( FullArea
, activeScreen
, effects
->currentDesktop() );
215 QRect fullRect
= effects
->clientArea( FullArea
, activeScreen
, effects
->currentDesktop() );
219 glGetFloatv( GL_COLOR_CLEAR_VALUE
, clearColor
);
220 glClearColor( backgroundColor
.redF(), backgroundColor
.greenF(), backgroundColor
.blueF(), 1.0 );
221 glClear( GL_COLOR_BUFFER_BIT
);
222 glClearColor( clearColor
[0], clearColor
[1], clearColor
[2], clearColor
[3] );
225 if( wallpaper
&& !slide
)
228 wallpaper
->render( region
, rect
);
232 glPushAttrib( GL_CURRENT_BIT
| GL_ENABLE_BIT
);
233 glEnable( GL_BLEND
);
234 glBlendFunc( GL_SRC_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
);
236 if( effects
->numScreens() > 1 && !slide
&& !bigCube
)
238 windowsOnOtherScreens
.clear();
239 // unfortunatelly we have to change the projection matrix in dual screen mode
240 glMatrixMode( GL_PROJECTION
);
247 float ymax
= zNear
* tan( fovy
* M_PI
/ 360.0f
);
249 float xmin
= ymin
* aspect
;
250 float xmax
= ymax
* aspect
;
251 float xTranslate
= 0.0;
252 float yTranslate
= 0.0;
253 float xminFactor
= 1.0;
254 float xmaxFactor
= 1.0;
255 float yminFactor
= 1.0;
256 float ymaxFactor
= 1.0;
257 if( rect
.x() == 0 && rect
.width() != fullRect
.width() )
259 // horizontal layout: left screen
260 xminFactor
= (float)rect
.width()/(float)fullRect
.width();
261 xmaxFactor
= ((float)fullRect
.width()-(float)rect
.width()*0.5f
)/((float)fullRect
.width()*0.5f
);
262 xTranslate
= (float)fullRect
.width()*0.5f
-(float)rect
.width()*0.5f
;
264 if( rect
.x() != 0 && rect
.width() != fullRect
.width() )
266 // horizontal layout: right screen
267 xminFactor
= ((float)fullRect
.width()-(float)rect
.width()*0.5f
)/((float)fullRect
.width()*0.5f
);
268 xmaxFactor
= (float)rect
.width()/(float)fullRect
.width();
269 xTranslate
= (float)fullRect
.width()*0.5f
-(float)rect
.width()*0.5f
;
271 if( rect
.y() == 0 && rect
.height() != fullRect
.height() )
273 // vertical layout: top screen
274 yminFactor
= ((float)fullRect
.height()-(float)rect
.height()*0.5f
)/((float)fullRect
.height()*0.5f
);
275 ymaxFactor
= (float)rect
.height()/(float)fullRect
.height();
276 yTranslate
= (float)fullRect
.height()*0.5f
-(float)rect
.height()*0.5f
;
278 if( rect
.y() != 0 && rect
.height() != fullRect
.height() )
280 // vertical layout: bottom screen
281 yminFactor
= (float)rect
.height()/(float)fullRect
.height();
282 ymaxFactor
= ((float)fullRect
.height()-(float)rect
.height()*0.5f
)/((float)fullRect
.height()*0.5f
);
283 yTranslate
= (float)fullRect
.height()*0.5f
-(float)rect
.height()*0.5f
;
285 glFrustum( xmin
*xminFactor
, xmax
*xmaxFactor
, ymin
*yminFactor
, ymax
*ymaxFactor
, zNear
, zFar
);
286 glMatrixMode( GL_MODELVIEW
);
288 glTranslatef( xTranslate
, yTranslate
, 0.0 );
292 if( reflection
&& (!slide
) )
294 // restrict painting the reflections to the current screen
295 PaintClipper::push( QRegion( rect
));
297 // we can use a huge scale factor (needed to calculate the rearground vertices)
298 // as we restrict with a PaintClipper painting on the current screen
299 float scaleFactor
= 1000000 * tan( 60.0 * M_PI
/ 360.0f
)/rect
.height();
300 glScalef( 1.0, -1.0, 1.0 );
301 glTranslatef( 0.0, -rect
.height()*2, 0.0 );
303 glEnable( GL_CLIP_PLANE0
);
304 reflectionPainting
= true;
305 paintScene( mask
, region
, data
);
306 reflectionPainting
= false;
307 glDisable( GL_CLIP_PLANE0
);
311 if( effects
->numScreens() > 1 && rect
.x() != fullRect
.x() && !slide
&& !bigCube
)
313 // have to change the reflection area in horizontal layout and right screen
314 glTranslatef( -rect
.x(), 0.0, 0.0 );
316 glTranslatef( rect
.x() + rect
.width()*0.5f
, 0.0, 0.0 );
318 -rect
.width()*0.5f
, rect
.height(), 0.0,
319 rect
.width()*0.5f
, rect
.height(), 0.0,
320 (float)rect
.width()*scaleFactor
, rect
.height(), -5000,
321 -(float)rect
.width()*scaleFactor
, rect
.height(), -5000 };
325 alpha
= 0.3 + 0.4 * timeLine
.value();
327 alpha
= 0.3 + 0.4 * ( 1.0 - timeLine
.value() );
328 glColor4f( 0.0, 0.0, 0.0, alpha
);
329 glBegin( GL_POLYGON
);
330 glVertex3f( vertices
[0], vertices
[1], vertices
[2] );
331 glVertex3f( vertices
[3], vertices
[4], vertices
[5] );
334 glColor4f( 0.0, 0.0, 0.0, alpha
);
335 glVertex3f( vertices
[6], vertices
[7], vertices
[8] );
336 glVertex3f( vertices
[9], vertices
[10], vertices
[11] );
339 PaintClipper::pop( QRegion( rect
));
342 paintScene( mask
, region
, data
);
345 if( effects
->numScreens() > 1 && !slide
&& !bigCube
)
348 // revert change of projection matrix
349 glMatrixMode( GL_PROJECTION
);
351 glMatrixMode( GL_MODELVIEW
);
354 glDisable( GL_BLEND
);
357 // desktop name box - inspired from coverswitch
358 if( displayDesktopName
&& (!slide
) )
362 color_frame
= KColorScheme( QPalette::Active
, KColorScheme::Window
).background().color();
363 color_frame
.setAlphaF( 0.5 );
364 color_text
= KColorScheme( QPalette::Active
, KColorScheme::Window
).foreground().color();
367 color_frame
.setAlphaF( 0.5 * timeLine
.value() );
368 color_text
.setAlphaF( timeLine
.value() );
372 color_frame
.setAlphaF( 0.5 - 0.5 * timeLine
.value() );
373 color_text
.setAlphaF( 1.0 - timeLine
.value() );
376 text_font
.setBold( true );
377 text_font
.setPointSize( 14 );
378 glPushAttrib( GL_CURRENT_BIT
);
379 glColor4f( color_frame
.redF(), color_frame
.greenF(), color_frame
.blueF(), color_frame
.alphaF());
380 QRect frameRect
= QRect( rect
.width()*0.33f
+ rect
.x(),
381 rect
.height() + rect
.y() - QFontMetrics( text_font
).height() * 1.2f
,
383 QFontMetrics( text_font
).height() * 1.2f
);
384 renderRoundBoxWithEdge( frameRect
);
385 effects
->paintText( effects
->desktopName( frontDesktop
),
392 if( effects
->numScreens() > 1 && !slide
&& !bigCube
)
394 foreach( EffectWindow
* w
, windowsOnOtherScreens
)
396 WindowPaintData
wData( w
);
397 if( start
&& !w
->isDesktop() && !w
->isDock() )
398 wData
.opacity
*= (1.0 - timeLine
.value());
399 if( stop
&& !w
->isDesktop() && !w
->isDock() )
400 wData
.opacity
*= timeLine
.value();
401 effects
->paintWindow( w
, 0, QRegion( w
->x(), w
->y(), w
->width(), w
->height() ), wData
);
407 effects
->paintScreen( mask
, region
, data
);
411 void CubeEffect::paintScene( int mask
, QRegion region
, ScreenPaintData
& data
)
413 QRect rect
= effects
->clientArea( FullScreenArea
, activeScreen
, effects
->currentDesktop());
414 if( effects
->numScreens() > 1 && (slide
|| bigCube
) )
415 rect
= effects
->clientArea( FullArea
, activeScreen
, effects
->currentDesktop() );
418 if( effects
->numScreens() > 1 && !slide
&& !bigCube
)
420 QRect fullRect
= effects
->clientArea( FullArea
, activeScreen
, effects
->currentDesktop() );
421 xScale
= (float)rect
.width()/(float)fullRect
.width();
422 yScale
= (float)rect
.height()/(float)fullRect
.height();
425 xScale
= xScale
+ (1.0 - xScale
) * (1.0 - timeLine
.value());
426 yScale
= yScale
+ (1.0 - yScale
) * (1.0 - timeLine
.value());
428 glTranslatef( -rect
.x()*(1.0 - timeLine
.value()), 0.0, 0.0 );
430 glTranslatef( 0.0, -rect
.y()*(1.0 - timeLine
.value()), 0.0 );
434 xScale
= xScale
+ (1.0 - xScale
) * timeLine
.value();
435 yScale
= yScale
+ (1.0 - yScale
) * timeLine
.value();
437 glTranslatef( -rect
.x()*timeLine
.value(), 0.0, 0.0 );
439 glTranslatef( 0.0, -rect
.y()*timeLine
.value(), 0.0 );
441 glScalef( xScale
, yScale
, 1.0 );
444 int rightSteps
= effects
->numberOfDesktops()/2;
445 int leftSteps
= rightSteps
+1;
446 int rightSideCounter
= 0;
447 int leftSideCounter
= 0;
448 float internalCubeAngle
= 360.0f
/ effects
->numberOfDesktops();
449 cube_painting
= true;
450 int desktopIndex
= 0;
451 float zTranslate
= zPosition
+ zoom
;
453 zTranslate
*= timeLine
.value();
455 zTranslate
*= ( 1.0 - timeLine
.value() );
459 bool topCapAfter
= false;
460 bool topCapBefore
= false;
462 // Rotation of the cube
463 float cubeAngle
= (float)((float)(effects
->numberOfDesktops() - 2 )/(float)effects
->numberOfDesktops() * 180.0f
);
464 float point
= rect
.width()/2*tan(cubeAngle
*0.5f
*M_PI
/180.0f
);
465 float zTexture
= rect
.width()/2*tan(45.0f
*M_PI
/180.0f
);
466 if( verticalRotating
|| verticalPosition
!= Normal
|| manualVerticalAngle
!= 0.0 )
468 // change the verticalPosition if manualVerticalAngle > 90 or < -90 degrees
469 if( manualVerticalAngle
<= -90.0 )
471 manualVerticalAngle
+= 90.0;
472 if( verticalPosition
== Normal
)
473 verticalPosition
= Down
;
474 if( verticalPosition
== Up
)
475 verticalPosition
= Normal
;
477 if( manualVerticalAngle
>= 90.0 )
479 manualVerticalAngle
-= 90.0;
480 if( verticalPosition
== Normal
)
481 verticalPosition
= Up
;
482 if( verticalPosition
== Down
)
483 verticalPosition
= Normal
;
486 if( verticalPosition
== Up
)
489 if( !verticalRotating
)
491 if( manualVerticalAngle
< 0.0 )
492 angle
+= manualVerticalAngle
;
494 manualVerticalAngle
= 0.0;
497 else if( verticalPosition
== Down
)
500 if( !verticalRotating
)
502 if( manualVerticalAngle
> 0.0 )
503 angle
+= manualVerticalAngle
;
505 manualVerticalAngle
= 0.0;
510 angle
= manualVerticalAngle
;
512 if( verticalRotating
)
514 angle
*= verticalTimeLine
.value();
515 if( verticalPosition
== Normal
&& verticalRotationDirection
== Upwards
)
516 angle
= -90.0 + 90*verticalTimeLine
.value();
517 if( verticalPosition
== Normal
&& verticalRotationDirection
== Downwards
)
518 angle
= 90.0 - 90*verticalTimeLine
.value();
519 angle
+= manualVerticalAngle
* (1.0-verticalTimeLine
.value());
522 angle
*= (1.0 - timeLine
.value());
523 glTranslatef( rect
.width()/2, rect
.height()/2, -point
-zTranslate
);
524 glRotatef( angle
, 1.0, 0.0, 0.0 );
525 glTranslatef( -rect
.width()/2, -rect
.height()/2, point
+zTranslate
);
527 // calculate if the caps have to be painted before/after or during desktop painting
533 glGetFloatv( GL_PROJECTION_MATRIX
, P
);
534 glGetFloatv( GL_MODELVIEW_MATRIX
, M
);
535 glGetFloatv( GL_VIEWPORT
, V
);
537 // calculate y coordinate of the top of front desktop
538 float X
= M
[0]*0.0 + M
[4]*0.0 + M
[8]*(-zTranslate
) + M
[12]*1;
539 float Y
= M
[1]*0.0 + M
[5]*0.0 + M
[9]*(-zTranslate
) + M
[13]*1;
540 float Z
= M
[2]*0.0 + M
[6]*0.0 + M
[10]*(-zTranslate
) + M
[14]*1;
541 float W
= M
[3]*0.0 + M
[7]*0.0 + M
[11]*(-zTranslate
) + M
[15]*1;
542 float clipY
= P
[1]*X
+ P
[5]*Y
+ P
[9]*Z
+ P
[13]*W
;
543 float clipW
= P
[3]*X
+ P
[7]*Y
+ P
[11]*Z
+ P
[15]*W
;
544 float normY
= clipY
/clipW
;
545 float yFront
= (V
[3]/2)*normY
+(V
[3]-V
[1])/2;
547 // calculate y coordinate of the bottom of front desktop
548 X
= M
[0]*0.0 + M
[4]*rect
.height() + M
[8]*(-zTranslate
) + M
[12]*1;
549 Y
= M
[1]*0.0 + M
[5]*rect
.height() + M
[9]*(-zTranslate
) + M
[13]*1;
550 Z
= M
[2]*0.0 + M
[6]*rect
.height() + M
[10]*(-zTranslate
) + M
[14]*1;
551 W
= M
[3]*0.0 + M
[7]*rect
.height() + M
[11]*(-zTranslate
) + M
[15]*1;
552 clipY
= P
[1]*X
+ P
[5]*Y
+ P
[9]*Z
+ P
[13]*W
;
553 clipW
= P
[3]*X
+ P
[7]*Y
+ P
[11]*Z
+ P
[15]*W
;
555 float yFrontBottom
= (V
[3]/2)*normY
+(V
[3]-V
[1])/2;
557 // change matrix to a rear position
559 glTranslatef( 0.0, 0.0, -point
-zTranslate
);
560 float desktops
= (effects
->numberOfDesktops()/2.0);
561 glRotatef( desktops
*internalCubeAngle
, 1.0, 0.0, 0.0 );
562 glTranslatef( 0.0, 0.0, point
);
563 glGetFloatv(GL_MODELVIEW_MATRIX
, M
);
564 // calculate y coordinate of the top of rear desktop
565 X
= M
[0]*0.0 + M
[4]*0.0 + M
[8]*0.0 + M
[12]*1;
566 Y
= M
[1]*0.0 + M
[5]*0.0 + M
[9]*0.0 + M
[13]*1;
567 Z
= M
[2]*0.0 + M
[6]*0.0 + M
[10]*0.0 + M
[14]*1;
568 W
= M
[3]*0.0 + M
[7]*0.0 + M
[11]*0.0 + M
[15]*1;
569 clipY
= P
[1]*X
+ P
[5]*Y
+ P
[9]*Z
+ P
[13]*W
;
570 clipW
= P
[3]*X
+ P
[7]*Y
+ P
[11]*Z
+ P
[15]*W
;
572 float yBack
= (V
[3]/2)*normY
+(V
[3]-V
[1])/2;
574 // calculate y coordniate of the bottom of rear desktop
575 glTranslatef( 0.0, -rect
.height(), 0.0 );
576 glGetFloatv(GL_MODELVIEW_MATRIX
, M
);
577 X
= M
[0]*0.0 + M
[4]*0.0 + M
[8]*0.0 + M
[12]*1;
578 Y
= M
[1]*0.0 + M
[5]*0.0 + M
[9]*0.0 + M
[13]*1;
579 Z
= M
[2]*0.0 + M
[6]*0.0 + M
[10]*0.0 + M
[14]*1;
580 W
= M
[3]*0.0 + M
[7]*0.0 + M
[11]*0.0 + M
[15]*1;
581 clipY
= P
[1]*X
+ P
[5]*Y
+ P
[9]*Z
+ P
[13]*W
;
582 clipW
= P
[3]*X
+ P
[7]*Y
+ P
[11]*Z
+ P
[15]*W
;
584 float yBackBottom
= (V
[3]/2)*normY
+(V
[3]-V
[1])/2;
586 if( yBack
>= yFront
)
588 if( yBackBottom
<= yFrontBottom
)
592 if( rotating
|| (manualAngle
!= 0.0) )
594 int tempFrontDesktop
= frontDesktop
;
595 if( manualAngle
> internalCubeAngle
* 0.5f
)
597 manualAngle
-= internalCubeAngle
;
599 if( tempFrontDesktop
== 0 )
600 tempFrontDesktop
= effects
->numberOfDesktops();
602 if( manualAngle
< -internalCubeAngle
* 0.5f
)
604 manualAngle
+= internalCubeAngle
;
606 if( tempFrontDesktop
> effects
->numberOfDesktops() )
607 tempFrontDesktop
= 1;
609 float rotationAngle
= internalCubeAngle
* timeLine
.value();
610 if( rotationAngle
> internalCubeAngle
* 0.5f
)
612 rotationAngle
-= internalCubeAngle
;
613 if( !desktopChangedWhileRotating
)
615 desktopChangedWhileRotating
= true;
616 if( rotationDirection
== Left
)
620 else if( rotationDirection
== Right
)
624 if( tempFrontDesktop
> effects
->numberOfDesktops() )
625 tempFrontDesktop
= 1;
626 else if( tempFrontDesktop
== 0 )
627 tempFrontDesktop
= effects
->numberOfDesktops();
630 // don't change front desktop during stop animation as this would break some logic
632 frontDesktop
= tempFrontDesktop
;
633 if( rotationDirection
== Left
)
638 rotationAngle
= manualAngle
* (1.0 - timeLine
.value());
640 rotationAngle
+= manualAngle
* (1.0 - timeLine
.value());
641 glTranslatef( rect
.width()/2, rect
.height()/2, -point
-zTranslate
);
642 glRotatef( rotationAngle
, 0.0, 1.0, 0.0 );
643 glTranslatef( -rect
.width()/2, -rect
.height()/2, point
+zTranslate
);
646 if( topCapBefore
|| topCapAfter
)
648 if( (topCapAfter
&& !reflectionPainting
) || (topCapBefore
&& reflectionPainting
) )
650 // paint the bottom cap
652 glTranslatef( 0.0, rect
.height(), 0.0 );
653 paintCap( point
, zTexture
);
654 glTranslatef( 0.0, -rect
.height(), 0.0 );
657 if( (topCapBefore
&& !reflectionPainting
) || (topCapAfter
&& reflectionPainting
) )
660 paintCap( point
, zTexture
);
664 for( int i
=0; i
<effects
->numberOfDesktops(); i
++ )
666 if( !topCapAfter
&& !topCapBefore
&& i
== effects
->numberOfDesktops()/2 -1 && !slide
)
668 // paint the bottom cap
670 glTranslatef( 0.0, rect
.height(), 0.0 );
671 paintCap( point
, zTexture
);
672 glTranslatef( 0.0, -rect
.height(), 0.0 );
675 paintCap( point
, zTexture
);
677 if( i
%2 == 0 && i
!= effects
->numberOfDesktops() -1)
679 // desktops on the right (including back)
680 desktopIndex
= rightSteps
- rightSideCounter
;
685 // desktops on the left (including front)
686 desktopIndex
= leftSteps
+ leftSideCounter
;
690 // start painting the cube
691 painting_desktop
= (desktopIndex
+ frontDesktop
)%effects
->numberOfDesktops();
692 if( painting_desktop
== 0 )
694 painting_desktop
= effects
->numberOfDesktops();
698 // only paint required desktops during slide phase
699 if( painting_desktop
!= frontDesktop
)
701 int leftDesktop
= frontDesktop
- 1;
702 int rightDesktop
= frontDesktop
+ 1;
703 if( leftDesktop
== 0 )
704 leftDesktop
= effects
->numberOfDesktops();
705 if( rightDesktop
> effects
->numberOfDesktops() )
707 if( !desktopChangedWhileRotating
&& rotationDirection
== Left
&& painting_desktop
!= rightDesktop
)
711 if( desktopChangedWhileRotating
&& rotationDirection
== Left
&& painting_desktop
!= leftDesktop
)
715 if( !desktopChangedWhileRotating
&& rotationDirection
== Right
&& painting_desktop
!= leftDesktop
)
719 if( desktopChangedWhileRotating
&& rotationDirection
== Right
&& painting_desktop
!= rightDesktop
)
725 ScreenPaintData newData
= data
;
726 RotationData rot
= RotationData();
727 rot
.axis
= RotationData::YAxis
;
728 rot
.angle
= internalCubeAngle
* desktopIndex
;
729 rot
.xRotationPoint
= rect
.width()/2;
730 rot
.zRotationPoint
= -point
;
731 newData
.rotation
= &rot
;
732 newData
.zTranslate
= -zTranslate
;
733 effects
->paintScreen( mask
, region
, newData
);
735 if( topCapBefore
|| topCapAfter
)
737 if( (topCapAfter
&& !reflectionPainting
) || (topCapBefore
&& reflectionPainting
) )
740 paintCap( point
, zTexture
);
742 if( (topCapBefore
&& !reflectionPainting
) || (topCapAfter
&& reflectionPainting
) )
744 // paint the bottom cap
746 glTranslatef( 0.0, rect
.height(), 0.0 );
747 paintCap( point
, zTexture
);
748 glTranslatef( 0.0, -rect
.height(), 0.0 );
752 cube_painting
= false;
753 painting_desktop
= effects
->currentDesktop();
756 void CubeEffect::paintCap( float z
, float zTexture
)
758 QRect rect
= effects
->clientArea( FullArea
, activeScreen
, effects
->currentDesktop());
759 if( ( !paintCaps
) || effects
->numberOfDesktops() <= 2 )
761 float opacity
= cubeOpacity
;
763 opacity
= 1.0 - (1.0 - opacity
)*timeLine
.value();
765 opacity
= 1.0 - (1.0 - opacity
)*( 1.0 - timeLine
.value() );
766 glColor4f( capColor
.redF(), capColor
.greenF(), capColor
.blueF(), opacity
);
767 float angle
= 360.0f
/effects
->numberOfDesktops();
769 float zTranslate
= zPosition
+ zoom
;
771 zTranslate
*= timeLine
.value();
773 zTranslate
*= ( 1.0 - timeLine
.value() );
774 glTranslatef( rect
.width()/2, 0.0, -z
-zTranslate
);
775 glRotatef( (1-frontDesktop
)*angle
, 0.0, 1.0, 0.0 );
777 if( !capListCreated
)
779 capListCreated
= true;
780 glNewList( capList
, GL_COMPILE_AND_EXECUTE
);
781 bool texture
= false;
782 if( texturedCaps
&& effects
->numberOfDesktops() > 3 && capTexture
)
785 paintCapStep( z
, zTexture
, true );
788 paintCapStep( z
, zTexture
, false );
792 glCallList( capList
);
796 void CubeEffect::paintCapStep( float z
, float zTexture
, bool texture
)
798 QRect rect
= effects
->clientArea( FullArea
, activeScreen
, effects
->currentDesktop());
799 float angle
= 360.0f
/effects
->numberOfDesktops();
802 for( int i
=0; i
<effects
->numberOfDesktops(); i
++ )
804 int triangleRows
= effects
->numberOfDesktops()*5;
805 float zTriangleDistance
= z
/(float)triangleRows
;
806 float widthTriangle
= tan( angle
*0.5 * M_PI
/180.0 ) * zTriangleDistance
;
807 float currentWidth
= 0.0;
808 glBegin( GL_TRIANGLES
);
809 float cosValue
= cos( i
*angle
* M_PI
/180.0 );
810 float sinValue
= sin( i
*angle
* M_PI
/180.0 );
811 for( int j
=0; j
<triangleRows
; j
++ )
813 float previousWidth
= currentWidth
;
814 currentWidth
= tan( angle
*0.5 * M_PI
/180.0 ) * zTriangleDistance
* (j
+1);
815 int evenTriangles
= 0;
816 int oddTriangles
= 0;
817 for( int k
=0; k
<floor(currentWidth
/widthTriangle
*2-1+0.5f
); k
++ )
819 float x1
= -previousWidth
;
820 float x2
= -currentWidth
;
827 x1
+= evenTriangles
*widthTriangle
*2;
828 x2
+= evenTriangles
*widthTriangle
*2;
829 x3
= x2
+widthTriangle
*2;
830 z1
= j
*zTriangleDistance
;
831 z2
= (j
+1)*zTriangleDistance
;
832 z3
= (j
+1)*zTriangleDistance
;
833 float xRot
= cosValue
* x1
- sinValue
* z1
;
834 float zRot
= sinValue
* x1
+ cosValue
* z1
;
837 xRot
= cosValue
* x2
- sinValue
* z2
;
838 zRot
= sinValue
* x2
+ cosValue
* z2
;
841 xRot
= cosValue
* x3
- sinValue
* z3
;
842 zRot
= sinValue
* x3
+ cosValue
* z3
;
849 x1
+= oddTriangles
*widthTriangle
*2;
850 x2
+= (oddTriangles
+1)*widthTriangle
*2;
851 x3
= x1
+widthTriangle
*2;
852 z1
= j
*zTriangleDistance
;
853 z2
= (j
+1)*zTriangleDistance
;
854 z3
= j
*zTriangleDistance
;
855 float xRot
= cosValue
* x1
- sinValue
* z1
;
856 float zRot
= sinValue
* x1
+ cosValue
* z1
;
859 xRot
= cosValue
* x2
- sinValue
* z2
;
860 zRot
= sinValue
* x2
+ cosValue
* z2
;
863 xRot
= cosValue
* x3
- sinValue
* z3
;
864 zRot
= sinValue
* x3
+ cosValue
* z3
;
877 texX1
= x1
/(rect
.width())+0.5;
878 texY1
= 0.5 - z1
/zTexture
* 0.5;
879 texX2
= x2
/(rect
.width())+0.5;
880 texY2
= 0.5 - z2
/zTexture
* 0.5;
881 texX3
= x3
/(rect
.width())+0.5;
882 texY3
= 0.5 - z3
/zTexture
* 0.5;
883 glTexCoord2f( texX1
, texY1
);
885 glVertex3f( x1
, 0.0, z1
);
888 glTexCoord2f( texX2
, texY2
);
890 glVertex3f( x2
, 0.0, z2
);
893 glTexCoord2f( texX3
, texY3
);
895 glVertex3f( x3
, 0.0, z3
);
902 capTexture
->unbind();
906 void CubeEffect::postPaintScreen()
908 effects
->postPaintScreen();
913 if( timeLine
.value() == 1.0 )
916 timeLine
.setProgress(0.0);
918 if( !rotations
.empty() )
920 rotationDirection
= rotations
.dequeue();
922 // change the curve shape if current shape is not easeInOut
923 if( currentShape
!= TimeLine::EaseInOutCurve
)
925 // more rotations follow -> linear curve
926 if( !rotations
.empty() )
928 currentShape
= TimeLine::LinearCurve
;
930 // last rotation step -> easeOut curve
933 currentShape
= TimeLine::EaseOutCurve
;
935 timeLine
.setCurveShape( currentShape
);
939 // if there is at least one more rotation, we can change to easeIn
940 if( !rotations
.empty() )
942 currentShape
= TimeLine::EaseInCurve
;
943 timeLine
.setCurveShape( currentShape
);
948 effects
->addRepaintFull();
949 return; // schedule_close could have been called, start has to finish first
953 if( timeLine
.value() == 1.0 )
955 effects
->setCurrentDesktop( frontDesktop
);
957 timeLine
.setProgress(0.0);
959 // set the new desktop
961 effects
->ungrabKeyboard();
962 keyboard_grab
= false;
963 effects
->destroyInputWindow( input
);
965 effects
->setActiveFullScreenEffect( 0 );
967 // delete the GL lists
968 glDeleteLists( capList
, 1 );
970 effects
->addRepaintFull();
972 if( rotating
|| verticalRotating
)
974 if( rotating
&& timeLine
.value() == 1.0 )
976 timeLine
.setProgress(0.0);
978 desktopChangedWhileRotating
= false;
981 if( !rotations
.empty() )
983 rotationDirection
= rotations
.dequeue();
985 // change the curve shape if current shape is not easeInOut
986 if( currentShape
!= TimeLine::EaseInOutCurve
)
988 // more rotations follow -> linear curve
989 if( !rotations
.empty() )
991 currentShape
= TimeLine::LinearCurve
;
993 // last rotation step -> easeOut curve
996 currentShape
= TimeLine::EaseOutCurve
;
998 timeLine
.setCurveShape( currentShape
);
1002 // if there is at least one more rotation, we can change to easeIn
1003 if( !rotations
.empty() )
1005 currentShape
= TimeLine::EaseInCurve
;
1006 timeLine
.setCurveShape( currentShape
);
1012 // reset curve shape if there are no more rotations
1013 if( currentShape
!= TimeLine::EaseInOutCurve
)
1015 currentShape
= TimeLine::EaseInOutCurve
;
1016 timeLine
.setCurveShape( currentShape
);
1020 if( verticalRotating
&& verticalTimeLine
.value() == 1.0 )
1022 verticalTimeLine
.setProgress(0.0);
1023 verticalRotating
= false;
1024 manualVerticalAngle
= 0.0;
1026 if( !verticalRotations
.empty() )
1028 verticalRotationDirection
= verticalRotations
.dequeue();
1029 verticalRotating
= true;
1030 if( verticalRotationDirection
== Upwards
)
1032 if( verticalPosition
== Normal
)
1033 verticalPosition
= Up
;
1034 if( verticalPosition
== Down
)
1035 verticalPosition
= Normal
;
1037 if( verticalRotationDirection
== Downwards
)
1039 if( verticalPosition
== Normal
)
1040 verticalPosition
= Down
;
1041 if( verticalPosition
== Up
)
1042 verticalPosition
= Normal
;
1046 effects
->addRepaintFull();
1047 return; // rotation has to end before cube is closed
1049 if( schedule_close
)
1051 schedule_close
= false;
1060 timeLine
.setDuration( rotationDuration
);
1061 effects
->setActiveFullScreenEffect( 0 );
1063 effects
->addRepaintFull();
1068 void CubeEffect::prePaintWindow( EffectWindow
* w
, WindowPrePaintData
& data
, int time
)
1074 if( ( w
->isDesktop() || w
->isDock() ) && w
->screen() != activeScreen
&& w
->isOnDesktop( effects
->currentDesktop() ) )
1076 windowsOnOtherScreens
.append( w
);
1078 if( (start
|| stop
) && w
->screen() != activeScreen
&& w
->isOnDesktop( effects
->currentDesktop() )
1079 && !w
->isDesktop() && !w
->isDock() )
1081 windowsOnOtherScreens
.append( w
);
1083 if( w
->isOnDesktop( painting_desktop
))
1085 QRect rect
= effects
->clientArea( FullArea
, activeScreen
, painting_desktop
);
1086 if( w
->x() < rect
.x() )
1088 data
.quads
= data
.quads
.splitAtX( -w
->x() );
1090 if( w
->x() + w
->width() > rect
.x() + rect
.width() )
1092 data
.quads
= data
.quads
.splitAtX( rect
.width() - w
->x() );
1094 if( w
->y() < rect
.y() )
1096 data
.quads
= data
.quads
.splitAtY( -w
->y() );
1098 if( w
->y() + w
->height() > rect
.y() + rect
.height() )
1100 data
.quads
= data
.quads
.splitAtY( rect
.height() - w
->y() );
1102 w
->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP
);
1106 // check for windows belonging to the previous desktop
1107 int prev_desktop
= painting_desktop
-1;
1108 if( prev_desktop
== 0 )
1109 prev_desktop
= effects
->numberOfDesktops();
1110 if( w
->isOnDesktop( prev_desktop
) )
1112 QRect rect
= effects
->clientArea( FullArea
, activeScreen
, prev_desktop
);
1113 if( w
->x()+w
->width() > rect
.x() + rect
.width() )
1115 w
->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP
);
1116 data
.quads
= data
.quads
.splitAtX( rect
.width() - w
->x() );
1117 if( w
->y() < rect
.y() )
1119 data
.quads
= data
.quads
.splitAtY( -w
->y() );
1121 if( w
->y() + w
->height() > rect
.y() + rect
.height() )
1123 data
.quads
= data
.quads
.splitAtY( rect
.height() - w
->y() );
1125 data
.setTransformed();
1126 effects
->prePaintWindow( w
, data
, time
);
1130 // check for windows belonging to the next desktop
1131 int next_desktop
= painting_desktop
+1;
1132 if( next_desktop
> effects
->numberOfDesktops() )
1134 if( w
->isOnDesktop( next_desktop
) )
1136 QRect rect
= effects
->clientArea( FullArea
, activeScreen
, next_desktop
);
1137 if( w
->x() < rect
.x() )
1139 w
->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP
);
1140 data
.quads
= data
.quads
.splitAtX( -w
->x() );
1141 if( w
->y() < rect
.y() )
1143 data
.quads
= data
.quads
.splitAtY( -w
->y() );
1145 if( w
->y() + w
->height() > rect
.y() + rect
.height() )
1147 data
.quads
= data
.quads
.splitAtY( rect
.height() - w
->y() );
1149 data
.setTransformed();
1150 effects
->prePaintWindow( w
, data
, time
);
1154 w
->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP
);
1158 effects
->prePaintWindow( w
, data
, time
);
1161 void CubeEffect::paintWindow( EffectWindow
* w
, int mask
, QRegion region
, WindowPaintData
& data
)
1163 if( activated
&& cube_painting
)
1165 //kDebug(1212) << w->caption();
1166 float opacity
= cubeOpacity
;
1171 opacity
= 1.0 - (1.0 - opacity
)*timeLine
.value();
1172 if( reflectionPainting
)
1173 opacity
= 0.5 + ( cubeOpacity
- 0.5 )*timeLine
.value();
1174 // fade in windows belonging to different desktops
1175 if( painting_desktop
== effects
->currentDesktop() && (!w
->isOnDesktop( painting_desktop
)) )
1176 opacity
= timeLine
.value() * cubeOpacity
;
1180 opacity
= 1.0 - (1.0 - opacity
)*( 1.0 - timeLine
.value() );
1181 if( reflectionPainting
)
1182 opacity
= 0.5 + ( cubeOpacity
- 0.5 )*( 1.0 - timeLine
.value() );
1183 // fade out windows belonging to different desktops
1184 if( painting_desktop
== effects
->currentDesktop() && (!w
->isOnDesktop( painting_desktop
)) )
1185 opacity
= cubeOpacity
* (1.0 - timeLine
.value());
1187 bool slideOpacity
= false;
1188 // fade in windows from different desktops in first slide step
1189 if( slide
&& painting_desktop
== oldDesktop
&& (!w
->isOnDesktop( painting_desktop
)) )
1191 opacity
= timeLine
.value();
1192 slideOpacity
= true;
1194 // fade out windows from different desktops in last slide step
1195 if( slide
&& rotations
.empty() && painting_desktop
== effects
->currentDesktop() && (!w
->isOnDesktop( painting_desktop
)) )
1197 opacity
= 1.0 - timeLine
.value();
1198 slideOpacity
= true;
1200 // check for windows belonging to the previous desktop
1201 int prev_desktop
= painting_desktop
-1;
1202 if( prev_desktop
== 0 )
1203 prev_desktop
= effects
->numberOfDesktops();
1204 int next_desktop
= painting_desktop
+1;
1205 if( next_desktop
> effects
->numberOfDesktops() )
1207 if( w
->isOnDesktop( prev_desktop
) && ( mask
& PAINT_WINDOW_TRANSFORMED
) )
1209 QRect rect
= effects
->clientArea( FullArea
, activeScreen
, prev_desktop
);
1210 data
.xTranslate
= -rect
.width();
1211 WindowQuadList new_quads
;
1212 foreach( const WindowQuad
&quad
, data
.quads
)
1214 if( quad
.right() > rect
.width() - w
->x() )
1216 new_quads
.append( quad
);
1219 data
.quads
= new_quads
;
1221 if( w
->isOnDesktop( next_desktop
) && ( mask
& PAINT_WINDOW_TRANSFORMED
) )
1223 QRect rect
= effects
->clientArea( FullArea
, activeScreen
, next_desktop
);
1224 data
.xTranslate
= rect
.width();
1225 WindowQuadList new_quads
;
1226 foreach( const WindowQuad
&quad
, data
.quads
)
1228 if( w
->x() + quad
.right() <= rect
.x() )
1230 new_quads
.append( quad
);
1233 data
.quads
= new_quads
;
1235 QRect rect
= effects
->clientArea( FullArea
, activeScreen
, painting_desktop
);
1239 // we have to change opacity values for fade in/out of windows which are shown on front-desktop
1240 if( prev_desktop
== effects
->currentDesktop() && w
->x() < rect
.x() )
1243 opacity
= timeLine
.value() * cubeOpacity
;
1245 opacity
= cubeOpacity
* (1.0 - timeLine
.value());
1247 if( next_desktop
== effects
->currentDesktop() && w
->x() + w
->width() > rect
.x() + rect
.width() )
1250 opacity
= timeLine
.value() * cubeOpacity
;
1252 opacity
= cubeOpacity
* (1.0 - timeLine
.value());
1255 if( !slide
|| (slide
&& !w
->isDesktop()) || slideOpacity
)
1257 // HACK set opacity to 0.99 in case of fully opaque to ensure that windows are painted in correct sequence
1259 if( opacity
> 0.99f
)
1261 data
.opacity
*= opacity
;
1264 if( w
->isOnDesktop(painting_desktop
) && w
->x() < rect
.x() )
1266 WindowQuadList new_quads
;
1267 foreach( const WindowQuad
&quad
, data
.quads
)
1269 if( quad
.right() > -w
->x() )
1271 new_quads
.append( quad
);
1274 data
.quads
= new_quads
;
1276 if( w
->isOnDesktop(painting_desktop
) && w
->x() + w
->width() > rect
.x() + rect
.width() )
1278 WindowQuadList new_quads
;
1279 foreach( const WindowQuad
&quad
, data
.quads
)
1281 if( quad
.right() <= rect
.width() - w
->x() )
1283 new_quads
.append( quad
);
1286 data
.quads
= new_quads
;
1288 if( w
->y() < rect
.y() )
1290 WindowQuadList new_quads
;
1291 foreach( const WindowQuad
&quad
, data
.quads
)
1293 if( quad
.bottom() > -w
->y() )
1295 new_quads
.append( quad
);
1298 data
.quads
= new_quads
;
1300 if( w
->y() + w
->height() > rect
.y() + rect
.height() )
1302 WindowQuadList new_quads
;
1303 foreach( const WindowQuad
&quad
, data
.quads
)
1305 if( quad
.bottom() <= rect
.height() - w
->y() )
1307 new_quads
.append( quad
);
1310 data
.quads
= new_quads
;
1313 effects
->paintWindow( w
, mask
, region
, data
);
1316 bool CubeEffect::borderActivated( ElectricBorder border
)
1318 if( effects
->activeFullScreenEffect() && effects
->activeFullScreenEffect() != this )
1320 if( border
== borderActivate
&& !activated
)
1322 kDebug(1212) << "border activated";
1329 void CubeEffect::toggle()
1331 if( effects
->activeFullScreenEffect() && effects
->activeFullScreenEffect() != this ||
1332 effects
->numberOfDesktops() < 2 )
1344 void CubeEffect::grabbedKeyboardEvent( QKeyEvent
* e
)
1348 // taken from desktopgrid.cpp
1349 if( e
->type() == QEvent::KeyPress
)
1352 // switch by F<number> or just <number>
1353 if( e
->key() >= Qt::Key_F1
&& e
->key() <= Qt::Key_F35
)
1354 desktop
= e
->key() - Qt::Key_F1
+ 1;
1355 else if( e
->key() >= Qt::Key_0
&& e
->key() <= Qt::Key_9
)
1356 desktop
= e
->key() == Qt::Key_0
? 10 : e
->key() - Qt::Key_0
;
1359 if( desktop
<= effects
->numberOfDesktops())
1361 // we have to rotate to chosen desktop
1362 // and end effect when rotation finished
1363 rotateToDesktop( desktop
);
1369 { // wrap only on autorepeat
1371 // rotate to previous desktop
1372 kDebug(1212) << "left";
1373 if( !rotating
&& !start
)
1376 rotationDirection
= Left
;
1380 if( rotations
.count() < effects
->numberOfDesktops() )
1381 rotations
.enqueue( Left
);
1385 // rotate to next desktop
1386 kDebug(1212) << "right";
1387 if( !rotating
&& !start
)
1390 rotationDirection
= Right
;
1394 if( rotations
.count() < effects
->numberOfDesktops() )
1395 rotations
.enqueue( Right
);
1399 kDebug(1212) << "up";
1400 if( verticalPosition
!= Up
)
1402 if( !verticalRotating
)
1404 verticalRotating
= true;
1405 verticalRotationDirection
= Upwards
;
1406 if( verticalPosition
== Normal
)
1407 verticalPosition
= Up
;
1408 if( verticalPosition
== Down
)
1409 verticalPosition
= Normal
;
1413 verticalRotations
.enqueue( Upwards
);
1416 else if( manualVerticalAngle
< 0.0 && !verticalRotating
)
1418 // rotate to up position from the manual position
1419 verticalRotating
= true;
1420 verticalRotationDirection
= Upwards
;
1421 verticalPosition
= Up
;
1422 manualVerticalAngle
+= 90.0;
1426 kDebug(1212) << "down";
1427 if( verticalPosition
!= Down
)
1429 if( !verticalRotating
)
1431 verticalRotating
= true;
1432 verticalRotationDirection
= Downwards
;
1433 if( verticalPosition
== Normal
)
1434 verticalPosition
= Down
;
1435 if( verticalPosition
== Up
)
1436 verticalPosition
= Normal
;
1440 verticalRotations
.enqueue( Downwards
);
1443 else if( manualVerticalAngle
> 0.0 && !verticalRotating
)
1445 // rotate to down position from the manual position
1446 verticalRotating
= true;
1447 verticalRotationDirection
= Downwards
;
1448 verticalPosition
= Down
;
1449 manualVerticalAngle
-= 90.0;
1452 case Qt::Key_Escape
:
1453 rotateToDesktop( effects
->currentDesktop() );
1457 case Qt::Key_Return
:
1463 zoom
= qMax( -zPosition
, zoom
);
1471 effects
->addRepaintFull();
1475 void CubeEffect::rotateToDesktop( int desktop
)
1477 int tempFrontDesktop
= frontDesktop
;
1478 if( !rotations
.empty() )
1480 // all scheduled rotations will be removed as a speed up
1483 if( rotating
&& !desktopChangedWhileRotating
)
1485 // front desktop will change during the actual rotation - this has to be considered
1486 if( rotationDirection
== Left
)
1490 else if( rotationDirection
== Right
)
1494 if( tempFrontDesktop
> effects
->numberOfDesktops() )
1495 tempFrontDesktop
= 1;
1496 else if( tempFrontDesktop
== 0 )
1497 tempFrontDesktop
= effects
->numberOfDesktops();
1499 // find the fastest rotation path from tempFrontDesktop to desktop
1500 int rightRotations
= tempFrontDesktop
- desktop
;
1501 if( rightRotations
< 0 )
1502 rightRotations
+= effects
->numberOfDesktops();
1503 int leftRotations
= desktop
- tempFrontDesktop
;
1504 if( leftRotations
< 0 )
1505 leftRotations
+= effects
->numberOfDesktops();
1506 if( leftRotations
<= rightRotations
)
1508 for( int i
=0; i
<leftRotations
; i
++ )
1510 rotations
.enqueue( Left
);
1515 for( int i
=0; i
<rightRotations
; i
++ )
1517 rotations
.enqueue( Right
);
1520 if( !start
&& !rotating
&& !rotations
.empty() )
1523 rotationDirection
= rotations
.dequeue();
1525 // change timeline curve if more rotations are following
1526 if( !rotations
.empty() )
1528 currentShape
= TimeLine::EaseInCurve
;
1529 timeLine
.setCurveShape( currentShape
);
1530 // change timeline duration in slide mode
1532 timeLine
.setDuration( rotationDuration
/ (rotations
.count()+1) );
1536 void CubeEffect::setActive( bool active
)
1541 activeScreen
= effects
->activeScreen();
1544 keyboard_grab
= effects
->grabKeyboard( this );
1545 input
= effects
->createInputWindow( this, 0, 0, displayWidth(), displayHeight(),
1546 Qt::OpenHandCursor
);
1547 frontDesktop
= effects
->currentDesktop();
1551 effects
->setActiveFullScreenEffect( this );
1552 kDebug(1212) << "Cube is activated";
1553 verticalPosition
= Normal
;
1554 verticalRotating
= false;
1556 manualVerticalAngle
= 0.0;
1557 if( reflection
&& !slide
)
1559 // clip parts above the reflection area
1560 double eqn
[4] = {0.0, 1.0, 0.0, 0.0};
1562 QRect rect
= effects
->clientArea( FullScreenArea
, activeScreen
, effects
->currentDesktop());
1563 if( effects
->numScreens() > 1 && bigCube
)
1564 rect
= effects
->clientArea( FullArea
, activeScreen
, effects
->currentDesktop() );
1565 glTranslatef( 0.0, rect
.height(), 0.0 );
1566 glClipPlane( GL_CLIP_PLANE0
, eqn
);
1569 // create the needed GL lists
1570 capList
= glGenLists(1);
1571 capListCreated
= false;
1573 effects
->addRepaintFull();
1577 schedule_close
= true;
1578 // we have to add a repaint, to start the deactivating
1579 effects
->addRepaintFull();
1583 void CubeEffect::mouseChanged( const QPoint
& pos
, const QPoint
& oldpos
, Qt::MouseButtons buttons
,
1584 Qt::MouseButtons oldbuttons
, Qt::KeyboardModifiers modifiers
, Qt::KeyboardModifiers oldmodifiers
)
1592 QRect rect
= effects
->clientArea( FullScreenArea
, activeScreen
, effects
->currentDesktop());
1593 if( effects
->numScreens() > 1 && (slide
|| bigCube
) )
1594 rect
= effects
->clientArea( FullArea
, activeScreen
, effects
->currentDesktop() );
1595 if( buttons
.testFlag( Qt::LeftButton
) )
1597 bool repaint
= false;
1598 // vertical movement only if there is not a rotation
1599 if( !verticalRotating
)
1601 // display height corresponds to 180*
1602 int deltaY
= pos
.y() - oldpos
.y();
1603 float deltaVerticalDegrees
= (float)deltaY
/rect
.height()*180.0f
;
1604 manualVerticalAngle
-= deltaVerticalDegrees
;
1605 if( deltaVerticalDegrees
!= 0.0 )
1608 // horizontal movement only if there is not a rotation
1611 // display width corresponds to sum of angles of the polyhedron
1612 int deltaX
= oldpos
.x() - pos
.x();
1613 float deltaDegrees
= (float)deltaX
/rect
.width() * 360.0f
;
1614 manualAngle
-= deltaDegrees
;
1615 if( deltaDegrees
!= 0.0 )
1619 effects
->addRepaintFull();
1621 if( !oldbuttons
.testFlag( Qt::LeftButton
) && buttons
.testFlag( Qt::LeftButton
) )
1623 XDefineCursor( display(), input
, QCursor( Qt::ClosedHandCursor
).handle() );
1625 if( oldbuttons
.testFlag( Qt::LeftButton
) && !buttons
.testFlag( Qt::LeftButton
) )
1627 XDefineCursor( display(), input
, QCursor( Qt::OpenHandCursor
).handle() );
1628 if( closeOnMouseRelease
)
1631 if( oldbuttons
.testFlag( Qt::RightButton
) && !buttons
.testFlag( Qt::RightButton
) )
1633 // end effect on right mouse button
1638 void CubeEffect::desktopChanged( int old
)
1640 if( effects
->activeFullScreenEffect() && effects
->activeFullScreenEffect() != this )
1644 if( !animateDesktopChange
)
1650 rotateToDesktop( effects
->currentDesktop() );
1655 void CubeEffect::tabBoxAdded( int mode
)
1659 if( effects
->activeFullScreenEffect() && effects
->activeFullScreenEffect() != this )
1661 if( useForTabBox
&& mode
!= TabBoxWindowsMode
)
1663 effects
->refTabBox();
1666 rotateToDesktop( effects
->currentTabBoxDesktop() );
1670 void CubeEffect::tabBoxUpdated()
1673 rotateToDesktop( effects
->currentTabBoxDesktop() );
1676 void CubeEffect::tabBoxClosed()
1680 effects
->unrefTabBox();