not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kwin / effects / coverswitch.cpp
blobb7369a1990e12ff4af20c770f097fab0ad08a5d5
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 *********************************************************************/
20 #include "coverswitch.h"
22 #include <kwinconfig.h>
23 #include <QFont>
24 #include <klocale.h>
25 #include <kapplication.h>
26 #include <kcolorscheme.h>
27 #include <kconfiggroup.h>
29 #include <kwinglutils.h>
31 #include <math.h>
33 #include <kdebug.h>
35 #include <GL/gl.h>
37 namespace KWin
40 KWIN_EFFECT( coverswitch, CoverSwitchEffect )
41 KWIN_EFFECT_SUPPORTED( coverswitch, CoverSwitchEffect::supported() )
43 CoverSwitchEffect::CoverSwitchEffect()
44 : mActivated( 0 )
45 , angle( 60.0 )
46 , animation( false )
47 , start( false )
48 , stop( false )
49 , stopRequested( false )
50 , startRequested( false )
51 , zPosition( 900.0 )
52 , scaleFactor( 0.0 )
53 , direction( Left )
54 , selected_window( 0 )
56 reconfigure( ReconfigureAll );
59 CoverSwitchEffect::~CoverSwitchEffect()
63 bool CoverSwitchEffect::supported()
65 return effects->compositingType() == OpenGLCompositing;
68 void CoverSwitchEffect::reconfigure( ReconfigureFlags )
70 KConfigGroup conf = effects->effectConfig( "CoverSwitch" );
71 animationDuration = animationTime( conf, "Duration", 200 );
72 animateSwitch = conf.readEntry( "AnimateSwitch", true );
73 animateStart = conf.readEntry( "AnimateStart", true );
74 animateStop = conf.readEntry( "AnimateStop", true );
75 reflection = conf.readEntry( "Reflection", true );
76 zPosition = conf.readEntry( "ZPosition", 900.0 );
77 thumbnails = conf.readEntry( "Thumbnails", true );
78 dynamicThumbnails = conf.readEntry( "DynamicThumbnails", true );
79 thumbnailWindows = conf.readEntry( "ThumbnailWindows", 8 );
80 timeLine.setCurveShape( TimeLine::EaseInOutCurve );
81 timeLine.setDuration( animationDuration );
83 // thumbnail bar
84 color_frame = KColorScheme( QPalette::Active, KColorScheme::Window ).background().color();
85 color_frame.setAlphaF( 0.9 );
86 color_highlight = KColorScheme( QPalette::Active, KColorScheme::Selection ).background().color();
87 color_highlight.setAlphaF( 0.9 );
88 frame_margin = 10;
89 highlight_margin = 5;
92 void CoverSwitchEffect::prePaintScreen( ScreenPrePaintData& data, int time )
94 if( mActivated || stop || stopRequested )
96 data.mask |= Effect::PAINT_SCREEN_WITH_TRANSFORMED_WINDOWS;
97 if( animation || start || stop )
99 timeLine.addTime( (double)time );
100 if( thumbnails && (!dynamicThumbnails ||
101 (dynamicThumbnails && effects->currentTabBoxWindowList().size() >= thumbnailWindows)) )
102 calculateItemSizes();
105 effects->prePaintScreen(data, time);
108 void CoverSwitchEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
110 effects->paintScreen( mask, region, data );
112 if( mActivated || stop || stopRequested )
114 if( effects->numScreens() > 1 )
116 // unfortunatelly we have to change the projection matrix in dual screen mode
117 QRect fullRect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() );
118 glMatrixMode( GL_PROJECTION );
119 glPushMatrix();
120 glLoadIdentity();
121 float fovy = 60.0f;
122 float aspect = 1.0f;
123 float zNear = 0.1f;
124 float zFar = 100.0f;
125 float ymax = zNear * tan( fovy * M_PI / 360.0f );
126 float ymin = -ymax;
127 float xmin = ymin * aspect;
128 float xmax = ymax * aspect;
129 float xTranslate = 0.0;
130 float yTranslate = 0.0;
131 float xminFactor = 1.0;
132 float xmaxFactor = 1.0;
133 float yminFactor = 1.0;
134 float ymaxFactor = 1.0;
135 if( area.x() == 0 && area.width() != fullRect.width() )
137 // horizontal layout: left screen
138 xminFactor = (float)area.width()/(float)fullRect.width();
139 xmaxFactor = ((float)fullRect.width()-(float)area.width()*0.5f)/((float)fullRect.width()*0.5f);
140 xTranslate = (float)fullRect.width()*0.5f-(float)area.width()*0.5f;
142 if( area.x() != 0 && area.width() != fullRect.width() )
144 // horizontal layout: right screen
145 xminFactor = ((float)fullRect.width()-(float)area.width()*0.5f)/((float)fullRect.width()*0.5f);
146 xmaxFactor = (float)area.width()/(float)fullRect.width();
147 xTranslate = (float)fullRect.width()*0.5f-(float)area.width()*0.5f;
149 if( area.y() == 0 && area.height() != fullRect.height() )
151 // vertical layout: top screen
152 yminFactor = ((float)fullRect.height()-(float)area.height()*0.5f)/((float)fullRect.height()*0.5f);
153 ymaxFactor = (float)area.height()/(float)fullRect.height();
154 yTranslate = (float)fullRect.height()*0.5f-(float)area.height()*0.5f;
156 if( area.y() != 0 && area.height() != fullRect.height() )
158 // vertical layout: bottom screen
159 yminFactor = (float)area.height()/(float)fullRect.height();
160 ymaxFactor = ((float)fullRect.height()-(float)area.height()*0.5f)/((float)fullRect.height()*0.5f);
161 yTranslate = (float)fullRect.height()*0.5f-(float)area.height()*0.5f;
163 glFrustum( xmin*xminFactor, xmax*xmaxFactor, ymin*yminFactor, ymax*ymaxFactor, zNear, zFar );
164 glMatrixMode( GL_MODELVIEW );
165 glPushMatrix();
166 glTranslatef( xTranslate, yTranslate, 0.0 );
169 QList< EffectWindow* > tempList = effects->currentTabBoxWindowList();
170 int index = tempList.indexOf( effects->currentTabBoxWindow() );
171 if( animation || start || stop )
173 if( !start && !stop )
175 if( direction == Right )
176 index++;
177 else
178 index--;
179 if( index < 0 )
180 index = tempList.count() + index;
181 if( index >= tempList.count() )
182 index = index % tempList.count();
184 foreach( Direction direction, scheduled_directions )
186 if( direction == Right )
187 index++;
188 else
189 index--;
190 if( index < 0 )
191 index = tempList.count() + index;
192 if( index >= tempList.count() )
193 index = index % tempList.count();
196 int leftIndex = index -1;
197 if( leftIndex < 0 )
198 leftIndex = tempList.count() -1;
199 int rightIndex = index +1;
200 if( rightIndex == tempList.count() )
201 rightIndex = 0;
203 EffectWindow* frontWindow = tempList[ index ];
204 leftWindows.clear();
205 rightWindows.clear();
207 bool evenWindows = ( tempList.count() % 2 == 0 ) ? true : false;
208 int leftWindowCount = 0;
209 if( evenWindows )
210 leftWindowCount = tempList.count()/2 - 1;
211 else
212 leftWindowCount = ( tempList.count() - 1 )/2;
213 for( int i=0; i < leftWindowCount; i++ )
215 int tempIndex = ( leftIndex - i );
216 if( tempIndex < 0 )
217 tempIndex = tempList.count() + tempIndex;
218 leftWindows.prepend( tempList[ tempIndex ] );
220 int rightWindowCount = 0;
221 if( evenWindows )
222 rightWindowCount = tempList.count()/2;
223 else
224 rightWindowCount = ( tempList.count() - 1 )/2;
225 for( int i=0; i < rightWindowCount; i++ )
227 int tempIndex = ( rightIndex + i ) % tempList.count();
228 rightWindows.prepend( tempList[ tempIndex ] );
231 if( reflection )
233 // restrict painting the reflections to the current screen
234 QRegion clip = QRegion( area );
235 PaintClipper::push( clip );
236 // no reflections during start and stop animation
237 if( !start && !stop )
238 paintScene( frontWindow, &leftWindows, &rightWindows, true );
239 PaintClipper::pop( clip );
240 glEnable( GL_BLEND );
241 glBlendFunc( GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA );
242 glPolygonMode( GL_FRONT, GL_FILL );
243 glPushMatrix();
244 QRect fullRect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() );
245 // we can use a huge scale factor (needed to calculate the rearground vertices)
246 // as we restrict with a PaintClipper painting on the current screen
247 float reflectionScaleFactor = 100000 * tan( 60.0 * M_PI / 360.0f )/area.width();
248 if( effects->numScreens() > 1 && area.x() != fullRect.x() )
250 // have to change the reflection area in horizontal layout and right screen
251 glTranslatef( -area.x(), 0.0, 0.0 );
253 glTranslatef( area.x() + area.width()*0.5f, 0.0, 0.0 );
254 float vertices[] = {
255 -area.width()*0.5f, area.height(), 0.0,
256 area.width()*0.5f, area.height(), 0.0,
257 (float)area.width()*reflectionScaleFactor, area.height(), -5000,
258 -(float)area.width()*reflectionScaleFactor, area.height(), -5000 };
259 // foreground
260 float alpha = 1.0;
261 if( start )
262 alpha = timeLine.value();
263 else if( stop )
264 alpha = 1.0 - timeLine.value();
265 glColor4f( 0.0, 0.0, 0.0, alpha );
267 int y = 0;
268 // have to adjust the y values to fit OpenGL
269 // in OpenGL y==0 is at bottom, in Qt at top
270 if( effects->numScreens() > 1 )
272 QRect fullArea = effects->clientArea( FullArea, 0, 1 );
273 if( fullArea.height() != area.height() )
275 if( area.y() == 0 )
276 y = fullArea.height() - area.height();
277 else
278 y = fullArea.height() - area.y() - area.height();
281 // use scissor to restrict painting of the reflection plane to current screen
282 glScissor( area.x(), y, area.width(), area.height() );
283 glEnable( GL_SCISSOR_TEST );
284 glBegin( GL_POLYGON );
285 glVertex3f( vertices[0], vertices[1], vertices[2] );
286 glVertex3f( vertices[3], vertices[4], vertices[5] );
287 // rearground
288 alpha = -1.0;
289 glColor4f( 0.0, 0.0, 0.0, alpha );
290 glVertex3f( vertices[6], vertices[7], vertices[8] );
291 glVertex3f( vertices[9], vertices[10], vertices[11] );
292 glEnd();
293 glDisable( GL_SCISSOR_TEST );
295 glPopMatrix();
296 glDisable( GL_BLEND );
298 paintScene( frontWindow, &leftWindows, &rightWindows );
300 if( effects->numScreens() > 1 )
302 glPopMatrix();
303 // revert change of projection matrix
304 glMatrixMode( GL_PROJECTION );
305 glPopMatrix();
306 glMatrixMode( GL_MODELVIEW );
309 // caption of selected window
310 QColor color_frame;
311 QColor color_text;
312 color_frame = KColorScheme( QPalette::Active, KColorScheme::Window ).background().color();
313 color_frame.setAlphaF( 0.9 );
314 color_text = KColorScheme( QPalette::Active, KColorScheme::Window ).foreground().color();
315 if( start )
317 color_frame.setAlphaF( 0.9 * timeLine.value() );
318 color_text.setAlphaF( timeLine.value() );
320 else if( stop )
322 color_frame.setAlphaF( 0.9 - 0.9 * timeLine.value() );
323 color_text.setAlphaF( 1.0 - timeLine.value() );
325 QFont text_font;
326 text_font.setBold( true );
327 text_font.setPointSize( 20 );
328 glPushAttrib( GL_CURRENT_BIT );
329 glColor4f( color_frame.redF(), color_frame.greenF(), color_frame.blueF(), color_frame.alphaF());
330 QRect frameRect = QRect( area.width()*0.25f + area.x(),
331 area.height()*0.9f + area.y(),
332 area.width()*0.5f,
333 QFontMetrics( text_font ).height() * 1.2f );
334 renderRoundBoxWithEdge( frameRect );
335 effects->paintText( effects->currentTabBoxWindow()->caption(),
336 frameRect.center(),
337 frameRect.width() - 100,
338 color_text,
339 text_font );
340 glPopAttrib();
341 // icon of selected window
342 QPixmap iconPixmap = effects->currentTabBoxWindow()->icon();
343 if( start || stop )
345 int alpha = 255.0f * timeLine.value();
346 if( stop )
348 alpha = 255.0f - alpha;
350 QPixmap transparency = iconPixmap.copy( iconPixmap.rect() );
351 transparency.fill( QColor( 255, 255, 255, alpha ) );
352 iconPixmap.setAlphaChannel( transparency.alphaChannel() );
354 GLTexture* icon = new GLTexture( iconPixmap );
355 icon->bind();
356 glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT );
357 icon->bind();
358 glEnable( GL_BLEND );
359 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
360 // icon takes 80 % of the height of the frame. So each 10 % space left on the top and bottom
361 QRect iconRect = QRect( frameRect.x() + frameRect.height()*0.1f,
362 frameRect.y() + frameRect.height()*0.1f,
363 frameRect.height()*0.8f,
364 frameRect.height()*0.8f );
365 icon->render( region, iconRect);
366 icon->unbind();
367 delete icon;
368 glDisable( GL_BLEND );
369 glPopAttrib();
371 if( ( thumbnails && (!dynamicThumbnails ||
372 (dynamicThumbnails && effects->currentTabBoxWindowList().size() >= thumbnailWindows)) )
373 && !( start || stop ) )
375 paintFrame();
376 // HACK: PaintClipper is used because window split is somehow wrong if the height is greater than width
377 PaintClipper::push( frame_area.adjusted( frame_margin, frame_margin, -frame_margin, -frame_margin ));
378 paintHighlight( highlight_area );
379 foreach( EffectWindow* w, windows.keys())
381 paintWindowThumbnail( w );
382 paintWindowIcon( w );
384 PaintClipper::pop( frame_area.adjusted( frame_margin, frame_margin, -frame_margin, -frame_margin ) );
389 void CoverSwitchEffect::postPaintScreen()
391 if( ( mActivated && ( animation || start ) ) || stop || stopRequested )
393 if( timeLine.value() == 1.0 )
395 timeLine.setProgress(0.0);
396 if( stop )
398 stop = false;
399 effects->setActiveFullScreenEffect( 0 );
400 if( startRequested )
402 startRequested = false;
403 mActivated = true;
404 effects->refTabBox();
405 if( animateStart )
407 start = true;
411 else if( !scheduled_directions.isEmpty() )
413 direction = scheduled_directions.dequeue();
414 if( start )
416 animation = true;
417 start = false;
420 else
422 animation = false;
423 start = false;
424 if( stopRequested )
426 stopRequested = false;
427 stop = true;
431 effects->addRepaintFull();
433 effects->postPaintScreen();
436 void CoverSwitchEffect::paintScene( EffectWindow* frontWindow, QList< EffectWindow* >* leftWindows,
437 QList< EffectWindow* >* rightWindows, bool reflectedWindows )
439 // LAYOUT
440 // one window in the front. Other windows left and right rotated
441 // for odd number of windows: left: (n-1)/2; front: 1; right: (n-1)/2
442 // for even number of windows: left: n/2; front: 1; right: n/2 -1
444 // ANIMATION
445 // forward (alt+tab)
446 // all left windows are moved to next position
447 // top most left window is rotated and moved to front window position
448 // front window is rotated and moved to next right window position
449 // right windows are moved to next position
450 // last right window becomes totally transparent in half the time
451 // appears transparent on left side and becomes totally opaque again
452 // backward (alt+shift+tab) same as forward but opposite direction
453 int width = area.width();
454 int leftWindowCount = leftWindows->count();
455 int rightWindowCount = rightWindows->count();
456 RotationData rot;
457 rot.axis = RotationData::YAxis;
460 // Problem during animation: a window which is painted after another window
461 // appears in front of the other
462 // so during animation the painting order has to be rearreanged
463 // paint sequence no animation: left, right, front
464 // paint sequence forward animation: right, front, left
466 if( !animation )
468 paintWindows( leftWindows, true, reflectedWindows );
469 paintWindows( rightWindows, false, reflectedWindows );
470 paintFrontWindow( frontWindow, width, leftWindowCount, rightWindowCount, reflectedWindows );
472 else
474 if( direction == Right )
476 if( timeLine.value() < 0.5 )
478 // paint in normal way
479 paintWindows( leftWindows, true, reflectedWindows );
480 paintWindows( rightWindows, false, reflectedWindows );
481 paintFrontWindow( frontWindow, width, leftWindowCount, rightWindowCount, reflectedWindows );
483 else
485 paintWindows( rightWindows, false, reflectedWindows );
486 paintFrontWindow( frontWindow, width, leftWindowCount, rightWindowCount, reflectedWindows );
487 paintWindows( leftWindows, true, reflectedWindows, rightWindows->at( 0 ) );
490 else
492 paintWindows( leftWindows, true, reflectedWindows );
493 if( timeLine.value() < 0.5 )
495 paintWindows( rightWindows, false, reflectedWindows );
496 paintFrontWindow( frontWindow, width, leftWindowCount, rightWindowCount, reflectedWindows );
498 else
500 EffectWindow* leftWindow;
501 if( leftWindowCount > 0)
503 leftWindow = leftWindows->at( 0 );
504 paintFrontWindow( frontWindow, width, leftWindowCount, rightWindowCount, reflectedWindows );
506 else
507 leftWindow = frontWindow;
508 paintWindows( rightWindows, false, reflectedWindows, leftWindow );
514 void CoverSwitchEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
516 if( mActivated || stop || stopRequested )
518 if( !( mask & PAINT_WINDOW_TRANSFORMED ) && !w->isDesktop() )
520 if( ( start || stop ) && w->isDock() )
522 data.opacity = 1.0 - timeLine.value();
523 if( stop )
524 data.opacity = timeLine.value();
526 else
527 return;
530 if ( ( start || stop ) && (!w->isOnCurrentDesktop() || w->isMinimized() ) )
532 if (stop) // Fade out windows not on the current desktop
533 data.opacity = (1.0 - timeLine.value());
534 else // Fade in Windows from other desktops when animation is started
535 data.opacity = timeLine.value();
537 effects->paintWindow( w, mask, region, data );
540 void CoverSwitchEffect::tabBoxAdded( int mode )
542 if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this )
543 return;
544 if( !mActivated )
546 // only for windows mode
547 if( mode == TabBoxWindowsMode && effects->currentTabBoxWindowList().count() > 0 )
549 input = effects->createFullScreenInputWindow( this, Qt::ArrowCursor );
550 activeScreen = effects->activeScreen();
551 if( !stop && !stopRequested )
553 effects->refTabBox();
554 effects->setActiveFullScreenEffect( this );
555 scheduled_directions.clear();
556 selected_window = effects->currentTabBoxWindow();
557 direction = Left;
558 mActivated = true;
559 if( animateStart )
561 start = true;
564 // Calculation of correct area
565 area = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop());
566 scaleFactor = (zPosition+1100) * 2.0 * tan( 60.0 * M_PI / 360.0f )/displayWidth();
567 if( displayWidth()-area.width() != 0 )
569 // one of the screens is smaller than the other (horizontal)
570 if( area.width() < displayWidth() - area.width() )
571 scaleFactor *= (float)area.width()/(float)(displayWidth()-area.width());
572 else if( area.width() != displayWidth() - area.width() )
574 // vertical layout with different width
575 // but we don't want to catch screens with same width and different height
576 if( displayHeight() != area.height() )
577 scaleFactor *= (float)area.width()/(float)(displayWidth());
581 effects->addRepaintFull();
583 else
585 startRequested = true;
587 if( thumbnails && (!dynamicThumbnails ||
588 (dynamicThumbnails && effects->currentTabBoxWindowList().size() >= thumbnailWindows)) )
590 highlight_is_set = false;
591 calculateFrameSize();
592 calculateItemSizes();
598 void CoverSwitchEffect::tabBoxClosed()
600 if( mActivated )
602 if( animateStop )
604 if( !animation && !start )
606 stop = true;
608 else if( start && scheduled_directions.isEmpty() )
610 start = false;
611 stop = true;
612 timeLine.setProgress( 1.0 - timeLine.value() );
614 else
616 stopRequested = true;
619 else
620 effects->setActiveFullScreenEffect( 0 );
621 mActivated = false;
622 effects->unrefTabBox();
623 effects->destroyInputWindow( input );
624 effects->addRepaintFull();
625 if( thumbnails && (!dynamicThumbnails ||
626 (dynamicThumbnails && effects->currentTabBoxWindowList().size() >= thumbnailWindows)) )
628 qDeleteAll( windows );
629 windows.clear();
634 void CoverSwitchEffect::tabBoxUpdated()
636 if( mActivated )
638 if( animateSwitch && effects->currentTabBoxWindowList().count() > 1)
640 // determine the switch direction
641 if( selected_window != effects->currentTabBoxWindow() )
643 if( selected_window != NULL )
645 int old_index = effects->currentTabBoxWindowList().indexOf( selected_window );
646 int new_index = effects->currentTabBoxWindowList().indexOf( effects->currentTabBoxWindow() );
647 Direction new_direction;
648 int distance = new_index - old_index;
649 if( distance > 0 )
650 new_direction = Left;
651 if( distance < 0 )
652 new_direction = Right;
653 if( effects->currentTabBoxWindowList().count() == 2 )
655 new_direction = Left;
656 distance = 1;
658 if( distance != 0 )
660 distance = abs( distance );
661 int tempDistance = effects->currentTabBoxWindowList().count() - distance;
662 if( tempDistance < abs( distance ) )
664 distance = tempDistance;
665 if( new_direction == Left )
666 new_direction = Right;
667 else
668 new_direction = Left;
670 if( !animation && !start )
672 animation = true;
673 direction = new_direction;
674 distance--;
676 for( int i=0; i<distance; i++ )
678 if( !scheduled_directions.isEmpty() && scheduled_directions.last() != new_direction )
679 scheduled_directions.pop_back();
680 else
681 scheduled_directions.enqueue( new_direction );
682 if( scheduled_directions.count() == effects->currentTabBoxWindowList().count() )
683 scheduled_directions.clear();
687 selected_window = effects->currentTabBoxWindow();
690 if( thumbnails && (!dynamicThumbnails ||
691 (dynamicThumbnails && effects->currentTabBoxWindowList().size() >= thumbnailWindows)) )
693 calculateFrameSize();
694 calculateItemSizes();
696 effects->addRepaintFull();
700 void CoverSwitchEffect::paintWindowCover( EffectWindow* w, bool reflectedWindow, WindowPaintData& data )
702 QRect windowRect = w->geometry();
703 data.yTranslate = area.height() - windowRect.y() - windowRect.height();
704 data.zTranslate = -zPosition;
705 if( start )
707 if( w->isMinimized() )
709 data.opacity *= timeLine.value();
711 else
713 data.xTranslate *= timeLine.value();
714 data.yTranslate *= timeLine.value();
715 if( effects->numScreens() > 1)
717 QRect clientRect = effects->clientArea( FullScreenArea, w->screen(), effects->currentDesktop() );
718 QRect fullRect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() );
719 if( w->screen() == activeScreen )
721 if( clientRect.width() != fullRect.width() && clientRect.x() != fullRect.x() )
723 data.xTranslate -= clientRect.x()*(1.0f-timeLine.value());
725 if( clientRect.height() != fullRect.height() && clientRect.y() != fullRect.y() )
727 data.yTranslate -= clientRect.y()*(1.0f-timeLine.value());
730 else
732 if( clientRect.width() != fullRect.width() && clientRect.x() < area.x())
734 data.xTranslate -= clientRect.width()*(1.0f-timeLine.value());
736 if( clientRect.height() != fullRect.height() && clientRect.y() < area.y() )
738 data.yTranslate -= clientRect.height()*(1.0f-timeLine.value());
742 data.zTranslate *= timeLine.value();
743 if( data.rotation )
744 data.rotation->angle *= timeLine.value();
747 if( stop )
749 if( w->isMinimized() && w != effects->activeWindow() )
751 data.opacity *= (1.0 - timeLine.value());
753 else
755 data.xTranslate *= (1.0 - timeLine.value());
756 data.yTranslate *= (1.0 - timeLine.value());
757 if( effects->numScreens() > 1)
759 QRect clientRect = effects->clientArea( FullScreenArea, w->screen(), effects->currentDesktop() );
760 QRect rect = effects->clientArea( FullScreenArea, activeScreen, effects->currentDesktop() );
761 QRect fullRect = effects->clientArea( FullArea, activeScreen, effects->currentDesktop() );
762 if( w->screen() == activeScreen )
764 if( clientRect.width() != fullRect.width() && clientRect.x() != fullRect.x() )
766 data.xTranslate -= clientRect.x()*timeLine.value();
768 if( clientRect.height() != fullRect.height() && clientRect.y() != fullRect.y() )
770 data.yTranslate -= clientRect.y()*timeLine.value();
773 else
775 if( clientRect.width() != fullRect.width() && clientRect.x() < rect.x())
777 data.xTranslate -= clientRect.width()*timeLine.value();
779 if( clientRect.height() != fullRect.height() && clientRect.y() < area.y() )
781 data.yTranslate -= clientRect.height()*timeLine.value();
785 data.zTranslate *= (1.0 - timeLine.value());
786 if( data.rotation )
787 data.rotation->angle *= (1.0 - timeLine.value());
791 QRect thumbnail = infiniteRegion();
793 if( reflectedWindow )
795 glPushMatrix();
796 glScalef( 1.0, -1.0, 1.0 );
797 data.yTranslate = - area.height() - windowRect.y() - windowRect.height();
798 effects->paintWindow( w,
799 PAINT_WINDOW_TRANSFORMED,
800 infiniteRegion(), data );
801 glPopMatrix();
803 else
805 effects->paintWindow( w,
806 PAINT_WINDOW_TRANSFORMED,
807 infiniteRegion(), data );
811 void CoverSwitchEffect::paintFrontWindow( EffectWindow* frontWindow, int width, int leftWindows, int rightWindows, bool reflectedWindow )
813 if( frontWindow == NULL )
814 return;
815 float distance = 0.0;
816 bool specialHandlingForward = false;
817 WindowPaintData data( frontWindow );
818 data.xTranslate = area.width()*0.5 - frontWindow->geometry().x() - frontWindow->geometry().width()*0.5;
819 if( leftWindows == 0 )
821 leftWindows = 1;
822 if( !start && !stop )
823 specialHandlingForward = true;
825 if( rightWindows == 0 )
827 rightWindows = 1;
829 if( animation )
831 if( direction == Right )
833 // move to right
834 distance = -frontWindow->geometry().width()*0.5f + area.width()*0.5f +
835 (((float)displayWidth()*0.5*scaleFactor)-(float)area.width()*0.5f)/rightWindows;
836 data.xTranslate += distance * timeLine.value();
837 RotationData rot;
838 rot.axis = RotationData::YAxis;
839 rot.angle = -angle*timeLine.value();
840 rot.xRotationPoint = frontWindow->geometry().width();
841 data.rotation = &rot;
843 else
845 // move to left
846 distance = frontWindow->geometry().width()*0.5f - area.width()*0.5f +
847 ((float)width*0.5f-((float)displayWidth()*0.5*scaleFactor))/leftWindows;
848 float factor = 1.0;
849 if( specialHandlingForward )
850 factor = 2.0;
851 data.xTranslate += distance * timeLine.value() * factor;
852 RotationData rot;
853 rot.axis = RotationData::YAxis;
854 rot.angle = angle*timeLine.value();
855 data.rotation = &rot;
858 if( specialHandlingForward )
860 data.opacity *= (1.0 - timeLine.value() * 2.0);
861 paintWindowCover( frontWindow, reflectedWindow, data );
863 else
864 paintWindowCover( frontWindow, reflectedWindow, data );
867 void CoverSwitchEffect::paintWindows( QList< EffectWindow* >* windows, bool left, bool reflectedWindows, EffectWindow* additionalWindow )
869 int width = area.width();
870 int windowCount = windows->count();
871 EffectWindow* window;
873 int rotateFactor = 1;
874 if( !left )
876 rotateFactor = -1;
879 float xTranslate = -((float)(width)*0.5f-((float)displayWidth()*0.5*scaleFactor));
880 if( !left )
881 xTranslate = ((float)displayWidth()*0.5*scaleFactor)-(float)width*0.5f;
882 // handling for additional window from other side
883 // has to appear on this side after half of the time
884 if( animation && timeLine.value() >= 0.5 && additionalWindow != NULL )
886 RotationData rot;
887 rot.axis = RotationData::YAxis;
888 rot.angle = angle;
889 rot.angle = angle*rotateFactor;
890 WindowPaintData data( additionalWindow );
891 if( left )
892 data.xTranslate += -xTranslate - additionalWindow->geometry().x();
893 else
895 data.xTranslate += xTranslate + area.width() -
896 additionalWindow->geometry().x() - additionalWindow->geometry().width();
897 rot.xRotationPoint = additionalWindow->geometry().width();
899 data.rotation = &rot;
900 data.opacity *= ( timeLine.value() - 0.5 ) * 2.0;
901 paintWindowCover( additionalWindow, reflectedWindows, data );
903 RotationData rot;
904 rot.axis = RotationData::YAxis;
905 // normal behaviour
906 for( int i=0; i < windowCount; i++ )
908 window = windows->at( i );
909 if( window == NULL )
910 continue;
911 WindowPaintData data( window );
912 rot.angle = angle;
913 if( left )
914 data.xTranslate += -xTranslate + xTranslate*i/windowCount - window->geometry().x();
915 else
916 data.xTranslate += xTranslate + width - xTranslate*i/windowCount - window->geometry().x() - window->geometry().width();
917 if( animation )
919 if( direction == Right )
921 if( ( i == windowCount - 1 ) && left )
923 // right most window on left side -> move to front
924 // have to move one window distance plus half the difference between the window and the desktop size
925 data.xTranslate += (xTranslate/windowCount + (width - window->geometry().width())*0.5f)*timeLine.value();
926 rot.angle = ( angle - angle * timeLine.value() );
928 // right most window does not have to be moved
929 else if( !left && ( i == 0 ) ); // do nothing
930 else
932 // all other windows - move to next position
933 data.xTranslate += xTranslate/windowCount * timeLine.value();
936 else
938 if( ( i == windowCount - 1 ) && !left )
940 // left most window on right side -> move to front
941 data.xTranslate -= (xTranslate/windowCount + (width - window->geometry().width())*0.5f)*timeLine.value();
942 rot.angle = ( angle - angle * timeLine.value() );
944 // left most window does not have to be moved
945 else if( i==0 && left); // do nothing
946 else
948 // all other windows - move to next position
949 data.xTranslate -= xTranslate/windowCount * timeLine.value();
953 if( left )
954 rot.xRotationPoint = 0.0;
955 else
956 rot.xRotationPoint = window->geometry().width();
957 rot.angle *= rotateFactor;
958 data.rotation = &rot;
959 // make window most to edge transparent if animation
960 if( animation && i == 0 && ( ( direction == Left && left ) || ( direction == Right && !left ) ) )
962 // only for the first half of the animation
963 if( timeLine.value() < 0.5 )
965 data.opacity *= (1.0 - timeLine.value() * 2.0);
966 paintWindowCover( window, reflectedWindows, data );
969 else
971 paintWindowCover( window, reflectedWindows, data );
976 // thumbnail bar - taken from boxswitch effect
977 void CoverSwitchEffect::calculateFrameSize()
979 int itemcount;
981 QRect screenr = effects->clientArea( PlacementArea, activeScreen, effects->currentDesktop());
982 itemcount = effects->currentTabBoxWindowList().count();
983 item_max_size.setWidth( (screenr.width()*0.95f - frame_margin * 2)/itemcount );
984 if( item_max_size.width() > 250 )
985 item_max_size.setWidth( 250 );
986 item_max_size.setHeight( item_max_size.width() * ((float)screenr.height()/(float)screenr.width()) );
987 // Shrink the size until all windows/desktops can fit onscreen
988 frame_area.setWidth( frame_margin * 2 + itemcount * item_max_size.width());
989 frame_area.setHeight( frame_margin * 2 + item_max_size.height() );
991 frame_area.moveTo( screenr.x() + ( screenr.width() - frame_area.width()) / 2,
992 screenr.y() + screenr.height()*0.05f );
995 void CoverSwitchEffect::calculateItemSizes()
997 windows.clear();
998 EffectWindowList original_windows = effects->currentTabBoxWindowList();
999 int index = original_windows.indexOf( effects->currentTabBoxWindow() );
1000 int leftIndex = index;
1001 int rightIndex = index + 1;
1002 if( rightIndex == original_windows.count() )
1003 rightIndex = 0;
1004 EffectWindowList ordered_windows;
1006 int leftWindowCount = original_windows.count()/2;
1007 int rightWindowCount = leftWindowCount;
1008 if( original_windows.count()%2 == 1 )
1009 leftWindowCount++;
1010 for( int i=0; i < leftWindowCount; i++ )
1012 int tempIndex = ( leftIndex - i );
1013 if( tempIndex < 0 )
1014 tempIndex = original_windows.count() + tempIndex;
1015 ordered_windows.prepend( original_windows[ tempIndex ] );
1017 for( int i=0; i < rightWindowCount; i++ )
1019 int tempIndex = ( rightIndex + i ) % original_windows.count();
1020 ordered_windows.append( original_windows[ tempIndex ] );
1022 // move items cause of schedule
1023 for( int i=0; i < scheduled_directions.count(); i++ )
1025 Direction actual = scheduled_directions[ i ];
1026 if( actual == Left )
1028 EffectWindow* w = ordered_windows.takeLast();
1029 ordered_windows.prepend( w );
1031 else
1033 EffectWindow* w = ordered_windows.takeFirst();
1034 ordered_windows.append( w );
1037 if( animation && timeLine.value() < 0.5 )
1039 if( direction == Left )
1041 EffectWindow* w = ordered_windows.takeLast();
1042 edge_window = w;
1043 ordered_windows.prepend( w );
1045 else
1047 EffectWindow* w = ordered_windows.takeFirst();
1048 edge_window = w;
1049 ordered_windows.append( w );
1052 else if( animation && timeLine.value() >= 0.5 )
1054 if( animation && direction == Left )
1055 edge_window = ordered_windows.last();
1056 if( animation && direction == Right )
1057 edge_window = ordered_windows.first();
1059 int offset = 0;
1060 if( animation )
1062 if( direction == Left )
1063 offset = (float)item_max_size.width()*(1.0-timeLine.value());
1064 else
1065 offset = -(float)item_max_size.width()*(1.0-timeLine.value());
1067 for( int i = 0; i < ordered_windows.count(); i++ )
1069 EffectWindow* w = ordered_windows.at( i );
1070 windows[ w ] = new ItemInfo();
1072 float moveIndex = i;
1073 if( animation && timeLine.value() < 0.5 )
1075 if( direction == Left )
1076 moveIndex--;
1077 else
1078 moveIndex++;
1080 if( ordered_windows.count()%2 == 0 )
1081 moveIndex += 0.5;
1082 windows[ w ]->area = QRect( frame_area.x() + frame_margin
1083 + moveIndex * item_max_size.width() + offset,
1084 frame_area.y() + frame_margin,
1085 item_max_size.width(), item_max_size.height());
1086 windows[ w ]->clickable = windows[ w ]->area;
1088 if( ordered_windows.count()%2 == 0 )
1090 right_window = ordered_windows.last();
1092 if( !highlight_is_set )
1094 highlight_area = windows[ effects->currentTabBoxWindow() ]->area;
1095 highlight_is_set = true;
1099 void CoverSwitchEffect::paintFrame()
1101 glPushAttrib( GL_CURRENT_BIT );
1102 glColor4f( color_frame.redF(), color_frame.greenF(), color_frame.blueF(), color_frame.alphaF());
1103 renderRoundBoxWithEdge( frame_area );
1104 glPopAttrib();
1107 void CoverSwitchEffect::paintHighlight( QRect area )
1109 glPushAttrib( GL_CURRENT_BIT );
1110 glColor4f( color_highlight.redF(), color_highlight.greenF(), color_highlight.blueF(), color_highlight.alphaF());
1111 renderRoundBox( area, 6 );
1112 glPopAttrib();
1115 void CoverSwitchEffect::paintWindowThumbnail( EffectWindow* w )
1117 if( !windows.contains( w ))
1118 return;
1119 WindowPaintData data( w );
1121 setPositionTransformations( data,
1122 windows[ w ]->thumbnail, w,
1123 windows[ w ]->area.adjusted( highlight_margin, highlight_margin, -highlight_margin, -highlight_margin ),
1124 Qt::KeepAspectRatio );
1126 if( animation && ( w == edge_window ) && ( windows.size() % 2 == 1 ) )
1128 // in case of animation:
1129 // the window which has to change the side will be split and painted on both sides of the edge
1130 double splitPoint = 0.0;
1131 if( direction == Left )
1133 splitPoint = w->geometry().width()*timeLine.value();
1135 else
1137 splitPoint = w->geometry().width() - w->geometry().width()*timeLine.value();
1139 data.quads = data.quads.splitAtX( splitPoint );
1140 WindowQuadList left_quads;
1141 WindowQuadList right_quads;
1142 foreach( const WindowQuad &quad, data.quads )
1144 if( quad.left() >= splitPoint )
1145 left_quads << quad;
1146 if( quad.right() <= splitPoint )
1147 right_quads << quad;
1149 // the base position of the window is changed after half of the animation
1150 if( timeLine.value() < 0.5 )
1152 if( direction == Left )
1153 data.quads = left_quads;
1154 else
1155 data.quads = right_quads;
1157 else
1159 if( direction == Left )
1160 data.quads = right_quads;
1161 else
1162 data.quads = left_quads;
1165 // paint one part of the thumbnail
1166 effects->drawWindow( w,
1167 PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSFORMED,
1168 windows[ w ]->thumbnail, data );
1170 QRect secondThumbnail;
1172 // paint the second part of the thumbnail:
1173 // the other window quads are needed and a new rect for transformation has to be calculated
1174 if( direction == Left )
1176 if( timeLine.value() < 0.5 )
1178 data.quads = right_quads;
1179 secondThumbnail = QRect( frame_area.x() + frame_area.width() - frame_margin
1180 - (float)item_max_size.width()*timeLine.value(),
1181 frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height());
1183 else
1185 data.quads = left_quads;
1186 secondThumbnail = QRect( frame_area.x() + frame_margin - (float)item_max_size.width()*timeLine.value(),
1187 frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height());
1188 if( right_window )
1189 secondThumbnail = QRect( frame_area.x() + frame_margin -
1190 (float)item_max_size.width()*(timeLine.value()-0.5),
1191 frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height());
1194 else
1196 if( timeLine.value() < 0.5 )
1198 data.quads = left_quads;
1199 secondThumbnail = QRect( frame_area.x() + frame_margin -
1200 (float)item_max_size.width()*(1.0 - timeLine.value()),
1201 frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height());
1203 else
1205 data.quads = right_quads;
1206 secondThumbnail = QRect( frame_area.x() + frame_area.width() - frame_margin
1207 - (float)item_max_size.width()*(1.0 - timeLine.value()),
1208 frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height());
1211 setPositionTransformations( data,
1212 windows[ w ]->thumbnail, w,
1213 secondThumbnail.adjusted( highlight_margin, highlight_margin, -highlight_margin, -highlight_margin ),
1214 Qt::KeepAspectRatio );
1215 effects->drawWindow( w,
1216 PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSFORMED,
1217 windows[ w ]->thumbnail, data );
1219 else if( ( windows.size() % 2 == 0 ) && ( w == right_window ) )
1221 // in case of even number of thumbnails:
1222 // the window on the right is painted one half on left and on half on the right side
1223 float animationOffset = 0.0f;
1224 double splitPoint = w->geometry().width()*0.5;
1225 if( animation && timeLine.value() <= 0.5 )
1227 // in case of animation the right window has only to be split during first half of animation
1228 if( direction == Left )
1230 splitPoint += w->geometry().width()*timeLine.value();
1231 animationOffset = -(float)item_max_size.width()*timeLine.value();
1233 else
1235 splitPoint -= w->geometry().width()*timeLine.value();
1236 animationOffset = (float)item_max_size.width()*timeLine.value();
1239 if( animation && timeLine.value() > 0.5 )
1241 // at half of animation a different window has become the right window
1242 // we have to adjust the splitting again
1243 if( direction == Left )
1245 splitPoint -= w->geometry().width()*(1.0-timeLine.value());
1246 animationOffset = (float)item_max_size.width()*(1.0-timeLine.value());
1248 else
1250 splitPoint += w->geometry().width()*(1.0-timeLine.value());
1251 animationOffset = -(float)item_max_size.width()*(1.0-timeLine.value());
1254 data.quads = data.quads.splitAtX( splitPoint );
1255 WindowQuadList rightQuads;
1256 WindowQuadList leftQuads;
1257 foreach( const WindowQuad &quad, data.quads )
1259 if( quad.right() <= splitPoint )
1260 leftQuads << quad;
1261 else
1262 rightQuads << quad;
1265 // left quads are painted on right side of frame
1266 data.quads = leftQuads;
1267 effects->drawWindow( w,
1268 PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSFORMED,
1269 windows[ w ]->thumbnail, data );
1271 // right quads are painted on left side of frame
1272 data.quads = rightQuads;
1273 QRect secondThumbnail;
1274 secondThumbnail = QRect( frame_area.x() + frame_margin -
1275 (float)item_max_size.width()*0.5 + animationOffset,
1276 frame_area.y() + frame_margin, item_max_size.width(), item_max_size.height());
1277 setPositionTransformations( data,
1278 windows[ w ]->thumbnail, w,
1279 secondThumbnail.adjusted( highlight_margin, highlight_margin, -highlight_margin, -highlight_margin ),
1280 Qt::KeepAspectRatio );
1281 effects->drawWindow( w,
1282 PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSFORMED,
1283 windows[ w ]->thumbnail, data );
1285 else
1287 effects->drawWindow( w,
1288 PAINT_WINDOW_OPAQUE | PAINT_WINDOW_TRANSFORMED,
1289 windows[ w ]->thumbnail, data );
1293 void CoverSwitchEffect::paintWindowIcon( EffectWindow* w )
1295 if( !windows.contains( w ))
1296 return;
1297 // Don't render null icons
1298 if( w->icon().isNull() )
1300 return;
1303 if( windows[ w ]->icon.cacheKey() != w->icon().cacheKey())
1304 { // make sure windows[ w ]->icon is the right QPixmap, and rebind
1305 windows[ w ]->icon = w->icon();
1306 if( ( windows.size() % 2 == 1 ) && animation && w == edge_window )
1308 int alpha;
1309 if( timeLine.value() < 0.5 )
1310 alpha = 255.0f * (1.0 - timeLine.value()*2.0);
1311 else
1312 alpha = 255.0f * (timeLine.value()*2.0 - 1.0);
1313 QPixmap transparency = windows[ w ]->icon.copy( windows[ w ]->icon.rect() );
1314 transparency.fill( QColor( 255, 255, 255, alpha ) );
1315 windows[ w ]->icon.setAlphaChannel( transparency.alphaChannel() );
1317 windows[ w ]->iconTexture.load( windows[ w ]->icon );
1318 windows[ w ]->iconTexture.setFilter( GL_LINEAR );
1320 int width = windows[ w ]->icon.width();
1321 int height = windows[ w ]->icon.height();
1322 int x = windows[ w ]->area.x() + windows[ w ]->area.width() - width - highlight_margin;
1323 int y = windows[ w ]->area.y() + windows[ w ]->area.height() - height - highlight_margin;
1324 if( ( windows.size() % 2 == 0 ) )
1326 if( w == right_window )
1328 // in case of right window the icon has to be painted on the left side of the frame
1329 x = frame_area.x() + windows[ w ]->area.width()*0.5 - width - highlight_margin;
1330 if( animation )
1332 if( timeLine.value() <= 0.5 )
1334 if( direction == Left )
1336 x -= windows[ w ]->area.width()*timeLine.value();
1337 x = qMax( x, frame_area.x() + frame_margin );
1339 else
1340 x += windows[ w ]->area.width()*timeLine.value();
1342 else
1344 if( direction == Left )
1345 x += windows[ w ]->area.width()*(1.0-timeLine.value());
1346 else
1348 x -= windows[ w ]->area.width()*(1.0-timeLine.value());
1349 x = qMax( x, frame_area.x() + frame_margin );
1355 else
1357 // during animation the icon of the edge window has to change position
1358 if( animation && w == edge_window )
1360 if( timeLine.value() < 0.5 )
1362 if( direction == Left )
1363 x += windows[ w ]->area.width()*timeLine.value();
1364 else
1365 x -= windows[ w ]->area.width()*timeLine.value();
1367 else
1369 if( direction == Left )
1370 x -= windows[ w ]->area.width()*(1.0 - timeLine.value());
1371 else
1372 x += windows[ w ]->area.width()*(1.0 - timeLine.value());
1376 glPushAttrib( GL_CURRENT_BIT | GL_ENABLE_BIT );
1377 glEnable( GL_BLEND );
1378 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1379 // Render some background
1380 float alpha = 0.5;
1381 if( ( windows.size() % 2 == 1 ) && animation && w == edge_window )
1383 if( timeLine.value() < 0.5 )
1384 alpha *= (1.0 - timeLine.value()*2.0);
1385 else
1386 alpha *= (timeLine.value()*2.0 - 1.0);
1388 glColor4f( 0, 0, 0, alpha );
1389 renderRoundBox( QRect( x-3, y-3, width+6, height+6 ), 3 );
1390 // Render the icon
1391 glColor4f( 1, 1, 1, 1 );
1392 windows[ w ]->iconTexture.bind();
1393 windows[ w ]->iconTexture.render( infiniteRegion(), QRect( x, y, width, height ));
1394 windows[ w ]->iconTexture.unbind();
1395 glPopAttrib();
1398 void CoverSwitchEffect::windowInputMouseEvent( Window w, QEvent* e )
1400 assert( w == input );
1401 if( e->type() != QEvent::MouseButtonPress )
1402 return;
1403 // we don't want click events during animations
1404 if( animation )
1405 return;
1406 QPoint pos = static_cast< QMouseEvent* >( e )->pos();
1408 // has one of the thumbnails been clicked?
1409 if( (thumbnails && (!dynamicThumbnails ||
1410 (dynamicThumbnails && effects->currentTabBoxWindowList().size() >= thumbnailWindows))))
1412 // determine which item was clicked
1413 foreach( EffectWindow* w, windows.keys())
1415 if( windows[ w ]->clickable.contains( pos ))
1417 effects->setTabBoxWindow( w );
1418 return;
1421 // special handling for second half of window in case of animation and even number of windows
1422 if( windows.size() % 2 == 0 )
1424 QRect additionalRect = QRect( frame_area.x() + frame_margin,
1425 frame_area.y() + frame_margin,
1426 item_max_size.width()*0.5, item_max_size.height());
1427 if( additionalRect.contains( pos ))
1429 effects->setTabBoxWindow( right_window );
1430 return;
1435 // determine if a window has been clicked
1436 // not interested in events above a fullscreen window (ignoring panel size)
1437 if( pos.y() < (area.height()*scaleFactor - area.height())*0.5f*(1.0f/scaleFactor) )
1438 return;
1440 if( pos.x() < (area.width()*scaleFactor - selected_window->width())*0.5f*(1.0f/scaleFactor) )
1442 float availableSize = (area.width()*scaleFactor - area.width())*0.5f*(1.0f/scaleFactor);
1443 for( int i=0;i<leftWindows.count();i++ )
1445 int windowPos = availableSize/leftWindows.count()*i;
1446 if( pos.x() < windowPos )
1447 continue;
1448 if( i+1 < leftWindows.count() )
1450 if( pos.x() > availableSize/leftWindows.count()*(i+1) )
1451 continue;
1454 effects->setTabBoxWindow( leftWindows[i] );
1455 return;
1459 if( pos.x() > area.width() - (area.width()*scaleFactor - selected_window->width())*0.5f*(1.0f/scaleFactor) )
1461 float availableSize = (area.width()*scaleFactor - area.width())*0.5f*(1.0f/scaleFactor);
1462 for( int i=0;i<rightWindows.count();i++ )
1464 int windowPos = area.width() - availableSize/rightWindows.count()*i;
1465 if( pos.x() > windowPos )
1466 continue;
1467 if( i+1 < rightWindows.count() )
1469 if( pos.x() < area.width() - availableSize/rightWindows.count()*(i+1) )
1470 continue;
1473 effects->setTabBoxWindow( rightWindows[i] );
1474 return;
1480 } // namespace