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