00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "client.h"
00030 #include "workspace.h"
00031
00032 #include <kapplication.h>
00033 #include <kglobal.h>
00034 #include <QPainter>
00035 #include <kwindowsystem.h>
00036
00037 #include "placement.h"
00038 #include "notifications.h"
00039 #include "geometrytip.h"
00040 #include "rules.h"
00041 #include "effects.h"
00042 #include <QX11Info>
00043
00044 #include <kephal/screens.h>
00045
00046 namespace KWin
00047 {
00048
00049
00050
00051
00052
00056 void Workspace::desktopResized()
00057 {
00058 QRect geom = Kephal::ScreenUtils::desktopGeometry();
00059 NETSize desktop_geometry;
00060 desktop_geometry.width = geom.width();
00061 desktop_geometry.height = geom.height();
00062 rootInfo->setDesktopGeometry( -1, desktop_geometry );
00063
00064 updateClientArea();
00065 destroyElectricBorders();
00066 updateElectricBorders();
00067 if( compositing() )
00068 {
00069 finishCompositing();
00070 QTimer::singleShot( 0, this, SLOT( setupCompositing() ) );
00071 }
00072 }
00073
00086 void Workspace::updateClientArea( bool force )
00087 {
00088 int nscreens = Kephal::ScreenUtils::numScreens();
00089 kDebug(1212) << "screens: " << nscreens << "desktops: " << numberOfDesktops();
00090 QVector< QRect > new_wareas( numberOfDesktops() + 1 );
00091 QVector< QVector< QRect > > new_sareas( numberOfDesktops() + 1 );
00092 QVector< QRect > screens( nscreens );
00093 QRect desktopArea = Kephal::ScreenUtils::desktopGeometry();
00094 for( int iS = 0;
00095 iS < nscreens;
00096 iS ++ )
00097 {
00098 screens [iS] = Kephal::ScreenUtils::screenGeometry( iS );
00099 }
00100 for( int i = 1;
00101 i <= numberOfDesktops();
00102 ++i )
00103 {
00104 new_wareas[ i ] = desktopArea;
00105 new_sareas[ i ].resize( nscreens );
00106 for( int iS = 0;
00107 iS < nscreens;
00108 iS ++ )
00109 new_sareas[ i ][ iS ] = screens[ iS ];
00110 }
00111 for ( ClientList::ConstIterator it = clients.constBegin(); it != clients.constEnd(); ++it)
00112 {
00113 if( !(*it)->hasStrut())
00114 continue;
00115 QRect r = (*it)->adjustedClientArea( desktopArea, desktopArea );
00116 if( (*it)->isOnAllDesktops())
00117 {
00118 for( int i = 1;
00119 i <= numberOfDesktops();
00120 ++i )
00121 {
00122 new_wareas[ i ] = new_wareas[ i ].intersected( r );
00123 for( int iS = 0;
00124 iS < nscreens;
00125 iS ++ )
00126 {
00127 new_sareas[ i ][ iS ] = new_sareas[ i ][ iS ].intersected(
00128 (*it)->adjustedClientArea( desktopArea, screens[ iS ] ));
00129 }
00130 }
00131 }
00132 else
00133 {
00134 new_wareas[ (*it)->desktop() ] = new_wareas[ (*it)->desktop() ].intersected( r );
00135 for( int iS = 0;
00136 iS < nscreens;
00137 iS ++ )
00138 {
00139
00140 new_sareas[ (*it)->desktop() ][ iS ]
00141 = new_sareas[ (*it)->desktop() ][ iS ].intersected(
00142 (*it)->adjustedClientArea( desktopArea, screens[ iS ] ));
00143 }
00144 }
00145 }
00146 #if 0
00147 for( int i = 1;
00148 i <= numberOfDesktops();
00149 ++i )
00150 {
00151 for( int iS = 0;
00152 iS < nscreens;
00153 iS ++ )
00154 kDebug (1212) << "new_sarea: " << new_sareas[ i ][ iS ];
00155 }
00156 #endif
00157
00158 if( topmenu_space != NULL )
00159 {
00160 QRect topmenu_area = desktopArea;
00161 topmenu_area.setTop( topMenuHeight());
00162 for( int i = 1;
00163 i <= numberOfDesktops();
00164 ++i )
00165 new_wareas[ i ] = new_wareas[ i ].intersected( topmenu_area );
00166 }
00167
00168 bool changed = force;
00169
00170 if(screenarea.isEmpty())
00171 changed = true;
00172
00173 for( int i = 1;
00174 !changed && i <= numberOfDesktops();
00175 ++i )
00176 {
00177 if( workarea[ i ] != new_wareas[ i ] )
00178 changed = true;
00179 if( screenarea[ i ].size() != new_sareas[ i ].size())
00180 changed = true;
00181 for( int iS = 0;
00182 !changed && iS < nscreens;
00183 iS ++ )
00184 if (new_sareas[ i ][ iS ] != screenarea [ i ][ iS ])
00185 changed = true;
00186 }
00187
00188 if ( changed )
00189 {
00190 workarea = new_wareas;
00191 screenarea = new_sareas;
00192 NETRect r;
00193 for( int i = 1; i <= numberOfDesktops(); i++)
00194 {
00195 r.pos.x = workarea[ i ].x();
00196 r.pos.y = workarea[ i ].y();
00197 r.size.width = workarea[ i ].width();
00198 r.size.height = workarea[ i ].height();
00199 rootInfo->setWorkArea( i, r );
00200 }
00201
00202 updateTopMenuGeometry();
00203 for( ClientList::ConstIterator it = clients.constBegin();
00204 it != clients.constEnd();
00205 ++it)
00206 (*it)->checkWorkspacePosition();
00207 for( ClientList::ConstIterator it = desktops.constBegin();
00208 it != desktops.constEnd();
00209 ++it)
00210 (*it)->checkWorkspacePosition();
00211 }
00212
00213 kDebug(1212) << "Done.";
00214 }
00215
00216 void Workspace::updateClientArea()
00217 {
00218 updateClientArea( false );
00219 }
00220
00221
00229 QRect Workspace::clientArea( clientAreaOption opt, int screen, int desktop ) const
00230 {
00231 if( desktop == NETWinInfo::OnAllDesktops || desktop == 0 )
00232 desktop = currentDesktop();
00233 if( screen == -1 )
00234 screen = activeScreen();
00235
00236 QRect sarea = (!screenarea.isEmpty()
00237 && screen < screenarea[ desktop ].size())
00238 ? screenarea[ desktop ][ screen ]
00239 : Kephal::ScreenUtils::screenGeometry( screen );
00240 QRect warea = workarea[ desktop ].isNull()
00241 ? Kephal::ScreenUtils::desktopGeometry()
00242 : workarea[ desktop ];
00243 switch (opt)
00244 {
00245 case MaximizeArea:
00246 if (options->xineramaMaximizeEnabled)
00247 return sarea;
00248 else
00249 return warea;
00250 case MaximizeFullArea:
00251 if (options->xineramaMaximizeEnabled)
00252 return Kephal::ScreenUtils::screenGeometry( screen );
00253 else
00254 return Kephal::ScreenUtils::desktopGeometry();
00255 case FullScreenArea:
00256 if (options->xineramaFullscreenEnabled)
00257 return Kephal::ScreenUtils::screenGeometry( screen );
00258 else
00259 return Kephal::ScreenUtils::desktopGeometry();
00260 case PlacementArea:
00261 if (options->xineramaPlacementEnabled)
00262 return sarea;
00263 else
00264 return warea;
00265 case MovementArea:
00266 if (options->xineramaMovementEnabled)
00267 return Kephal::ScreenUtils::screenGeometry( screen );
00268 else
00269 return Kephal::ScreenUtils::desktopGeometry();
00270 case WorkArea:
00271 return warea;
00272 case FullArea:
00273 return Kephal::ScreenUtils::desktopGeometry();
00274 case ScreenArea:
00275 return Kephal::ScreenUtils::screenGeometry( screen );
00276 }
00277 abort();
00278 }
00279
00280 QRect Workspace::clientArea( clientAreaOption opt, const QPoint& p, int desktop ) const
00281 {
00282 int screen = Kephal::ScreenUtils::screenId( p );
00283 return clientArea( opt, screen, desktop );
00284 }
00285
00286 QRect Workspace::clientArea( clientAreaOption opt, const Client* c ) const
00287 {
00288 return clientArea( opt, c->geometry().center(), c->desktop());
00289 }
00290
00291
00297 QPoint Workspace::adjustClientPosition( Client* c, QPoint pos, bool unrestricted )
00298 {
00299
00300
00301
00302 if (options->windowSnapZone || options->borderSnapZone || options->centerSnapZone )
00303 {
00304 const bool sOWO=options->snapOnlyWhenOverlapping;
00305 const QRect maxRect = clientArea(MovementArea, pos+c->rect().center(), c->desktop());
00306 const int xmin = maxRect.left();
00307 const int xmax = maxRect.right()+1;
00308 const int ymin = maxRect.top();
00309 const int ymax = maxRect.bottom()+1;
00310
00311 const int cx(pos.x());
00312 const int cy(pos.y());
00313 const int cw(c->width());
00314 const int ch(c->height());
00315 const int rx(cx+cw);
00316 const int ry(cy+ch);
00317
00318 int nx(cx), ny(cy);
00319 int deltaX(xmax);
00320 int deltaY(ymax);
00321
00322 int lx, ly, lrx, lry;
00323
00324
00325 int snap = options->borderSnapZone;
00326 if (snap)
00327 {
00328 if ((sOWO?(cx<xmin):true) && (qAbs(xmin-cx)<snap))
00329 {
00330 deltaX = xmin-cx;
00331 nx = xmin;
00332 }
00333 if ((sOWO?(rx>xmax):true) && (qAbs(rx-xmax)<snap) && (qAbs(xmax-rx) < deltaX))
00334 {
00335 deltaX = rx-xmax;
00336 nx = xmax - cw;
00337 }
00338
00339 if ((sOWO?(cy<ymin):true) && (qAbs(ymin-cy)<snap))
00340 {
00341 deltaY = ymin-cy;
00342 ny = ymin;
00343 }
00344 if ((sOWO?(ry>ymax):true) && (qAbs(ry-ymax)<snap) && (qAbs(ymax-ry) < deltaY))
00345 {
00346 deltaY =ry-ymax;
00347 ny = ymax - ch;
00348 }
00349 }
00350
00351
00352 snap = options->windowSnapZone;
00353 if (snap)
00354 {
00355 QList<Client *>::ConstIterator l;
00356 for (l = clients.constBegin();l != clients.constEnd();++l )
00357 {
00358 if ((*l)->isOnDesktop(currentDesktop()) &&
00359 !(*l)->isMinimized()
00360 && (*l) != c )
00361 {
00362 lx = (*l)->x();
00363 ly = (*l)->y();
00364 lrx = lx + (*l)->width();
00365 lry = ly + (*l)->height();
00366
00367 if ( (( cy <= lry ) && ( cy >= ly )) ||
00368 (( ry >= ly ) && ( ry <= lry )) ||
00369 (( cy <= ly ) && ( ry >= lry )) )
00370 {
00371 if ((sOWO?(cx<lrx):true) && (qAbs(lrx-cx)<snap) && ( qAbs(lrx -cx) < deltaX) )
00372 {
00373 deltaX = qAbs( lrx - cx );
00374 nx = lrx;
00375 }
00376 if ((sOWO?(rx>lx):true) && (qAbs(rx-lx)<snap) && ( qAbs( rx - lx )<deltaX) )
00377 {
00378 deltaX = qAbs(rx - lx);
00379 nx = lx - cw;
00380 }
00381 }
00382
00383 if ( (( cx <= lrx ) && ( cx >= lx )) ||
00384 (( rx >= lx ) && ( rx <= lrx )) ||
00385 (( cx <= lx ) && ( rx >= lrx )) )
00386 {
00387 if ((sOWO?(cy<lry):true) && (qAbs(lry-cy)<snap) && (qAbs( lry -cy ) < deltaY))
00388 {
00389 deltaY = qAbs( lry - cy );
00390 ny = lry;
00391 }
00392
00393 if ((sOWO?(ry>ly):true) && (qAbs(ry-ly)<snap) && (qAbs( ry - ly ) < deltaY ))
00394 {
00395 deltaY = qAbs( ry - ly );
00396 ny = ly - ch;
00397 }
00398 }
00399
00400
00401 if( nx == lrx || nx+cw == lx )
00402 {
00403 if ((sOWO?(ry>lry):true) && (qAbs(lry-ry)<snap) && (qAbs(lry-ry) < deltaY))
00404 {
00405 deltaY = qAbs( lry - ry );
00406 ny = lry - ch;
00407 }
00408 if ((sOWO?(cy<ly):true) && (qAbs(cy-ly)<snap) && (qAbs(cy-ly) < deltaY))
00409 {
00410 deltaY = qAbs( cy - ly );
00411 ny = ly;
00412 }
00413 }
00414 if( ny == lry || ny+ch == ly )
00415 {
00416 if ((sOWO?(rx>lrx):true) && (qAbs(lrx-rx)<snap) && (qAbs(lrx-rx) < deltaX))
00417 {
00418 deltaX = qAbs( lrx - rx );
00419 nx = lrx - cw;
00420 }
00421 if ((sOWO?(cx<lx):true) && (qAbs(cx-lx)<snap) && (qAbs(cx-lx) < deltaX))
00422 {
00423 deltaX = qAbs( cx - lx );
00424 nx = lx;
00425 }
00426 }
00427 }
00428 }
00429 }
00430
00431
00432 snap = options->centerSnapZone;
00433 if (snap)
00434 {
00435 int diffX = qAbs( (xmin + xmax)/2 - (cx + cw/2) );
00436 int diffY = qAbs( (ymin + ymax)/2 - (cy + ch/2) );
00437 if (diffX < snap && diffY < snap && diffX < deltaX && diffY < deltaY)
00438 {
00439 deltaX = diffX;
00440 deltaY = diffY;
00441 nx = (xmin + xmax)/2 - cw/2;
00442 ny = (ymin + ymax)/2 - ch/2;
00443 }
00444 else if ( options->borderSnapZone )
00445 {
00446 if( ( nx == xmin || nx == xmax - cw ) && diffY < snap && diffY < deltaY)
00447 {
00448 deltaY = diffY;
00449 ny = (ymin + ymax)/2 - ch/2;
00450 }
00451 else if ( (( unrestricted ? ny == ymin : ny <= ymin) || ny == ymax - ch ) &&
00452 diffX < snap && diffX < deltaX)
00453 {
00454 deltaX = diffX;
00455 nx = (xmin + xmax)/2 - cw/2;
00456 }
00457 }
00458 }
00459
00460 pos = QPoint(nx, ny);
00461 }
00462 return pos;
00463 }
00464
00465 QRect Workspace::adjustClientSize( Client* c, QRect moveResizeGeom, int mode )
00466 {
00467
00468
00469
00470 if ( options->windowSnapZone || options->borderSnapZone )
00471 {
00472 const bool sOWO=options->snapOnlyWhenOverlapping;
00473
00474 const QRect maxRect = clientArea(MovementArea, c->rect().center(), c->desktop());
00475 const int xmin = maxRect.left();
00476 const int xmax = maxRect.right();
00477 const int ymin = maxRect.top();
00478 const int ymax = maxRect.bottom();
00479
00480 const int cx(moveResizeGeom.left());
00481 const int cy(moveResizeGeom.top());
00482 const int rx(moveResizeGeom.right());
00483 const int ry(moveResizeGeom.bottom());
00484
00485 int newcx(cx), newcy(cy);
00486 int newrx(rx), newry(ry);
00487 int deltaX(xmax);
00488 int deltaY(ymax);
00489
00490 int lx, ly, lrx, lry;
00491
00492
00493 int snap = options->borderSnapZone;
00494 if (snap)
00495 {
00496 deltaX = int(snap);
00497 deltaY = int(snap);
00498
00499 #define SNAP_BORDER_TOP \
00500 if ((sOWO?(newcy<ymin):true) && (qAbs(ymin-newcy)<deltaY)) \
00501 { \
00502 deltaY = qAbs(ymin-newcy); \
00503 newcy = ymin; \
00504 }
00505
00506 #define SNAP_BORDER_BOTTOM \
00507 if ((sOWO?(newry>ymax):true) && (qAbs(ymax-newry)<deltaY)) \
00508 { \
00509 deltaY = qAbs(ymax-newcy); \
00510 newry = ymax; \
00511 }
00512
00513 #define SNAP_BORDER_LEFT \
00514 if ((sOWO?(newcx<xmin):true) && (qAbs(xmin-newcx)<deltaX)) \
00515 { \
00516 deltaX = qAbs(xmin-newcx); \
00517 newcx = xmin; \
00518 }
00519
00520 #define SNAP_BORDER_RIGHT \
00521 if ((sOWO?(newrx>xmax):true) && (qAbs(xmax-newrx)<deltaX)) \
00522 { \
00523 deltaX = qAbs(xmax-newrx); \
00524 newrx = xmax; \
00525 }
00526 switch ( mode )
00527 {
00528 case PositionBottomRight:
00529 SNAP_BORDER_BOTTOM
00530 SNAP_BORDER_RIGHT
00531 break;
00532 case PositionRight:
00533 SNAP_BORDER_RIGHT
00534 break;
00535 case PositionBottom:
00536 SNAP_BORDER_BOTTOM
00537 break;
00538 case PositionTopLeft:
00539 SNAP_BORDER_TOP
00540 SNAP_BORDER_LEFT
00541 break;
00542 case PositionLeft:
00543 SNAP_BORDER_LEFT
00544 break;
00545 case PositionTop:
00546 SNAP_BORDER_TOP
00547 break;
00548 case PositionTopRight:
00549 SNAP_BORDER_TOP
00550 SNAP_BORDER_RIGHT
00551 break;
00552 case PositionBottomLeft:
00553 SNAP_BORDER_BOTTOM
00554 SNAP_BORDER_LEFT
00555 break;
00556 default:
00557 abort();
00558 break;
00559 }
00560
00561
00562 }
00563
00564
00565 snap = options->windowSnapZone;
00566 if (snap)
00567 {
00568 deltaX = int(snap);
00569 deltaY = int(snap);
00570 QList<Client *>::ConstIterator l;
00571 for (l = clients.constBegin();l != clients.constEnd();++l )
00572 {
00573 if ((*l)->isOnDesktop(currentDesktop()) &&
00574 !(*l)->isMinimized()
00575 && (*l) != c )
00576 {
00577 lx = (*l)->x()-1;
00578 ly = (*l)->y()-1;
00579 lrx =(*l)->x() + (*l)->width();
00580 lry =(*l)->y() + (*l)->height();
00581
00582 #define WITHIN_HEIGHT ((( newcy <= lry ) && ( newcy >= ly )) || \
00583 (( newry >= ly ) && ( newry <= lry )) || \
00584 (( newcy <= ly ) && ( newry >= lry )) )
00585
00586 #define WITHIN_WIDTH ( (( cx <= lrx ) && ( cx >= lx )) || \
00587 (( rx >= lx ) && ( rx <= lrx )) || \
00588 (( cx <= lx ) && ( rx >= lrx )) )
00589
00590 #define SNAP_WINDOW_TOP if ( (sOWO?(newcy<lry):true) \
00591 && WITHIN_WIDTH \
00592 && (qAbs( lry - newcy ) < deltaY) ) { \
00593 deltaY = qAbs( lry - newcy ); \
00594 newcy=lry; \
00595 }
00596
00597 #define SNAP_WINDOW_BOTTOM if ( (sOWO?(newry>ly):true) \
00598 && WITHIN_WIDTH \
00599 && (qAbs( ly - newry ) < deltaY) ) { \
00600 deltaY = qAbs( ly - newry ); \
00601 newry=ly; \
00602 }
00603
00604 #define SNAP_WINDOW_LEFT if ( (sOWO?(newcx<lrx):true) \
00605 && WITHIN_HEIGHT \
00606 && (qAbs( lrx - newcx ) < deltaX)) { \
00607 deltaX = qAbs( lrx - newcx ); \
00608 newcx=lrx; \
00609 }
00610
00611 #define SNAP_WINDOW_RIGHT if ( (sOWO?(newrx>lx):true) \
00612 && WITHIN_HEIGHT \
00613 && (qAbs( lx - newrx ) < deltaX)) \
00614 { \
00615 deltaX = qAbs( lx - newrx ); \
00616 newrx=lx; \
00617 }
00618
00619 #define SNAP_WINDOW_C_TOP if ( (sOWO?(newcy<ly):true) \
00620 && (newcx == lrx || newrx == lx) \
00621 && qAbs(ly-newcy) < deltaY ) { \
00622 deltaY = qAbs( ly - newcy + 1 ); \
00623 newcy = ly + 1; \
00624 }
00625
00626 #define SNAP_WINDOW_C_BOTTOM if ( (sOWO?(newry>lry):true) \
00627 && (newcx == lrx || newrx == lx) \
00628 && qAbs(lry-newry) < deltaY ) { \
00629 deltaY = qAbs( lry - newry - 1 ); \
00630 newry = lry - 1; \
00631 }
00632
00633 #define SNAP_WINDOW_C_LEFT if ( (sOWO?(newcx<lx):true) \
00634 && (newcy == lry || newry == ly) \
00635 && qAbs(lx-newcx) < deltaX ) { \
00636 deltaX = qAbs( lx - newcx + 1 ); \
00637 newcx = lx + 1; \
00638 }
00639
00640 #define SNAP_WINDOW_C_RIGHT if ( (sOWO?(newrx>lrx):true) \
00641 && (newcy == lry || newry == ly) \
00642 && qAbs(lrx-newrx) < deltaX ) { \
00643 deltaX = qAbs( lrx - newrx - 1 ); \
00644 newrx = lrx - 1; \
00645 }
00646
00647 switch ( mode )
00648 {
00649 case PositionBottomRight:
00650 SNAP_WINDOW_BOTTOM
00651 SNAP_WINDOW_RIGHT
00652 SNAP_WINDOW_C_BOTTOM
00653 SNAP_WINDOW_C_RIGHT
00654 break;
00655 case PositionRight:
00656 SNAP_WINDOW_RIGHT
00657 SNAP_WINDOW_C_RIGHT
00658 break;
00659 case PositionBottom:
00660 SNAP_WINDOW_BOTTOM
00661 SNAP_WINDOW_C_BOTTOM
00662 break;
00663 case PositionTopLeft:
00664 SNAP_WINDOW_TOP
00665 SNAP_WINDOW_LEFT
00666 SNAP_WINDOW_C_TOP
00667 SNAP_WINDOW_C_LEFT
00668 break;
00669 case PositionLeft:
00670 SNAP_WINDOW_LEFT
00671 SNAP_WINDOW_C_LEFT
00672 break;
00673 case PositionTop:
00674 SNAP_WINDOW_TOP
00675 SNAP_WINDOW_C_TOP
00676 break;
00677 case PositionTopRight:
00678 SNAP_WINDOW_TOP
00679 SNAP_WINDOW_RIGHT
00680 SNAP_WINDOW_C_TOP
00681 SNAP_WINDOW_C_RIGHT
00682 break;
00683 case PositionBottomLeft:
00684 SNAP_WINDOW_BOTTOM
00685 SNAP_WINDOW_LEFT
00686 SNAP_WINDOW_C_BOTTOM
00687 SNAP_WINDOW_C_LEFT
00688 break;
00689 default:
00690 abort();
00691 break;
00692 }
00693 }
00694 }
00695 }
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 moveResizeGeom = QRect(QPoint(newcx, newcy), QPoint(newrx, newry));
00708 }
00709 return moveResizeGeom;
00710 }
00711
00715 void Workspace::setClientIsMoving( Client *c )
00716 {
00717 Q_ASSERT(!c || !movingClient);
00718
00719 movingClient = c;
00720 if (movingClient)
00721 ++block_focus;
00722 else
00723 --block_focus;
00724 }
00725
00729 void Workspace::cascadeDesktop()
00730 {
00731
00732 Q_ASSERT( block_stacking_updates == 0 );
00733 ClientList::ConstIterator it(stackingOrder().begin());
00734 initPositioning->reinitCascading( currentDesktop());
00735 QRect area = clientArea( PlacementArea, QPoint( 0, 0 ), currentDesktop());
00736 for (; it != stackingOrder().end(); ++it)
00737 {
00738 if((!(*it)->isOnDesktop(currentDesktop())) ||
00739 ((*it)->isMinimized()) ||
00740 ((*it)->isOnAllDesktops()) ||
00741 (!(*it)->isMovable()) )
00742 continue;
00743 initPositioning->placeCascaded(*it, area);
00744 }
00745 }
00746
00751 void Workspace::unclutterDesktop()
00752 {
00753 for ( int i = clients.size() - 1; i>=0; i-- )
00754 {
00755 if( ( !clients.at( i )->isOnDesktop( currentDesktop() ) ) ||
00756 (clients.at( i )->isMinimized()) ||
00757 (clients.at( i )->isOnAllDesktops()) ||
00758 (!clients.at( i )->isMovable()) )
00759 continue;
00760 initPositioning->placeSmart(clients.at( i ), QRect());
00761 }
00762 }
00763
00764
00765 void Workspace::updateTopMenuGeometry( Client* c )
00766 {
00767 if( !managingTopMenus())
00768 return;
00769 if( c != NULL )
00770 {
00771 XEvent ev;
00772 ev.xclient.display = display();
00773 ev.xclient.type = ClientMessage;
00774 ev.xclient.window = c->window();
00775 static Atom msg_type_atom = XInternAtom( display(), "_KDE_TOPMENU_MINSIZE", False );
00776 ev.xclient.message_type = msg_type_atom;
00777 ev.xclient.format = 32;
00778 ev.xclient.data.l[0] = xTime();
00779 ev.xclient.data.l[1] = topmenu_space->width();
00780 ev.xclient.data.l[2] = topmenu_space->height();
00781 ev.xclient.data.l[3] = 0;
00782 ev.xclient.data.l[4] = 0;
00783 XSendEvent( display(), c->window(), False, NoEventMask, &ev );
00784 KWindowSystem::setStrut( c->window(), 0, 0, topmenu_height, 0 );
00785 c->checkWorkspacePosition();
00786 return;
00787 }
00788
00789 QRect area;
00790 area = clientArea( MaximizeFullArea, QPoint( 0, 0 ), 1 );
00791 area.setHeight( topMenuHeight());
00792 topmenu_space->setGeometry( area );
00793 for( ClientList::ConstIterator it = topmenus.constBegin();
00794 it != topmenus.constEnd();
00795 ++it )
00796 updateTopMenuGeometry( *it );
00797 }
00798
00799
00800
00801
00802
00803
00804 void Client::keepInArea( QRect area, bool partial )
00805 {
00806 if( partial )
00807 {
00808
00809 area.setLeft( qMin( area.left() - width() + 100, area.left()));
00810 area.setTop( qMin( area.top() - height() + 100, area.top()));
00811 area.setRight( qMax( area.right() + width() - 100, area.right()));
00812 area.setBottom( qMax( area.bottom() + height() - 100, area.bottom()));
00813 }
00814 if( !partial )
00815 {
00816 if( area.width() < width() || area.height() < height())
00817 resizeWithChecks( qMin( area.width(), width()), qMin( area.height(), height()));
00818 }
00819 if ( geometry().right() > area.right() && width() < area.width() )
00820 move( area.right() - width(), y() );
00821 if ( geometry().bottom() > area.bottom() && height() < area.height() )
00822 move( x(), area.bottom() - height() );
00823 if( !area.contains( geometry().topLeft() ))
00824 {
00825 int tx = x();
00826 int ty = y();
00827 if ( tx < area.x() )
00828 tx = area.x();
00829 if ( ty < area.y() )
00830 ty = area.y();
00831 move( tx, ty );
00832 }
00833 }
00834
00840
00841
00842 QRect Client::adjustedClientArea( const QRect &desktopArea, const QRect& area ) const
00843 {
00844 QRect r = area;
00845
00846 if( isTopMenu())
00847 return r;
00848 NETExtendedStrut str = strut();
00849 QRect stareaL = QRect(
00850 0,
00851 str . left_start,
00852 str . left_width,
00853 str . left_end - str . left_start + 1 );
00854 QRect stareaR = QRect (
00855 desktopArea . right () - str . right_width + 1,
00856 str . right_start,
00857 str . right_width,
00858 str . right_end - str . right_start + 1 );
00859 QRect stareaT = QRect (
00860 str . top_start,
00861 0,
00862 str . top_end - str . top_start + 1,
00863 str . top_width);
00864 QRect stareaB = QRect (
00865 str . bottom_start,
00866 desktopArea . bottom () - str . bottom_width + 1,
00867 str . bottom_end - str . bottom_start + 1,
00868 str . bottom_width);
00869
00870 QRect screenarea = workspace()->clientArea( ScreenArea, this );
00871
00872
00873
00874 if( area == Kephal::ScreenUtils::desktopGeometry())
00875 {
00876 if( stareaL.left() < screenarea.left())
00877 stareaL = QRect();
00878 if( stareaR.right() > screenarea.right())
00879 stareaR = QRect();
00880 if( stareaT.top() < screenarea.top())
00881 stareaT = QRect();
00882 if( stareaB.bottom() < screenarea.bottom())
00883 stareaB = QRect();
00884 }
00885
00886
00887
00888 stareaL.setLeft( qMax( stareaL.left(), screenarea.left()));
00889 stareaR.setRight( qMin( stareaR.right(), screenarea.right()));
00890 stareaT.setTop( qMax( stareaT.top(), screenarea.top()));
00891 stareaB.setBottom( qMin( stareaB.bottom(), screenarea.bottom()));
00892
00893 if (stareaL . intersects (area)) {
00894
00895 r . setLeft( stareaL . right() + 1 );
00896 }
00897 if (stareaR . intersects (area)) {
00898
00899 r . setRight( stareaR . left() - 1 );
00900 }
00901 if (stareaT . intersects (area)) {
00902
00903 r . setTop( stareaT . bottom() + 1 );
00904 }
00905 if (stareaB . intersects (area)) {
00906
00907 r . setBottom( stareaB . top() - 1 );
00908 }
00909 return r;
00910 }
00911
00912 NETExtendedStrut Client::strut() const
00913 {
00914 NETExtendedStrut ext = info->extendedStrut();
00915 NETStrut str = info->strut();
00916 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
00917 && ( str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0 ))
00918 {
00919
00920 if( str.left != 0 )
00921 {
00922 ext.left_width = str.left;
00923 ext.left_start = 0;
00924 ext.left_end = displayHeight();
00925 }
00926 if( str.right != 0 )
00927 {
00928 ext.right_width = str.right;
00929 ext.right_start = 0;
00930 ext.right_end = displayHeight();
00931 }
00932 if( str.top != 0 )
00933 {
00934 ext.top_width = str.top;
00935 ext.top_start = 0;
00936 ext.top_end = displayWidth();
00937 }
00938 if( str.bottom != 0 )
00939 {
00940 ext.bottom_width = str.bottom;
00941 ext.bottom_start = 0;
00942 ext.bottom_end = displayWidth();
00943 }
00944 }
00945 return ext;
00946 }
00947
00948 bool Client::hasStrut() const
00949 {
00950 NETExtendedStrut ext = strut();
00951 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0 )
00952 return false;
00953 return true;
00954 }
00955
00956
00957
00958 void Client::updateWorkareaDiffs()
00959 {
00960 QRect area = workspace()->clientArea( WorkArea, this );
00961 QRect geom = geometry();
00962 workarea_diff_x = computeWorkareaDiff( geom.left(), geom.right(), area.left(), area.right());
00963 workarea_diff_y = computeWorkareaDiff( geom.top(), geom.bottom(), area.top(), area.bottom());
00964 }
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974 int Client::computeWorkareaDiff( int left, int right, int a_left, int a_right )
00975 {
00976 int left_diff = left - a_left;
00977 int right_diff = a_right - right;
00978 if( left_diff < 0 || right_diff < 0 )
00979 return INT_MIN;
00980 else
00981 {
00982
00983 int max_diff = ( a_right - a_left ) / 10;
00984 if( left_diff < right_diff )
00985 return left_diff < max_diff ? -left_diff - 1 : INT_MAX;
00986 else if( left_diff > right_diff )
00987 return right_diff < max_diff ? right_diff + 1 : INT_MAX;
00988 return INT_MAX;
00989 }
00990 }
00991
00992 void Client::checkWorkspacePosition()
00993 {
00994 if( isDesktop())
00995 return;
00996 if( isFullScreen())
00997 {
00998 QRect area = workspace()->clientArea( FullScreenArea, this );
00999 if( geometry() != area )
01000 setGeometry( area );
01001 return;
01002 }
01003 if( isDock())
01004 return;
01005 if( isTopMenu())
01006 {
01007 if( workspace()->managingTopMenus())
01008 {
01009 QRect area;
01010 ClientList mainclients = mainClients();
01011 if( mainclients.count() == 1 )
01012 area = workspace()->clientArea( MaximizeFullArea, mainclients.first());
01013 else
01014 area = workspace()->clientArea( MaximizeFullArea, QPoint( 0, 0 ), desktop());
01015 area.setHeight( workspace()->topMenuHeight());
01016
01017 setGeometry( area );
01018 }
01019 return;
01020 }
01021
01022 if( maximizeMode() != MaximizeRestore )
01023
01024 changeMaximize( false, false, true );
01025
01026 if( !isShade())
01027 {
01028 int old_diff_x = workarea_diff_x;
01029 int old_diff_y = workarea_diff_y;
01030 updateWorkareaDiffs();
01031
01032
01033
01034
01035
01036
01037 if( workspace()->initializing())
01038 return;
01039
01040 QRect area = workspace()->clientArea( WorkArea, this );
01041 QRect new_geom = geometry();
01042 QRect tmp_rect_x( new_geom.left(), 0, new_geom.width(), 0 );
01043 QRect tmp_area_x( area.left(), 0, area.width(), 0 );
01044 checkDirection( workarea_diff_x, old_diff_x, tmp_rect_x, tmp_area_x );
01045
01046 QRect tmp_rect_y( new_geom.top(), 0, new_geom.height(), 0 );
01047 QRect tmp_area_y( area.top(), 0, area.height(), 0 );
01048 checkDirection( workarea_diff_y, old_diff_y, tmp_rect_y, tmp_area_y );
01049 new_geom = QRect( tmp_rect_x.left(), tmp_rect_y.left(), tmp_rect_x.width(), tmp_rect_y.width());
01050 QRect final_geom( new_geom.topLeft(), adjustedSize( new_geom.size()));
01051 if( final_geom != new_geom )
01052 {
01053 if( old_diff_x != INT_MAX && old_diff_x > 0 )
01054 final_geom.moveRight( area.right() - ( old_diff_x - 1 ));
01055 if( old_diff_y != INT_MAX && old_diff_y > 0 )
01056 final_geom.moveBottom( area.bottom() - ( old_diff_y - 1 ));
01057 }
01058 if( final_geom != geometry() )
01059 setGeometry( final_geom );
01060
01061 }
01062 }
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074 void Client::checkDirection( int new_diff, int old_diff, QRect& rect, const QRect& area )
01075 {
01076 if( old_diff != INT_MIN )
01077 {
01078 if( old_diff == INT_MAX )
01079 {
01080 if( new_diff == INT_MIN )
01081 {
01082 rect.setLeft( area.left());
01083 rect.setRight( area.right());
01084 }
01085 return;
01086 }
01087 if( isMovable())
01088 {
01089 if( old_diff < 0 )
01090 rect.moveLeft( area.left() + ( -old_diff - 1 ));
01091 else
01092 rect.moveRight( area.right() - ( old_diff - 1 ));
01093 }
01094 else if( isResizable())
01095 {
01096 if( old_diff < 0 )
01097 rect.setLeft( area.left() + ( -old_diff - 1 ) );
01098 else
01099 rect.setRight( area.right() - ( old_diff - 1 ));
01100 }
01101 if( rect.width() > area.width() && isResizable())
01102 rect.setWidth( area.width());
01103 if( isMovable())
01104 {
01105 if( rect.left() < area.left())
01106 rect.moveLeft( area.left());
01107 else if( rect.right() > area.right())
01108 rect.moveRight( area.right());
01109 }
01110 }
01111 if( rect.right() < area.left() + 5 || rect.left() > area.right() - 5 )
01112 {
01113 if( isMovable())
01114 {
01115 if( rect.left() < area.left() + 5 )
01116 rect.moveRight( area.left() + 5 );
01117 if( rect.right() > area.right() - 5 )
01118 rect.moveLeft( area.right() - 5 );
01119 }
01120 }
01121 }
01122
01126 QSize Client::adjustedSize( const QSize& frame, Sizemode mode ) const
01127 {
01128
01129
01130 QSize wsize( frame.width() - ( border_left + border_right ),
01131 frame.height() - ( border_top + border_bottom ));
01132 if( wsize.isEmpty())
01133 wsize = QSize( 1, 1 );
01134
01135 return sizeForClientSize( wsize, mode, false );
01136 }
01137
01138
01139
01140 QSize Client::adjustedSize() const
01141 {
01142 return sizeForClientSize( clientSize());
01143 }
01144
01153 QSize Client::sizeForClientSize( const QSize& wsize, Sizemode mode, bool noframe ) const
01154 {
01155 int w = wsize.width();
01156 int h = wsize.height();
01157 if( w < 1 || h < 1 )
01158 {
01159 kWarning(1212) << "sizeForClientSize() with empty size!" ;
01160 kWarning(1212) << kBacktrace() ;
01161 }
01162 if (w<1) w = 1;
01163 if (h<1) h = 1;
01164
01165
01166
01167 QSize min_size = minSize();
01168 QSize max_size = maxSize();
01169 if( decoration != NULL )
01170 {
01171 QSize decominsize = decoration->minimumSize();
01172 QSize border_size( border_left + border_right, border_top + border_bottom );
01173 if( border_size.width() > decominsize.width())
01174 decominsize.setWidth( border_size.width());
01175 if( border_size.height() > decominsize.height())
01176 decominsize.setHeight( border_size.height());
01177 if( decominsize.width() > min_size.width())
01178 min_size.setWidth( decominsize.width());
01179 if( decominsize.height() > min_size.height())
01180 min_size.setHeight( decominsize.height());
01181 }
01182 w = qMin( max_size.width(), w );
01183 h = qMin( max_size.height(), h );
01184 w = qMax( min_size.width(), w );
01185 h = qMax( min_size.height(), h );
01186
01187 int w1 = w;
01188 int h1 = h;
01189 int width_inc = xSizeHint.width_inc;
01190 int height_inc = xSizeHint.height_inc;
01191 int basew_inc = xSizeHint.min_width;
01192 int baseh_inc = xSizeHint.min_height;
01193 w = int(( w - basew_inc ) / width_inc ) * width_inc + basew_inc;
01194 h = int(( h - baseh_inc ) / height_inc ) * height_inc + baseh_inc;
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210 if( xSizeHint.flags & PAspect )
01211 {
01212 double min_aspect_w = xSizeHint.min_aspect.x;
01213 double min_aspect_h = xSizeHint.min_aspect.y;
01214 double max_aspect_w = xSizeHint.max_aspect.x;
01215 double max_aspect_h = xSizeHint.max_aspect.y;
01216
01217
01218
01219 w -= xSizeHint.base_width;
01220 h -= xSizeHint.base_height;
01221 int max_width = max_size.width() - xSizeHint.base_width;
01222 int min_width = min_size.width() - xSizeHint.base_width;
01223 int max_height = max_size.height() - xSizeHint.base_height;
01224 int min_height = min_size.height() - xSizeHint.base_height;
01225 #define ASPECT_CHECK_GROW_W \
01226 if( min_aspect_w * h > min_aspect_h * w ) \
01227 { \
01228 int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
01229 if( w + delta <= max_width ) \
01230 w += delta; \
01231 }
01232 #define ASPECT_CHECK_SHRINK_H_GROW_W \
01233 if( min_aspect_w * h > min_aspect_h * w ) \
01234 { \
01235 int delta = int( h - w * min_aspect_h / min_aspect_w ) / height_inc * height_inc; \
01236 if( h - delta >= min_height ) \
01237 h -= delta; \
01238 else \
01239 { \
01240 int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
01241 if( w + delta <= max_width ) \
01242 w += delta; \
01243 } \
01244 }
01245 #define ASPECT_CHECK_GROW_H \
01246 if( max_aspect_w * h < max_aspect_h * w ) \
01247 { \
01248 int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
01249 if( h + delta <= max_height ) \
01250 h += delta; \
01251 }
01252 #define ASPECT_CHECK_SHRINK_W_GROW_H \
01253 if( max_aspect_w * h < max_aspect_h * w ) \
01254 { \
01255 int delta = int( w - max_aspect_w * h / max_aspect_h ) / width_inc * width_inc; \
01256 if( w - delta >= min_width ) \
01257 w -= delta; \
01258 else \
01259 { \
01260 int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
01261 if( h + delta <= max_height ) \
01262 h += delta; \
01263 } \
01264 }
01265 switch( mode )
01266 {
01267 case SizemodeAny:
01268 #if 0 // make SizemodeAny equal to SizemodeFixedW - prefer keeping fixed width,
01269
01270 {
01271 ASPECT_CHECK_SHRINK_H_GROW_W
01272 ASPECT_CHECK_SHRINK_W_GROW_H
01273 ASPECT_CHECK_GROW_H
01274 ASPECT_CHECK_GROW_W
01275 break;
01276 }
01277 #endif
01278 case SizemodeFixedW:
01279 {
01280
01281 ASPECT_CHECK_GROW_H
01282 ASPECT_CHECK_SHRINK_H_GROW_W
01283 ASPECT_CHECK_SHRINK_W_GROW_H
01284 ASPECT_CHECK_GROW_W
01285 break;
01286 }
01287 case SizemodeFixedH:
01288 {
01289 ASPECT_CHECK_GROW_W
01290 ASPECT_CHECK_SHRINK_W_GROW_H
01291 ASPECT_CHECK_SHRINK_H_GROW_W
01292 ASPECT_CHECK_GROW_H
01293 break;
01294 }
01295 case SizemodeMax:
01296 {
01297
01298 ASPECT_CHECK_SHRINK_H_GROW_W
01299 ASPECT_CHECK_SHRINK_W_GROW_H
01300 ASPECT_CHECK_GROW_W
01301 ASPECT_CHECK_GROW_H
01302 break;
01303 }
01304 }
01305 #undef ASPECT_CHECK_SHRINK_H_GROW_W
01306 #undef ASPECT_CHECK_SHRINK_W_GROW_H
01307 #undef ASPECT_CHECK_GROW_W
01308 #undef ASPECT_CHECK_GROW_H
01309 w += xSizeHint.base_width;
01310 h += xSizeHint.base_height;
01311 }
01312 if( !rules()->checkStrictGeometry( false ))
01313 {
01314
01315 if( maximizeMode() & MaximizeHorizontal )
01316 w = w1;
01317 if( maximizeMode() & MaximizeVertical )
01318 h = h1;
01319 }
01320
01321 if( !noframe )
01322 {
01323 w += border_left + border_right;
01324 h += border_top + border_bottom;
01325 }
01326 return rules()->checkSize( QSize( w, h ));
01327 }
01328
01332 void Client::getWmNormalHints()
01333 {
01334 long msize;
01335 if (XGetWMNormalHints(display(), window(), &xSizeHint, &msize) == 0 )
01336 xSizeHint.flags = 0;
01337
01338
01339 if( ! ( xSizeHint.flags & PMinSize ))
01340 xSizeHint.min_width = xSizeHint.min_height = 0;
01341 if( xSizeHint.flags & PBaseSize )
01342 {
01343
01344
01345
01346 if( ! ( xSizeHint.flags & PMinSize ))
01347 {
01348 xSizeHint.min_width = xSizeHint.base_width;
01349 xSizeHint.min_height = xSizeHint.base_height;
01350 }
01351 }
01352 else
01353 xSizeHint.base_width = xSizeHint.base_height = 0;
01354 if( ! ( xSizeHint.flags & PMaxSize ))
01355 xSizeHint.max_width = xSizeHint.max_height = INT_MAX;
01356 else
01357 {
01358 xSizeHint.max_width = qMax( xSizeHint.max_width, 1 );
01359 xSizeHint.max_height = qMax( xSizeHint.max_height, 1 );
01360 }
01361 if( xSizeHint.flags & PResizeInc )
01362 {
01363 xSizeHint.width_inc = qMax( xSizeHint.width_inc, 1 );
01364 xSizeHint.height_inc = qMax( xSizeHint.height_inc, 1 );
01365 }
01366 else
01367 {
01368 xSizeHint.width_inc = 1;
01369 xSizeHint.height_inc = 1;
01370 }
01371 if( xSizeHint.flags & PAspect )
01372 {
01373 xSizeHint.min_aspect.y = qMax( xSizeHint.min_aspect.y, 1 );
01374 xSizeHint.max_aspect.y = qMax( xSizeHint.max_aspect.y, 1 );
01375 }
01376 else
01377 {
01378 xSizeHint.min_aspect.x = 1;
01379 xSizeHint.min_aspect.y = INT_MAX;
01380 xSizeHint.max_aspect.x = INT_MAX;
01381 xSizeHint.max_aspect.y = 1;
01382 }
01383 if( ! ( xSizeHint.flags & PWinGravity ))
01384 xSizeHint.win_gravity = NorthWestGravity;
01385 if( isManaged())
01386 {
01387 QSize new_size = adjustedSize();
01388 if( new_size != size() && !isFullScreen())
01389 {
01390 QRect orig_geometry = geometry();
01391 resizeWithChecks( new_size );
01392 if( ( !isSpecialWindow() || isToolbar()) && !isFullScreen())
01393 {
01394
01395
01396 QRect area = workspace()->clientArea( MovementArea, this );
01397 if( area.contains( orig_geometry ))
01398 keepInArea( area );
01399 area = workspace()->clientArea( WorkArea, this );
01400 if( area.contains( orig_geometry ))
01401 keepInArea( area );
01402 }
01403 }
01404 }
01405 updateAllowedActions();
01406 }
01407
01408 QSize Client::minSize() const
01409 {
01410 return rules()->checkMinSize( QSize( xSizeHint.min_width, xSizeHint.min_height ));
01411 }
01412
01413 QSize Client::maxSize() const
01414 {
01415 return rules()->checkMaxSize( QSize( xSizeHint.max_width, xSizeHint.max_height ));
01416 }
01417
01423 void Client::sendSyntheticConfigureNotify()
01424 {
01425 XConfigureEvent c;
01426 c.type = ConfigureNotify;
01427 c.send_event = True;
01428 c.event = window();
01429 c.window = window();
01430 c.x = x() + clientPos().x();
01431 c.y = y() + clientPos().y();
01432 c.width = clientSize().width();
01433 c.height = clientSize().height();
01434 c.border_width = 0;
01435 c.above = None;
01436 c.override_redirect = 0;
01437 XSendEvent( display(), c.event, true, StructureNotifyMask, (XEvent*)&c );
01438 }
01439
01440 const QPoint Client::calculateGravitation( bool invert, int gravity ) const
01441 {
01442 int dx, dy;
01443 dx = dy = 0;
01444
01445 if( gravity == 0 )
01446 gravity = xSizeHint.win_gravity;
01447
01448
01449 switch (gravity)
01450 {
01451 case NorthWestGravity:
01452 default:
01453 dx = border_left;
01454 dy = border_top;
01455 break;
01456 case NorthGravity:
01457 dx = 0;
01458 dy = border_top;
01459 break;
01460 case NorthEastGravity:
01461 dx = -border_right;
01462 dy = border_top;
01463 break;
01464 case WestGravity:
01465 dx = border_left;
01466 dy = 0;
01467 break;
01468 case CenterGravity:
01469 break;
01470 case StaticGravity:
01471 dx = 0;
01472 dy = 0;
01473 break;
01474 case EastGravity:
01475 dx = -border_right;
01476 dy = 0;
01477 break;
01478 case SouthWestGravity:
01479 dx = border_left ;
01480 dy = -border_bottom;
01481 break;
01482 case SouthGravity:
01483 dx = 0;
01484 dy = -border_bottom;
01485 break;
01486 case SouthEastGravity:
01487 dx = -border_right;
01488 dy = -border_bottom;
01489 break;
01490 }
01491 if( gravity != CenterGravity )
01492 {
01493 dx -= border_left;
01494 dy -= border_top;
01495 }
01496 else
01497 {
01498 dx = - ( border_left + border_right ) / 2;
01499 dy = - ( border_top + border_bottom ) / 2;
01500 }
01501 if( !invert )
01502 return QPoint( x() + dx, y() + dy );
01503 else
01504 return QPoint( x() - dx, y() - dy );
01505 }
01506
01507 void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, int gravity, bool from_tool )
01508 {
01509 if( gravity == 0 )
01510 gravity = xSizeHint.win_gravity;
01511 if( value_mask & ( CWX | CWY ))
01512 {
01513 QPoint new_pos = calculateGravitation( true, gravity );
01514 if ( value_mask & CWX )
01515 new_pos.setX( rx );
01516 if ( value_mask & CWY )
01517 new_pos.setY( ry );
01518
01519
01520
01521
01522
01523 if ( new_pos.x() == x() + clientPos().x() && new_pos.y() == y() + clientPos().y()
01524 && gravity == NorthWestGravity && !from_tool )
01525 {
01526 new_pos.setX( x());
01527 new_pos.setY( y());
01528 }
01529
01530 int nw = clientSize().width();
01531 int nh = clientSize().height();
01532 if ( value_mask & CWWidth )
01533 nw = rw;
01534 if ( value_mask & CWHeight )
01535 nh = rh;
01536 QSize ns = sizeForClientSize( QSize( nw, nh ) );
01537 new_pos = rules()->checkPosition( new_pos );
01538
01539
01540 if ( maximizeMode() != MaximizeFull
01541 || ns != size())
01542 {
01543 QRect orig_geometry = geometry();
01544 GeometryUpdatesBlocker blocker( this );
01545 move( new_pos );
01546 plainResize( ns );
01547 setGeometry( QRect( calculateGravitation( false, gravity ), size()));
01548 updateFullScreenHack( QRect( new_pos, QSize( nw, nh )));
01549 QRect area = workspace()->clientArea( WorkArea, this );
01550 if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen()
01551 && area.contains( orig_geometry ))
01552 keepInArea( area );
01553
01554
01555
01556
01557
01558 if (hasStrut ())
01559 workspace() -> updateClientArea ();
01560 }
01561 }
01562
01563 if ( value_mask & (CWWidth | CWHeight )
01564 && ! ( value_mask & ( CWX | CWY )) )
01565 {
01566 int nw = clientSize().width();
01567 int nh = clientSize().height();
01568 if ( value_mask & CWWidth )
01569 nw = rw;
01570 if ( value_mask & CWHeight )
01571 nh = rh;
01572 QSize ns = sizeForClientSize( QSize( nw, nh ) );
01573
01574 if( ns != size())
01575 {
01576 QRect orig_geometry = geometry();
01577 GeometryUpdatesBlocker blocker( this );
01578 int save_gravity = xSizeHint.win_gravity;
01579 xSizeHint.win_gravity = gravity;
01580 resizeWithChecks( ns );
01581 xSizeHint.win_gravity = save_gravity;
01582 updateFullScreenHack( QRect( calculateGravitation( true, xSizeHint.win_gravity ), QSize( nw, nh )));
01583 if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen())
01584 {
01585
01586
01587 QRect area = workspace()->clientArea( MovementArea, this );
01588 if( area.contains( orig_geometry ))
01589 keepInArea( area );
01590 area = workspace()->clientArea( WorkArea, this );
01591 if( area.contains( orig_geometry ))
01592 keepInArea( area );
01593 }
01594 }
01595 }
01596
01597
01598
01599 }
01600
01601 void Client::resizeWithChecks( int w, int h, ForceGeometry_t force )
01602 {
01603 assert( !shade_geometry_change );
01604 if( isShade())
01605 {
01606 if( h == border_top + border_bottom )
01607 {
01608 kWarning(1212) << "Shaded geometry passed for size:" ;
01609 kWarning(1212) << kBacktrace() ;
01610 }
01611 }
01612 int newx = x();
01613 int newy = y();
01614 QRect area = workspace()->clientArea( WorkArea, this );
01615
01616 if( w > area.width())
01617 w = area.width();
01618 if( h > area.height())
01619 h = area.height();
01620 QSize tmp = adjustedSize( QSize( w, h ));
01621 w = tmp.width();
01622 h = tmp.height();
01623 switch( xSizeHint.win_gravity )
01624 {
01625 case NorthWestGravity:
01626 default:
01627 break;
01628 case NorthGravity:
01629 newx = ( newx + width() / 2 ) - ( w / 2 );
01630 break;
01631 case NorthEastGravity:
01632 newx = newx + width() - w;
01633 break;
01634 case WestGravity:
01635 newy = ( newy + height() / 2 ) - ( h / 2 );
01636 break;
01637 case CenterGravity:
01638 newx = ( newx + width() / 2 ) - ( w / 2 );
01639 newy = ( newy + height() / 2 ) - ( h / 2 );
01640 break;
01641 case StaticGravity:
01642
01643 break;
01644 case EastGravity:
01645 newx = newx + width() - w;
01646 newy = ( newy + height() / 2 ) - ( h / 2 );
01647 break;
01648 case SouthWestGravity:
01649 newy = newy + height() - h;
01650 break;
01651 case SouthGravity:
01652 newx = ( newx + width() / 2 ) - ( w / 2 );
01653 newy = newy + height() - h;
01654 break;
01655 case SouthEastGravity:
01656 newx = newx + width() - w;
01657 newy = newy + height() - h;
01658 break;
01659 }
01660
01661
01662 if( workarea_diff_x != INT_MIN && w <= area.width())
01663 {
01664 if( newx < area.left())
01665 newx = area.left();
01666 if( newx + w > area.right() + 1 )
01667 newx = area.right() + 1 - w;
01668 assert( newx >= area.left() && newx + w <= area.right() + 1 );
01669 }
01670 if( workarea_diff_y != INT_MIN && h <= area.height())
01671 {
01672 if( newy < area.top())
01673 newy = area.top();
01674 if( newy + h > area.bottom() + 1 )
01675 newy = area.bottom() + 1 - h;
01676 assert( newy >= area.top() && newy + h <= area.bottom() + 1 );
01677 }
01678 setGeometry( newx, newy, w, h, force );
01679 }
01680
01681
01682 void Client::NETMoveResizeWindow( int flags, int x, int y, int width, int height )
01683 {
01684 int gravity = flags & 0xff;
01685 int value_mask = 0;
01686 if( flags & ( 1 << 8 ))
01687 value_mask |= CWX;
01688 if( flags & ( 1 << 9 ))
01689 value_mask |= CWY;
01690 if( flags & ( 1 << 10 ))
01691 value_mask |= CWWidth;
01692 if( flags & ( 1 << 11 ))
01693 value_mask |= CWHeight;
01694 configureRequest( value_mask, x, y, width, height, gravity, true );
01695 }
01696
01701 bool Client::isMovable() const
01702 {
01703 if( !motif_may_move || isFullScreen())
01704 return false;
01705 if( isSpecialWindow() && !isSplash() && !isToolbar())
01706 return false;
01707 if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() )
01708 return false;
01709 if( rules()->checkPosition( invalidPoint ) != invalidPoint )
01710 return false;
01711 return true;
01712 }
01713
01717 bool Client::isMovableAcrossScreens() const
01718 {
01719 if( !motif_may_move )
01720 return false;
01721 if( isSpecialWindow() && !isSplash() && !isToolbar())
01722 return false;
01723 if( rules()->checkPosition( invalidPoint ) != invalidPoint )
01724 return false;
01725 return true;
01726 }
01727
01731 bool Client::isResizable() const
01732 {
01733 if( !motif_may_resize || isFullScreen())
01734 return false;
01735 if( isSpecialWindow() || isSplash() || isToolbar())
01736 return false;
01737 if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() )
01738 return false;
01739 if( rules()->checkSize( QSize()).isValid())
01740 return false;
01741
01742 QSize min = minSize();
01743 QSize max = maxSize();
01744 return min.width() < max.width() || min.height() < max.height();
01745 }
01746
01747
01748
01749
01750 bool Client::isMaximizable() const
01751 {
01752 {
01753
01754 TemporaryAssign< MaximizeMode > tmp( max_mode, MaximizeRestore );
01755 if( !isMovable() || !isResizable() || isToolbar())
01756 return false;
01757 }
01758 if ( maximizeMode() != MaximizeRestore )
01759 return true;
01760 QSize max = maxSize();
01761 #if 0
01762 if( max.width() < 32767 || max.height() < 32767 )
01763 return false;
01764 #else
01765
01766
01767 QSize areasize = workspace()->clientArea( MaximizeArea, this ).size();
01768 if( max.width() < areasize.width() || max.height() < areasize.height())
01769 return false;
01770 #endif
01771 return true;
01772 }
01773
01774
01778 void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
01779 {
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791 if( shade_geometry_change )
01792 ;
01793 else if( isShade())
01794 {
01795 if( h == border_top + border_bottom )
01796 {
01797 kDebug(1212) << "Shaded geometry passed for size:";
01798 kDebug(1212) << kBacktrace();
01799 }
01800 else
01801 {
01802 client_size = QSize( w - border_left - border_right, h - border_top - border_bottom );
01803 h = border_top + border_bottom;
01804 }
01805 }
01806 else
01807 {
01808 client_size = QSize( w - border_left - border_right, h - border_top - border_bottom );
01809 }
01810 QRect g( x, y, w, h );
01811 if( block_geometry_updates == 0 && g != rules()->checkGeometry( g ))
01812 {
01813 kDebug(1212) << "forced geometry fail:" << g << ":" << rules()->checkGeometry( g );
01814 kDebug(1212) << kBacktrace();
01815 }
01816 if( force == NormalGeometrySet && geom == g && pending_geometry_update == PendingGeometryNone )
01817 return;
01818 geom = g;
01819 updateWorkareaDiffs();
01820 if( block_geometry_updates != 0 )
01821 {
01822 if( pending_geometry_update == PendingGeometryForced )
01823 {}
01824 else if( force == ForceGeometrySet )
01825 pending_geometry_update = PendingGeometryForced;
01826 else
01827 pending_geometry_update = PendingGeometryNormal;
01828 return;
01829 }
01830 bool resized = ( geom_before_block.size() != geom.size() || pending_geometry_update == PendingGeometryForced );
01831 if( resized )
01832 {
01833 resizeDecoration( QSize( w, h ));
01834 XMoveResizeWindow( display(), frameId(), x, y, w, h );
01835 if( !isShade())
01836 {
01837 QSize cs = clientSize();
01838 XMoveResizeWindow( display(), wrapperId(), clientPos().x(), clientPos().y(),
01839 cs.width(), cs.height());
01840 XMoveResizeWindow( display(), window(), 0, 0, cs.width(), cs.height());
01841 }
01842 updateShape();
01843 }
01844 else
01845 XMoveWindow( display(), frameId(), x, y );
01846
01847 sendSyntheticConfigureNotify();
01848 updateWindowRules();
01849 checkMaximizeGeometry();
01850 workspace()->checkActiveScreen( this );
01851 workspace()->updateStackingOrder();
01852 workspace()->checkUnredirect();
01853 if( resized )
01854 {
01855 discardWindowPixmap();
01856 if( scene != NULL )
01857 scene->windowGeometryShapeChanged( this );
01858 if( effects != NULL )
01859 static_cast<EffectsHandlerImpl*>(effects)->windowGeometryShapeChanged( effectWindow(), geom_before_block );
01860 }
01861 addWorkspaceRepaint( geom_before_block );
01862 addWorkspaceRepaint( geom );
01863 geom_before_block = geom;
01864 }
01865
01866 void Client::plainResize( int w, int h, ForceGeometry_t force )
01867 {
01868
01869 if( shade_geometry_change )
01870 ;
01871 else if( isShade())
01872 {
01873 if( h == border_top + border_bottom )
01874 {
01875 kDebug(1212) << "Shaded geometry passed for size:";
01876 kDebug(1212) << kBacktrace();
01877 }
01878 else
01879 {
01880 client_size = QSize( w - border_left - border_right, h - border_top - border_bottom );
01881 h = border_top + border_bottom;
01882 }
01883 }
01884 else
01885 {
01886 client_size = QSize( w - border_left - border_right, h - border_top - border_bottom );
01887 }
01888 QSize s( w, h );
01889 if( block_geometry_updates == 0 && s != rules()->checkSize( s ))
01890 {
01891 kDebug(1212) << "forced size fail:" << s << ":" << rules()->checkSize( s );
01892 kDebug(1212) << kBacktrace();
01893 }
01894
01895 assert( pending_geometry_update == PendingGeometryNone || block_geometry_updates > 0 );
01896 if( force == NormalGeometrySet && geom.size() == s )
01897 return;
01898 geom.setSize( s );
01899 updateWorkareaDiffs();
01900 if( block_geometry_updates != 0 )
01901 {
01902 if( pending_geometry_update == PendingGeometryForced )
01903 {}
01904 else if( force == ForceGeometrySet )
01905 pending_geometry_update = PendingGeometryForced;
01906 else
01907 pending_geometry_update = PendingGeometryNormal;
01908 return;
01909 }
01910 resizeDecoration( s );
01911 XResizeWindow( display(), frameId(), w, h );
01912
01913 if( !isShade())
01914 {
01915 QSize cs = clientSize();
01916 XMoveResizeWindow( display(), wrapperId(), clientPos().x(), clientPos().y(),
01917 cs.width(), cs.height());
01918 XMoveResizeWindow( display(), window(), 0, 0, cs.width(), cs.height());
01919 }
01920 updateShape();
01921 sendSyntheticConfigureNotify();
01922 updateWindowRules();
01923 checkMaximizeGeometry();
01924 workspace()->checkActiveScreen( this );
01925 workspace()->updateStackingOrder();
01926 workspace()->checkUnredirect();
01927 discardWindowPixmap();
01928 if( scene != NULL )
01929 scene->windowGeometryShapeChanged( this );
01930 if( effects != NULL )
01931 static_cast<EffectsHandlerImpl*>(effects)->windowGeometryShapeChanged( effectWindow(), geom_before_block );
01932 addWorkspaceRepaint( geom_before_block );
01933 addWorkspaceRepaint( geom );
01934 geom_before_block = geom;
01935 }
01936
01940 void Client::move( int x, int y, ForceGeometry_t force )
01941 {
01942
01943 assert( pending_geometry_update == PendingGeometryNone || block_geometry_updates > 0 );
01944 QPoint p( x, y );
01945 if( block_geometry_updates == 0 && p != rules()->checkPosition( p ))
01946 {
01947 kDebug(1212) << "forced position fail:" << p << ":" << rules()->checkPosition( p );
01948 kDebug(1212) << kBacktrace();
01949 }
01950 if( force == NormalGeometrySet && geom.topLeft() == p )
01951 return;
01952 geom.moveTopLeft( p );
01953 updateWorkareaDiffs();
01954 if( block_geometry_updates != 0 )
01955 {
01956 if( pending_geometry_update == PendingGeometryForced )
01957 {}
01958 else if( force == ForceGeometrySet )
01959 pending_geometry_update = PendingGeometryForced;
01960 else
01961 pending_geometry_update = PendingGeometryNormal;
01962 return;
01963 }
01964 XMoveWindow( display(), frameId(), x, y );
01965 sendSyntheticConfigureNotify();
01966 updateWindowRules();
01967 checkMaximizeGeometry();
01968 workspace()->checkActiveScreen( this );
01969 workspace()->updateStackingOrder();
01970 workspace()->checkUnredirect();
01971
01972 addWorkspaceRepaint( geom_before_block );
01973 addWorkspaceRepaint( geom );
01974 geom_before_block = geom;
01975 }
01976
01977 void Client::blockGeometryUpdates( bool block )
01978 {
01979 if( block )
01980 {
01981 if( block_geometry_updates == 0 )
01982 pending_geometry_update = PendingGeometryNone;
01983 ++block_geometry_updates;
01984 }
01985 else
01986 {
01987 if( --block_geometry_updates == 0 )
01988 {
01989 if( pending_geometry_update != PendingGeometryNone )
01990 {
01991 if( isShade())
01992 setGeometry( QRect( pos(), adjustedSize()), NormalGeometrySet );
01993 else
01994 setGeometry( geometry(), NormalGeometrySet );
01995 pending_geometry_update = PendingGeometryNone;
01996 }
01997 }
01998 }
01999 }
02000
02001 void Client::maximize( MaximizeMode m )
02002 {
02003 setMaximize( m & MaximizeVertical, m & MaximizeHorizontal );
02004 }
02005
02009 void Client::setMaximize( bool vertically, bool horizontally )
02010 {
02011 changeMaximize(
02012 max_mode & MaximizeVertical ? !vertically : vertically,
02013 max_mode & MaximizeHorizontal ? !horizontally : horizontally,
02014 false );
02015 }
02016
02017 void Client::changeMaximize( bool vertical, bool horizontal, bool adjust )
02018 {
02019 if( !isMaximizable())
02020 return;
02021
02022 MaximizeMode old_mode = max_mode;
02023
02024 if( !adjust )
02025 {
02026 if( vertical )
02027 max_mode = MaximizeMode( max_mode ^ MaximizeVertical );
02028 if( horizontal )
02029 max_mode = MaximizeMode( max_mode ^ MaximizeHorizontal );
02030 }
02031
02032 max_mode = rules()->checkMaximize( max_mode );
02033 if( !adjust && max_mode == old_mode )
02034 return;
02035
02036 GeometryUpdatesBlocker blocker( this );
02037
02038
02039
02040 if( ( old_mode == MaximizeVertical && max_mode == MaximizeHorizontal )
02041 || ( old_mode == MaximizeHorizontal && max_mode == MaximizeVertical ))
02042 {
02043 changeMaximize( false, false, false );
02044 }
02045
02046
02047 QRect clientArea = workspace()->clientArea( MaximizeArea, this );
02048
02049
02050 if( !adjust && !( y() == clientArea.top() && height() == clientArea.height()))
02051 {
02052 geom_restore.setTop( y());
02053 geom_restore.setHeight( height());
02054 }
02055 if( !adjust && !( x() == clientArea.left() && width() == clientArea.width()))
02056 {
02057 geom_restore.setLeft( x());
02058 geom_restore.setWidth( width());
02059 }
02060
02061 if( !adjust )
02062 {
02063 if(( vertical && !(old_mode & MaximizeVertical ))
02064 || ( horizontal && !( old_mode & MaximizeHorizontal )))
02065 Notify::raise( Notify::Maximize );
02066 else
02067 Notify::raise( Notify::UnMaximize );
02068 }
02069
02070 ForceGeometry_t geom_mode = NormalGeometrySet;
02071 if( decoration != NULL )
02072 {
02073 if( checkBorderSizes( false ))
02074 geom_mode = ForceGeometrySet;
02075 }
02076
02077
02078 if ( old_mode==MaximizeFull && max_mode==MaximizeRestore )
02079 {
02080 if ( maximizeModeRestore()==MaximizeVertical )
02081 {
02082 max_mode = MaximizeVertical;
02083 maxmode_restore = MaximizeRestore;
02084 }
02085 if ( maximizeModeRestore()==MaximizeHorizontal )
02086 {
02087 max_mode = MaximizeHorizontal;
02088 maxmode_restore = MaximizeRestore;
02089 }
02090 }
02091
02092 switch (max_mode)
02093 {
02094
02095 case MaximizeVertical:
02096 {
02097 if( old_mode & MaximizeHorizontal )
02098 {
02099 if( geom_restore.width() == 0 || !clientArea.contains( geom_restore.center() ))
02100 {
02101 plainResize( adjustedSize( QSize( width() * 2 / 3, clientArea.height()), SizemodeFixedH ), geom_mode );
02102 workspace()->placeSmart( this, clientArea );
02103 }
02104 else
02105 {
02106 setGeometry( QRect(QPoint( geom_restore.x(), clientArea.top()),
02107 adjustedSize(QSize( geom_restore.width(), clientArea.height()), SizemodeFixedH )), geom_mode );
02108 }
02109 }
02110 else
02111 {
02112 setGeometry( QRect(QPoint(x(), clientArea.top()),
02113 adjustedSize(QSize(width(), clientArea.height()), SizemodeFixedH )), geom_mode );
02114 }
02115 info->setState( NET::MaxVert, NET::Max );
02116 break;
02117 }
02118
02119 case MaximizeHorizontal:
02120 {
02121 if( old_mode & MaximizeVertical )
02122 {
02123 if( geom_restore.height() == 0 || !clientArea.contains( geom_restore.center() ) )
02124 {
02125 plainResize( adjustedSize( QSize( clientArea.width(), height() * 2 / 3 ), SizemodeFixedW ), geom_mode );
02126 workspace()->placeSmart( this, clientArea );
02127 }
02128 else
02129 {
02130 setGeometry( QRect( QPoint(clientArea.left(), geom_restore.y()),
02131 adjustedSize(QSize(clientArea.width(), geom_restore.height()), SizemodeFixedW )), geom_mode );
02132 }
02133 }
02134 else
02135 {
02136 setGeometry( QRect( QPoint(clientArea.left(), y()),
02137 adjustedSize(QSize(clientArea.width(), height()), SizemodeFixedW )), geom_mode );
02138 }
02139 info->setState( NET::MaxHoriz, NET::Max );
02140 break;
02141 }
02142
02143 case MaximizeRestore:
02144 {
02145 QRect restore = geometry();
02146
02147 if( old_mode & MaximizeVertical )
02148 {
02149 restore.setTop( geom_restore.top());
02150 restore.setBottom( geom_restore.bottom());
02151 }
02152 if( old_mode & MaximizeHorizontal )
02153 {
02154 restore.setLeft( geom_restore.left());
02155 restore.setRight( geom_restore.right());
02156 }
02157 if( !restore.isValid())
02158 {
02159 QSize s = QSize( clientArea.width()*2/3, clientArea.height()*2/3 );
02160 if( geom_restore.width() > 0 )
02161 s.setWidth( geom_restore.width());
02162 if( geom_restore.height() > 0 )
02163 s.setHeight( geom_restore.height());
02164 plainResize( adjustedSize( s ));
02165 workspace()->placeSmart( this, clientArea );
02166 restore = geometry();
02167 if( geom_restore.width() > 0 )
02168 restore.moveLeft( geom_restore.x());
02169 if( geom_restore.height() > 0 )
02170 restore.moveTop( geom_restore.y());
02171 }
02172 setGeometry( restore, geom_mode );
02173 if( !clientArea.contains( geom_restore.center() ))
02174 workspace()->place( this, clientArea );
02175 info->setState( 0, NET::Max );
02176 break;
02177 }
02178
02179 case MaximizeFull:
02180 {
02181 if( !adjust )
02182 {
02183 if( old_mode & MaximizeVertical )
02184 maxmode_restore = MaximizeVertical;
02185 if( old_mode & MaximizeHorizontal )
02186 maxmode_restore = MaximizeHorizontal;
02187 }
02188 QSize adjSize = adjustedSize(clientArea.size(), SizemodeMax );
02189 QRect r = QRect(clientArea.topLeft(), adjSize);
02190 setGeometry( r, geom_mode );
02191 info->setState( NET::Max, NET::Max );
02192 break;
02193 }
02194 default:
02195 break;
02196 }
02197
02198 updateAllowedActions();
02199 if( decoration != NULL )
02200 decoration->maximizeChange();
02201 updateWindowRules();
02202 }
02203
02204 void Client::resetMaximize()
02205 {
02206 if( max_mode == MaximizeRestore )
02207 return;
02208 max_mode = MaximizeRestore;
02209 Notify::raise( Notify::UnMaximize );
02210 info->setState( 0, NET::Max );
02211 updateAllowedActions();
02212 if( decoration != NULL )
02213 decoration->borders( border_left, border_right, border_top, border_bottom );
02214 if( isShade())
02215 setGeometry( QRect( pos(), sizeForClientSize( clientSize())), ForceGeometrySet );
02216 else
02217 setGeometry( geometry(), ForceGeometrySet );
02218 if( decoration != NULL )
02219 decoration->maximizeChange();
02220 }
02221
02222 void Client::checkMaximizeGeometry()
02223 {
02224
02225
02226 if( isShade())
02227 return;
02228 if( isMove() || isResize())
02229 return;
02230
02231 static int recursion_protection = 0;
02232 if( recursion_protection > 3 )
02233 {
02234 kWarning( 1212 ) << "Check maximize overflow - you loose!" ;
02235 kWarning( 1212 ) << kBacktrace() ;
02236 return;
02237 }
02238 ++recursion_protection;
02239 QRect max_area = workspace()->clientArea( MaximizeArea, this );
02240 if( geometry() == max_area )
02241 {
02242 if( max_mode != MaximizeFull )
02243 maximize( MaximizeFull );
02244 }
02245 else if( x() == max_area.left() && width() == max_area.width())
02246 {
02247 if( max_mode != MaximizeHorizontal )
02248 maximize( MaximizeHorizontal );
02249 }
02250 else if( y() == max_area.top() && height() == max_area.height())
02251 {
02252 if( max_mode != MaximizeVertical )
02253 maximize( MaximizeVertical );
02254 }
02255 else if( max_mode != MaximizeRestore )
02256 {
02257 resetMaximize();
02258 }
02259 --recursion_protection;
02260 }
02261
02262 bool Client::isFullScreenable( bool fullscreen_hack ) const
02263 {
02264 if( !rules()->checkFullScreen( true ))
02265 return false;
02266 if( fullscreen_hack )
02267 return isNormalWindow();
02268 if( rules()->checkStrictGeometry( false ))
02269 {
02270
02271 QRect fsarea = workspace()->clientArea( FullScreenArea, this );
02272 if( sizeForClientSize( fsarea.size(), SizemodeAny, true ) != fsarea.size())
02273 return false;
02274 }
02275
02276 return !isSpecialWindow();
02277 }
02278
02279 bool Client::userCanSetFullScreen() const
02280 {
02281 if( fullscreen_mode == FullScreenHack )
02282 return false;
02283 if( !isFullScreenable( false ))
02284 return false;
02285
02286 TemporaryAssign< FullScreenMode > tmp( fullscreen_mode, FullScreenNone );
02287 return isNormalWindow() && isMaximizable();
02288 }
02289
02290 void Client::setFullScreen( bool set, bool user )
02291 {
02292 if( !isFullScreen() && !set )
02293 return;
02294 if( fullscreen_mode == FullScreenHack )
02295 return;
02296 if( user && !userCanSetFullScreen())
02297 return;
02298 set = rules()->checkFullScreen( set );
02299 setShade( ShadeNone );
02300 bool was_fs = isFullScreen();
02301 if( !was_fs )
02302 geom_fs_restore = geometry();
02303 fullscreen_mode = set ? FullScreenNormal : FullScreenNone;
02304 if( was_fs == isFullScreen())
02305 return;
02306 StackingUpdatesBlocker blocker1( workspace());
02307 GeometryUpdatesBlocker blocker2( this );
02308 workspace()->updateClientLayer( this );
02309 info->setState( isFullScreen() ? NET::FullScreen : 0, NET::FullScreen );
02310 updateDecoration( false, false );
02311 if( isFullScreen())
02312 if( info->fullscreenMonitors().isSet())
02313 setGeometry( fullscreenMonitorsArea( info->fullscreenMonitors()));
02314 else
02315 setGeometry( workspace()->clientArea( FullScreenArea, this ));
02316 else
02317 {
02318 if( !geom_fs_restore.isNull())
02319 setGeometry( QRect( geom_fs_restore.topLeft(), adjustedSize( geom_fs_restore.size())));
02320
02321 else
02322 {
02323 setGeometry( workspace()->clientArea( MaximizeArea, this ));
02324 }
02325 }
02326 updateWindowRules();
02327 workspace()->checkUnredirect();
02328 }
02329
02330
02331 void Client::updateFullscreenMonitors( NETFullscreenMonitors topology )
02332 {
02333 int nscreens = Kephal::ScreenUtils::numScreens();
02334
02335
02336
02337
02338
02339 if( topology.top >= nscreens ||
02340 topology.bottom >= nscreens ||
02341 topology.left >= nscreens ||
02342 topology.right >= nscreens )
02343 {
02344 kWarning( 1212 ) << "fullscreenMonitors update failed. request higher than number of screens.";
02345 return;
02346 }
02347
02348 info->setFullscreenMonitors( topology );
02349 if( isFullScreen())
02350 setGeometry( fullscreenMonitorsArea( topology ));
02351 }
02352
02353
02358 QRect Client::fullscreenMonitorsArea(NETFullscreenMonitors requestedTopology) const
02359 {
02360 QRect top, bottom, left, right, total;
02361
02362 top = Kephal::ScreenUtils::screenGeometry( requestedTopology.top );
02363 bottom = Kephal::ScreenUtils::screenGeometry(requestedTopology.bottom );
02364 left = Kephal::ScreenUtils::screenGeometry(requestedTopology.left );
02365 right = Kephal::ScreenUtils::screenGeometry(requestedTopology.right );
02366 total = top.united( bottom.united( left.united( right ) ) );
02367
02368
02369
02370
02371 return total;
02372 }
02373
02374
02375 int Client::checkFullScreenHack( const QRect& geom ) const
02376 {
02377
02378 if( noBorder() && app_noborder && isFullScreenable( true ))
02379 {
02380 if( geom.size() == workspace()->clientArea( FullArea, geom.center(), desktop()).size())
02381 return 2;
02382 if( geom.size() == workspace()->clientArea( ScreenArea, geom.center(), desktop()).size())
02383 return 1;
02384 }
02385 return 0;
02386 }
02387
02388 void Client::updateFullScreenHack( const QRect& geom )
02389 {
02390 int type = checkFullScreenHack( geom );
02391 if( fullscreen_mode == FullScreenNone && type != 0 )
02392 {
02393 fullscreen_mode = FullScreenHack;
02394 updateDecoration( false, false );
02395 QRect geom;
02396 if( rules()->checkStrictGeometry( false ))
02397 {
02398 geom = type == 2
02399 ? workspace()->clientArea( FullArea, geom.center(), desktop())
02400 : workspace()->clientArea( ScreenArea, geom.center(), desktop());
02401 }
02402 else
02403 geom = workspace()->clientArea( FullScreenArea, geom.center(), desktop());
02404 setGeometry( geom );
02405 }
02406 else if( fullscreen_mode == FullScreenHack && type == 0 )
02407 {
02408 fullscreen_mode = FullScreenNone;
02409 updateDecoration( false, false );
02410
02411 }
02412 StackingUpdatesBlocker blocker( workspace());
02413 workspace()->updateClientLayer( this );
02414 }
02415
02416 static QRect* visible_bound = 0;
02417 static GeometryTip* geometryTip = 0;
02418
02419 void Client::drawbound( const QRect& geom )
02420 {
02421 assert( visible_bound == NULL );
02422 visible_bound = new QRect( geom );
02423 doDrawbound( *visible_bound, false );
02424 }
02425
02426 void Client::clearbound()
02427 {
02428 if( visible_bound == NULL )
02429 return;
02430 doDrawbound( *visible_bound, true );
02431 delete visible_bound;
02432 visible_bound = 0;
02433 }
02434
02435 void Client::doDrawbound( const QRect& geom, bool clear )
02436 {
02437 if( decoration != NULL && decoration->drawbound( geom, clear ))
02438 return;
02439 XGCValues xgc;
02440 xgc.function = GXxor;
02441 xgc.foreground = WhitePixel( display(), DefaultScreen( display()));
02442 xgc.line_width = 5;
02443 xgc.subwindow_mode = IncludeInferiors;
02444 GC gc = XCreateGC( display(), DefaultRootWindow( display()),
02445 GCFunction | GCForeground | GCLineWidth | GCSubwindowMode, &xgc );
02446
02447
02448 QRect g = geom;
02449 if( g.width() > 5 )
02450 {
02451 g.setLeft( g.left() + 2 );
02452 g.setRight( g.right() - 2 );
02453 }
02454 if( g.height() > 5 )
02455 {
02456 g.setTop( g.top() + 2 );
02457 g.setBottom( g.bottom() - 2 );
02458 }
02459 XDrawRectangle( display(), DefaultRootWindow( display()), gc, g.x(), g.y(), g.width(), g.height());
02460 XFreeGC( display(), gc );
02461 }
02462
02463 void Client::positionGeometryTip()
02464 {
02465 assert( isMove() || isResize());
02466
02467 if (options->showGeometryTip())
02468 {
02469 if( !geometryTip )
02470 {
02471 bool save_under = ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
02472 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque );
02473 geometryTip = new GeometryTip( &xSizeHint, save_under );
02474 }
02475 QRect wgeom( moveResizeGeom );
02476 wgeom.setWidth( wgeom.width() - ( width() - clientSize().width()));
02477 wgeom.setHeight( wgeom.height() - ( height() - clientSize().height()));
02478 if( isShade())
02479 wgeom.setHeight( 0 );
02480 geometryTip->setGeometry( wgeom );
02481 if( !geometryTip->isVisible())
02482 geometryTip->show();
02483 geometryTip->raise();
02484 }
02485 }
02486
02487 class EatAllPaintEvents
02488 : public QObject
02489 {
02490 protected:
02491 virtual bool eventFilter( QObject* o, QEvent* e )
02492 { return e->type() == QEvent::Paint && o != geometryTip; }
02493 };
02494
02495 static EatAllPaintEvents* eater = 0;
02496
02497 bool Client::startMoveResize()
02498 {
02499 assert( !moveResizeMode );
02500 assert( QWidget::keyboardGrabber() == NULL );
02501 assert( QWidget::mouseGrabber() == NULL );
02502 stopDelayedMoveResize();
02503 if( QApplication::activePopupWidget() != NULL )
02504 return false;
02505 bool has_grab = false;
02506
02507
02508
02509 XSetWindowAttributes attrs;
02510 QRect r = workspace()->clientArea( FullArea, this );
02511 move_resize_grab_window = XCreateWindow( display(), rootWindow(), r.x(), r.y(),
02512 r.width(), r.height(), 0, CopyFromParent, InputOnly, CopyFromParent, 0, &attrs );
02513 XMapRaised( display(), move_resize_grab_window );
02514 if( XGrabPointer( display(), move_resize_grab_window, False,
02515 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask,
02516 GrabModeAsync, GrabModeAsync, move_resize_grab_window, cursor.handle(), xTime() ) == Success )
02517 has_grab = true;
02518 if( grabXKeyboard( frameId()))
02519 has_grab = move_resize_has_keyboard_grab = true;
02520 if( !has_grab )
02521 {
02522 XDestroyWindow( display(), move_resize_grab_window );
02523 move_resize_grab_window = None;
02524 return false;
02525 }
02526 if ( maximizeMode() != MaximizeRestore )
02527 resetMaximize();
02528 moveResizeMode = true;
02529 workspace()->setClientIsMoving(this);
02530 initialMoveResizeGeom = moveResizeGeom = geometry();
02531 checkUnrestrictedMoveResize();
02532 if ( ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
02533 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque ) )
02534 {
02535 grabXServer();
02536 kapp->sendPostedEvents();
02537
02538
02539
02540
02541
02542 eater = new EatAllPaintEvents;
02543
02544 }
02545 Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart );
02546 if( effects )
02547 static_cast<EffectsHandlerImpl*>(effects)->windowUserMovedResized( effectWindow(), true, false );
02548 if( options->electricBorders() == Options::ElectricMoveOnly )
02549 workspace()->reserveElectricBorderSwitching( true );
02550 return true;
02551 }
02552
02553 void Client::finishMoveResize( bool cancel )
02554 {
02555 leaveMoveResize();
02556 if( cancel )
02557 setGeometry( initialMoveResizeGeom );
02558 else
02559 setGeometry( moveResizeGeom );
02560 checkMaximizeGeometry();
02561
02562 Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd );
02563 if( effects )
02564 static_cast<EffectsHandlerImpl*>(effects)->windowUserMovedResized( effectWindow(), false, true );
02565 }
02566
02567 void Client::leaveMoveResize()
02568 {
02569 clearbound();
02570 if (geometryTip)
02571 {
02572 geometryTip->hide();
02573 delete geometryTip;
02574 geometryTip = NULL;
02575 }
02576 if ( ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
02577 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque ) )
02578 ungrabXServer();
02579 if( move_resize_has_keyboard_grab )
02580 ungrabXKeyboard();
02581 move_resize_has_keyboard_grab = false;
02582 XUngrabPointer( display(), xTime() );
02583 XDestroyWindow( display(), move_resize_grab_window );
02584 move_resize_grab_window = None;
02585 workspace()->setClientIsMoving(0);
02586 if( move_faked_activity )
02587 workspace()->unfakeActivity( this );
02588 move_faked_activity = false;
02589 moveResizeMode = false;
02590 delete eater;
02591 eater = 0;
02592 delete sync_timeout;
02593 sync_timeout = NULL;
02594 if( options->electricBorders() == Options::ElectricMoveOnly )
02595 workspace()->reserveElectricBorderSwitching( false );
02596 }
02597
02598
02599
02600
02601
02602 void Client::checkUnrestrictedMoveResize()
02603 {
02604 if( unrestrictedMoveResize )
02605 return;
02606 QRect desktopArea = workspace()->clientArea( WorkArea, moveResizeGeom.center(), desktop());
02607 int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
02608
02609
02610 left_marge = qMin( 100 + border_right, moveResizeGeom.width());
02611 right_marge = qMin( 100 + border_left, moveResizeGeom.width());
02612
02613 titlebar_marge = initialMoveResizeGeom.height();
02614 top_marge = border_bottom;
02615 bottom_marge = border_top;
02616 if( isResize())
02617 {
02618 if( moveResizeGeom.bottom() < desktopArea.top() + top_marge )
02619 unrestrictedMoveResize = true;
02620 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
02621 unrestrictedMoveResize = true;
02622 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
02623 unrestrictedMoveResize = true;
02624 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
02625 unrestrictedMoveResize = true;
02626 if( !unrestrictedMoveResize && moveResizeGeom.top() < desktopArea.top() )
02627 unrestrictedMoveResize = true;
02628 }
02629 if( isMove())
02630 {
02631 if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 )
02632 unrestrictedMoveResize = true;
02633
02634 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
02635 unrestrictedMoveResize = true;
02636 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
02637 unrestrictedMoveResize = true;
02638 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
02639 unrestrictedMoveResize = true;
02640 }
02641 }
02642
02643
02644
02645
02646 void Client::startDelayedMoveResize()
02647 {
02648 delete delayedMoveResizeTimer;
02649 delayedMoveResizeTimer = new QTimer( this );
02650 connect( delayedMoveResizeTimer, SIGNAL( timeout()), this, SLOT( delayedMoveResize()));
02651 delayedMoveResizeTimer->setSingleShot( true );
02652 delayedMoveResizeTimer->start( QApplication::doubleClickInterval());
02653 }
02654
02655 void Client::stopDelayedMoveResize()
02656 {
02657 delete delayedMoveResizeTimer;
02658 delayedMoveResizeTimer = NULL;
02659 }
02660
02661 void Client::delayedMoveResize()
02662 {
02663 assert( buttonDown );
02664 if( !startMoveResize())
02665 buttonDown = false;
02666 updateCursor();
02667 stopDelayedMoveResize();
02668 }
02669
02670 void Client::handleMoveResize( int x, int y, int x_root, int y_root )
02671 {
02672 if(( mode == PositionCenter && !isMovableAcrossScreens() )
02673 || ( mode != PositionCenter && ( isShade() || !isResizable())))
02674 return;
02675
02676 if ( !moveResizeMode )
02677 {
02678 QPoint p( QPoint( x, y ) - moveOffset );
02679 if (p.manhattanLength() >= 6)
02680 {
02681 if( !startMoveResize())
02682 {
02683 buttonDown = false;
02684 updateCursor();
02685 return;
02686 }
02687 updateCursor();
02688 }
02689 else
02690 return;
02691 }
02692
02693
02694 if ( mode != PositionCenter && shade_mode != ShadeNone )
02695 setShade( ShadeNone );
02696
02697 QPoint globalPos( x_root, y_root );
02698
02699
02700 QPoint topleft = globalPos - moveOffset;
02701 QPoint bottomright = globalPos + invertedMoveOffset;
02702 QRect previousMoveResizeGeom = moveResizeGeom;
02703
02704
02705
02706
02707
02708 QRect desktopArea = workspace()->clientArea( WorkArea, globalPos, desktop());
02709 int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
02710 if( unrestrictedMoveResize )
02711 left_marge = right_marge = top_marge = bottom_marge = titlebar_marge = 5;
02712 else
02713 {
02714
02715 left_marge = qMin( 100 + border_right, moveResizeGeom.width());
02716 right_marge = qMin( 100 + border_left, moveResizeGeom.width());
02717
02718 titlebar_marge = initialMoveResizeGeom.height();
02719 top_marge = border_bottom;
02720 bottom_marge = border_top;
02721 }
02722
02723 bool update = false;
02724 if( isResize())
02725 {
02726
02727 QRect orig = initialMoveResizeGeom;
02728 Sizemode sizemode = SizemodeAny;
02729 switch ( mode )
02730 {
02731 case PositionTopLeft:
02732 moveResizeGeom = QRect( topleft, orig.bottomRight() ) ;
02733 break;
02734 case PositionBottomRight:
02735 moveResizeGeom = QRect( orig.topLeft(), bottomright ) ;
02736 break;
02737 case PositionBottomLeft:
02738 moveResizeGeom = QRect( QPoint( topleft.x(), orig.y() ), QPoint( orig.right(), bottomright.y()) ) ;
02739 break;
02740 case PositionTopRight:
02741 moveResizeGeom = QRect( QPoint( orig.x(), topleft.y() ), QPoint( bottomright.x(), orig.bottom()) ) ;
02742 break;
02743 case PositionTop:
02744 moveResizeGeom = QRect( QPoint( orig.left(), topleft.y() ), orig.bottomRight() ) ;
02745 sizemode = SizemodeFixedH;
02746 break;
02747 case PositionBottom:
02748 moveResizeGeom = QRect( orig.topLeft(), QPoint( orig.right(), bottomright.y() ) ) ;
02749 sizemode = SizemodeFixedH;
02750 break;
02751 case PositionLeft:
02752 moveResizeGeom = QRect( QPoint( topleft.x(), orig.top() ), orig.bottomRight() ) ;
02753 sizemode = SizemodeFixedW;
02754 break;
02755 case PositionRight:
02756 moveResizeGeom = QRect( orig.topLeft(), QPoint( bottomright.x(), orig.bottom() ) ) ;
02757 sizemode = SizemodeFixedW;
02758 break;
02759 case PositionCenter:
02760 default:
02761 abort();
02762 break;
02763 }
02764
02765
02766 moveResizeGeom = workspace()->adjustClientSize( this, moveResizeGeom, mode );
02767
02768
02769 if( moveResizeGeom.bottom() < desktopArea.top() + top_marge )
02770 moveResizeGeom.setBottom( desktopArea.top() + top_marge );
02771 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
02772 moveResizeGeom.setTop( desktopArea.bottom() - bottom_marge );
02773 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
02774 moveResizeGeom.setRight( desktopArea.left() + left_marge );
02775 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
02776 moveResizeGeom.setLeft(desktopArea.right() - right_marge );
02777 if( !unrestrictedMoveResize && moveResizeGeom.top() < desktopArea.top() )
02778 moveResizeGeom.setTop( desktopArea.top());
02779
02780 QSize size = adjustedSize( moveResizeGeom.size(), sizemode );
02781
02782 topleft = QPoint( moveResizeGeom.right() - size.width() + 1, moveResizeGeom.bottom() - size.height() + 1 );
02783 bottomright = QPoint( moveResizeGeom.left() + size.width() - 1, moveResizeGeom.top() + size.height() - 1 );
02784 orig = moveResizeGeom;
02785 switch ( mode )
02786 {
02787 case PositionTopLeft:
02788 moveResizeGeom = QRect( topleft, orig.bottomRight() ) ;
02789 break;
02790 case PositionBottomRight:
02791 moveResizeGeom = QRect( orig.topLeft(), bottomright ) ;
02792 break;
02793 case PositionBottomLeft:
02794 moveResizeGeom = QRect( QPoint( topleft.x(), orig.y() ), QPoint( orig.right(), bottomright.y()) ) ;
02795 break;
02796 case PositionTopRight:
02797 moveResizeGeom = QRect( QPoint( orig.x(), topleft.y() ), QPoint( bottomright.x(), orig.bottom()) ) ;
02798 break;
02799
02800
02801
02802 case PositionTop:
02803 moveResizeGeom = QRect( QPoint( orig.left(), topleft.y() ), QPoint( bottomright.x(), orig.bottom()) ) ;
02804 break;
02805 case PositionBottom:
02806 moveResizeGeom = QRect( orig.topLeft(), QPoint( bottomright.x(), bottomright.y() ) ) ;
02807 break;
02808 case PositionLeft:
02809 moveResizeGeom = QRect( QPoint( topleft.x(), orig.top() ), QPoint( orig.right(), bottomright.y()));
02810 break;
02811 case PositionRight:
02812 moveResizeGeom = QRect( orig.topLeft(), QPoint( bottomright.x(), bottomright.y() ) ) ;
02813 break;
02814 case PositionCenter:
02815 default:
02816 abort();
02817 break;
02818 }
02819 if( moveResizeGeom.size() != previousMoveResizeGeom.size())
02820 update = true;
02821 }
02822 else if( isMove())
02823 {
02824 assert( mode == PositionCenter );
02825 if( !isMovable() )
02826 {
02827 int screen = workspace()->screenNumber( globalPos );
02828 moveResizeGeom = workspace()->clientArea( MaximizeArea, screen, 0 );
02829 }
02830 else
02831 {
02832
02833 moveResizeGeom.moveTopLeft( topleft );
02834 moveResizeGeom.moveTopLeft( workspace()->adjustClientPosition( this, moveResizeGeom.topLeft(),
02835 unrestrictedMoveResize ));
02836
02837 if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 )
02838 moveResizeGeom.moveBottom( desktopArea.top() + titlebar_marge - 1 );
02839
02840 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
02841 moveResizeGeom.moveTop( desktopArea.bottom() - bottom_marge );
02842 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
02843 moveResizeGeom.moveRight( desktopArea.left() + left_marge );
02844 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
02845 moveResizeGeom.moveLeft(desktopArea.right() - right_marge );
02846 }
02847 if( moveResizeGeom.topLeft() != previousMoveResizeGeom.topLeft())
02848 update = true;
02849 }
02850 else
02851 abort();
02852
02853 if( isResize())
02854 {
02855 if( sync_timeout != NULL )
02856 {
02857 sync_resize_pending = true;
02858 return;
02859 }
02860 }
02861
02862 if( update )
02863 performMoveResize();
02864 if ( isMove() )
02865 workspace()->checkElectricBorder(globalPos, xTime());
02866 }
02867
02868 void Client::performMoveResize()
02869 {
02870 #ifdef HAVE_XSYNC
02871 if( isResize() && sync_counter != None )
02872 {
02873 sync_timeout = new QTimer( this );
02874 connect( sync_timeout, SIGNAL( timeout()), SLOT( syncTimeout()));
02875 sync_timeout->setSingleShot( true );
02876 sync_timeout->start( 500 );
02877 sendSyncRequest();
02878 }
02879 #endif
02880 sync_resize_pending = false;
02881 if( rules()->checkMoveResizeMode
02882 ( isResize() ? options->resizeMode : options->moveMode ) == Options::Opaque )
02883 {
02884 setGeometry( moveResizeGeom );
02885 positionGeometryTip();
02886 }
02887 else if( rules()->checkMoveResizeMode
02888 ( isResize() ? options->resizeMode : options->moveMode ) == Options::Transparent )
02889 {
02890 clearbound();
02891 positionGeometryTip();
02892 drawbound( moveResizeGeom );
02893 }
02894 if( effects )
02895 static_cast<EffectsHandlerImpl*>(effects)->windowUserMovedResized( effectWindow(), false, false );
02896 }
02897
02898 void Client::syncTimeout()
02899 {
02900 sync_timeout->deleteLater();
02901 sync_timeout = NULL;
02902 if( sync_resize_pending )
02903 performMoveResize();
02904 }
02905
02906 }