not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kwin / effects / desktopgrid.cpp
blob25b6a57ba9cb6dfd195c6b0ce95f8e9b776883c4
1 /********************************************************************
2 KWin - the KDE window manager
3 This file is part of the KDE project.
5 Copyright (C) 2007 Lubos Lunak <l.lunak@kde.org>
6 Copyright (C) 2008 Lucas Murray <lmurray@undefinedfire.com>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *********************************************************************/
22 #include "desktopgrid.h"
24 #include <math.h>
26 #include <kaction.h>
27 #include <kactioncollection.h>
28 #include <kdebug.h>
29 #include <klocale.h>
30 #include <kconfiggroup.h>
31 #include <netwm_def.h>
32 #include <QEvent>
33 #include <QMouseEvent>
35 namespace KWin
38 KWIN_EFFECT( desktopgrid, DesktopGridEffect )
40 DesktopGridEffect::DesktopGridEffect()
41 : borderActivate( ElectricNone )
42 , activated( false )
43 , timeline()
44 , keyboardGrab( false )
45 , wasWindowMove( false )
46 , windowMove( NULL )
47 , windowMoveDiff()
48 , gridSize()
49 , orientation( Qt::Horizontal )
50 , activeCell( 1, 1 )
51 , scale()
52 , unscaledBorder()
53 , scaledSize()
54 , scaledOffset()
56 // Load shortcuts
57 KActionCollection* actionCollection = new KActionCollection( this );
58 KAction* a = (KAction*) actionCollection->addAction( "ShowDesktopGrid" );
59 a->setText( i18n( "Show Desktop Grid" ));
60 a->setGlobalShortcut( KShortcut( Qt::CTRL + Qt::Key_F8 ));
61 connect( a, SIGNAL( triggered( bool )), this, SLOT( toggle() ));
63 // Load all other configuration details
64 reconfigure( ReconfigureAll );
67 DesktopGridEffect::~DesktopGridEffect()
69 effects->unreserveElectricBorder( borderActivate );
72 void DesktopGridEffect::reconfigure( ReconfigureFlags )
74 KConfigGroup conf = effects->effectConfig( "DesktopGrid" );
76 effects->unreserveElectricBorder( borderActivate );
77 borderActivate = ElectricBorder( conf.readEntry( "BorderActivate", int( ElectricNone )));
78 effects->reserveElectricBorder( borderActivate );
80 zoomDuration = animationTime( conf, "ZoomDuration", 300 );
81 timeline.setCurveShape( TimeLine::EaseInOutCurve );
82 timeline.setDuration( zoomDuration );
84 border = conf.readEntry( "BorderWidth", 10 );
85 desktopNameAlignment = Qt::Alignment( conf.readEntry( "DesktopNameAlignment", 0 ));
86 layoutMode = conf.readEntry( "LayoutMode", int( LayoutPager ));
87 customLayoutRows = conf.readEntry( "CustomLayoutRows", 2 );
90 //-----------------------------------------------------------------------------
91 // Screen painting
93 void DesktopGridEffect::prePaintScreen( ScreenPrePaintData& data, int time )
95 if( timeline.value() != 0 || activated )
97 if( activated )
98 timeline.addTime(time);
99 else
100 timeline.removeTime(time);
101 for( int i = 0; i < effects->numberOfDesktops(); i++ )
103 if( i == highlightedDesktop - 1 )
104 hoverTimeline[i].addTime(time);
105 else
106 hoverTimeline[i].removeTime(time);
108 // PAINT_SCREEN_BACKGROUND_FIRST is needed because screen will be actually painted more than once,
109 // so with normal screen painting second screen paint would erase parts of the first paint
110 if( timeline.value() != 0 )
111 data.mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST;
112 if( !activated && timeline.value() == 0 )
113 finish();
115 effects->prePaintScreen( data, time );
118 void DesktopGridEffect::paintScreen( int mask, QRegion region, ScreenPaintData& data )
120 if( timeline.value() == 0 )
122 effects->paintScreen( mask, region, data );
123 return;
125 for( int desktop = 1; desktop <= effects->numberOfDesktops(); desktop++ )
127 ScreenPaintData d = data;
128 paintingDesktop = desktop;
129 effects->paintScreen( mask, region, d );
132 if( desktopNameAlignment )
134 double progress = timeline.value();
135 QColor textColor( 255, 255, 255, 255 * progress );
136 QColor bgColor( 0, 0, 0, 178 * progress ); // 70%
137 QFont f;
138 f.setBold( true );
139 f.setPointSize( 12 );
140 for( int screen = 0; screen < effects->numScreens(); screen++ )
142 QRect screenGeom = effects->clientArea( ScreenArea, screen, 0 );
143 PaintClipper pc( screenGeom ); // TODO: Doesn't work in XRender for some reason?
144 for( int desktop = 1; desktop <= effects->numberOfDesktops(); desktop++ )
146 QPointF posTL( scalePos( screenGeom.topLeft(), desktop, screen ));
147 QPointF posBR( scalePos( screenGeom.bottomRight(), desktop, screen ));
148 QRect textArea( posTL.x(), posTL.y(), posBR.x() - posTL.x(), posBR.y() - posTL.y() );
149 textArea.adjust( textArea.width() / 10, textArea.height() / 10,
150 -textArea.width() / 10, -textArea.height() / 10 );
151 effects->paintTextWithBackground( effects->desktopName( desktop ),
152 textArea, textColor, bgColor, f, desktopNameAlignment );
158 void DesktopGridEffect::postPaintScreen()
160 if( activated ? timeline.value() != 1 : timeline.value() != 0 )
161 effects->addRepaintFull(); // Repaint during zoom
162 if( activated )
164 for( int i = 0; i < effects->numberOfDesktops(); i++ )
166 if( hoverTimeline[i].value() != 0.0 && hoverTimeline[i].value() != 1.0 )
167 { // Repaint during soft highlighting
168 effects->addRepaintFull();
169 break;
173 effects->postPaintScreen();
176 //-----------------------------------------------------------------------------
177 // Window painting
179 void DesktopGridEffect::prePaintWindow( EffectWindow* w, WindowPrePaintData& data, int time )
181 if( timeline.value() != 0 )
183 if( w->isOnDesktop( paintingDesktop ))
185 w->enablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
186 data.mask |= PAINT_WINDOW_TRANSFORMED;
188 // Split windows at screen edges
189 for( int screen = 0; screen < effects->numScreens(); screen++ )
191 QRect screenGeom = effects->clientArea( ScreenArea, screen, 0 );
192 if( w->x() < screenGeom.x() )
193 data.quads = data.quads.splitAtX( screenGeom.x() - w->x() );
194 if( w->x() + w->width() > screenGeom.x() + screenGeom.width() )
195 data.quads = data.quads.splitAtX( screenGeom.x() + screenGeom.width() - w->x() );
196 if( w->y() < screenGeom.y() )
197 data.quads = data.quads.splitAtY( screenGeom.y() - w->y() );
198 if( w->y() + w->height() > screenGeom.y() + screenGeom.height() )
199 data.quads = data.quads.splitAtY( screenGeom.y() + screenGeom.height() - w->y() );
202 else
203 w->disablePainting( EffectWindow::PAINT_DISABLED_BY_DESKTOP );
205 effects->prePaintWindow( w, data, time );
208 void DesktopGridEffect::paintWindow( EffectWindow* w, int mask, QRegion region, WindowPaintData& data )
210 if( timeline.value() != 0 )
212 double xScale = data.xScale;
213 double yScale = data.yScale;
215 // Don't change brightness of windows on all desktops as this causes flickering
216 if( !w->isOnAllDesktops() || w->isDesktop() )
217 data.brightness *= 1.0 - ( 0.3 * ( 1.0 - hoverTimeline[paintingDesktop - 1].value() ));
219 for( int screen = 0; screen < effects->numScreens(); screen++ )
221 // Assume desktop windows can never be on two screens at once (Plasma makes one window per screen)
222 if( w->isDesktop() )
223 screen = w->screen();
224 QRect screenGeom = effects->clientArea( ScreenArea, screen, 0 );
226 // Display all quads on the same screen on the same pass
227 WindowQuadList screenQuads;
228 foreach( const WindowQuad &quad, data.quads )
230 QRect quadRect(
231 w->x() + quad.left(), w->y() + quad.top(),
232 quad.right() - quad.left(), quad.bottom() - quad.top()
234 if( quadRect.intersects( screenGeom ))
235 screenQuads.append( quad );
237 if( screenQuads.isEmpty() )
238 continue; // Nothing is being displayed, don't bother
239 WindowPaintData d = data;
240 d.quads = screenQuads;
242 QPointF newPos = scalePos( QPoint( w->x(), w->y() ), paintingDesktop, screen);
243 double progress = timeline.value();
244 d.xScale = interpolate( 1, xScale * scale[screen], progress);
245 d.yScale = interpolate( 1, yScale * scale[screen], progress);
246 d.xTranslate += qRound( newPos.x() - w->x() );
247 d.yTranslate += qRound( newPos.y() - w->y() );
249 if( effects->compositingType() == XRenderCompositing )
250 { // More exact clipping as XRender displays the entire window instead of just the quad
251 QPointF screenPosF = scalePos( screenGeom.topLeft(), paintingDesktop ).toPoint();
252 QPoint screenPos(
253 qRound( screenPosF.x() ),
254 qRound( screenPosF.y() )
256 QSize screenSize(
257 qRound( interpolate( screenGeom.width(), scaledSize[screen].width(), progress )),
258 qRound( interpolate( screenGeom.height(), scaledSize[screen].height(), progress ))
260 PaintClipper pc( effects->clientArea( ScreenArea, screen, 0 ) & QRect( screenPos, screenSize ));
261 effects->paintWindow( w, mask, region, d );
263 else
265 PaintClipper pc( effects->clientArea( ScreenArea, screen, 0 ));
266 effects->paintWindow( w, mask, region, d );
268 // Assume desktop windows can never be on two screens at once (Plasma makes one window per screen)
269 if( w->isDesktop() )
270 break;
273 else
274 effects->paintWindow( w, mask, region, data );
277 //-----------------------------------------------------------------------------
278 // User interaction
280 void DesktopGridEffect::windowClosed( EffectWindow* w )
282 if( w == windowMove )
284 effects->setElevatedWindow( windowMove, false );
285 windowMove = NULL;
289 void DesktopGridEffect::windowInputMouseEvent( Window, QEvent* e )
291 if(( e->type() != QEvent::MouseMove
292 && e->type() != QEvent::MouseButtonPress
293 && e->type() != QEvent::MouseButtonRelease )
294 || timeline.value() != 1 ) // Block user input during animations
295 return;
296 QMouseEvent* me = static_cast< QMouseEvent* >( e );
297 if( e->type() == QEvent::MouseMove )
299 int d = posToDesktop( me->pos());
300 if( windowMove != NULL )
301 { // Handle window moving
302 if( !wasWindowMove ) // Activate on move
303 effects->activateWindow( windowMove );
304 wasWindowMove = true;
305 effects->moveWindow( windowMove, unscalePos( me->pos(), NULL ) + windowMoveDiff );
306 // TODO: Window snap
307 if( d != highlightedDesktop && !windowMove->isOnAllDesktops() )
308 effects->windowToDesktop( windowMove, d ); // Not true all desktop move
310 if( d != highlightedDesktop ) // Highlight desktop
311 setHighlightedDesktop( d );
313 if( e->type() == QEvent::MouseButtonPress )
315 if( me->buttons() == Qt::LeftButton )
317 QRect rect;
318 EffectWindow* w = windowAt( me->pos());
319 if( w != NULL && w->isMovable())
320 { // Prepare it for moving
321 windowMoveDiff = w->pos() - unscalePos( me->pos(), NULL );
322 windowMove = w;
323 effects->setElevatedWindow( windowMove, true );
326 else if(( me->buttons() == Qt::MidButton || me->buttons() == Qt::RightButton ) && windowMove == NULL )
328 EffectWindow* w = windowAt( me->pos());
329 if( w != NULL )
331 if( w->isOnAllDesktops())
332 effects->windowToDesktop( w, posToDesktop( me->pos()));
333 else
334 effects->windowToDesktop( w, NET::OnAllDesktops );
335 effects->addRepaintFull();
339 if( e->type() == QEvent::MouseButtonRelease && me->button() == Qt::LeftButton )
341 if( !wasWindowMove )
343 setCurrentDesktop( highlightedDesktop );
344 setActive( false );
346 if( windowMove )
348 effects->activateWindow( windowMove ); // Just in case it was deactivated
349 effects->setElevatedWindow( windowMove, false );
350 windowMove = NULL;
352 wasWindowMove = false;
356 void DesktopGridEffect::grabbedKeyboardEvent( QKeyEvent* e )
358 if( e->type() == QEvent::KeyPress )
360 int desktop = -1;
361 // switch by F<number> or just <number>
362 if( e->key() >= Qt::Key_F1 && e->key() <= Qt::Key_F35 )
363 desktop = e->key() - Qt::Key_F1 + 1;
364 else if( e->key() >= Qt::Key_0 && e->key() <= Qt::Key_9 )
365 desktop = e->key() == Qt::Key_0 ? 10 : e->key() - Qt::Key_0;
366 if( desktop != -1 )
368 if( desktop <= effects->numberOfDesktops())
370 setHighlightedDesktop( desktop );
371 setCurrentDesktop( desktop );
372 setActive( false );
374 return;
376 switch( e->key())
377 { // Wrap only on autorepeat
378 case Qt::Key_Left:
379 setHighlightedDesktop( desktopToLeft( highlightedDesktop, !e->isAutoRepeat()));
380 break;
381 case Qt::Key_Right:
382 setHighlightedDesktop( desktopToRight( highlightedDesktop, !e->isAutoRepeat()));
383 break;
384 case Qt::Key_Up:
385 setHighlightedDesktop( desktopUp( highlightedDesktop, !e->isAutoRepeat()));
386 break;
387 case Qt::Key_Down:
388 setHighlightedDesktop( desktopDown( highlightedDesktop, !e->isAutoRepeat()));
389 break;
390 case Qt::Key_Escape:
391 setActive( false );
392 return;
393 case Qt::Key_Enter:
394 case Qt::Key_Return:
395 case Qt::Key_Space:
396 setCurrentDesktop( highlightedDesktop );
397 setActive( false );
398 return;
399 default:
400 break;
405 bool DesktopGridEffect::borderActivated( ElectricBorder border )
407 if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this )
408 return false;
409 if( border == borderActivate && !activated )
411 toggle();
412 return true;
414 return false;
417 //-----------------------------------------------------------------------------
418 // Helper functions
420 // Transform a point to its position on the scaled grid
421 QPointF DesktopGridEffect::scalePos( const QPoint& pos, int desktop, int screen ) const
423 if( screen == -1 )
424 screen = effects->screenNumber( pos );
425 QRect screenGeom = effects->clientArea( ScreenArea, screen, 0 );
426 QPoint desktopCell;
427 if( orientation == Qt::Horizontal )
429 desktopCell.setX(( desktop - 1 ) % gridSize.width() + 1 );
430 desktopCell.setY(( desktop - 1 ) / gridSize.width() + 1 );
432 else
434 desktopCell.setX(( desktop - 1 ) / gridSize.height() + 1 );
435 desktopCell.setY(( desktop - 1 ) % gridSize.height() + 1 );
438 double progress = timeline.value();
439 QPointF point(
440 interpolate(
442 ( screenGeom.width() + unscaledBorder[screen] ) * ( desktopCell.x() - 1 )
443 - ( screenGeom.width() + unscaledBorder[screen] ) * ( activeCell.x() - 1 )
444 ) + pos.x(),
446 ( scaledSize[screen].width() + border ) * ( desktopCell.x() - 1 )
447 + scaledOffset[screen].x()
448 + ( pos.x() - screenGeom.x() ) * scale[screen]
450 progress ),
451 interpolate(
453 ( screenGeom.height() + unscaledBorder[screen] ) * ( desktopCell.y() - 1 )
454 - ( screenGeom.height() + unscaledBorder[screen] ) * ( activeCell.y() - 1 )
455 ) + pos.y(),
457 ( scaledSize[screen].height() + border ) * ( desktopCell.y() - 1 )
458 + scaledOffset[screen].y()
459 + ( pos.y() - screenGeom.y() ) * scale[screen]
461 progress )
464 return point;
467 // Detransform a point to its position on the full grid
468 // TODO: Doesn't correctly interpolate (Final position is correct though), don't forget to copy to posToDesktop()
469 QPoint DesktopGridEffect::unscalePos( const QPoint& pos, int* desktop ) const
471 int screen = effects->screenNumber( pos );
472 QRect screenGeom = effects->clientArea( ScreenArea, screen, 0 );
474 //double progress = timeline.value();
475 double scaledX = /*interpolate(
476 ( pos.x() - screenGeom.x() + unscaledBorder[screen] / 2.0 ) / ( screenGeom.width() + unscaledBorder[screen] ) + activeCell.x() - 1,*/
477 ( pos.x() - scaledOffset[screen].x() + double( border ) / 2.0 ) / ( scaledSize[screen].width() + border )/*,
478 progress )*/;
479 double scaledY = /*interpolate(
480 ( pos.y() - screenGeom.y() + unscaledBorder[screen] / 2.0 ) / ( screenGeom.height() + unscaledBorder[screen] ) + activeCell.y() - 1,*/
481 ( pos.y() - scaledOffset[screen].y() + double( border ) / 2.0 ) / ( scaledSize[screen].height() + border )/*,
482 progress )*/;
483 int gx = qBound( 0, int( scaledX ), gridSize.width() - 1 ); // Zero-based
484 int gy = qBound( 0, int( scaledY ), gridSize.height() - 1 );
485 scaledX -= gx;
486 scaledY -= gy;
487 if( desktop != NULL )
489 if( orientation == Qt::Horizontal )
490 *desktop = gy * gridSize.width() + gx + 1;
491 else
492 *desktop = gx * gridSize.height() + gy + 1;
495 return QPoint(
496 qBound(
497 screenGeom.x(),
498 qRound(
499 scaledX * ( screenGeom.width() + unscaledBorder[screen] )
500 - unscaledBorder[screen] / 2.0
501 + screenGeom.x()
503 screenGeom.right()
505 qBound(
506 screenGeom.y(),
507 qRound(
508 scaledY * ( screenGeom.height() + unscaledBorder[screen] )
509 - unscaledBorder[screen] / 2.0
510 + screenGeom.y()
512 screenGeom.bottom()
517 int DesktopGridEffect::posToDesktop( const QPoint& pos ) const
518 { // Copied from unscalePos()
519 int screen = effects->screenNumber( pos );
520 QRect screenGeom = effects->clientArea( ScreenArea, screen, 0 );
522 //double progress = timeline.value();
523 double scaledX = /*interpolate(
524 ( pos.x() - screenGeom.x() + unscaledBorder[screen] / 2.0 ) / ( screenGeom.width() + unscaledBorder[screen] ) + activeCell.x() - 1,*/
525 ( pos.x() - scaledOffset[screen].x() + double( border ) / 2.0 ) / ( scaledSize[screen].width() + border )/*,
526 progress )*/;
527 double scaledY = /*interpolate(
528 ( pos.y() - screenGeom.y() + unscaledBorder[screen] / 2.0 ) / ( screenGeom.height() + unscaledBorder[screen] ) + activeCell.y() - 1,*/
529 ( pos.y() - scaledOffset[screen].y() + double( border ) / 2.0 ) / ( scaledSize[screen].height() + border )/*,
530 progress )*/;
531 int gx = qBound( 0, int( scaledX ), gridSize.width() - 1 ); // Zero-based
532 int gy = qBound( 0, int( scaledY ), gridSize.height() - 1 );
533 scaledX -= gx;
534 scaledY -= gy;
535 if( orientation == Qt::Horizontal )
536 return gy * gridSize.width() + gx + 1;
537 return gx * gridSize.height() + gy + 1;
540 EffectWindow* DesktopGridEffect::windowAt( QPoint pos ) const
542 // Get stacking order top first
543 EffectWindowList windows = effects->stackingOrder();
544 EffectWindowList::Iterator begin = windows.begin();
545 EffectWindowList::Iterator end = windows.end();
546 --end;
547 while( begin < end )
548 qSwap( *begin++, *end-- );
550 int desktop;
551 pos = unscalePos( pos, &desktop );
552 foreach( EffectWindow* w, windows )
553 if( w->isOnDesktop( desktop ) && w->geometry().contains( pos ))
554 return w;
555 return NULL;
558 void DesktopGridEffect::setCurrentDesktop( int desktop )
560 if( orientation == Qt::Horizontal )
562 activeCell.setX(( desktop - 1 ) % gridSize.width() + 1 );
563 activeCell.setY(( desktop - 1 ) / gridSize.width() + 1 );
565 else
567 activeCell.setX(( desktop - 1 ) / gridSize.height() + 1 );
568 activeCell.setY(( desktop - 1 ) % gridSize.height() + 1 );
570 if( effects->currentDesktop() != desktop )
571 effects->setCurrentDesktop( desktop );
574 void DesktopGridEffect::setHighlightedDesktop( int d )
576 if( d == highlightedDesktop || d <= 0 || d > effects->numberOfDesktops() )
577 return;
578 highlightedDesktop = d;
579 effects->addRepaintFull();
582 int DesktopGridEffect::desktopToRight( int desktop, bool wrap ) const
583 { // Copied from Workspace::desktopToRight()
584 int dt = desktop - 1;
585 if( orientation == Qt::Vertical )
587 dt += gridSize.height();
588 if( dt >= effects->numberOfDesktops() )
590 if( wrap )
591 dt -= effects->numberOfDesktops();
592 else
593 return desktop;
596 else
598 int d = ( dt % gridSize.width() ) + 1;
599 if( d >= gridSize.width() )
601 if( wrap )
602 d -= gridSize.width();
603 else
604 return desktop;
606 dt = dt - ( dt % gridSize.width() ) + d;
608 return dt + 1;
611 int DesktopGridEffect::desktopToLeft( int desktop, bool wrap ) const
612 { // Copied from Workspace::desktopToLeft()
613 int dt = desktop - 1;
614 if( orientation == Qt::Vertical )
616 dt -= gridSize.height();
617 if( dt < 0 )
619 if( wrap )
620 dt += effects->numberOfDesktops();
621 else
622 return desktop;
625 else
627 int d = ( dt % gridSize.width() ) - 1;
628 if( d < 0 )
630 if( wrap )
631 d += gridSize.width();
632 else
633 return desktop;
635 dt = dt - ( dt % gridSize.width() ) + d;
637 return dt + 1;
640 int DesktopGridEffect::desktopUp( int desktop, bool wrap ) const
641 { // Copied from Workspace::desktopUp()
642 int dt = desktop - 1;
643 if( orientation == Qt::Horizontal )
645 dt -= gridSize.width();
646 if( dt < 0 )
648 if( wrap )
649 dt += effects->numberOfDesktops();
650 else
651 return desktop;
654 else
656 int d = ( dt % gridSize.height() ) - 1;
657 if( d < 0 )
659 if( wrap )
660 d += gridSize.height();
661 else
662 return desktop;
664 dt = dt - ( dt % gridSize.height() ) + d;
666 return dt + 1;
669 int DesktopGridEffect::desktopDown( int desktop, bool wrap ) const
670 { // Copied from Workspace::desktopDown()
671 int dt = desktop - 1;
672 if( orientation == Qt::Horizontal )
674 dt += gridSize.width();
675 if( dt >= effects->numberOfDesktops() )
677 if( wrap )
678 dt -= effects->numberOfDesktops();
679 else
680 return desktop;
683 else
685 int d = ( dt % gridSize.height() ) + 1;
686 if( d >= gridSize.height() )
688 if( wrap )
689 d -= gridSize.height();
690 else
691 return desktop;
693 dt = dt - ( dt % gridSize.height() ) + d;
695 return dt + 1;
698 //-----------------------------------------------------------------------------
699 // Activation
701 void DesktopGridEffect::toggle()
703 setActive( !activated );
706 void DesktopGridEffect::setActive( bool active )
708 if( effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this )
709 return; // Only one fullscreen effect at a time thanks
710 if( effects->numberOfDesktops() < 2 )
711 return; // No point if there is only one desktop
712 if( activated == active )
713 return; // Already in that state
715 activated = active;
716 if( activated && timeline.value() == 0 )
717 setup();
718 effects->addRepaintFull();
721 void DesktopGridEffect::setup()
723 keyboardGrab = effects->grabKeyboard( this );
724 input = effects->createInputWindow( this, 0, 0, displayWidth(), displayHeight(),
725 Qt::PointingHandCursor );
726 effects->setActiveFullScreenEffect( this );
727 setHighlightedDesktop( effects->currentDesktop() );
729 // Soft highlighting
730 hoverTimeline.clear();
731 for( int i = 0; i < effects->numberOfDesktops(); i++ )
733 TimeLine newTimeline( animationTime( 250 ));
734 newTimeline.setCurveShape( TimeLine::EaseInOutCurve );
735 hoverTimeline.append( newTimeline );
737 hoverTimeline[effects->currentDesktop() - 1].setProgress( 1.0 );
739 // We need these variables for every paint so lets cache them
740 int x, y;
741 int numDesktops = effects->numberOfDesktops();
742 switch( layoutMode )
744 default:
745 case LayoutPager:
746 effects->calcDesktopLayout( &gridSize.rwidth(), &gridSize.rheight(), &orientation );
747 break;
748 case LayoutAutomatic:
749 y = sqrt( numDesktops ) + 0.5;
750 x = float( numDesktops ) / float( y ) + 0.5;
751 if( x * y < numDesktops )
752 x++;
753 orientation = Qt::Horizontal;
754 gridSize.setWidth( x );
755 gridSize.setHeight( y );
756 break;
757 case LayoutCustom:
758 effects->calcDesktopLayout( &gridSize.rwidth(), &gridSize.rheight(), &orientation );
759 gridSize.setWidth( ceil( effects->numberOfDesktops() / double( customLayoutRows )));
760 gridSize.setHeight( customLayoutRows );
761 break;
763 setCurrentDesktop( effects->currentDesktop() );
764 scale.clear();
765 unscaledBorder.clear();
766 scaledSize.clear();
767 scaledOffset.clear();
768 for( int i = 0; i < effects->numScreens(); i++ )
770 QRect geom = effects->clientArea( ScreenArea, i, 0 );
771 double sScale;
772 if( gridSize.width() > gridSize.height() )
773 sScale = ( geom.width() - border * ( gridSize.width() + 1 )) / double( geom.width() * gridSize.width() );
774 else
775 sScale = ( geom.height() - border * ( gridSize.height() + 1 )) / double( geom.height() * gridSize.height() );
776 double sBorder = border / sScale;
777 QSizeF size(
778 double( geom.width() ) * sScale,
779 double( geom.height() ) * sScale
781 QPointF offset(
782 geom.x() + ( geom.width() - size.width() * gridSize.width() - border * ( gridSize.width() - 1 )) / 2.0,
783 geom.y() + ( geom.height() - size.height() * gridSize.height() - border * ( gridSize.height() - 1 )) / 2.0
785 scale.append( sScale );
786 unscaledBorder.append( sBorder );
787 scaledSize.append( size );
788 scaledOffset.append( offset );
792 void DesktopGridEffect::finish()
794 if( keyboardGrab )
795 effects->ungrabKeyboard();
796 keyboardGrab = false;
797 effects->destroyInputWindow( input );
798 effects->setActiveFullScreenEffect( 0 );
801 } // namespace
803 #include "desktopgrid.moc"