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 extern Time qt_x_time;
00033
00034 namespace KWinInternal
00035 {
00036
00037
00038
00039
00040
00044 void Workspace::desktopResized()
00045 {
00046
00047 TQRect geom = KApplication::desktop()->geometry();
00048 NETSize desktop_geometry;
00049 desktop_geometry.width = geom.width();
00050 desktop_geometry.height = geom.height();
00051 rootInfo->setDesktopGeometry( -1, desktop_geometry );
00052
00053 updateClientArea( true );
00054 checkElectricBorders( true );
00055 }
00056
00060 void Workspace::kDestopResized()
00061 {
00062
00063 TQRect geom = KApplication::desktop()->geometry();
00064 NETSize desktop_geometry;
00065 desktop_geometry.width = geom.width();
00066 desktop_geometry.height = geom.height();
00067 rootInfo->setDesktopGeometry( -1, desktop_geometry );
00068
00069 updateClientArea( true );
00070 checkElectricBorders( true );
00071 }
00072
00085 void Workspace::updateClientArea( bool force )
00086 {
00087 TQDesktopWidget *desktopwidget = KApplication::desktop();
00088 int nscreens = desktopwidget -> numScreens ();
00089
00090 TQRect* new_wareas = new QRect[ numberOfDesktops() + 1 ];
00091 TQRect** new_sareas = new TQRect*[ numberOfDesktops() + 1];
00092 TQRect* screens = new TQRect [ nscreens ];
00093 TQRect desktopArea = desktopwidget -> geometry ();
00094 for( int iS = 0;
00095 iS < nscreens;
00096 iS ++ )
00097 {
00098 screens [iS] = desktopwidget -> screenGeometry (iS);
00099 }
00100 for( int i = 1;
00101 i <= numberOfDesktops();
00102 ++i )
00103 {
00104 new_wareas[ i ] = desktopArea;
00105 new_sareas[ i ] = new TQRect [ nscreens ];
00106 for( int iS = 0;
00107 iS < nscreens;
00108 iS ++ )
00109 new_sareas[ i ][ iS ] = screens[ iS ];
00110 }
00111 for ( ClientList::ConstIterator it = clients.begin(); it != clients.end(); ++it)
00112 {
00113 if( !(*it)->hasStrut())
00114 continue;
00115 TQRect r = (*it)->adjustedClientArea( desktopArea, desktopArea );
00116 if( (*it)->isOnAllDesktops())
00117 for( int i = 1;
00118 i <= numberOfDesktops();
00119 ++i )
00120 {
00121 new_wareas[ i ] = new_wareas[ i ].intersect( r );
00122 for( int iS = 0;
00123 iS < nscreens;
00124 iS ++ )
00125 new_sareas[ i ][ iS ] =
00126 new_sareas[ i ][ iS ].intersect(
00127 (*it)->adjustedClientArea( desktopArea, screens[ iS ] )
00128 );
00129 }
00130 else
00131 {
00132 new_wareas[ (*it)->desktop() ] = new_wareas[ (*it)->desktop() ].intersect( r );
00133 for( int iS = 0;
00134 iS < nscreens;
00135 iS ++ )
00136 {
00137
00138 new_sareas[ (*it)->desktop() ][ iS ] =
00139 new_sareas[ (*it)->desktop() ][ iS ].intersect(
00140 (*it)->adjustedClientArea( desktopArea, screens[ iS ] )
00141 );
00142 }
00143 }
00144 }
00145 #if 0
00146 for( int i = 1;
00147 i <= numberOfDesktops();
00148 ++i )
00149 {
00150 for( int iS = 0;
00151 iS < nscreens;
00152 iS ++ )
00153 kdDebug () << "new_sarea: " << new_sareas[ i ][ iS ] << endl;
00154 }
00155 #endif
00156
00157 if( topmenu_space != NULL )
00158 {
00159 TQRect topmenu_area = desktopArea;
00160 topmenu_area.setTop( topMenuHeight());
00161 for( int i = 1;
00162 i <= numberOfDesktops();
00163 ++i )
00164 new_wareas[ i ] = new_wareas[ i ].intersect( topmenu_area );
00165 }
00166
00167 bool changed = force;
00168
00169 if (! screenarea)
00170 changed = true;
00171
00172 for( int i = 1;
00173 !changed && i <= numberOfDesktops();
00174 ++i )
00175 {
00176 if( workarea[ i ] != new_wareas[ i ] )
00177 changed = true;
00178 for( int iS = 0;
00179 iS < nscreens;
00180 iS ++ )
00181 if (new_sareas[ i ][ iS ] != screenarea [ i ][ iS ])
00182 changed = true;
00183 }
00184
00185 if ( changed )
00186 {
00187 delete[] workarea;
00188 workarea = new_wareas;
00189 new_wareas = NULL;
00190 delete[] screenarea;
00191 screenarea = new_sareas;
00192 new_sareas = NULL;
00193 NETRect r;
00194 for( int i = 1; i <= numberOfDesktops(); i++)
00195 {
00196 r.pos.x = workarea[ i ].x();
00197 r.pos.y = workarea[ i ].y();
00198 r.size.width = workarea[ i ].width();
00199 r.size.height = workarea[ i ].height();
00200 rootInfo->setWorkArea( i, r );
00201 }
00202
00203 updateTopMenuGeometry();
00204 for( ClientList::ConstIterator it = clients.begin();
00205 it != clients.end();
00206 ++it)
00207 (*it)->checkWorkspacePosition();
00208 for( ClientList::ConstIterator it = desktops.begin();
00209 it != desktops.end();
00210 ++it)
00211 (*it)->checkWorkspacePosition();
00212 }
00213 delete[] screens;
00214 delete[] new_sareas;
00215 delete[] new_wareas;
00216 }
00217
00218 void Workspace::updateClientArea()
00219 {
00220 updateClientArea( false );
00221 }
00222
00223
00231 TQRect Workspace::clientArea( clientAreaOption opt, int screen, int desktop ) const
00232 {
00233 if( desktop == NETWinInfo::OnAllDesktops || desktop == 0 )
00234 desktop = currentDesktop();
00235 TQDesktopWidget *desktopwidget = kapp->desktop();
00236 TQRect sarea = screenarea
00237 ? screenarea[ desktop ][ screen ]
00238 : desktopwidget->screenGeometry( screen );
00239 TQRect warea = workarea[ desktop ].isNull()
00240 ? kapp->desktop()->geometry()
00241 : workarea[ desktop ];
00242 switch (opt)
00243 {
00244 case MaximizeArea:
00245 if (options->xineramaMaximizeEnabled)
00246 if (desktopwidget->numScreens() < 2)
00247 return warea;
00248 else
00249 return sarea;
00250 else
00251 return warea;
00252 case MaximizeFullArea:
00253 if (options->xineramaMaximizeEnabled)
00254 if (desktopwidget->numScreens() < 2)
00255 return desktopwidget->geometry();
00256 else
00257 return desktopwidget->screenGeometry( screen );
00258 else
00259 return desktopwidget->geometry();
00260 case FullScreenArea:
00261 if (options->xineramaFullscreenEnabled)
00262 if (desktopwidget->numScreens() < 2)
00263 return desktopwidget->geometry();
00264 else
00265 return desktopwidget->screenGeometry( screen );
00266 else
00267 return desktopwidget->geometry();
00268 case PlacementArea:
00269 if (options->xineramaPlacementEnabled)
00270 if (desktopwidget->numScreens() < 2)
00271 return warea;
00272 else
00273 return sarea;
00274 else
00275 return warea;
00276 case MovementArea:
00277 if (options->xineramaMovementEnabled)
00278 if (desktopwidget->numScreens() < 2)
00279 return desktopwidget->geometry();
00280 else
00281 return desktopwidget->screenGeometry( screen );
00282 else
00283 return desktopwidget->geometry();
00284 case WorkArea:
00285 return warea;
00286 case FullArea:
00287 return desktopwidget->geometry();
00288 case ScreenArea:
00289 if (desktopwidget->numScreens() < 2)
00290 return desktopwidget->geometry();
00291 else
00292 return desktopwidget->screenGeometry( screen );
00293 }
00294 assert( false );
00295 return TQRect();
00296 }
00297
00298 TQRect Workspace::clientArea( clientAreaOption opt, const TQPoint& p, int desktop ) const
00299 {
00300 TQDesktopWidget *desktopwidget = KApplication::desktop();
00301 int screen = desktopwidget->screenNumber( p );
00302 if( screen < 0 )
00303 screen = desktopwidget->primaryScreen();
00304 return clientArea( opt, screen, desktop );
00305 }
00306
00307 TQRect Workspace::clientArea( clientAreaOption opt, const Client* c ) const
00308 {
00309 return clientArea( opt, c->geometry().center(), c->desktop());
00310 }
00311
00312
00318 TQPoint Workspace::adjustClientPosition( Client* c, TQPoint pos )
00319 {
00320
00321
00322
00323 if (options->windowSnapZone || options->borderSnapZone )
00324 {
00325 const bool sOWO=options->snapOnlyWhenOverlapping;
00326 const TQRect maxRect = clientArea(MovementArea, pos+c->rect().center(), c->desktop());
00327 const int xmin = maxRect.left();
00328 const int xmax = maxRect.right()+1;
00329 const int ymin = maxRect.top();
00330 const int ymax = maxRect.bottom()+1;
00331
00332 const int cx(pos.x());
00333 const int cy(pos.y());
00334 const int cw(c->width());
00335 const int ch(c->height());
00336 const int rx(cx+cw);
00337 const int ry(cy+ch);
00338
00339 int nx(cx), ny(cy);
00340 int deltaX(xmax);
00341 int deltaY(ymax);
00342
00343 int lx, ly, lrx, lry;
00344
00345
00346 int snap = options->borderSnapZone;
00347 if (snap)
00348 {
00349 if ((sOWO?(cx<xmin):true) && (QABS(xmin-cx)<snap))
00350 {
00351 deltaX = xmin-cx;
00352 nx = xmin;
00353 }
00354 if ((sOWO?(rx>xmax):true) && (QABS(rx-xmax)<snap) && (QABS(xmax-rx) < deltaX))
00355 {
00356 deltaX = rx-xmax;
00357 nx = xmax - cw;
00358 }
00359
00360 if ((sOWO?(cy<ymin):true) && (QABS(ymin-cy)<snap))
00361 {
00362 deltaY = ymin-cy;
00363 ny = ymin;
00364 }
00365 if ((sOWO?(ry>ymax):true) && (QABS(ry-ymax)<snap) && (QABS(ymax-ry) < deltaY))
00366 {
00367 deltaY =ry-ymax;
00368 ny = ymax - ch;
00369 }
00370 }
00371
00372
00373 snap = options->windowSnapZone;
00374 if (snap)
00375 {
00376 TQValueList<Client *>::ConstIterator l;
00377 for (l = clients.begin();l != clients.end();++l )
00378 {
00379 if ((*l)->isOnDesktop(currentDesktop()) &&
00380 !(*l)->isMinimized()
00381 && (*l) != c )
00382 {
00383 lx = (*l)->x();
00384 ly = (*l)->y();
00385 lrx = lx + (*l)->width();
00386 lry = ly + (*l)->height();
00387
00388 if ( (( cy <= lry ) && ( cy >= ly )) ||
00389 (( ry >= ly ) && ( ry <= lry )) ||
00390 (( cy <= ly ) && ( ry >= lry )) )
00391 {
00392 if ((sOWO?(cx<lrx):true) && (QABS(lrx-cx)<snap) && ( QABS(lrx -cx) < deltaX) )
00393 {
00394 deltaX = QABS( lrx - cx );
00395 nx = lrx;
00396 }
00397 if ((sOWO?(rx>lx):true) && (QABS(rx-lx)<snap) && ( QABS( rx - lx )<deltaX) )
00398 {
00399 deltaX = QABS(rx - lx);
00400 nx = lx - cw;
00401 }
00402 }
00403
00404 if ( (( cx <= lrx ) && ( cx >= lx )) ||
00405 (( rx >= lx ) && ( rx <= lrx )) ||
00406 (( cx <= lx ) && ( rx >= lrx )) )
00407 {
00408 if ((sOWO?(cy<lry):true) && (QABS(lry-cy)<snap) && (QABS( lry -cy ) < deltaY))
00409 {
00410 deltaY = QABS( lry - cy );
00411 ny = lry;
00412 }
00413
00414 if ((sOWO?(ry>ly):true) && (QABS(ry-ly)<snap) && (QABS( ry - ly ) < deltaY ))
00415 {
00416 deltaY = QABS( ry - ly );
00417 ny = ly - ch;
00418 }
00419 }
00420 }
00421 }
00422 }
00423 pos = TQPoint(nx, ny);
00424 }
00425 return pos;
00426 }
00427
00428 TQRect Workspace::adjustClientSize( Client* c, TQRect moveResizeGeom, int mode )
00429 {
00430
00431
00432
00433 if ( options->windowSnapZone || options->borderSnapZone )
00434 {
00435 const bool sOWO=options->snapOnlyWhenOverlapping;
00436
00437 const TQRect maxRect = clientArea(MovementArea, c->rect().center(), c->desktop());
00438 const int xmin = maxRect.left();
00439 const int xmax = maxRect.right();
00440 const int ymin = maxRect.top();
00441 const int ymax = maxRect.bottom();
00442
00443 const int cx(moveResizeGeom.left());
00444 const int cy(moveResizeGeom.top());
00445 const int rx(moveResizeGeom.right());
00446 const int ry(moveResizeGeom.bottom());
00447
00448 int newcx(cx), newcy(cy);
00449 int newrx(rx), newry(ry);
00450 int deltaX(xmax);
00451 int deltaY(ymax);
00452
00453 int lx, ly, lrx, lry;
00454
00455
00456 int snap = options->borderSnapZone;
00457 if (snap)
00458 {
00459 deltaX = int(snap);
00460 deltaY = int(snap);
00461
00462 #define SNAP_BORDER_TOP \
00463 if ((sOWO?(newcy<ymin):true) && (QABS(ymin-newcy)<deltaY)) \
00464 { \
00465 deltaY = QABS(ymin-newcy); \
00466 newcy = ymin; \
00467 }
00468
00469 #define SNAP_BORDER_BOTTOM \
00470 if ((sOWO?(newry>ymax):true) && (QABS(ymax-newry)<deltaY)) \
00471 { \
00472 deltaY = QABS(ymax-newcy); \
00473 newry = ymax; \
00474 }
00475
00476 #define SNAP_BORDER_LEFT \
00477 if ((sOWO?(newcx<xmin):true) && (QABS(xmin-newcx)<deltaX)) \
00478 { \
00479 deltaX = QABS(xmin-newcx); \
00480 newcx = xmin; \
00481 }
00482
00483 #define SNAP_BORDER_RIGHT \
00484 if ((sOWO?(newrx>xmax):true) && (QABS(xmax-newrx)<deltaX)) \
00485 { \
00486 deltaX = QABS(xmax-newrx); \
00487 newrx = xmax; \
00488 }
00489 switch ( mode )
00490 {
00491 case PositionBottomRight:
00492 SNAP_BORDER_BOTTOM
00493 SNAP_BORDER_RIGHT
00494 break;
00495 case PositionRight:
00496 SNAP_BORDER_RIGHT
00497 break;
00498 case PositionBottom:
00499 SNAP_BORDER_BOTTOM
00500 break;
00501 case PositionTopLeft:
00502 SNAP_BORDER_TOP
00503 SNAP_BORDER_LEFT
00504 break;
00505 case PositionLeft:
00506 SNAP_BORDER_LEFT
00507 break;
00508 case PositionTop:
00509 SNAP_BORDER_TOP
00510 break;
00511 case PositionTopRight:
00512 SNAP_BORDER_TOP
00513 SNAP_BORDER_RIGHT
00514 break;
00515 case PositionBottomLeft:
00516 SNAP_BORDER_BOTTOM
00517 SNAP_BORDER_LEFT
00518 break;
00519 default:
00520 assert( false );
00521 break;
00522 }
00523
00524
00525 }
00526
00527
00528 snap = options->windowSnapZone;
00529 if (snap)
00530 {
00531 deltaX = int(snap);
00532 deltaY = int(snap);
00533 TQValueList<Client *>::ConstIterator l;
00534 for (l = clients.begin();l != clients.end();++l )
00535 {
00536 if ((*l)->isOnDesktop(currentDesktop()) &&
00537 !(*l)->isMinimized()
00538 && (*l) != c )
00539 {
00540 lx = (*l)->x()-1;
00541 ly = (*l)->y()-1;
00542 lrx =(*l)->x() + (*l)->width();
00543 lry =(*l)->y() + (*l)->height();
00544
00545 #define WITHIN_HEIGHT ((( newcy <= lry ) && ( newcy >= ly )) || \
00546 (( newry >= ly ) && ( newry <= lry )) || \
00547 (( newcy <= ly ) && ( newry >= lry )) )
00548
00549 #define WITHIN_WIDTH ( (( cx <= lrx ) && ( cx >= lx )) || \
00550 (( rx >= lx ) && ( rx <= lrx )) || \
00551 (( cx <= lx ) && ( rx >= lrx )) )
00552
00553 #define SNAP_WINDOW_TOP if ( (sOWO?(newcy<lry):true) \
00554 && WITHIN_WIDTH \
00555 && (QABS( lry - newcy ) < deltaY) ) { \
00556 deltaY = QABS( lry - newcy ); \
00557 newcy=lry; \
00558 }
00559
00560 #define SNAP_WINDOW_BOTTOM if ( (sOWO?(newry>ly):true) \
00561 && WITHIN_WIDTH \
00562 && (QABS( ly - newry ) < deltaY) ) { \
00563 deltaY = QABS( ly - newry ); \
00564 newry=ly; \
00565 }
00566
00567 #define SNAP_WINDOW_LEFT if ( (sOWO?(newcx<lrx):true) \
00568 && WITHIN_HEIGHT \
00569 && (QABS( lrx - newcx ) < deltaX)) { \
00570 deltaX = QABS( lrx - newcx ); \
00571 newcx=lrx; \
00572 }
00573
00574 #define SNAP_WINDOW_RIGHT if ( (sOWO?(newrx>lx):true) \
00575 && WITHIN_HEIGHT \
00576 && (QABS( lx - newrx ) < deltaX)) \
00577 { \
00578 deltaX = QABS( lx - newrx ); \
00579 newrx=lx; \
00580 }
00581
00582 switch ( mode )
00583 {
00584 case PositionBottomRight:
00585 SNAP_WINDOW_BOTTOM
00586 SNAP_WINDOW_RIGHT
00587 break;
00588 case PositionRight:
00589 SNAP_WINDOW_RIGHT
00590 break;
00591 case PositionBottom:
00592 SNAP_WINDOW_BOTTOM
00593 break;
00594 case PositionTopLeft:
00595 SNAP_WINDOW_TOP
00596 SNAP_WINDOW_LEFT
00597 break;
00598 case PositionLeft:
00599 SNAP_WINDOW_LEFT
00600 break;
00601 case PositionTop:
00602 SNAP_WINDOW_TOP
00603 break;
00604 case PositionTopRight:
00605 SNAP_WINDOW_TOP
00606 SNAP_WINDOW_RIGHT
00607 break;
00608 case PositionBottomLeft:
00609 SNAP_WINDOW_BOTTOM
00610 SNAP_WINDOW_LEFT
00611 break;
00612 default:
00613 assert( false );
00614 break;
00615 }
00616 }
00617 }
00618 }
00619 moveResizeGeom = TQRect(TQPoint(newcx, newcy), TQPoint(newrx, newry));
00620 }
00621 return moveResizeGeom;
00622 }
00623
00627 void Workspace::setClientIsMoving( Client *c )
00628 {
00629 Q_ASSERT(!c || !movingClient);
00630
00631 movingClient = c;
00632 if (movingClient)
00633 ++block_focus;
00634 else
00635 --block_focus;
00636 }
00637
00641 void Workspace::cascadeDesktop()
00642 {
00643
00644 Q_ASSERT( block_stacking_updates == 0 );
00645 ClientList::ConstIterator it(stackingOrder().begin());
00646 initPositioning->reinitCascading( currentDesktop());
00647 TQRect area = clientArea( PlacementArea, TQPoint( 0, 0 ), currentDesktop());
00648 for (; it != stackingOrder().end(); ++it)
00649 {
00650 if((!(*it)->isOnDesktop(currentDesktop())) ||
00651 ((*it)->isMinimized()) ||
00652 ((*it)->isOnAllDesktops()) ||
00653 (!(*it)->isMovable()) )
00654 continue;
00655 initPositioning->placeCascaded(*it, area);
00656 }
00657 }
00658
00663 void Workspace::unclutterDesktop()
00664 {
00665 ClientList::Iterator it(clients.fromLast());
00666 for (; it != clients.end(); --it)
00667 {
00668 if((!(*it)->isOnDesktop(currentDesktop())) ||
00669 ((*it)->isMinimized()) ||
00670 ((*it)->isOnAllDesktops()) ||
00671 (!(*it)->isMovable()) )
00672 continue;
00673 initPositioning->placeSmart(*it, TQRect());
00674 }
00675 }
00676
00677
00678 void Workspace::updateTopMenuGeometry( Client* c )
00679 {
00680 if( !managingTopMenus())
00681 return;
00682 if( c != NULL )
00683 {
00684 XEvent ev;
00685 ev.xclient.display = qt_xdisplay();
00686 ev.xclient.type = ClientMessage;
00687 ev.xclient.window = c->window();
00688 static Atom msg_type_atom = XInternAtom( qt_xdisplay(), "_KDE_TOPMENU_MINSIZE", False );
00689 ev.xclient.message_type = msg_type_atom;
00690 ev.xclient.format = 32;
00691 ev.xclient.data.l[0] = qt_x_time;
00692 ev.xclient.data.l[1] = topmenu_space->width();
00693 ev.xclient.data.l[2] = topmenu_space->height();
00694 ev.xclient.data.l[3] = 0;
00695 ev.xclient.data.l[4] = 0;
00696 XSendEvent( qt_xdisplay(), c->window(), False, NoEventMask, &ev );
00697 KWin::setStrut( c->window(), 0, 0, topmenu_height, 0 );
00698 c->checkWorkspacePosition();
00699 return;
00700 }
00701
00702 TQRect area;
00703 area = clientArea( MaximizeFullArea, TQPoint( 0, 0 ), 1 );
00704 area.setHeight( topMenuHeight());
00705 topmenu_space->setGeometry( area );
00706 for( ClientList::ConstIterator it = topmenus.begin();
00707 it != topmenus.end();
00708 ++it )
00709 updateTopMenuGeometry( *it );
00710 }
00711
00712
00713
00714
00715
00716
00717 void Client::keepInArea( TQRect area, bool partial )
00718 {
00719 if( partial )
00720 {
00721
00722 area.setLeft( QMIN( area.left() - width() + 100, area.left()));
00723 area.setTop( QMIN( area.top() - height() + 100, area.top()));
00724 area.setRight( QMAX( area.right() + width() - 100, area.right()));
00725 area.setBottom( QMAX( area.bottom() + height() - 100, area.bottom()));
00726 }
00727 if ( geometry().right() > area.right() && width() < area.width() )
00728 move( area.right() - width(), y() );
00729 if ( geometry().bottom() > area.bottom() && height() < area.height() )
00730 move( x(), area.bottom() - height() );
00731 if( !area.contains( geometry().topLeft() ))
00732 {
00733 int tx = x();
00734 int ty = y();
00735 if ( tx < area.x() )
00736 tx = area.x();
00737 if ( ty < area.y() )
00738 ty = area.y();
00739 move( tx, ty );
00740 }
00741 }
00742
00748
00749
00750 TQRect Client::adjustedClientArea( const TQRect &desktopArea, const TQRect& area ) const
00751 {
00752 TQRect r = area;
00753
00754 if( isTopMenu())
00755 return r;
00756 NETExtendedStrut str = strut();
00757 TQRect stareaL = TQRect(
00758 0,
00759 str . left_start,
00760 str . left_width,
00761 str . left_end - str . left_start + 1 );
00762 TQRect stareaR = TQRect (
00763 desktopArea . right () - str . right_width + 1,
00764 str . right_start,
00765 str . right_width,
00766 str . right_end - str . right_start + 1 );
00767 TQRect stareaT = TQRect (
00768 str . top_start,
00769 0,
00770 str . top_end - str . top_start + 1,
00771 str . top_width);
00772 TQRect stareaB = TQRect (
00773 str . bottom_start,
00774 desktopArea . bottom () - str . bottom_width + 1,
00775 str . bottom_end - str . bottom_start + 1,
00776 str . bottom_width);
00777
00778 NETExtendedStrut ext = info->extendedStrut();
00779 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
00780 && ( str.left_width != 0 || str.right_width != 0 || str.top_width != 0 || str.bottom_width != 0 )) {
00781
00782
00783
00784
00785
00786
00787
00788 if (stareaT.top() == geometry().top() && stareaT.bottom() == geometry().bottom()) {
00789 stareaT.setLeft(geometry().left());
00790 stareaT.setRight(geometry().right());
00791
00792 }
00793 if (stareaB.top() == geometry().top() && stareaB.bottom() == geometry().bottom()) {
00794 stareaB.setLeft(geometry().left());
00795 stareaB.setRight(geometry().right());
00796
00797 }
00798 if (stareaL.left() == geometry().left() && stareaL.right() == geometry().right()) {
00799 stareaL.setTop(geometry().top());
00800 stareaL.setBottom(geometry().bottom());
00801
00802 }
00803 if (stareaR.left() == geometry().left() && stareaR.right() == geometry().right()) {
00804 stareaR.setTop(geometry().top());
00805 stareaR.setBottom(geometry().bottom());
00806
00807 }
00808 }
00809
00810 TQRect screenarea = workspace()->clientArea( ScreenArea, this );
00811
00812
00813
00814 if( area == kapp->desktop()->geometry())
00815 {
00816 if( stareaL.left() < screenarea.left())
00817 stareaL = TQRect();
00818 if( stareaR.right() > screenarea.right())
00819 stareaR = TQRect();
00820 if( stareaT.top() < screenarea.top())
00821 stareaT = TQRect();
00822 if( stareaB.bottom() < screenarea.bottom())
00823 stareaB = TQRect();
00824 }
00825
00826
00827
00828 stareaL.setLeft( KMAX( stareaL.left(), screenarea.left()));
00829 stareaR.setRight( KMIN( stareaR.right(), screenarea.right()));
00830 stareaT.setTop( KMAX( stareaT.top(), screenarea.top()));
00831 stareaB.setBottom( KMIN( stareaB.bottom(), screenarea.bottom()));
00832
00833 if (stareaL . intersects (area)) {
00834
00835 r . setLeft( stareaL . right() + 1 );
00836 }
00837 if (stareaR . intersects (area)) {
00838
00839 r . setRight( stareaR . left() - 1 );
00840 }
00841 if (stareaT . intersects (area)) {
00842
00843 r . setTop( stareaT . bottom() + 1 );
00844 }
00845 if (stareaB . intersects (area)) {
00846
00847 r . setBottom( stareaB . top() - 1 );
00848 }
00849 return r;
00850 }
00851
00852 NETExtendedStrut Client::strut() const
00853 {
00854 NETExtendedStrut ext = info->extendedStrut();
00855 NETStrut str = info->strut();
00856 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0
00857 && ( str.left != 0 || str.right != 0 || str.top != 0 || str.bottom != 0 ))
00858 {
00859
00860 if( str.left != 0 )
00861 {
00862 ext.left_width = str.left;
00863 ext.left_start = 0;
00864 ext.left_end = XDisplayHeight( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00865 }
00866 if( str.right != 0 )
00867 {
00868 ext.right_width = str.right;
00869 ext.right_start = 0;
00870 ext.right_end = XDisplayHeight( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00871 }
00872 if( str.top != 0 )
00873 {
00874 ext.top_width = str.top;
00875 ext.top_start = 0;
00876 ext.top_end = XDisplayWidth( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00877 }
00878 if( str.bottom != 0 )
00879 {
00880 ext.bottom_width = str.bottom;
00881 ext.bottom_start = 0;
00882 ext.bottom_end = XDisplayWidth( qt_xdisplay(), DefaultScreen( qt_xdisplay()));
00883 }
00884 }
00885 return ext;
00886 }
00887
00888 bool Client::hasStrut() const
00889 {
00890 NETExtendedStrut ext = strut();
00891 if( ext.left_width == 0 && ext.right_width == 0 && ext.top_width == 0 && ext.bottom_width == 0 )
00892 return false;
00893 return true;
00894 }
00895
00896
00897
00898 void Client::updateWorkareaDiffs()
00899 {
00900 TQRect area = workspace()->clientArea( WorkArea, this );
00901 TQRect geom = geometry();
00902 workarea_diff_x = computeWorkareaDiff( geom.left(), geom.right(), area.left(), area.right());
00903 workarea_diff_y = computeWorkareaDiff( geom.top(), geom.bottom(), area.top(), area.bottom());
00904 }
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914 int Client::computeWorkareaDiff( int left, int right, int a_left, int a_right )
00915 {
00916 int left_diff = left - a_left;
00917 int right_diff = a_right - right;
00918 if( left_diff < 0 || right_diff < 0 )
00919 return INT_MIN;
00920 else
00921 {
00922
00923 int max_diff = ( a_right - a_left ) / 10;
00924 if( left_diff < right_diff )
00925 return left_diff < max_diff ? -left_diff - 1 : INT_MAX;
00926 else if( left_diff > right_diff )
00927 return right_diff < max_diff ? right_diff + 1 : INT_MAX;
00928 return INT_MAX;
00929 }
00930 }
00931
00932 void Client::checkWorkspacePosition()
00933 {
00934 if( isDesktop())
00935 {
00936 TQRect area = workspace()->clientArea( FullArea, this );
00937 if( geometry() != area )
00938 setGeometry( area );
00939 return;
00940 }
00941 if( isFullScreen())
00942 {
00943 TQRect area = workspace()->clientArea( FullScreenArea, this );
00944 if( geometry() != area )
00945 setGeometry( area );
00946 return;
00947 }
00948 if( isDock())
00949 return;
00950 if( isTopMenu())
00951 {
00952 if( workspace()->managingTopMenus())
00953 {
00954 TQRect area;
00955 ClientList mainclients = mainClients();
00956 if( mainclients.count() == 1 )
00957 area = workspace()->clientArea( MaximizeFullArea, mainclients.first());
00958 else
00959 area = workspace()->clientArea( MaximizeFullArea, TQPoint( 0, 0 ), desktop());
00960 area.setHeight( workspace()->topMenuHeight());
00961
00962 setGeometry( area );
00963 }
00964 return;
00965 }
00966
00967 if( maximizeMode() != MaximizeRestore )
00968
00969 changeMaximize( false, false, true );
00970
00971 if( !isShade())
00972 {
00973 int old_diff_x = workarea_diff_x;
00974 int old_diff_y = workarea_diff_y;
00975 updateWorkareaDiffs();
00976
00977
00978
00979
00980
00981
00982 if( workspace()->initializing())
00983 return;
00984
00985 TQRect area = workspace()->clientArea( WorkArea, this );
00986 TQRect new_geom = geometry();
00987 TQRect tmp_rect_x( new_geom.left(), 0, new_geom.width(), 0 );
00988 TQRect tmp_area_x( area.left(), 0, area.width(), 0 );
00989 checkDirection( workarea_diff_x, old_diff_x, tmp_rect_x, tmp_area_x );
00990
00991 TQRect tmp_rect_y( new_geom.top(), 0, new_geom.height(), 0 );
00992 TQRect tmp_area_y( area.top(), 0, area.height(), 0 );
00993 checkDirection( workarea_diff_y, old_diff_y, tmp_rect_y, tmp_area_y );
00994 new_geom = TQRect( tmp_rect_x.left(), tmp_rect_y.left(), tmp_rect_x.width(), tmp_rect_y.width());
00995 TQRect final_geom( new_geom.topLeft(), adjustedSize( new_geom.size()));
00996 if( final_geom != new_geom )
00997 {
00998 if( old_diff_x != INT_MAX && old_diff_x > 0 )
00999 final_geom.moveRight( area.right() - ( old_diff_x - 1 ));
01000 if( old_diff_y != INT_MAX && old_diff_y > 0 )
01001 final_geom.moveBottom( area.bottom() - ( old_diff_y - 1 ));
01002 }
01003 if( final_geom != geometry() )
01004 setGeometry( final_geom );
01005
01006 }
01007 }
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 void Client::checkDirection( int new_diff, int old_diff, TQRect& rect, const TQRect& area )
01020 {
01021 if( old_diff != INT_MIN )
01022 {
01023 if( old_diff == INT_MAX )
01024 {
01025 if( new_diff == INT_MIN )
01026 {
01027 rect.setLeft( area.left());
01028 rect.setRight( area.right());
01029 }
01030 return;
01031 }
01032 if( isMovable())
01033 {
01034 if( old_diff < 0 )
01035 rect.moveLeft( area.left() + ( -old_diff - 1 ));
01036 else
01037 rect.moveRight( area.right() - ( old_diff - 1 ));
01038 }
01039 else if( isResizable())
01040 {
01041 if( old_diff < 0 )
01042 rect.setLeft( area.left() + ( -old_diff - 1 ) );
01043 else
01044 rect.setRight( area.right() - ( old_diff - 1 ));
01045 }
01046 if( rect.width() > area.width() && isResizable())
01047 rect.setWidth( area.width());
01048 if( isMovable())
01049 {
01050 if( rect.left() < area.left())
01051 rect.moveLeft( area.left());
01052 else if( rect.right() > area.right())
01053 rect.moveRight( area.right());
01054 }
01055 }
01056 if( rect.right() < area.left() + 5 || rect.left() > area.right() - 5 )
01057 {
01058 if( isMovable())
01059 {
01060 if( rect.left() < area.left() + 5 )
01061 rect.moveRight( area.left() + 5 );
01062 if( rect.right() > area.right() - 5 )
01063 rect.moveLeft( area.right() - 5 );
01064 }
01065 }
01066 if (!moveResizeMode && options->shadowEnabled(isActive()))
01067 {
01068
01069
01070 removeShadow();
01071 drawIntersectingShadows();
01072 if (options->shadowEnabled(isActive()))
01073 drawDelayedShadow();
01074 }
01075 }
01076
01080 TQSize Client::adjustedSize( const TQSize& frame, Sizemode mode ) const
01081 {
01082
01083
01084 TQSize wsize( frame.width() - ( border_left + border_right ),
01085 frame.height() - ( border_top + border_bottom ));
01086 if( wsize.isEmpty())
01087 wsize = TQSize( 1, 1 );
01088
01089 return sizeForClientSize( wsize, mode, false );
01090 }
01091
01092
01093
01094 TQSize Client::adjustedSize() const
01095 {
01096 return sizeForClientSize( clientSize());
01097 }
01098
01107 TQSize Client::sizeForClientSize( const TQSize& wsize, Sizemode mode, bool noframe ) const
01108 {
01109 int w = wsize.width();
01110 int h = wsize.height();
01111 if( w < 1 || h < 1 )
01112 {
01113 kdWarning() << "sizeForClientSize() with empty size!" << endl;
01114 kdWarning() << kdBacktrace() << endl;
01115 }
01116 if (w<1) w = 1;
01117 if (h<1) h = 1;
01118
01119
01120
01121 TQSize min_size = minSize();
01122 TQSize max_size = maxSize();
01123 if( decoration != NULL )
01124 {
01125 TQSize decominsize = decoration->minimumSize();
01126 TQSize border_size( border_left + border_right, border_top + border_bottom );
01127 if( border_size.width() > decominsize.width())
01128 decominsize.setWidth( border_size.width());
01129 if( border_size.height() > decominsize.height())
01130 decominsize.setHeight( border_size.height());
01131 if( decominsize.width() > min_size.width())
01132 min_size.setWidth( decominsize.width());
01133 if( decominsize.height() > min_size.height())
01134 min_size.setHeight( decominsize.height());
01135 }
01136 w = QMIN( max_size.width(), w );
01137 h = QMIN( max_size.height(), h );
01138 w = QMAX( min_size.width(), w );
01139 h = QMAX( min_size.height(), h );
01140
01141 int w1 = w;
01142 int h1 = h;
01143 int width_inc = xSizeHint.width_inc;
01144 int height_inc = xSizeHint.height_inc;
01145 int basew_inc = xSizeHint.min_width;
01146 int baseh_inc = xSizeHint.min_height;
01147 w = int(( w - basew_inc ) / width_inc ) * width_inc + basew_inc;
01148 h = int(( h - baseh_inc ) / height_inc ) * height_inc + baseh_inc;
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164 if( xSizeHint.flags & PAspect )
01165 {
01166 double min_aspect_w = xSizeHint.min_aspect.x;
01167 double min_aspect_h = xSizeHint.min_aspect.y;
01168 double max_aspect_w = xSizeHint.max_aspect.x;
01169 double max_aspect_h = xSizeHint.max_aspect.y;
01170
01171
01172
01173 w -= xSizeHint.base_width;
01174 h -= xSizeHint.base_height;
01175 int max_width = max_size.width() - xSizeHint.base_width;
01176 int min_width = min_size.width() - xSizeHint.base_width;
01177 int max_height = max_size.height() - xSizeHint.base_height;
01178 int min_height = min_size.height() - xSizeHint.base_height;
01179 #define ASPECT_CHECK_GROW_W \
01180 if( min_aspect_w * h > min_aspect_h * w ) \
01181 { \
01182 int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
01183 if( w + delta <= max_width ) \
01184 w += delta; \
01185 }
01186 #define ASPECT_CHECK_SHRINK_H_GROW_W \
01187 if( min_aspect_w * h > min_aspect_h * w ) \
01188 { \
01189 int delta = int( h - w * min_aspect_h / min_aspect_w ) / height_inc * height_inc; \
01190 if( h - delta >= min_height ) \
01191 h -= delta; \
01192 else \
01193 { \
01194 int delta = int( min_aspect_w * h / min_aspect_h - w ) / width_inc * width_inc; \
01195 if( w + delta <= max_width ) \
01196 w += delta; \
01197 } \
01198 }
01199 #define ASPECT_CHECK_GROW_H \
01200 if( max_aspect_w * h < max_aspect_h * w ) \
01201 { \
01202 int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
01203 if( h + delta <= max_height ) \
01204 h += delta; \
01205 }
01206 #define ASPECT_CHECK_SHRINK_W_GROW_H \
01207 if( max_aspect_w * h < max_aspect_h * w ) \
01208 { \
01209 int delta = int( w - max_aspect_w * h / max_aspect_h ) / width_inc * width_inc; \
01210 if( w - delta >= min_width ) \
01211 w -= delta; \
01212 else \
01213 { \
01214 int delta = int( w * max_aspect_h / max_aspect_w - h ) / height_inc * height_inc; \
01215 if( h + delta <= max_height ) \
01216 h += delta; \
01217 } \
01218 }
01219 switch( mode )
01220 {
01221 case SizemodeAny:
01222 #if 0 // make SizemodeAny equal to SizemodeFixedW - prefer keeping fixed width,
01223
01224 {
01225 ASPECT_CHECK_SHRINK_H_GROW_W
01226 ASPECT_CHECK_SHRINK_W_GROW_H
01227 ASPECT_CHECK_GROW_H
01228 ASPECT_CHECK_GROW_W
01229 break;
01230 }
01231 #endif
01232 case SizemodeFixedW:
01233 {
01234
01235 ASPECT_CHECK_GROW_H
01236 ASPECT_CHECK_SHRINK_H_GROW_W
01237 ASPECT_CHECK_SHRINK_W_GROW_H
01238 ASPECT_CHECK_GROW_W
01239 break;
01240 }
01241 case SizemodeFixedH:
01242 {
01243 ASPECT_CHECK_GROW_W
01244 ASPECT_CHECK_SHRINK_W_GROW_H
01245 ASPECT_CHECK_SHRINK_H_GROW_W
01246 ASPECT_CHECK_GROW_H
01247 break;
01248 }
01249 case SizemodeMax:
01250 {
01251
01252 ASPECT_CHECK_SHRINK_H_GROW_W
01253 ASPECT_CHECK_SHRINK_W_GROW_H
01254 ASPECT_CHECK_GROW_W
01255 ASPECT_CHECK_GROW_H
01256 break;
01257 }
01258 }
01259 #undef ASPECT_CHECK_SHRINK_H_GROW_W
01260 #undef ASPECT_CHECK_SHRINK_W_GROW_H
01261 #undef ASPECT_CHECK_GROW_W
01262 #undef ASPECT_CHECK_GROW_H
01263 w += xSizeHint.base_width;
01264 h += xSizeHint.base_height;
01265 }
01266 if( !rules()->checkStrictGeometry( false ))
01267 {
01268
01269 if( maximizeMode() & MaximizeHorizontal )
01270 w = w1;
01271 if( maximizeMode() & MaximizeVertical )
01272 h = h1;
01273 }
01274
01275 if( !noframe )
01276 {
01277 w += border_left + border_right;
01278 h += border_top + border_bottom;
01279 }
01280 return rules()->checkSize( TQSize( w, h ));
01281 }
01282
01286 void Client::getWmNormalHints()
01287 {
01288 long msize;
01289 if (XGetWMNormalHints(qt_xdisplay(), window(), &xSizeHint, &msize) == 0 )
01290 xSizeHint.flags = 0;
01291
01292
01293 if( ! ( xSizeHint.flags & PMinSize ))
01294 xSizeHint.min_width = xSizeHint.min_height = 0;
01295 if( xSizeHint.flags & PBaseSize )
01296 {
01297
01298
01299
01300 if( ! ( xSizeHint.flags & PMinSize ))
01301 {
01302 xSizeHint.min_width = xSizeHint.base_width;
01303 xSizeHint.min_height = xSizeHint.base_height;
01304 }
01305 }
01306 else
01307 xSizeHint.base_width = xSizeHint.base_height = 0;
01308 if( ! ( xSizeHint.flags & PMaxSize ))
01309 xSizeHint.max_width = xSizeHint.max_height = INT_MAX;
01310 else
01311 {
01312 xSizeHint.max_width = QMAX( xSizeHint.max_width, 1 );
01313 xSizeHint.max_height = QMAX( xSizeHint.max_height, 1 );
01314 }
01315 if( xSizeHint.flags & PResizeInc )
01316 {
01317 xSizeHint.width_inc = kMax( xSizeHint.width_inc, 1 );
01318 xSizeHint.height_inc = kMax( xSizeHint.height_inc, 1 );
01319 }
01320 else
01321 {
01322 xSizeHint.width_inc = 1;
01323 xSizeHint.height_inc = 1;
01324 }
01325 if( xSizeHint.flags & PAspect )
01326 {
01327 xSizeHint.min_aspect.y = kMax( xSizeHint.min_aspect.y, 1 );
01328 xSizeHint.max_aspect.y = kMax( xSizeHint.max_aspect.y, 1 );
01329 }
01330 else
01331 {
01332 xSizeHint.min_aspect.x = 1;
01333 xSizeHint.min_aspect.y = INT_MAX;
01334 xSizeHint.max_aspect.x = INT_MAX;
01335 xSizeHint.max_aspect.y = 1;
01336 }
01337 if( ! ( xSizeHint.flags & PWinGravity ))
01338 xSizeHint.win_gravity = NorthWestGravity;
01339 if( isManaged())
01340 {
01341 TQSize new_size = adjustedSize();
01342 if( new_size != size() && !isFullScreen())
01343 {
01344 TQRect orig_geometry = geometry();
01345 resizeWithChecks( new_size );
01346 if( ( !isSpecialWindow() || isToolbar()) && !isFullScreen())
01347 {
01348
01349
01350 TQRect area = workspace()->clientArea( MovementArea, this );
01351 if( area.contains( orig_geometry ))
01352 keepInArea( area );
01353 area = workspace()->clientArea( WorkArea, this );
01354 if( area.contains( orig_geometry ))
01355 keepInArea( area );
01356 }
01357 }
01358 }
01359 updateAllowedActions();
01360 }
01361
01362 TQSize Client::minSize() const
01363 {
01364 return rules()->checkMinSize( TQSize( xSizeHint.min_width, xSizeHint.min_height ));
01365 }
01366
01367 TQSize Client::maxSize() const
01368 {
01369 return rules()->checkMaxSize( TQSize( xSizeHint.max_width, xSizeHint.max_height ));
01370 }
01371
01377 void Client::sendSyntheticConfigureNotify()
01378 {
01379 XConfigureEvent c;
01380 c.type = ConfigureNotify;
01381 c.send_event = True;
01382 c.event = window();
01383 c.window = window();
01384 c.x = x() + clientPos().x();
01385 c.y = y() + clientPos().y();
01386 c.width = clientSize().width();
01387 c.height = clientSize().height();
01388 c.border_width = 0;
01389 c.above = None;
01390 c.override_redirect = 0;
01391 XSendEvent( qt_xdisplay(), c.event, TRUE, StructureNotifyMask, (XEvent*)&c );
01392 }
01393
01394 const TQPoint Client::calculateGravitation( bool invert, int gravity ) const
01395 {
01396 int dx, dy;
01397 dx = dy = 0;
01398
01399 if( gravity == 0 )
01400 gravity = xSizeHint.win_gravity;
01401
01402
01403 switch (gravity)
01404 {
01405 case NorthWestGravity:
01406 default:
01407 dx = border_left;
01408 dy = border_top;
01409 break;
01410 case NorthGravity:
01411 dx = 0;
01412 dy = border_top;
01413 break;
01414 case NorthEastGravity:
01415 dx = -border_right;
01416 dy = border_top;
01417 break;
01418 case WestGravity:
01419 dx = border_left;
01420 dy = 0;
01421 break;
01422 case CenterGravity:
01423 break;
01424 case StaticGravity:
01425 dx = 0;
01426 dy = 0;
01427 break;
01428 case EastGravity:
01429 dx = -border_right;
01430 dy = 0;
01431 break;
01432 case SouthWestGravity:
01433 dx = border_left ;
01434 dy = -border_bottom;
01435 break;
01436 case SouthGravity:
01437 dx = 0;
01438 dy = -border_bottom;
01439 break;
01440 case SouthEastGravity:
01441 dx = -border_right;
01442 dy = -border_bottom;
01443 break;
01444 }
01445 if( gravity != CenterGravity )
01446 {
01447 dx -= border_left;
01448 dy -= border_top;
01449 }
01450 else
01451 {
01452 dx = - ( border_left + border_right ) / 2;
01453 dy = - ( border_top + border_bottom ) / 2;
01454 }
01455 if( !invert )
01456 return TQPoint( x() + dx, y() + dy );
01457 else
01458 return TQPoint( x() - dx, y() - dy );
01459 }
01460
01461 void Client::configureRequest( int value_mask, int rx, int ry, int rw, int rh, int gravity, bool from_tool )
01462 {
01463 if( gravity == 0 )
01464 gravity = xSizeHint.win_gravity;
01465 if( value_mask & ( CWX | CWY ))
01466 {
01467 TQPoint new_pos = calculateGravitation( true, gravity );
01468 if ( value_mask & CWX )
01469 new_pos.setX( rx );
01470 if ( value_mask & CWY )
01471 new_pos.setY( ry );
01472
01473
01474
01475
01476
01477 if ( new_pos.x() == x() + clientPos().x() && new_pos.y() == y() + clientPos().y()
01478 && gravity == NorthWestGravity && !from_tool )
01479 {
01480 new_pos.setX( x());
01481 new_pos.setY( y());
01482 }
01483
01484 int nw = clientSize().width();
01485 int nh = clientSize().height();
01486 if ( value_mask & CWWidth )
01487 nw = rw;
01488 if ( value_mask & CWHeight )
01489 nh = rh;
01490 TQSize ns = sizeForClientSize( TQSize( nw, nh ) );
01491 new_pos = rules()->checkPosition( new_pos );
01492
01493
01494 if ( maximizeMode() != MaximizeFull
01495 || ns != size())
01496 {
01497 TQRect orig_geometry = geometry();
01498 GeometryUpdatesPostponer blocker( this );
01499 move( new_pos );
01500 plainResize( ns );
01501 setGeometry( TQRect( calculateGravitation( false, gravity ), size()));
01502 updateFullScreenHack( TQRect( new_pos, TQSize( nw, nh )));
01503 TQRect area = workspace()->clientArea( WorkArea, this );
01504 if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen()
01505 && area.contains( orig_geometry ))
01506 keepInArea( area );
01507
01508
01509
01510
01511
01512 if (hasStrut ())
01513 workspace() -> updateClientArea ();
01514 }
01515 }
01516
01517 if ( value_mask & (CWWidth | CWHeight )
01518 && ! ( value_mask & ( CWX | CWY )) )
01519 {
01520 int nw = clientSize().width();
01521 int nh = clientSize().height();
01522 if ( value_mask & CWWidth )
01523 nw = rw;
01524 if ( value_mask & CWHeight )
01525 nh = rh;
01526 TQSize ns = sizeForClientSize( TQSize( nw, nh ) );
01527
01528 if( ns != size())
01529 {
01530 TQRect orig_geometry = geometry();
01531 GeometryUpdatesPostponer blocker( this );
01532 int save_gravity = xSizeHint.win_gravity;
01533 xSizeHint.win_gravity = gravity;
01534 resizeWithChecks( ns );
01535 xSizeHint.win_gravity = save_gravity;
01536 updateFullScreenHack( TQRect( calculateGravitation( true, xSizeHint.win_gravity ), TQSize( nw, nh )));
01537 if( !from_tool && ( !isSpecialWindow() || isToolbar()) && !isFullScreen())
01538 {
01539
01540
01541 TQRect area = workspace()->clientArea( MovementArea, this );
01542 if( area.contains( orig_geometry ))
01543 keepInArea( area );
01544 area = workspace()->clientArea( WorkArea, this );
01545 if( area.contains( orig_geometry ))
01546 keepInArea( area );
01547 }
01548 }
01549 }
01550
01551
01552
01553 }
01554
01555 void Client::resizeWithChecks( int w, int h, ForceGeometry_t force )
01556 {
01557 if( shade_geometry_change )
01558 assert( false );
01559 else if( isShade())
01560 {
01561 if( h == border_top + border_bottom )
01562 {
01563 kdWarning() << "Shaded geometry passed for size:" << endl;
01564 kdWarning() << kdBacktrace() << endl;
01565 }
01566 }
01567 int newx = x();
01568 int newy = y();
01569 TQRect area = workspace()->clientArea( WorkArea, this );
01570
01571 if( w > area.width())
01572 w = area.width();
01573 if( h > area.height())
01574 h = area.height();
01575 TQSize tmp = adjustedSize( TQSize( w, h ));
01576 w = tmp.width();
01577 h = tmp.height();
01578 switch( xSizeHint.win_gravity )
01579 {
01580 case NorthWestGravity:
01581 default:
01582 break;
01583 case NorthGravity:
01584 newx = ( newx + width() / 2 ) - ( w / 2 );
01585 break;
01586 case NorthEastGravity:
01587 newx = newx + width() - w;
01588 break;
01589 case WestGravity:
01590 newy = ( newy + height() / 2 ) - ( h / 2 );
01591 break;
01592 case CenterGravity:
01593 newx = ( newx + width() / 2 ) - ( w / 2 );
01594 newy = ( newy + height() / 2 ) - ( h / 2 );
01595 break;
01596 case StaticGravity:
01597
01598 break;
01599 case EastGravity:
01600 newx = newx + width() - w;
01601 newy = ( newy + height() / 2 ) - ( h / 2 );
01602 break;
01603 case SouthWestGravity:
01604 newy = newy + height() - h;
01605 break;
01606 case SouthGravity:
01607 newx = ( newx + width() / 2 ) - ( w / 2 );
01608 newy = newy + height() - h;
01609 break;
01610 case SouthEastGravity:
01611 newx = newx + width() - w;
01612 newy = newy + height() - h;
01613 break;
01614 }
01615
01616
01617 if( workarea_diff_x != INT_MIN && w <= area.width())
01618 {
01619 if( newx < area.left())
01620 newx = area.left();
01621 if( newx + w > area.right() + 1 )
01622 newx = area.right() + 1 - w;
01623 assert( newx >= area.left() && newx + w <= area.right() + 1 );
01624 }
01625 if( workarea_diff_y != INT_MIN && h <= area.height())
01626 {
01627 if( newy < area.top())
01628 newy = area.top();
01629 if( newy + h > area.bottom() + 1 )
01630 newy = area.bottom() + 1 - h;
01631 assert( newy >= area.top() && newy + h <= area.bottom() + 1 );
01632 }
01633 setGeometry( newx, newy, w, h, force );
01634 }
01635
01636
01637 void Client::NETMoveResizeWindow( int flags, int x, int y, int width, int height )
01638 {
01639 int gravity = flags & 0xff;
01640 int value_mask = 0;
01641 if( flags & ( 1 << 8 ))
01642 value_mask |= CWX;
01643 if( flags & ( 1 << 9 ))
01644 value_mask |= CWY;
01645 if( flags & ( 1 << 10 ))
01646 value_mask |= CWWidth;
01647 if( flags & ( 1 << 11 ))
01648 value_mask |= CWHeight;
01649 configureRequest( value_mask, x, y, width, height, gravity, true );
01650 }
01651
01656 bool Client::isMovable() const
01657 {
01658 if( !motif_may_move || isFullScreen())
01659 return false;
01660 if( isSpecialWindow() && !isSplash() && !isToolbar())
01661 return false;
01662 if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() )
01663 return false;
01664 if( rules()->checkPosition( invalidPoint ) != invalidPoint )
01665 return false;
01666 return true;
01667 }
01668
01672 bool Client::isResizable() const
01673 {
01674 if( !motif_may_resize || isFullScreen())
01675 return false;
01676 if( isSpecialWindow() )
01677 return false;
01678 if( maximizeMode() == MaximizeFull && !options->moveResizeMaximizedWindows() )
01679 return false;
01680 if( rules()->checkSize( TQSize()).isValid())
01681 return false;
01682
01683 TQSize min = minSize();
01684 TQSize max = maxSize();
01685 return min.width() < max.width() || min.height() < max.height();
01686 }
01687
01688
01689
01690
01691 bool Client::isMaximizable() const
01692 {
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( Qt::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 && o != 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(), qt_x_time ) == Success )
02323 has_grab = true;
02324 if( XGrabKeyboard( qt_xdisplay(), frameId(), False, GrabModeAsync, GrabModeAsync, 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(), qt_x_time );
02393 XUngrabPointer( qt_xdisplay(), 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, qt_x_time);
02646 }
02647
02648
02649 }