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"
27 #include <kactioncollection.h>
30 #include <kconfiggroup.h>
31 #include <netwm_def.h>
33 #include <QMouseEvent>
38 KWIN_EFFECT( desktopgrid
, DesktopGridEffect
)
40 DesktopGridEffect::DesktopGridEffect()
41 : borderActivate( ElectricNone
)
44 , keyboardGrab( false )
45 , wasWindowMove( false )
49 , orientation( Qt::Horizontal
)
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 //-----------------------------------------------------------------------------
93 void DesktopGridEffect::prePaintScreen( ScreenPrePaintData
& data
, int time
)
95 if( timeline
.value() != 0 || activated
)
98 timeline
.addTime(time
);
100 timeline
.removeTime(time
);
101 for( int i
= 0; i
< effects
->numberOfDesktops(); i
++ )
103 if( i
== highlightedDesktop
- 1 )
104 hoverTimeline
[i
].addTime(time
);
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 )
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
);
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%
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
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();
173 effects
->postPaintScreen();
176 //-----------------------------------------------------------------------------
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() );
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)
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
)
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();
253 qRound( screenPosF
.x() ),
254 qRound( screenPosF
.y() )
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
);
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)
274 effects
->paintWindow( w
, mask
, region
, data
);
277 //-----------------------------------------------------------------------------
280 void DesktopGridEffect::windowClosed( EffectWindow
* w
)
282 if( w
== windowMove
)
284 effects
->setElevatedWindow( windowMove
, false );
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
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
);
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
)
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
);
323 effects
->setElevatedWindow( windowMove
, true );
326 else if(( me
->buttons() == Qt::MidButton
|| me
->buttons() == Qt::RightButton
) && windowMove
== NULL
)
328 EffectWindow
* w
= windowAt( me
->pos());
331 if( w
->isOnAllDesktops())
332 effects
->windowToDesktop( w
, posToDesktop( me
->pos()));
334 effects
->windowToDesktop( w
, NET::OnAllDesktops
);
335 effects
->addRepaintFull();
339 if( e
->type() == QEvent::MouseButtonRelease
&& me
->button() == Qt::LeftButton
)
343 setCurrentDesktop( highlightedDesktop
);
348 effects
->activateWindow( windowMove
); // Just in case it was deactivated
349 effects
->setElevatedWindow( windowMove
, false );
352 wasWindowMove
= false;
356 void DesktopGridEffect::grabbedKeyboardEvent( QKeyEvent
* e
)
358 if( e
->type() == QEvent::KeyPress
)
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
;
368 if( desktop
<= effects
->numberOfDesktops())
370 setHighlightedDesktop( desktop
);
371 setCurrentDesktop( desktop
);
377 { // Wrap only on autorepeat
379 setHighlightedDesktop( desktopToLeft( highlightedDesktop
, !e
->isAutoRepeat()));
382 setHighlightedDesktop( desktopToRight( highlightedDesktop
, !e
->isAutoRepeat()));
385 setHighlightedDesktop( desktopUp( highlightedDesktop
, !e
->isAutoRepeat()));
388 setHighlightedDesktop( desktopDown( highlightedDesktop
, !e
->isAutoRepeat()));
396 setCurrentDesktop( highlightedDesktop
);
405 bool DesktopGridEffect::borderActivated( ElectricBorder border
)
407 if( effects
->activeFullScreenEffect() && effects
->activeFullScreenEffect() != this )
409 if( border
== borderActivate
&& !activated
)
417 //-----------------------------------------------------------------------------
420 // Transform a point to its position on the scaled grid
421 QPointF
DesktopGridEffect::scalePos( const QPoint
& pos
, int desktop
, int screen
) const
424 screen
= effects
->screenNumber( pos
);
425 QRect screenGeom
= effects
->clientArea( ScreenArea
, screen
, 0 );
427 if( orientation
== Qt::Horizontal
)
429 desktopCell
.setX(( desktop
- 1 ) % gridSize
.width() + 1 );
430 desktopCell
.setY(( desktop
- 1 ) / gridSize
.width() + 1 );
434 desktopCell
.setX(( desktop
- 1 ) / gridSize
.height() + 1 );
435 desktopCell
.setY(( desktop
- 1 ) % gridSize
.height() + 1 );
438 double progress
= timeline
.value();
442 ( screenGeom
.width() + unscaledBorder
[screen
] ) * ( desktopCell
.x() - 1 )
443 - ( screenGeom
.width() + unscaledBorder
[screen
] ) * ( activeCell
.x() - 1 )
446 ( scaledSize
[screen
].width() + border
) * ( desktopCell
.x() - 1 )
447 + scaledOffset
[screen
].x()
448 + ( pos
.x() - screenGeom
.x() ) * scale
[screen
]
453 ( screenGeom
.height() + unscaledBorder
[screen
] ) * ( desktopCell
.y() - 1 )
454 - ( screenGeom
.height() + unscaledBorder
[screen
] ) * ( activeCell
.y() - 1 )
457 ( scaledSize
[screen
].height() + border
) * ( desktopCell
.y() - 1 )
458 + scaledOffset
[screen
].y()
459 + ( pos
.y() - screenGeom
.y() ) * scale
[screen
]
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
)/*,
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
)/*,
483 int gx
= qBound( 0, int( scaledX
), gridSize
.width() - 1 ); // Zero-based
484 int gy
= qBound( 0, int( scaledY
), gridSize
.height() - 1 );
487 if( desktop
!= NULL
)
489 if( orientation
== Qt::Horizontal
)
490 *desktop
= gy
* gridSize
.width() + gx
+ 1;
492 *desktop
= gx
* gridSize
.height() + gy
+ 1;
499 scaledX
* ( screenGeom
.width() + unscaledBorder
[screen
] )
500 - unscaledBorder
[screen
] / 2.0
508 scaledY
* ( screenGeom
.height() + unscaledBorder
[screen
] )
509 - unscaledBorder
[screen
] / 2.0
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
)/*,
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
)/*,
531 int gx
= qBound( 0, int( scaledX
), gridSize
.width() - 1 ); // Zero-based
532 int gy
= qBound( 0, int( scaledY
), gridSize
.height() - 1 );
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();
548 qSwap( *begin
++, *end
-- );
551 pos
= unscalePos( pos
, &desktop
);
552 foreach( EffectWindow
* w
, windows
)
553 if( w
->isOnDesktop( desktop
) && w
->geometry().contains( pos
))
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 );
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() )
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() )
591 dt
-= effects
->numberOfDesktops();
598 int d
= ( dt
% gridSize
.width() ) + 1;
599 if( d
>= gridSize
.width() )
602 d
-= gridSize
.width();
606 dt
= dt
- ( dt
% gridSize
.width() ) + d
;
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();
620 dt
+= effects
->numberOfDesktops();
627 int d
= ( dt
% gridSize
.width() ) - 1;
631 d
+= gridSize
.width();
635 dt
= dt
- ( dt
% gridSize
.width() ) + d
;
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();
649 dt
+= effects
->numberOfDesktops();
656 int d
= ( dt
% gridSize
.height() ) - 1;
660 d
+= gridSize
.height();
664 dt
= dt
- ( dt
% gridSize
.height() ) + d
;
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() )
678 dt
-= effects
->numberOfDesktops();
685 int d
= ( dt
% gridSize
.height() ) + 1;
686 if( d
>= gridSize
.height() )
689 d
-= gridSize
.height();
693 dt
= dt
- ( dt
% gridSize
.height() ) + d
;
698 //-----------------------------------------------------------------------------
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
716 if( activated
&& timeline
.value() == 0 )
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() );
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
741 int numDesktops
= effects
->numberOfDesktops();
746 effects
->calcDesktopLayout( &gridSize
.rwidth(), &gridSize
.rheight(), &orientation
);
748 case LayoutAutomatic
:
749 y
= sqrt( numDesktops
) + 0.5;
750 x
= float( numDesktops
) / float( y
) + 0.5;
751 if( x
* y
< numDesktops
)
753 orientation
= Qt::Horizontal
;
754 gridSize
.setWidth( x
);
755 gridSize
.setHeight( y
);
758 effects
->calcDesktopLayout( &gridSize
.rwidth(), &gridSize
.rheight(), &orientation
);
759 gridSize
.setWidth( ceil( effects
->numberOfDesktops() / double( customLayoutRows
)));
760 gridSize
.setHeight( customLayoutRows
);
763 setCurrentDesktop( effects
->currentDesktop() );
765 unscaledBorder
.clear();
767 scaledOffset
.clear();
768 for( int i
= 0; i
< effects
->numScreens(); i
++ )
770 QRect geom
= effects
->clientArea( ScreenArea
, i
, 0 );
772 if( gridSize
.width() > gridSize
.height() )
773 sScale
= ( geom
.width() - border
* ( gridSize
.width() + 1 )) / double( geom
.width() * gridSize
.width() );
775 sScale
= ( geom
.height() - border
* ( gridSize
.height() + 1 )) / double( geom
.height() * gridSize
.height() );
776 double sBorder
= border
/ sScale
;
778 double( geom
.width() ) * sScale
,
779 double( geom
.height() ) * sScale
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()
795 effects
->ungrabKeyboard();
796 keyboardGrab
= false;
797 effects
->destroyInputWindow( input
);
798 effects
->setActiveFullScreenEffect( 0 );
803 #include "desktopgrid.moc"