00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "client.h"
00020 #include "workspace.h"
00021
00022 #include <kapplication.h>
00023 #include <kglobal.h>
00024 #include <qpainter.h>
00025 #include <kwin.h>
00026
00027 #include "placement.h"
00028 #include "notifications.h"
00029 #include "geometrytip.h"
00030 #include "rules.h"
00031
00032 extern Time qt_x_time;
00033
00034 namespace KWinInternal
00035 {
00036
00037
00038
00039
00040
00044 void Workspace::desktopResized()
00045 {
00046 updateClientArea();
00047 checkElectricBorders( true );
00048 }
00049
00062 void Workspace::updateClientArea( bool force )
00063 {
00064 QDesktopWidget *desktopwidget = KApplication::desktop();
00065 int nscreens = desktopwidget -> numScreens ();
00066
00067 QRect* new_wareas = new QRect[ numberOfDesktops() + 1 ];
00068 QRect** new_sareas = new QRect*[ numberOfDesktops() + 1];
00069 QRect* screens = new QRect [ nscreens ];
00070 QRect desktopArea = desktopwidget -> geometry ();
00071 for( int iS = 0;
00072 iS < nscreens;
00073 iS ++ )
00074 {
00075 screens [iS] = desktopwidget -> screenGeometry (iS);
00076 }
00077 for( int i = 1;
00078 i <= numberOfDesktops();
00079 ++i )
00080 {
00081 new_wareas[ i ] = desktopArea;
00082 new_sareas[ i ] = new QRect [ nscreens ];
00083 for( int iS = 0;
00084 iS < nscreens;
00085 iS ++ )
00086 new_sareas[ i ][ iS ] = screens[ iS ];
00087 }
00088 for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
00089 {
00090 QRect r = (*it)->adjustedClientArea( desktopArea, desktopArea );
00091 if( r == desktopArea )
00092 continue;
00093 if( (*it)->isOnAllDesktops())
00094 for( int i = 1;
00095 i <= numberOfDesktops();
00096 ++i )
00097 {
00098 new_wareas[ i ] = new_wareas[ i ].intersect( r );
00099 for( int iS = 0;
00100 iS < nscreens;
00101 iS ++ )
00102 new_sareas[ i ][ iS ] =
00103 new_sareas[ i ][ iS ].intersect(
00104 (*it)->adjustedClientArea( desktopArea, screens[ iS ] )
00105 );
00106 }
00107 else
00108 {
00109 new_wareas[ (*it)->desktop() ] = new_wareas[ (*it)->desktop() ].intersect( r );
00110 for( int iS = 0;
00111 iS < nscreens;
00112 iS ++ )
00113 {
00114
00115 new_sareas[ (*it)->desktop() ][ iS ] =
00116 new_sareas[ (*it)->desktop() ][ iS ].intersect(
00117 (*it)->adjustedClientArea( desktopArea, screens[ iS ] )
00118 );
00119 }
00120 }
00121 }
00122 #if 0
00123 for( int i = 1;
00124 i <= numberOfDesktops();
00125 ++i )
00126 {
00127 for( int iS = 0;
00128 iS < nscreens;
00129 iS ++ )
00130 kdDebug () << "new_sarea: " << new_sareas[ i ][ iS ] << endl;
00131 }
00132 #endif
00133
00134 if( topmenu_space != NULL )
00135 {
00136 QRect topmenu_area = desktopArea;
00137 topmenu_area.setTop( topMenuHeight());
00138 for( int i = 1;
00139 i <= numberOfDesktops();
00140 ++i )
00141 new_wareas[ i ] = new_wareas[ i ].intersect( topmenu_area );
00142 }
00143
00144 bool changed = force;
00145
00146 if (! screenarea)
00147 changed = true;
00148
00149 for( int i = 1;
00150 !changed && i <= numberOfDesktops();
00151 ++i )
00152 {
00153 if( workarea[ i ] != new_wareas[ i ] )
00154 changed = true;
00155 for( int iS = 0;
00156 iS < nscreens;
00157 iS ++ )
00158 if (new_sareas[ i ][ iS ] != screenarea [ i ][ iS ])
00159 changed = true;
00160 }
00161
00162 if ( changed )
00163 {
00164 delete[] workarea;
00165 workarea = new_wareas;
00166 new_wareas = NULL;
00167 delete[] screenarea;
00168 screenarea = new_sareas;
00169 new_sareas = NULL;
00170 NETRect r;
00171 for( int i = 1; i <= numberOfDesktops(); i++)
00172 {
00173 r.pos.x = workarea[ i ].x();
00174 r.pos.y = workarea[ i ].y();
00175 r.size.width = workarea[ i ].width();
00176 r.size.height = workarea[ i ].height();
00177 rootInfo->setWorkArea( i, r );
00178 }
00179
00180 updateTopMenuGeometry();
00181 for( ClientList::ConstIterator it = clients.begin();
00182 it != clients.end();
00183 ++it)
00184 (*it)->checkWorkspacePosition();
00185 }
00186 delete[] screens;
00187 delete[] new_sareas;
00188 delete[] new_wareas;
00189 }
00190
00191 void Workspace::updateClientArea()
00192 {
00193 updateClientArea( false );
00194 }
00195
00196
00204 QRect Workspace::clientArea( clientAreaOption opt, const QPoint& p, int desktop ) const
00205 {
00206 if( desktop == NETWinInfo::OnAllDesktops || desktop == 0 )
00207 desktop = currentDesktop();
00208 QDesktopWidget *desktopwidget = KApplication::desktop();
00209 int screen = desktopwidget->screenNumber( p );
00210 if( screen < 0 )
00211 screen = desktopwidget->primaryScreen();
00212 QRect sarea = screenarea
00213 ? screenarea[ desktop ][ screen ]
00214 : desktopwidget->screenGeometry( screen );
00215 QRect warea = workarea[ desktop ].isNull()
00216 ? QApplication::desktop()->geometry()
00217 : workarea[ desktop ];
00218 switch (opt)
00219 {
00220 case MaximizeArea:
00221 if (options->xineramaMaximizeEnabled)
00222 return sarea;
00223 else
00224 return warea;
00225 case MaximizeFullArea:
00226 if (options->xineramaMaximizeEnabled)
00227 return desktopwidget->screenGeometry( screen );
00228 else
00229 return desktopwidget->geometry();
00230 case FullScreenArea:
00231 if (options->xineramaFullscreenEnabled)
00232 return desktopwidget->screenGeometry( screen );
00233 else
00234 return desktopwidget->geometry();
00235 case PlacementArea:
00236 if (options->xineramaPlacementEnabled)
00237 return sarea;
00238 else
00239 return warea;
00240 case MovementArea:
00241 if (options->xineramaMovementEnabled)
00242 return desktopwidget->screenGeometry( screen );
00243 else
00244 return desktopwidget->geometry();
00245 case WorkArea:
00246 return warea;
00247 case FullArea:
00248 return desktopwidget->geometry();
00249 case ScreenArea:
00250 return sarea;
00251 }
00252 assert( false );
00253 return QRect();
00254 }
00255
00256 QRect Workspace::clientArea( clientAreaOption opt, const Client* c ) const
00257 {
00258 return clientArea( opt, c->geometry().center(), c->desktop());
00259 }
00260
00266 QPoint Workspace::adjustClientPosition( Client* c, QPoint pos )
00267 {
00268
00269
00270
00271 if (options->windowSnapZone || options->borderSnapZone )
00272 {
00273 const bool sOWO=options->snapOnlyWhenOverlapping;
00274 const QRect maxRect = clientArea(MovementArea, pos+c->rect().center(), c->desktop());
00275 const int xmin = maxRect.left();
00276 const int xmax = maxRect.right()+1;
00277 const int ymin = maxRect.top();
00278 const int ymax = maxRect.bottom()+1;
00279
00280 const int cx(pos.x());
00281 const int cy(pos.y());
00282 const int cw(c->width());
00283 const int ch(c->height());
00284 const int rx(cx+cw);
00285 const int ry(cy+ch);
00286
00287 int nx(cx), ny(cy);
00288 int deltaX(xmax);
00289 int deltaY(ymax);
00290
00291 int lx, ly, lrx, lry;
00292
00293
00294 int snap = options->borderSnapZone;
00295 if (snap)
00296 {
00297 if ((sOWO?(cx<xmin):true) && (QABS(xmin-cx)<snap))
00298 {
00299 deltaX = xmin-cx;
00300 nx = xmin;
00301 }
00302 if ((sOWO?(rx>xmax):true) && (QABS(rx-xmax)<snap) && (QABS(xmax-rx) < deltaX))
00303 {
00304 deltaX = rx-xmax;
00305 nx = xmax - cw;
00306 }
00307
00308 if ((sOWO?(cy<ymin):true) && (QABS(ymin-cy)<snap))
00309 {
00310 deltaY = ymin-cy;
00311 ny = ymin;
00312 }
00313 if ((sOWO?(ry>ymax):true) && (QABS(ry-ymax)<snap) && (QABS(ymax-ry) < deltaY))
00314 {
00315 deltaY =ry-ymax;
00316 ny = ymax - ch;
00317 }
00318 }
00319
00320
00321 snap = options->windowSnapZone;
00322 if (snap)
00323 {
00324 QValueList<Client *>::ConstIterator l;
00325 for (l = clients.begin();l != clients.end();++l )
00326 {
00327 if ((*l)->isOnDesktop(currentDesktop()) &&
00328 !(*l)->isMinimized()
00329 && (*l) != c )
00330 {
00331 lx = (*l)->x();
00332 ly = (*l)->y();
00333 lrx = lx + (*l)->width();
00334 lry = ly + (*l)->height();
00335
00336 if ( (( cy <= lry ) && ( cy >= ly )) ||
00337 (( ry >= ly ) && ( ry <= lry )) ||
00338 (( cy <= ly ) && ( ry >= lry )) )
00339 {
00340 if ((sOWO?(cx<lrx):true) && (QABS(lrx-cx)<snap) && ( QABS(lrx -cx) < deltaX) )
00341 {
00342 deltaX = QABS( lrx - cx );
00343 nx = lrx;
00344 }
00345 if ((sOWO?(rx>lx):true) && (QABS(rx-lx)<snap) && ( QABS( rx - lx )<deltaX) )
00346 {
00347 deltaX = QABS(rx - lx);
00348 nx = lx - cw;
00349 }
00350 }
00351
00352 if ( (( cx <= lrx ) && ( cx >= lx )) ||
00353 (( rx >= lx ) && ( rx <= lrx )) ||
00354 (( cx <= lx ) && ( rx >= lrx )) )
00355 {
00356 if ((sOWO?(cy<lry):true) && (QABS(lry-cy)<snap) && (QABS( lry -cy ) < deltaY))
00357 {
00358 deltaY = QABS( lry - cy );
00359 ny = lry;
00360 }
00361
00362 if ((sOWO?(ry>ly):true) && (QABS(ry-ly)<snap) && (QABS( ry - ly ) < deltaY ))
00363 {
00364 deltaY = QABS( ry - ly );
00365 ny = ly - ch;
00366 }
00367 }
00368 }
00369 }
00370 }
00371 pos = QPoint(nx, ny);
00372 }
00373 return pos;
00374 }
00375
00376 QRect Workspace::adjustClientSize( Client* c, QRect moveResizeGeom, int mode )
00377 {
00378
00379
00380
00381 if ( options->windowSnapZone || options->borderSnapZone )
00382 {
00383 const bool sOWO=options->snapOnlyWhenOverlapping;
00384
00385 const QRect maxRect = clientArea(MovementArea, c->rect().center(), c->desktop());
00386 const int xmin = maxRect.left();
00387 const int xmax = maxRect.right();
00388 const int ymin = maxRect.top();
00389 const int ymax = maxRect.bottom();
00390
00391 const int cx(moveResizeGeom.left());
00392 const int cy(moveResizeGeom.top());
00393 const int rx(moveResizeGeom.right());
00394 const int ry(moveResizeGeom.bottom());
00395
00396 int newcx(cx), newcy(cy);
00397 int newrx(rx), newry(ry);
00398 int deltaX(xmax);
00399 int deltaY(ymax);
00400
00401 int lx, ly, lrx, lry;
00402
00403
00404 int snap = options->borderSnapZone;
00405 if (snap)
00406 {
00407 deltaX = int(snap);
00408 deltaY = int(snap);
00409
00410 #define SNAP_BORDER_TOP \
00411 if ((sOWO?(newcy<ymin):true) && (QABS(ymin-newcy)<deltaY)) \
00412 { \
00413 deltaY = QABS(ymin-newcy); \
00414 newcy = ymin; \
00415 }
00416
00417 #define SNAP_BORDER_BOTTOM \
00418 if ((sOWO?(newry>ymax):true) && (QABS(ymax-newry)<deltaY)) \
00419 { \
00420 deltaY = QABS(ymax-newcy); \
00421 newry = ymax; \
00422 }
00423
00424 #define SNAP_BORDER_LEFT \
00425 if ((sOWO?(newcx<xmin):true) && (QABS(xmin-newcx)<deltaX)) \
00426 { \
00427 deltaX = QABS(xmin-newcx); \
00428 newcx = xmin; \
00429 }
00430
00431 #define SNAP_BORDER_RIGHT \
00432 if ((sOWO?(newrx>xmax):true) && (QABS(xmax-newrx)<deltaX)) \
00433 { \
00434 deltaX = QABS(xmax-newrx); \
00435 newrx = xmax; \
00436 }
00437 switch ( mode )
00438 {
00439 case PositionBottomRight:
00440 SNAP_BORDER_BOTTOM
00441 SNAP_BORDER_RIGHT
00442 break;
00443 case PositionRight:
00444 SNAP_BORDER_RIGHT
00445 break;
00446 case PositionBottom:
00447 SNAP_BORDER_BOTTOM
00448 break;
00449 case PositionTopLeft:
00450 SNAP_BORDER_TOP
00451 SNAP_BORDER_LEFT
00452 break;
00453 case PositionLeft:
00454 SNAP_BORDER_LEFT
00455 break;
00456 case PositionTop:
00457 SNAP_BORDER_TOP
00458 break;
00459 case PositionTopRight:
00460 SNAP_BORDER_TOP
00461 SNAP_BORDER_RIGHT
00462 break;
00463 case PositionBottomLeft:
00464 SNAP_BORDER_BOTTOM
00465 SNAP_BORDER_LEFT
00466 break;
00467 default:
00468 assert( false );
00469 break;
00470 }
00471
00472
00473 }
00474
00475
00476 snap = options->windowSnapZone;
00477 if (snap)
00478 {
00479 deltaX = int(snap);
00480 deltaY = int(snap);
00481 QValueList<Client *>::ConstIterator l;
00482 for (l = clients.begin();l != clients.end();++l )
00483 {
00484 if ((*l)->isOnDesktop(currentDesktop()) &&
00485 !(*l)->isMinimized()
00486 && (*l) != c )
00487 {
00488 lx = (*l)->x()-1;
00489 ly = (*l)->y()-1;
00490 lrx =(*l)->x() + (*l)->width();
00491 lry =(*l)->y() + (*l)->height();
00492
00493 #define WITHIN_HEIGHT ((( newcy <= lry ) && ( newcy >= ly )) || \
00494 (( newry >= ly ) && ( newry <= lry )) || \
00495 (( newcy <= ly ) && ( newry >= lry )) )
00496
00497 #define WITHIN_WIDTH ( (( cx <= lrx ) && ( cx >= lx )) || \
00498 (( rx >= lx ) && ( rx <= lrx )) || \
00499 (( cx <= lx ) && ( rx >= lrx )) )
00500
00501 #define SNAP_WINDOW_TOP if ( (sOWO?(newcy<lry):true) \
00502 && WITHIN_WIDTH \
00503 && (QABS( lry - newcy ) < deltaY) ) { \
00504 deltaY = QABS( lry - newcy ); \
00505 newcy=lry; \
00506 }
00507
00508 #define SNAP_WINDOW_BOTTOM if ( (sOWO?(newry>ly):true) \
00509 && WITHIN_WIDTH \
00510 && (QABS( ly - newry ) < deltaY) ) { \
00511 deltaY = QABS( ly - newry ); \
00512 newry=ly; \
00513 }
00514
00515 #define SNAP_WINDOW_LEFT if ( (sOWO?(newcx<lrx):true) \
00516 && WITHIN_HEIGHT \
00517 && (QABS( lrx - newcx ) < deltaX)) { \
00518 deltaX = QABS( lrx - newcx ); \
00519 newcx=lrx; \
00520 }
00521
00522 #define SNAP_WINDOW_RIGHT if ( (sOWO?(newrx>lx):true) \
00523 && WITHIN_HEIGHT \
00524 && (QABS( lx - newrx ) < deltaX)) \
00525 { \
00526 deltaX = QABS( lx - newrx ); \
00527 newrx=lx; \
00528 }
00529
00530 switch ( mode )
00531 {
00532 case PositionBottomRight:
00533 SNAP_WINDOW_BOTTOM
00534 SNAP_WINDOW_RIGHT
00535 break;
00536 case PositionRight:
00537 SNAP_WINDOW_RIGHT
00538 break;
00539 case PositionBottom:
00540 SNAP_WINDOW_BOTTOM
00541 break;
00542 case PositionTopLeft:
00543 SNAP_WINDOW_TOP
00544 SNAP_WINDOW_LEFT
00545 break;
00546 case PositionLeft:
00547 SNAP_WINDOW_LEFT
00548 break;
00549 case PositionTop:
00550 SNAP_WINDOW_TOP
00551 break;
00552 case PositionTopRight:
00553 SNAP_WINDOW_TOP
00554 SNAP_WINDOW_RIGHT
00555 break;
00556 case PositionBottomLeft:
00557 SNAP_WINDOW_BOTTOM
00558 SNAP_WINDOW_LEFT
00559 break;
00560 default:
00561 assert( false );
00562 break;
00563 }
00564 }
00565 }
00566 }
00567 moveResizeGeom = QRect(QPoint(newcx, newcy), QPoint(newrx, newry));
00568 }
00569 return moveResizeGeom;
00570 }
00571
00575 void Workspace::setClientIsMoving( Client *c )
00576 {
00577 Q_ASSERT(!c || !movingClient);
00578
00579 movingClient = c;
00580 if (movingClient)
00581 ++block_focus;
00582 else
00583 --block_focus;
00584 }
00585
00589 void Workspace::cascadeDesktop()
00590 {
00591
00592 Q_ASSERT( block_stacking_updates == 0 );
00593 ClientList::ConstIterator it(stackingOrder().begin());
00594 bool re_init_cascade_at_first_client = true;
00595 for (; it != stackingOrder().end(); ++it)
00596 {
00597 if((!(*it)->isOnDesktop(currentDesktop())) ||
00598 ((*it)->isMinimized()) ||
00599 ((*it)->isOnAllDesktops()) ||
00600 (!(*it)->isMovable()) )
00601 continue;
00602 initPositioning->placeCascaded(*it, QRect(), re_init_cascade_at_first_client);
00603
00604 if (re_init_cascade_at_first_client)
00605 re_init_cascade_at_first_client = false;
00606 }
00607 }
00608
00613 void Workspace::unclutterDesktop()
00614 {
00615 ClientList::Iterator it(clients.fromLast());
00616 for (; it != clients.end(); --it)
00617 {
00618 if((!(*it)->isOnDesktop(currentDesktop())) ||
00619 ((*it)->isMinimized()) ||
00620 ((*it)->isOnAllDesktops()) ||
00621 (!(*it)->isMovable()) )
00622 continue;
00623 initPositioning->placeSmart(*it, QRect());
00624 }
00625 }
00626
00627
00628 void Workspace::updateTopMenuGeometry( Client* c )
00629 {
00630 if( !managingTopMenus())
00631 return;
00632 if( c != NULL )
00633 {
00634 XEvent ev;
00635 ev.xclient.display = qt_xdisplay();
00636 ev.xclient.type = ClientMessage;
00637 ev.xclient.window = c->window();
00638 static Atom msg_type_atom = XInternAtom( qt_xdisplay(), "_KDE_TOPMENU_MINSIZE", False );
00639 ev.xclient.message_type = msg_type_atom;
00640 ev.xclient.format = 32;
00641 ev.xclient.data.l[0] = qt_x_time;
00642 ev.xclient.data.l[1] = topmenu_space->width();
00643 ev.xclient.data.l[2] = topmenu_space->height();
00644 ev.xclient.data.l[3] = 0;
00645 ev.xclient.data.l[4] = 0;
00646 XSendEvent( qt_xdisplay(), c->window(), False, NoEventMask, &ev );
00647 KWin::setStrut( c->window(), 0, 0, topmenu_height, 0 );
00648 c->checkWorkspacePosition();
00649 return;
00650 }
00651
00652 QRect area;
00653 area = clientArea( MaximizeFullArea, QPoint( 0, 0 ), 1 );
00654 area.setHeight( topMenuHeight());
00655 topmenu_space->setGeometry( area );
00656 for( ClientList::ConstIterator it = topmenus.begin();
00657 it != topmenus.end();
00658 ++it )
00659 updateTopMenuGeometry( *it );
00660 }
00661
00662
00663
00664
00665
00666
00667 void Client::keepInArea( const QRect& area )
00668 {
00669 if ( geometry().right() > area.right() && width() < area.width() )
00670 move( area.right() - width(), y() );
00671 if ( geometry().bottom() > area.bottom() && height() < area.height() )
00672 move( x(), area.bottom() - height() );
00673 if( !area.contains( geometry().topLeft() ))
00674 {
00675 int tx = x();
00676 int ty = y();
00677 if ( tx < area.x() )
00678 tx = area.x();
00679 if ( ty < area.y() )
00680 ty = area.y();
00681 move( tx, ty );
00682 }
00683 }
00684
00690
00691
00692 QRect Client::adjustedClientArea( const QRect &desktopArea, const QRect& area ) const
00693 {
00694 QRect r = area;
00695
00696 if( isTopMenu())
00697 return r;
00698 NETExtendedStrut str = strut();
00699 QRect stareaL = QRect(
00700 0,
00701 str . left_start,
00702 str . left_width,
00703 str . left_end - str . left_start + 1 );
00704 QRect stareaR = QRect (
00705 desktopArea . right () - str . right_width + 1,
00706 str . right_start,
00707 str . right_width,
00708 str . right_end - str . right_start + 1 );
00709 QRect stareaT = QRect (
00710 str . top_start,
00711 0,
00712 str . top_end - str . top_start + 1,
00713 str . top_width);
00714 QRect stareaB = QRect (
00715 str . bottom_start,
00716 desktopArea . bottom () - str . bottom_width + 1,
00717 str . bottom_end - str . bottom_start + 1,
00718 str . bottom_width);
00719
00720 NETExtendedStrut ext = info->extendedStrut();
00721 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
00722 && ( str.left_width != 0 || str.right_width != 0 || str.top_width != 0 || str.bottom_width != 0 )) {
00723
00724
00725
00726
00727
00728
00729
00730 if (stareaT.top() == geometry().top() && stareaT.bottom() == geometry().bottom()) {
00731 stareaT.setLeft(geometry().left());
00732 stareaT.setRight(geometry().right());
00733
00734 }
00735 if (stareaB.top() == geometry().top() && stareaB.bottom() == geometry().bottom()) {
00736 stareaB.setLeft(geometry().left());
00737 stareaB.setRight(geometry().right());
00738
00739 }
00740 if (stareaL.left() == geometry().left() && stareaL.right() == geometry().right()) {
00741 stareaL.setTop(geometry().top());
00742 stareaL.setBottom(geometry().bottom());
00743
00744 }
00745 if (stareaR.left() == geometry().left() && stareaR.right() == geometry().right()) {
00746 stareaR.setTop(geometry().top());
00747 stareaR.setBottom(geometry().bottom());
00748
00749 }
00750 }
00751 if (stareaL . intersects (area)) {
00752
00753 r . setLeft( stareaL . right() + 1 );
00754 }
00755 if (stareaR . intersects (area)) {
00756
00757 r . setRight( stareaR . left() - 1 );
00758 }
00759 if (stareaT . intersects (area)) {
00760
00761 r . setTop( stareaT . bottom() + 1 );
00762 }
00763 if (stareaB . intersects (area)) {
00764
00765 r . setBottom( stareaB . top() - 1 );
00766 }
00767 return r;
00768 }
00769
00770 NETExtendedStrut Client::strut() const
00771 {
00772 NETExtendedStrut ext = info->extendedStrut();
00773 NETStrut str = info->strut();
00774 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
00775 && ( str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0 ))
00776 {
00777
00778 if( str.left != 0 )
00779 {
00780 ext.left_width = str.left;
00781 ext.left_start = 0;
00782 ext.left_end = XDisplayHeight( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00783 }
00784 if( str.right != 0 )
00785 {
00786 ext.right_width = str.right;
00787 ext.right_start = 0;
00788 ext.right_end = XDisplayHeight( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00789 }
00790 if( str.top != 0 )
00791 {
00792 ext.top_width = str.top;
00793 ext.top_start = 0;
00794 ext.top_end = XDisplayWidth( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00795 }
00796 if( str.bottom != 0 )
00797 {
00798 ext.bottom_width = str.bottom;
00799 ext.bottom_start = 0;
00800 ext.bottom_end = XDisplayWidth( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00801 }
00802 }
00803 return ext;
00804 }
00805 bool Client::hasStrut() const
00806 {
00807 NETExtendedStrut ext = strut();
00808 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0 )
00809 {
00810 return false;
00811 }
00812 return true;
00813 }
00814
00815
00816
00817 void Client::updateWorkareaDiffs()
00818 {
00819 QRect area = workspace()->clientArea( WorkArea, this );
00820 QRect geom = geometry();
00821 workarea_diff_x = computeWorkareaDiff( geom.left(), geom.right(), area.left(), area.right());
00822 workarea_diff_y = computeWorkareaDiff( geom.top(), geom.bottom(), area.top(), area.bottom());
00823 }
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833 int Client::computeWorkareaDiff( int left, int right, int a_left, int a_right )
00834 {
00835 int left_diff = left - a_left;
00836 int right_diff = a_right - right;
00837 if( left_diff < 0 || right_diff < 0 )
00838 return INT_MIN;
00839 else
00840 {
00841
00842 int max_diff = ( a_right - a_left ) / 10;
00843 if( left_diff < right_diff )
00844 return left_diff < max_diff ? -left_diff - 1 : INT_MAX;
00845 else if( left_diff > right_diff )
00846 return right_diff < max_diff ? right_diff + 1 : INT_MAX;
00847 return INT_MAX;
00848 }
00849 }
00850
00851 void Client::checkWorkspacePosition()
00852 {
00853 if( maximizeMode() != MaximizeRestore )
00854
00855 changeMaximize( false, false, true );
00856
00857 if( isFullScreen())
00858 {
00859 QRect area = workspace()->clientArea( FullScreenArea, this );
00860 if( geometry() != area )
00861 setGeometry( area );
00862 return;
00863 }
00864 if( isDock())
00865 return;
00866 if( isOverride())
00867 return;
00868 if( isTopMenu())
00869 {
00870 if( workspace()->managingTopMenus())
00871 {
00872 QRect area;
00873 ClientList mainclients = mainClients();
00874 if( mainclients.count() == 1 )
00875 area = workspace()->clientArea( MaximizeFullArea, mainclients.first());
00876 else
00877 area = workspace()->clientArea( MaximizeFullArea, QPoint( 0, 0 ), desktop());
00878 area.setHeight( workspace()->topMenuHeight());
00879
00880 setGeometry( area );
00881 }
00882 return;
00883 }
00884
00885 if( !isShade())
00886 {
00887 int old_diff_x = workarea_diff_x;
00888 int old_diff_y = workarea_diff_y;
00889 updateWorkareaDiffs();
00890
00891
00892
00893
00894
00895
00896 if( workspace()->initializing())
00897 return;
00898
00899 QRect area = workspace()->clientArea( WorkArea, this );
00900 QRect new_geom = geometry();
00901 QRect tmp_rect_x( new_geom.left(), 0, new_geom.width(), 0 );
00902 QRect tmp_area_x( area.left(), 0, area.width(), 0 );
00903 checkDirection( workarea_diff_x, old_diff_x, tmp_rect_x, tmp_area_x );
00904
00905 QRect tmp_rect_y( new_geom.top(), 0, new_geom.height(), 0 );
00906 QRect tmp_area_y( area.top(), 0, area.height(), 0 );
00907 checkDirection( workarea_diff_y, old_diff_y, tmp_rect_y, tmp_area_y );
00908 new_geom = QRect( tmp_rect_x.left(), tmp_rect_y.left(), tmp_rect_x.width(), tmp_rect_y.width());
00909 QRect final_geom( new_geom.topLeft(), adjustedSize( new_geom.size()));
00910 if( final_geom != new_geom )
00911 {
00912 if( old_diff_x != INT_MAX && old_diff_x > 0 )
00913 final_geom.moveRight( area.right() - ( old_diff_x - 1 ));
00914 if( old_diff_y != INT_MAX && old_diff_y > 0 )
00915 final_geom.moveBottom( area.bottom() - ( old_diff_y - 1 ));
00916 }
00917 if( final_geom != geometry() )
00918 setGeometry( final_geom );
00919
00920 }
00921 }
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933 void Client::checkDirection( int new_diff, int old_diff, QRect& rect, const QRect& area )
00934 {
00935 if( old_diff != INT_MIN )
00936 {
00937 if( old_diff == INT_MAX )
00938 {
00939 if( new_diff == INT_MIN )
00940 {
00941 rect.setLeft( area.left());
00942 rect.setRight( area.right());
00943 }
00944 return;
00945 }
00946 if( isResizable())
00947 {
00948 if( rect.width() > area.width())
00949 rect.setWidth( area.width());
00950 if( rect.width() >= area.width() / 2 )
00951 {
00952 if( old_diff < 0 )
00953 rect.setLeft( area.left() + ( -old_diff - 1 ) );
00954 else
00955 rect.setRight( area.right() - ( old_diff - 1 ));
00956 }
00957 }
00958 if( isMovable())
00959 {
00960 if( old_diff < 0 )
00961 rect.moveLeft( area.left() + ( -old_diff - 1 ));
00962 else
00963 rect.moveRight( area.right() - ( old_diff - 1 ));
00964 }
00965
00966
00967
00968 if( isResizable())
00969 {
00970 if( old_diff < 0 )
00971 rect.setLeft( area.left() + ( -old_diff - 1 ) );
00972 else
00973 rect.setRight( area.right() - ( old_diff - 1 ));
00974 }
00975 }
00976 if( rect.right() < area.left() + 5 || rect.left() > area.right() - 5 )
00977 {
00978 if( isMovable())
00979 {
00980 if( rect.left() < area.left() + 5 )
00981 rect.moveRight( area.left() + 5 );
00982 if( rect.right() > area.right() - 5 )
00983 rect.moveLeft( area.right() - 5 );
00984 }
00985 }
00986 }
00987
00991 QSize Client::adjustedSize( const QSize& frame, Sizemode mode ) const
00992 {
00993
00994
00995 QSize wsize( frame.width() - ( border_left + border_right ),
00996 frame.height() - ( border_top + border_bottom ));
00997
00998 return sizeForClientSize( wsize, mode );
00999 }
01000
01009 QSize Client::sizeForClientSize( const QSize& wsize, Sizemode mode ) const
01010 {
01011 int w = wsize.width();
01012 int h = wsize.height();
01013 if (w<1) w = 1;
01014 if (h<1) h = 1;
01015
01016
01017
01018 QSize min_size = minSize();
01019 QSize max_size = maxSize();
01020 if( decoration != NULL )
01021 {
01022 QSize decominsize = decoration->minimumSize();
01023 QSize border_size( border_left + border_right, border_top + border_bottom );
01024 if( border_size.width() > decominsize.width())
01025 decominsize.setWidth( border_size.width());
01026 if( border_size.height() > decominsize.height())
01027 decominsize.setHeight( border_size.height());
01028 if( decominsize.width() > min_size.width())
01029 min_size.setWidth( decominsize.width());
01030 if( decominsize.height() > min_size.height())
01031 min_size.setHeight( decominsize.height());
01032 }
01033 w = QMIN( max_size.width(), w );
01034 h = QMIN( max_size.height(), h );
01035 w = QMAX( min_size.width(), w );
01036 h = QMAX( min_size.height(), h );
01037
01038 int w1 = w;
01039 int h1 = h;
01040 int width_inc = xSizeHint.width_inc;
01041 int height_inc = xSizeHint.height_inc;
01042 int basew_inc = xSizeHint.min_width;
01043 int baseh_inc = xSizeHint.min_height;
01044 w = int(( w - basew_inc ) / width_inc ) * width_inc + basew_inc;
01045 h = int(( h - baseh_inc ) / height_inc ) * height_inc + baseh_inc;
01046
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061 if( xSizeHint.flags & PAspect )
01062 {
01063 double min_aspect_w = xSizeHint.min_aspect.x;
01064 double min_aspect_h = xSizeHint.min_aspect.y;
01065 double max_aspect_w = xSizeHint.max_aspect.x;
01066 double max_aspect_h = xSizeHint.max_aspect.y;
01067 w -= xSizeHint.base_width;
01068 h -= xSizeHint.base_height;
01069 int max_width = max_size.width() - xSizeHint.base_width;
01070 int min_width = min_size.width() - xSizeHint.base_width;
01071 int max_height = max_size.height() - xSizeHint.base_height;
01072 int min_height = min_size.height() - xSizeHint.base_height;
01073 #define ASPECT_CHECK_GROW_W \
01074 if( min_aspect_w * h > min_aspect_h * w ) \
01075 { \
01076 int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
01077 if( w + delta <= max_width ) \
01078 w += delta; \
01079 }
01080 #define ASPECT_CHECK_SHRINK_H_GROW_W \
01081 if( min_aspect_w * h > min_aspect_h * w ) \
01082 { \
01083 int delta = int( h - w * min_aspect_h / min_aspect_w ) / height_inc * height_inc; \
01084 if( h - delta >= min_height ) \
01085 h -= delta; \
01086 else \
01087 { \
01088 int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
01089 if( w + delta <= max_width ) \
01090 w += delta; \
01091 } \
01092 }
01093 #define ASPECT_CHECK_GROW_H \
01094 if( max_aspect_w * h < max_aspect_h * w ) \
01095 { \
01096 int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
01097 if( h + delta <= max_height ) \
01098 h += delta; \
01099 }
01100 #define ASPECT_CHECK_SHRINK_W_GROW_H \
01101 if( max_aspect_w * h < max_aspect_h * w ) \
01102 { \
01103 int delta = int( w - max_aspect_w * h / max_aspect_h ) / width_inc * width_inc; \
01104 if( w - delta >= min_width ) \
01105 w -= delta; \
01106 else \
01107 { \
01108 int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
01109 if( h + delta <= max_height ) \
01110 h += delta; \
01111 } \
01112 }
01113 switch( mode )
01114 {
01115 case SizemodeAny:
01116 {
01117 ASPECT_CHECK_SHRINK_H_GROW_W
01118 ASPECT_CHECK_SHRINK_W_GROW_H
01119 ASPECT_CHECK_GROW_H
01120 ASPECT_CHECK_GROW_W
01121 break;
01122 }
01123 case SizemodeFixedW:
01124 {
01125
01126 ASPECT_CHECK_GROW_H
01127 ASPECT_CHECK_SHRINK_H_GROW_W
01128 ASPECT_CHECK_SHRINK_W_GROW_H
01129 ASPECT_CHECK_GROW_W
01130 break;
01131 }
01132 case SizemodeFixedH:
01133 {
01134 ASPECT_CHECK_GROW_W
01135 ASPECT_CHECK_SHRINK_W_GROW_H
01136 ASPECT_CHECK_SHRINK_H_GROW_W
01137 ASPECT_CHECK_GROW_H
01138 break;
01139 }
01140 case SizemodeMax:
01141 {
01142
01143 ASPECT_CHECK_SHRINK_H_GROW_W
01144 ASPECT_CHECK_SHRINK_W_GROW_H
01145 ASPECT_CHECK_GROW_W
01146 ASPECT_CHECK_GROW_H
01147 break;
01148 }
01149 case SizemodeShaded:
01150 break;
01151 }
01152 #undef ASPECT_CHECK_SHRINK_H_GROW_W
01153 #undef ASPECT_CHECK_SHRINK_W_GROW_H
01154 #undef ASPECT_CHECK_GROW_W
01155 #undef ASPECT_CHECK_GROW_H
01156 w += xSizeHint.base_width;
01157 h += xSizeHint.base_height;
01158 }
01159
01160 if( maximizeMode() & MaximizeHorizontal )
01161 w = w1;
01162 if( maximizeMode() & MaximizeVertical )
01163 h = h1;
01164
01165 w += border_left + border_right;
01166 h += border_top + border_bottom;
01167 QSize ret = rules()->checkSize( QSize( w, h ));
01168 if ( mode == SizemodeShaded && wsize.height() == 0 )
01169 ret.setHeight( border_top + border_bottom );
01170 return ret;
01171 }
01172
01176 void Client::getWmNormalHints()
01177 {
01178 long msize;
01179 if (XGetWMNormalHints(qt_xdisplay(), window(), &xSizeHint, &msize) == 0 )
01180 xSizeHint.flags = 0;
01181
01182
01183
01184
01185
01186 if( xSizeHint.flags & PBaseSize )
01187 {
01188 if( ! ( xSizeHint.flags & PMinSize ))
01189 {
01190 xSizeHint.flags |= PMinSize;
01191 xSizeHint.min_width = xSizeHint.base_width;
01192 xSizeHint.min_height = xSizeHint.base_height;
01193 }
01194 }
01195 else
01196 xSizeHint.base_width = xSizeHint.base_height = 0;
01197 if( ! ( xSizeHint.flags & PMinSize ))
01198 xSizeHint.min_width = xSizeHint.min_height = 0;
01199 if( ! ( xSizeHint.flags & PMaxSize ))
01200 xSizeHint.max_width = xSizeHint.max_height = INT_MAX;
01201 else
01202 {
01203 xSizeHint.max_width = QMAX( xSizeHint.max_width, 1 );
01204 xSizeHint.max_height = QMAX( xSizeHint.max_height, 1 );
01205 }
01206 if( xSizeHint.flags & PResizeInc )
01207 {
01208 xSizeHint.width_inc = kMax( xSizeHint.width_inc, 1 );
01209 xSizeHint.height_inc = kMax( xSizeHint.height_inc, 1 );
01210 }
01211 else
01212 {
01213 xSizeHint.width_inc = 1;
01214 xSizeHint.height_inc = 1;
01215 }
01216 if( xSizeHint.flags & PAspect )
01217 {
01218 xSizeHint.min_aspect.y = kMax( xSizeHint.min_aspect.y, 1 );
01219 xSizeHint.max_aspect.y = kMax( xSizeHint.max_aspect.y, 1 );
01220 }
01221 else
01222 {
01223 xSizeHint.min_aspect.x = 1;
01224 xSizeHint.min_aspect.y = INT_MAX;
01225 xSizeHint.max_aspect.x = INT_MAX;
01226 xSizeHint.max_aspect.y = 1;
01227 }
01228 if( ! ( xSizeHint.flags & PWinGravity ))
01229 xSizeHint.win_gravity = NorthWestGravity;
01230 if( isManaged())
01231 {
01232 QSize new_size = adjustedSize( size());
01233 if( new_size != size() && !isShade() && !isFullScreen())
01234 resizeWithChecks( new_size );
01235 }
01236 updateAllowedActions();
01237 }
01238
01239 QSize Client::minSize() const
01240 {
01241 return rules()->checkMinSize( QSize( xSizeHint.min_width, xSizeHint.min_height ));
01242 }
01243
01244 QSize Client::maxSize() const
01245 {
01246 return rules()->checkMaxSize( QSize( xSizeHint.max_width, xSizeHint.max_height ));
01247 }
01248
01254 void Client::sendSyntheticConfigureNotify()
01255 {
01256 XConfigureEvent c;
01257 c.type = ConfigureNotify;
01258 c.send_event = True;
01259 c.event = window();
01260 c.window = window();
01261 c.x = x() + clientPos().x();
01262 c.y = y() + clientPos().y();
01263 c.width = clientSize().width();
01264 c.height = clientSize().height();
01265 c.border_width = 0;
01266 c.above = None;
01267 c.override_redirect = 0;
01268 XSendEvent( qt_xdisplay(), c.event, TRUE, StructureNotifyMask, (XEvent*)&c );
01269 }
01270
01271 const QPoint Client::calculateGravitation( bool invert, int gravity ) const
01272 {
01273 int dx, dy;
01274 dx = dy = 0;
01275
01276 if( gravity == 0 )
01277 gravity = xSizeHint.win_gravity;
01278
01279
01280 switch (gravity)
01281 {
01282 case NorthWestGravity:
01283 default:
01284 dx = border_left;
01285 dy = border_top;
01286 break;
01287 case NorthGravity:
01288 dx = 0;
01289 dy = border_top;
01290 break;
01291 case NorthEastGravity:
01292 dx = -border_right;
01293 dy = border_top;
01294 break;
01295 case WestGravity:
01296 dx = border_left;
01297 dy = 0;
01298 break;
01299 case CenterGravity:
01300 break;
01301 case StaticGravity:
01302 dx = 0;
01303 dy = 0;
01304 break;
01305 case EastGravity:
01306 dx = -border_right;
01307 dy = 0;
01308 break;
01309 case SouthWestGravity:
01310 dx = border_left ;
01311 dy = -border_bottom;
01312 break;
01313 case SouthGravity:
01314 dx = 0;
01315 dy = -border_bottom;
01316 break;
01317 case SouthEastGravity:
01318 dx = -border_right;
01319 dy = -border_bottom;
01320 break;
01321 }
01322 if( gravity != CenterGravity )
01323 {
01324 dx -= border_left;
01325 dy -= border_top;
01326 }
01327 else
01328 {
01329 dx = - ( border_left + border_right ) / 2;
01330 dy = - ( border_top + border_bottom ) / 2;
01331 }
01332 if( !invert )
01333 return QPoint( x() + dx, y() + dy );
01334 else
01335 return QPoint( x() - dx, y() - dy );
01336 }
01337
01338 void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, int gravity, bool from_tool )
01339 {
01340 if( gravity == 0 )
01341 gravity = xSizeHint.win_gravity;
01342 if( value_mask & ( CWX | CWY ))
01343 {
01344 QPoint new_pos = calculateGravitation( true, gravity );
01345 if ( value_mask & CWX )
01346 new_pos.setX( rx );
01347 if ( value_mask & CWY )
01348 new_pos.setY( ry );
01349
01350
01351
01352
01353
01354 if ( new_pos.x() == x() + clientPos().x() &&
01355 new_pos.y() == y() + clientPos().y() && gravity == NorthWestGravity )
01356 {
01357 new_pos.setX( x());
01358 new_pos.setY( y());
01359 }
01360
01361 int nw = clientSize().width();
01362 int nh = clientSize().height();
01363 if ( value_mask & CWWidth )
01364 nw = rw;
01365 if ( value_mask & CWHeight )
01366 nh = rh;
01367 QSize ns = sizeForClientSize( QSize( nw, nh ) );
01368
01369
01370 if ( maximizeMode() != MaximizeFull
01371 || ns != size())
01372 {
01373 QRect orig_geometry = geometry();
01374 ++block_geometry;
01375 resetMaximize();
01376 move( new_pos );
01377 plainResize( ns );
01378 setGeometry( QRect( calculateGravitation( false, gravity ), size()));
01379 updateFullScreenHack( QRect( new_pos, QSize( nw, nh )));
01380 QRect area = workspace()->clientArea( WorkArea, this );
01381 if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen()
01382 && area.contains( orig_geometry ))
01383 keepInArea( area );
01384 --block_geometry;
01385 setGeometry( geometry(), ForceGeometrySet );
01386
01387
01388
01389
01390
01391 if (hasStrut ())
01392 workspace() -> updateClientArea ();
01393 }
01394 }
01395
01396 if ( value_mask & (CWWidth | CWHeight )
01397 && ! ( value_mask & ( CWX | CWY )) )
01398 {
01399 if ( isShade())
01400 setShade( ShadeNone );
01401
01402 int nw = clientSize().width();
01403 int nh = clientSize().height();
01404 if ( value_mask & CWWidth )
01405 nw = rw;
01406 if ( value_mask & CWHeight )
01407 nh = rh;
01408 QSize ns = sizeForClientSize( QSize( nw, nh ) );
01409
01410 if( ns != size())
01411 {
01412 QRect orig_geometry = geometry();
01413 ++block_geometry;
01414 resetMaximize();
01415 int save_gravity = xSizeHint.win_gravity;
01416 xSizeHint.win_gravity = gravity;
01417 resizeWithChecks( ns );
01418 xSizeHint.win_gravity = save_gravity;
01419 updateFullScreenHack( QRect( calculateGravitation( true, xSizeHint.win_gravity ), QSize( nw, nh )));
01420 QRect area = workspace()->clientArea( WorkArea, this );
01421 if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen()
01422 && area.contains( orig_geometry ))
01423 keepInArea( area );
01424 --block_geometry;
01425 setGeometry( geometry(), ForceGeometrySet );
01426 }
01427 }
01428
01429
01430
01431 }
01432
01433 void Client::resizeWithChecks( int w, int h, ForceGeometry_t force )
01434 {
01435 int newx = x();
01436 int newy = y();
01437 QRect area = workspace()->clientArea( WorkArea, this );
01438
01439 if( w > area.width())
01440 w = area.width();
01441 if( h > area.height())
01442 h = area.height();
01443 QSize tmp = adjustedSize( QSize( w, h ));
01444 w = tmp.width();
01445 h = tmp.height();
01446 switch( xSizeHint.win_gravity )
01447 {
01448 case NorthWestGravity:
01449 default:
01450 break;
01451 case NorthGravity:
01452 newx = ( newx + width() / 2 ) - ( w / 2 );
01453 break;
01454 case NorthEastGravity:
01455 newx = newx + width() - w;
01456 break;
01457 case WestGravity:
01458 newy = ( newy + height() / 2 ) - ( h / 2 );
01459 break;
01460 case CenterGravity:
01461 newx = ( newx + width() / 2 ) - ( w / 2 );
01462 newy = ( newy + height() / 2 ) - ( h / 2 );
01463 break;
01464 case StaticGravity:
01465
01466 break;
01467 case EastGravity:
01468 newx = newx + width() - w;
01469 newy = ( newy + height() / 2 ) - ( h / 2 );
01470 break;
01471 case SouthWestGravity:
01472 newy = newy + height() - h;
01473 break;
01474 case SouthGravity:
01475 newx = ( newx + width() / 2 ) - ( w / 2 );
01476 newy = newy + height() - h;
01477 break;
01478 case SouthEastGravity:
01479 newx = newx + width() - w;
01480 newy = newy + height() - h;
01481 break;
01482 }
01483
01484
01485 if( workarea_diff_x != INT_MIN && w <= area.width())
01486 {
01487 if( newx < area.left())
01488 newx = area.left();
01489 if( newx + w > area.right() + 1 )
01490 newx = area.right() + 1 - w;
01491 assert( newx >= area.left() && newx + w <= area.right() + 1 );
01492 }
01493 if( workarea_diff_y != INT_MIN && h <= area.height())
01494 {
01495 if( newy < area.top())
01496 newy = area.top();
01497 if( newy + h > area.bottom() + 1 )
01498 newy = area.bottom() + 1 - h;
01499 assert( newy >= area.top() && newy + h <= area.bottom() + 1 );
01500 }
01501 setGeometry( newx, newy, w, h, force );
01502 }
01503
01504
01505 void Client::NETMoveResizeWindow( int flags, int x, int y, int width, int height )
01506 {
01507 int gravity = flags & 0xff;
01508 int value_mask = 0;
01509 if( flags & ( 1 << 8 ))
01510 value_mask |= CWX;
01511 if( flags & ( 1 << 9 ))
01512 value_mask |= CWY;
01513 if( flags & ( 1 << 10 ))
01514 value_mask |= CWWidth;
01515 if( flags & ( 1 << 11 ))
01516 value_mask |= CWHeight;
01517 configureRequest( value_mask, x, y, width, height, gravity, true );
01518 }
01519
01524 bool Client::isMovable() const
01525 {
01526 if( !motif_may_move || isFullScreen())
01527 return false;
01528 if( isSpecialWindow() && !isOverride() && !isSplash() && !isToolbar())
01529 return false;
01530 if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() )
01531 return false;
01532 if( rules()->checkPosition( invalidPoint ) != invalidPoint )
01533 return false;
01534 return true;
01535 }
01536
01540 bool Client::isResizable() const
01541 {
01542 if( !motif_may_resize || isFullScreen())
01543 return false;
01544 if(( isSpecialWindow() || isSplash() || isToolbar()) && !isOverride())
01545 return false;
01546 if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() )
01547 return false;
01548 if( rules()->checkSize( QSize()).isValid())
01549 return false;
01550
01551 QSize min = minSize();
01552 QSize max = maxSize();
01553 return min.width() < max.width() || min.height() < max.height();
01554 }
01555
01556
01557
01558
01559 bool Client::isMaximizable() const
01560 {
01561 {
01562
01563 TemporaryAssign< MaximizeMode > tmp( max_mode, MaximizeRestore );
01564 if( !isMovable() || !isResizable() || isToolbar())
01565 return false;
01566 }
01567 if ( maximizeMode() != MaximizeRestore )
01568 return TRUE;
01569 QSize max = maxSize();
01570 #if 0
01571 if( max.width() < 32767 || max.height() < 32767 )
01572 return false;
01573 #else
01574
01575
01576 QSize areasize = workspace()->clientArea( MaximizeArea, this ).size();
01577 if( max.width() < areasize.width() || max.height() < areasize.height())
01578 return false;
01579 #endif
01580 return true;
01581 }
01582
01583
01587 void Client::setGeometry( int x, int y, int w, int h, ForceGeometry_t force )
01588 {
01589 if( force == NormalGeometrySet && frame_geometry == QRect( x, y, w, h ))
01590 return;
01591 frame_geometry = QRect( x, y, w, h );
01592 if( !isShade())
01593 client_size = QSize( w - border_left - border_right, h - border_top - border_bottom );
01594 else
01595 {
01596
01597 if( !shade_geometry_change && h != border_top + border_bottom )
01598 {
01599 kdDebug() << "h:" << h << ":t:" << border_top << ":b:" << border_bottom << endl;
01600 assert( false );
01601 }
01602 client_size = QSize( w - border_left - border_right, client_size.height());
01603 }
01604 updateWorkareaDiffs();
01605 if( block_geometry == 0 )
01606 {
01607 XMoveResizeWindow( qt_xdisplay(), frameId(), x, y, w, h );
01608 resizeDecoration( QSize( w, h ));
01609 if( !isShade())
01610 {
01611 QSize cs = clientSize();
01612 XMoveResizeWindow( qt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(),
01613 cs.width(), cs.height());
01614
01615 XMoveResizeWindow( qt_xdisplay(), window(), 0, 0, cs.width(), cs.height());
01616 }
01617 if( shape())
01618 updateShape();
01619
01620 updateWorkareaDiffs();
01621 sendSyntheticConfigureNotify();
01622 updateWindowRules();
01623 }
01624 }
01625
01626 void Client::plainResize( int w, int h, ForceGeometry_t force )
01627 {
01628 if( QSize( w, h ) != rules()->checkSize( QSize( w, h )))
01629 {
01630 kdDebug() << "forced size fail:" << QSize( w,h ) << ":" << rules()->checkSize( QSize( w, h )) << endl;
01631 kdDebug() << kdBacktrace() << endl;
01632 }
01633 if( force == NormalGeometrySet && frame_geometry.size() == QSize( w, h ))
01634 return;
01635 frame_geometry.setSize( QSize( w, h ));
01636 if( !isShade())
01637 client_size = QSize( w - border_left - border_right, h - border_top - border_bottom );
01638 else
01639 {
01640
01641 if( !shade_geometry_change && h != border_top + border_bottom )
01642 {
01643 kdDebug() << "h:" << h << ":t:" << border_top << ":b:" << border_bottom << endl;
01644 assert( false );
01645 }
01646 client_size = QSize( w - border_left - border_right, client_size.height());
01647 }
01648 updateWorkareaDiffs();
01649 if( block_geometry == 0 )
01650 {
01651
01652 XResizeWindow( qt_xdisplay(), frameId(), w, h );
01653 resizeDecoration( QSize( w, h ));
01654 if( !isShade())
01655 {
01656 QSize cs = clientSize();
01657 XMoveResizeWindow( qt_xdisplay(), wrapperId(), clientPos().x(), clientPos().y(),
01658 cs.width(), cs.height());
01659 XMoveResizeWindow( qt_xdisplay(), window(), 0, 0, cs.width(), cs.height());
01660 }
01661 if( shape())
01662 updateShape();
01663 updateWorkareaDiffs();
01664 sendSyntheticConfigureNotify();
01665 updateWindowRules();
01666 }
01667 }
01668
01672 void Client::move( int x, int y, ForceGeometry_t force )
01673 {
01674 if( force == NormalGeometrySet && frame_geometry.topLeft() == QPoint( x, y ))
01675 return;
01676 frame_geometry.moveTopLeft( QPoint( x, y ));
01677 updateWorkareaDiffs();
01678 if( block_geometry == 0 )
01679 {
01680 XMoveWindow( qt_xdisplay(), frameId(), x, y );
01681 sendSyntheticConfigureNotify();
01682 updateWindowRules();
01683 }
01684 }
01685
01686
01687 void Client::maximize( MaximizeMode m )
01688 {
01689 setMaximize( m & MaximizeVertical, m & MaximizeHorizontal );
01690 }
01691
01695 void Client::setMaximize( bool vertically, bool horizontally )
01696 {
01697 changeMaximize(
01698 max_mode & MaximizeVertical ? !vertically : vertically,
01699 max_mode & MaximizeHorizontal ? !horizontally : horizontally,
01700 false );
01701 }
01702
01703 void Client::changeMaximize( bool vertical, bool horizontal, bool adjust )
01704 {
01705 if( !isMaximizable())
01706 return;
01707
01708 MaximizeMode old_mode = max_mode;
01709
01710 if( !adjust )
01711 {
01712 if( vertical )
01713 max_mode = MaximizeMode( max_mode ^ MaximizeVertical );
01714 if( horizontal )
01715 max_mode = MaximizeMode( max_mode ^ MaximizeHorizontal );
01716 }
01717
01718 max_mode = rules()->checkMaximize( max_mode );
01719 if( !adjust && max_mode == old_mode )
01720 return;
01721
01722 if( isShade())
01723 setShade( ShadeNone );
01724
01725 ++block_geometry;
01726
01727
01728 Q_ASSERT( !( vertical && horizontal )
01729 || (( max_mode & MaximizeVertical != 0 ) == ( max_mode & MaximizeHorizontal != 0 )));
01730
01731
01732 bool maximalizing = false;
01733 if( vertical && !(old_mode & MaximizeVertical ))
01734 {
01735 geom_restore.setTop( y());
01736 geom_restore.setHeight( height());
01737 maximalizing = true;
01738 }
01739 if( horizontal && !( old_mode & MaximizeHorizontal ))
01740 {
01741 geom_restore.setLeft( x());
01742 geom_restore.setWidth( width());
01743 maximalizing = true;
01744 }
01745
01746 if( !adjust )
01747 {
01748 if( maximalizing )
01749 Notify::raise( Notify::Maximize );
01750 else
01751 Notify::raise( Notify::UnMaximize );
01752 }
01753
01754 if( decoration != NULL )
01755 decoration->borders( border_left, border_right, border_top, border_bottom );
01756
01757 QRect clientArea = workspace()->clientArea( MaximizeArea, this );
01758
01759 switch (max_mode)
01760 {
01761
01762 case MaximizeVertical:
01763 {
01764 if( old_mode & MaximizeHorizontal )
01765 {
01766 if( geom_restore.width() == 0 )
01767 {
01768 plainResize( adjustedSize(QSize(width(), clientArea.height()), SizemodeFixedH ));
01769 workspace()->placeSmart( this, clientArea );
01770 }
01771 else
01772 setGeometry( QRect(QPoint( geom_restore.x(), clientArea.top()),
01773 adjustedSize(QSize( geom_restore.width(), clientArea.height()), SizemodeFixedH )));
01774 }
01775 else
01776 setGeometry( QRect(QPoint(x(), clientArea.top()),
01777 adjustedSize(QSize(width(), clientArea.height()), SizemodeFixedH )));
01778 info->setState( NET::MaxVert, NET::Max );
01779 break;
01780 }
01781
01782 case MaximizeHorizontal:
01783 {
01784 if( old_mode & MaximizeVertical )
01785 {
01786 if( geom_restore.height() == 0 )
01787 {
01788 plainResize( adjustedSize(QSize(clientArea.width(), height()), SizemodeFixedW ));
01789 workspace()->placeSmart( this, clientArea );
01790 }
01791 else
01792 setGeometry( QRect( QPoint(clientArea.left(), geom_restore.y()),
01793 adjustedSize(QSize(clientArea.width(), geom_restore.height()), SizemodeFixedW )));
01794 }
01795 else
01796 setGeometry( QRect( QPoint(clientArea.left(), y()),
01797 adjustedSize(QSize(clientArea.width(), height()), SizemodeFixedW )));
01798 info->setState( NET::MaxHoriz, NET::Max );
01799 break;
01800 }
01801
01802 case MaximizeRestore:
01803 {
01804 QRect restore = geometry();
01805
01806 if( old_mode & MaximizeVertical )
01807 {
01808 restore.setTop( geom_restore.top());
01809 restore.setBottom( geom_restore.bottom());
01810 }
01811 if( old_mode & MaximizeHorizontal )
01812 {
01813 restore.setLeft( geom_restore.left());
01814 restore.setRight( geom_restore.right());
01815 }
01816 if( !restore.isValid())
01817 {
01818 QSize s = QSize( clientArea.width()*2/3, clientArea.height()*2/3 );
01819 if( geom_restore.width() > 0 )
01820 s.setWidth( geom_restore.width());
01821 if( geom_restore.height() > 0 )
01822 s.setHeight( geom_restore.height());
01823 plainResize( adjustedSize( s ));
01824 workspace()->placeSmart( this, clientArea );
01825 restore = geometry();
01826 if( geom_restore.width() > 0 )
01827 restore.moveLeft( geom_restore.x());
01828 if( geom_restore.height() > 0 )
01829 restore.moveTop( geom_restore.y());
01830 }
01831 setGeometry( restore );
01832 info->setState( 0, NET::Max );
01833 break;
01834 }
01835
01836 case MaximizeFull:
01837 {
01838 QSize adjSize = adjustedSize(clientArea.size(), SizemodeMax );
01839 QRect r = QRect(clientArea.topLeft(), adjSize);
01840 setGeometry( r );
01841 info->setState( NET::Max, NET::Max );
01842 break;
01843 }
01844 default:
01845 break;
01846 }
01847
01848 --block_geometry;
01849 setGeometry( geometry(), ForceGeometrySet );
01850
01851 updateAllowedActions();
01852 if( decoration != NULL )
01853 decoration->maximizeChange();
01854 updateWindowRules();
01855 }
01856
01857 void Client::resetMaximize()
01858 {
01859 if( max_mode == MaximizeRestore )
01860 return;
01861 max_mode = MaximizeRestore;
01862 Notify::raise( Notify::UnMaximize );
01863 info->setState( 0, NET::Max );
01864 updateAllowedActions();
01865 if( decoration != NULL )
01866 decoration->borders( border_left, border_right, border_top, border_bottom );
01867 setGeometry( geometry(), ForceGeometrySet );
01868 if( decoration != NULL )
01869 decoration->maximizeChange();
01870 }
01871
01872 bool Client::isFullScreenable( bool fullscreen_hack ) const
01873 {
01874 if( !rules()->checkFullScreen( true ))
01875 return false;
01876 if( fullscreen_hack )
01877 return isNormalWindow() || isOverride();
01878 else
01879 return !isSpecialWindow();
01880 }
01881
01882 bool Client::userCanSetFullScreen() const
01883 {
01884 if( fullscreen_mode == FullScreenHack )
01885 return false;
01886
01887 TemporaryAssign< FullScreenMode > tmp( fullscreen_mode, FullScreenNone );
01888 return isNormalWindow() && isMaximizable();
01889 }
01890
01891 void Client::setFullScreen( bool set, bool user )
01892 {
01893 if( !isFullScreen() && !set )
01894 return;
01895 if( fullscreen_mode == FullScreenHack )
01896 return;
01897 if( user && !userCanSetFullScreen())
01898 return;
01899 set = rules()->checkFullScreen( set );
01900 setShade( ShadeNone );
01901 bool was_fs = isFullScreen();
01902 if( !was_fs )
01903 geom_fs_restore = geometry();
01904 fullscreen_mode = set ? FullScreenNormal : FullScreenNone;
01905 if( was_fs == isFullScreen())
01906 return;
01907 StackingUpdatesBlocker blocker( workspace());
01908 workspace()->updateClientLayer( this );
01909 info->setState( isFullScreen() ? NET::FullScreen : 0, NET::FullScreen );
01910 updateDecoration( false, false );
01911 if( isFullScreen())
01912 setGeometry( workspace()->clientArea( FullScreenArea, this ));
01913 else
01914 {
01915 if( maximizeMode() != MaximizeRestore )
01916 changeMaximize( false, false, true );
01917 else if( !geom_fs_restore.isNull())
01918 setGeometry( QRect( geom_fs_restore.topLeft(), adjustedSize( geom_fs_restore.size())));
01919
01920 else
01921 {
01922 setGeometry( workspace()->clientArea( MaximizeArea, this ));
01923 }
01924 }
01925 updateWindowRules();
01926 }
01927
01928 bool Client::checkFullScreenHack( const QRect& geom ) const
01929 {
01930
01931 return (( geom.size() == workspace()->clientArea( FullArea, geom.center(), desktop()).size()
01932 || geom.size() == workspace()->clientArea( ScreenArea, geom.center(), desktop()).size())
01933 && noBorder() && !isUserNoBorder() && isFullScreenable( true ));
01934 }
01935
01936 void Client::updateFullScreenHack( const QRect& geom )
01937 {
01938 bool is_hack = checkFullScreenHack( geom );
01939 if( fullscreen_mode == FullScreenNone && is_hack )
01940 {
01941 fullscreen_mode = FullScreenHack;
01942 updateDecoration( false, false );
01943 setGeometry( workspace()->clientArea( FullScreenArea, this ));
01944 }
01945 else if( fullscreen_mode == FullScreenHack && !is_hack )
01946 {
01947 fullscreen_mode = FullScreenNone;
01948 updateDecoration( false, false );
01949
01950 }
01951 StackingUpdatesBlocker blocker( workspace());
01952 workspace()->updateClientLayer( this );
01953 }
01954
01955 static QRect* visible_bound = 0;
01956 static GeometryTip* geometryTip = 0;
01957
01958 void Client::drawbound( const QRect& geom )
01959 {
01960 assert( visible_bound == NULL );
01961 visible_bound = new QRect( geom );
01962 doDrawbound( *visible_bound, false );
01963 }
01964
01965 void Client::clearbound()
01966 {
01967 if( visible_bound == NULL )
01968 return;
01969 doDrawbound( *visible_bound, true );
01970 delete visible_bound;
01971 visible_bound = 0;
01972 }
01973
01974 void Client::doDrawbound( const QRect& geom, bool clear )
01975 {
01976 if( decoration != NULL && decoration->drawbound( geom, clear ))
01977 return;
01978 QPainter p ( workspace()->desktopWidget() );
01979 p.setPen( QPen( Qt::white, 5 ) );
01980 p.setRasterOp( Qt::XorROP );
01981
01982
01983 QRect g = geom;
01984 if( g.width() > 5 )
01985 {
01986 g.setLeft( g.left() + 2 );
01987 g.setRight( g.right() - 2 );
01988 }
01989 if( g.height() > 5 )
01990 {
01991 g.setTop( g.top() + 2 );
01992 g.setBottom( g.bottom() - 2 );
01993 }
01994 p.drawRect( g );
01995 }
01996
01997 void Client::positionGeometryTip()
01998 {
01999 assert( isMove() || isResize());
02000
02001 if (options->showGeometryTip())
02002 {
02003 if( !geometryTip )
02004 {
02005 bool save_under = ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
02006 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque );
02007 geometryTip = new GeometryTip( &xSizeHint, save_under );
02008 }
02009 QRect wgeom( moveResizeGeom );
02010 wgeom.setWidth( wgeom.width() - ( width() - clientSize().width()));
02011 wgeom.setHeight( wgeom.height() - ( height() - clientSize().height()));
02012 if( isShade())
02013 wgeom.setHeight( 0 );
02014 geometryTip->setGeometry( wgeom );
02015 if( !geometryTip->isVisible())
02016 {
02017 geometryTip->show();
02018 geometryTip->raise();
02019 }
02020 }
02021 }
02022
02023 class EatAllPaintEvents
02024 : public QObject
02025 {
02026 protected:
02027 virtual bool eventFilter( QObject* o, QEvent* e )
02028 { return e->type() == QEvent::Paint && o != geometryTip; }
02029 };
02030
02031 static EatAllPaintEvents* eater = 0;
02032
02033 bool Client::startMoveResize()
02034 {
02035 assert( !moveResizeMode );
02036 assert( QWidget::keyboardGrabber() == NULL );
02037 assert( QWidget::mouseGrabber() == NULL );
02038 if( QApplication::activePopupWidget() != NULL )
02039 return false;
02040 bool has_grab = false;
02041
02042
02043
02044 XSetWindowAttributes attrs;
02045 QRect r = workspace()->clientArea( FullArea, this );
02046 move_resize_grab_window = XCreateWindow( qt_xdisplay(), workspace()->rootWin(), r.x(), r.y(),
02047 r.width(), r.height(), 0, CopyFromParent, InputOnly, CopyFromParent, 0, &attrs );
02048 XMapRaised( qt_xdisplay(), move_resize_grab_window );
02049 if( XGrabPointer( qt_xdisplay(), move_resize_grab_window, False,
02050 ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask,
02051 GrabModeAsync, GrabModeAsync, None, cursor.handle(), qt_x_time ) == Success )
02052 has_grab = true;
02053 if( XGrabKeyboard( qt_xdisplay(), frameId(), False, GrabModeAsync, GrabModeAsync, qt_x_time ) == Success )
02054 has_grab = true;
02055 if( !has_grab )
02056 {
02057 XDestroyWindow( qt_xdisplay(), move_resize_grab_window );
02058 move_resize_grab_window = None;
02059 return false;
02060 }
02061 if ( maximizeMode() != MaximizeRestore )
02062 resetMaximize();
02063 moveResizeMode = true;
02064 workspace()->setClientIsMoving(this);
02065 initialMoveResizeGeom = moveResizeGeom = geometry();
02066 checkUnrestrictedMoveResize();
02067 if ( ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
02068 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque ) )
02069 {
02070 grabXServer();
02071 kapp->sendPostedEvents();
02072
02073
02074
02075
02076
02077 eater = new EatAllPaintEvents;
02078
02079 }
02080 Notify::raise( isResize() ? Notify::ResizeStart : Notify::MoveStart );
02081 return true;
02082 }
02083
02084 void Client::finishMoveResize( bool cancel )
02085 {
02086 leaveMoveResize();
02087 if( cancel )
02088 setGeometry( initialMoveResizeGeom );
02089 else
02090 setGeometry( moveResizeGeom );
02091
02092 Notify::raise( isResize() ? Notify::ResizeEnd : Notify::MoveEnd );
02093 }
02094
02095 void Client::leaveMoveResize()
02096 {
02097 clearbound();
02098 if (geometryTip)
02099 {
02100 geometryTip->hide();
02101 delete geometryTip;
02102 geometryTip = NULL;
02103 }
02104 if ( ( isMove() && rules()->checkMoveResizeMode( options->moveMode ) != Options::Opaque )
02105 || ( isResize() && rules()->checkMoveResizeMode( options->resizeMode ) != Options::Opaque ) )
02106 ungrabXServer();
02107 XUngrabKeyboard( qt_xdisplay(), qt_x_time );
02108 XUngrabPointer( qt_xdisplay(), qt_x_time );
02109 XDestroyWindow( qt_xdisplay(), move_resize_grab_window );
02110 move_resize_grab_window = None;
02111 workspace()->setClientIsMoving(0);
02112 if( move_faked_activity )
02113 workspace()->unfakeActivity( this );
02114 move_faked_activity = false;
02115 moveResizeMode = false;
02116 delete eater;
02117 eater = 0;
02118 }
02119
02120
02121
02122
02123
02124 void Client::checkUnrestrictedMoveResize()
02125 {
02126 if( unrestrictedMoveResize )
02127 return;
02128 QRect desktopArea = workspace()->clientArea( WorkArea, moveResizeGeom.center(), desktop());
02129 int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
02130
02131
02132 left_marge = KMIN( 100 + border_right, moveResizeGeom.width());
02133 right_marge = KMIN( 100 + border_left, moveResizeGeom.width());
02134
02135 titlebar_marge = initialMoveResizeGeom.height();
02136 top_marge = border_bottom;
02137 bottom_marge = border_top;
02138 if( isResize())
02139 {
02140 if( moveResizeGeom.bottom() < desktopArea.top() + top_marge )
02141 unrestrictedMoveResize = true;
02142 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
02143 unrestrictedMoveResize = true;
02144 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
02145 unrestrictedMoveResize = true;
02146 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
02147 unrestrictedMoveResize = true;
02148 if( !unrestrictedMoveResize && moveResizeGeom.top() < desktopArea.top() )
02149 unrestrictedMoveResize = true;
02150 }
02151 if( isMove())
02152 {
02153 if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 )
02154 unrestrictedMoveResize = true;
02155
02156 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
02157 unrestrictedMoveResize = true;
02158 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
02159 unrestrictedMoveResize = true;
02160 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
02161 unrestrictedMoveResize = true;
02162 }
02163 }
02164
02165 void Client::handleMoveResize( int x, int y, int x_root, int y_root )
02166 {
02167 if(( mode == PositionCenter && !isMovable())
02168 || ( mode != PositionCenter && ( isShade() || !isResizable())))
02169 return;
02170
02171 if ( !moveResizeMode )
02172 {
02173 QPoint p( QPoint( x, y ) - moveOffset );
02174 if (p.manhattanLength() >= 6)
02175 {
02176 if( !startMoveResize())
02177 {
02178 buttonDown = false;
02179 setCursor( mode );
02180 return;
02181 }
02182 }
02183 else
02184 return;
02185 }
02186
02187
02188 if ( mode != PositionCenter && shade_mode != ShadeNone )
02189 setShade( ShadeNone );
02190
02191 QPoint globalPos( x_root, y_root );
02192
02193
02194 QPoint topleft = globalPos - moveOffset;
02195 QPoint bottomright = globalPos + invertedMoveOffset;
02196 QRect previousMoveResizeGeom = moveResizeGeom;
02197
02198
02199
02200
02201
02202 QRect desktopArea = workspace()->clientArea( WorkArea, globalPos, desktop());
02203 int left_marge, right_marge, top_marge, bottom_marge, titlebar_marge;
02204 if( unrestrictedMoveResize )
02205 left_marge = right_marge = top_marge = bottom_marge = titlebar_marge = 5;
02206 else
02207 {
02208
02209 left_marge = KMIN( 100 + border_right, moveResizeGeom.width());
02210 right_marge = KMIN( 100 + border_left, moveResizeGeom.width());
02211
02212 titlebar_marge = initialMoveResizeGeom.height();
02213 top_marge = border_bottom;
02214 bottom_marge = border_top;
02215 }
02216
02217 bool update = false;
02218 if( isResize())
02219 {
02220
02221 QRect orig = initialMoveResizeGeom;
02222 Sizemode sizemode = SizemodeAny;
02223 switch ( mode )
02224 {
02225 case PositionTopLeft:
02226 moveResizeGeom = QRect( topleft, orig.bottomRight() ) ;
02227 break;
02228 case PositionBottomRight:
02229 moveResizeGeom = QRect( orig.topLeft(), bottomright ) ;
02230 break;
02231 case PositionBottomLeft:
02232 moveResizeGeom = QRect( QPoint( topleft.x(), orig.y() ), QPoint( orig.right(), bottomright.y()) ) ;
02233 break;
02234 case PositionTopRight:
02235 moveResizeGeom = QRect( QPoint( orig.x(), topleft.y() ), QPoint( bottomright.x(), orig.bottom()) ) ;
02236 break;
02237 case PositionTop:
02238 moveResizeGeom = QRect( QPoint( orig.left(), topleft.y() ), orig.bottomRight() ) ;
02239 sizemode = SizemodeFixedH;
02240 break;
02241 case PositionBottom:
02242 moveResizeGeom = QRect( orig.topLeft(), QPoint( orig.right(), bottomright.y() ) ) ;
02243 sizemode = SizemodeFixedH;
02244 break;
02245 case PositionLeft:
02246 moveResizeGeom = QRect( QPoint( topleft.x(), orig.top() ), orig.bottomRight() ) ;
02247 sizemode = SizemodeFixedW;
02248 break;
02249 case PositionRight:
02250 moveResizeGeom = QRect( orig.topLeft(), QPoint( bottomright.x(), orig.bottom() ) ) ;
02251 sizemode = SizemodeFixedW;
02252 break;
02253 case PositionCenter:
02254 default:
02255 assert( false );
02256 break;
02257 }
02258
02259
02260 moveResizeGeom = workspace()->adjustClientSize( this, moveResizeGeom, mode );
02261
02262
02263 if( moveResizeGeom.bottom() < desktopArea.top() + top_marge )
02264 moveResizeGeom.setBottom( desktopArea.top() + top_marge );
02265 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
02266 moveResizeGeom.setTop( desktopArea.bottom() - bottom_marge );
02267 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
02268 moveResizeGeom.setRight( desktopArea.left() + left_marge );
02269 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
02270 moveResizeGeom.setLeft(desktopArea.right() - right_marge );
02271 if( !unrestrictedMoveResize && moveResizeGeom.top() < desktopArea.top() )
02272 moveResizeGeom.setTop( desktopArea.top());
02273
02274 QSize size = adjustedSize( moveResizeGeom.size(), sizemode );
02275
02276 topleft = QPoint( moveResizeGeom.right() - size.width() + 1, moveResizeGeom.bottom() - size.height() + 1 );
02277 bottomright = QPoint( moveResizeGeom.left() + size.width() - 1, moveResizeGeom.top() + size.height() - 1 );
02278 orig = moveResizeGeom;
02279 switch ( mode )
02280 {
02281 case PositionTopLeft:
02282 moveResizeGeom = QRect( topleft, orig.bottomRight() ) ;
02283 break;
02284 case PositionBottomRight:
02285 moveResizeGeom = QRect( orig.topLeft(), bottomright ) ;
02286 break;
02287 case PositionBottomLeft:
02288 moveResizeGeom = QRect( QPoint( topleft.x(), orig.y() ), QPoint( orig.right(), bottomright.y()) ) ;
02289 break;
02290 case PositionTopRight:
02291 moveResizeGeom = QRect( QPoint( orig.x(), topleft.y() ), QPoint( bottomright.x(), orig.bottom()) ) ;
02292 break;
02293
02294
02295
02296 case PositionTop:
02297 moveResizeGeom = QRect( QPoint( orig.left(), topleft.y() ), QPoint( bottomright.x(), orig.bottom()) ) ;
02298 break;
02299 case PositionBottom:
02300 moveResizeGeom = QRect( orig.topLeft(), QPoint( bottomright.x(), bottomright.y() ) ) ;
02301 break;
02302 case PositionLeft:
02303 moveResizeGeom = QRect( QPoint( topleft.x(), orig.top() ), QPoint( orig.right(), bottomright.y()));
02304 break;
02305 case PositionRight:
02306 moveResizeGeom = QRect( orig.topLeft(), QPoint( bottomright.x(), bottomright.y() ) ) ;
02307 break;
02308 case PositionCenter:
02309 default:
02310 assert( false );
02311 break;
02312 }
02313 if( moveResizeGeom.size() != previousMoveResizeGeom.size())
02314 update = true;
02315 }
02316 else if( isMove())
02317 {
02318 assert( mode == PositionCenter );
02319
02320 moveResizeGeom.moveTopLeft( topleft );
02321 moveResizeGeom.moveTopLeft( workspace()->adjustClientPosition( this, moveResizeGeom.topLeft() ) );
02322
02323 if( moveResizeGeom.bottom() < desktopArea.top() + titlebar_marge - 1 )
02324 moveResizeGeom.moveBottom( desktopArea.top() + titlebar_marge - 1 );
02325
02326 if( moveResizeGeom.top() > desktopArea.bottom() - bottom_marge )
02327 moveResizeGeom.moveTop( desktopArea.bottom() - bottom_marge );
02328 if( moveResizeGeom.right() < desktopArea.left() + left_marge )
02329 moveResizeGeom.moveRight( desktopArea.left() + left_marge );
02330 if( moveResizeGeom.left() > desktopArea.right() - right_marge )
02331 moveResizeGeom.moveLeft(desktopArea.right() - right_marge );
02332 if( moveResizeGeom.topLeft() != previousMoveResizeGeom.topLeft())
02333 update = true;
02334 }
02335 else
02336 assert( false );
02337
02338 if( update )
02339 {
02340 if( rules()->checkMoveResizeMode
02341 ( isResize() ? options->resizeMode : options->moveMode ) == Options::Opaque )
02342 {
02343 setGeometry( moveResizeGeom );
02344 positionGeometryTip();
02345 }
02346 else if( rules()->checkMoveResizeMode
02347 ( isResize() ? options->resizeMode : options->moveMode ) == Options::Transparent )
02348 {
02349 clearbound();
02350 positionGeometryTip();
02351 drawbound( moveResizeGeom );
02352 }
02353 }
02354 if ( isMove() )
02355 workspace()->clientMoved(globalPos, qt_x_time);
02356 }
02357
02358
02359 }