kwin Library API Documentation

placement.cpp

00001 /***************************************************************** 00002 KWin - the KDE window manager 00003 This file is part of the KDE project. 00004 00005 Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org> 00006 Copyright (C) 1997 to 2002 Cristian Tibirna <tibirna@kde.org> 00007 Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org> 00008 00009 You can Freely distribute this program under the GNU General Public 00010 License. See the file "COPYING" for the exact licensing terms. 00011 ******************************************************************/ 00012 00013 #include "placement.h" 00014 00015 #include <qrect.h> 00016 #include <assert.h> 00017 00018 #ifndef KCMRULES 00019 #include "workspace.h" 00020 #include "client.h" 00021 #include "options.h" 00022 #include "rules.h" 00023 #endif 00024 00025 namespace KWinInternal 00026 { 00027 00028 #ifndef KCMRULES 00029 00030 Placement::Placement(Workspace* w) 00031 { 00032 m_WorkspacePtr = w; 00033 00034 //CT initialize the cascading info 00035 for( int i = 0; i < m_WorkspacePtr->numberOfDesktops(); i++) 00036 { 00037 DesktopCascadingInfo inf; 00038 inf.pos = QPoint(0,0); 00039 inf.col = 0; 00040 inf.row = 0; 00041 cci.append(inf); 00042 } 00043 00044 } 00045 00049 void Placement::place(Client* c, QRect& area ) 00050 { 00051 Policy policy = c->rules()->checkPlacement( Default ); 00052 if( policy != Default ) 00053 return place( c, policy, area ); 00054 00055 if( c->isUtility()) 00056 placeUtility(c, area); 00057 else if( c->isDialog()) 00058 placeDialog(c, area); 00059 else if( c->isSplash()) 00060 placeOnMainWindow( c, area ); // on mainwindow, if any, otherwise centered 00061 else 00062 place(c, options->placement, area); 00063 } 00064 00065 void Placement::place(Client* c, Policy policy, QRect& area ) 00066 { 00067 if( policy == Default ) 00068 policy = options->placement; 00069 if( policy == NoPlacement ) 00070 return; 00071 else if (policy == Random) 00072 placeAtRandom(c, area); 00073 else if (policy == Cascade) 00074 placeCascaded(c, area); 00075 else if (policy == Centered) 00076 placeCentered(c, area); 00077 else if (policy == ZeroCornered) 00078 placeZeroCornered(c, area); 00079 else if (policy == UnderMouse) 00080 placeUnderMouse(c, area); 00081 else if (policy == OnMainWindow) 00082 placeOnMainWindow(c, area); 00083 else 00084 placeSmart(c, area); 00085 } 00086 00090 void Placement::placeAtRandom(Client* c, const QRect& area ) 00091 { 00092 const int step = 24; 00093 static int px = step; 00094 static int py = 2 * step; 00095 int tx,ty; 00096 00097 const QRect maxRect = checkArea( c, area ); 00098 00099 if (px < maxRect.x()) 00100 px = maxRect.x(); 00101 if (py < maxRect.y()) 00102 py = maxRect.y(); 00103 00104 px += step; 00105 py += 2*step; 00106 00107 if (px > maxRect.width()/2) 00108 px = maxRect.x() + step; 00109 if (py > maxRect.height()/2) 00110 py = maxRect.y() + step; 00111 tx = px; 00112 ty = py; 00113 if (tx + c->width() > maxRect.right()) 00114 { 00115 tx = maxRect.right() - c->width(); 00116 if (tx < 0) 00117 tx = 0; 00118 px = maxRect.x(); 00119 } 00120 if (ty + c->height() > maxRect.bottom()) 00121 { 00122 ty = maxRect.bottom() - c->height(); 00123 if (ty < 0) 00124 ty = 0; 00125 py = maxRect.y(); 00126 } 00127 c->move(tx, ty); 00128 } 00129 00133 void Placement::placeSmart(Client* c, const QRect& area ) 00134 { 00135 /* 00136 * SmartPlacement by Cristian Tibirna (tibirna@kde.org) 00137 * adapted for kwm (16-19jan98) and for kwin (16Nov1999) using (with 00138 * permission) ideas from fvwm, authored by 00139 * Anthony Martin (amartin@engr.csulb.edu). 00140 * Xinerama supported added by Balaji Ramani (balaji@yablibli.com) 00141 * with ideas from xfce. 00142 */ 00143 00144 const int none = 0, h_wrong = -1, w_wrong = -2; // overlap types 00145 long int overlap, min_overlap = 0; 00146 int x_optimal, y_optimal; 00147 int possible; 00148 int desktop = c->desktop() == 0 || c->isOnAllDesktops() ? m_WorkspacePtr->currentDesktop() : c->desktop(); 00149 00150 int cxl, cxr, cyt, cyb; //temp coords 00151 int xl, xr, yt, yb; //temp coords 00152 int basket; //temp holder 00153 00154 // get the maximum allowed windows space 00155 const QRect maxRect = checkArea( c, area ); 00156 int x = maxRect.left(), y = maxRect.top(); 00157 x_optimal = x; y_optimal = y; 00158 00159 //client gabarit 00160 int ch = c->height() - 1; 00161 int cw = c->width() - 1; 00162 00163 bool first_pass = true; //CT lame flag. Don't like it. What else would do? 00164 00165 //loop over possible positions 00166 do 00167 { 00168 //test if enough room in x and y directions 00169 if (y + ch > maxRect.bottom() && ch < maxRect.height()) 00170 overlap = h_wrong; // this throws the algorithm to an exit 00171 else if(x + cw > maxRect.right()) 00172 overlap = w_wrong; 00173 else 00174 { 00175 overlap = none; //initialize 00176 00177 cxl = x; cxr = x + cw; 00178 cyt = y; cyb = y + ch; 00179 ClientList::ConstIterator l; 00180 for(l = m_WorkspacePtr->stackingOrder().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++l) 00181 { 00182 if((*l)->isOnDesktop(desktop) && 00183 (*l)->isShown( false ) && (*l) != c) 00184 { 00185 00186 xl = (*l)->x(); yt = (*l)->y(); 00187 xr = xl + (*l)->width(); yb = yt + (*l)->height(); 00188 00189 //if windows overlap, calc the overall overlapping 00190 if((cxl < xr) && (cxr > xl) && 00191 (cyt < yb) && (cyb > yt)) 00192 { 00193 xl = QMAX(cxl, xl); xr = QMIN(cxr, xr); 00194 yt = QMAX(cyt, yt); yb = QMIN(cyb, yb); 00195 if((*l)->keepAbove()) 00196 overlap += 16 * (xr - xl) * (yb - yt); 00197 else if((*l)->keepBelow() && !(*l)->isDock()) // ignore KeepBelow windows 00198 overlap += 0; // for placement (see Client::belongsToLayer() for Dock) 00199 else 00200 overlap += (xr - xl) * (yb - yt); 00201 } 00202 } 00203 } 00204 } 00205 00206 //CT first time we get no overlap we stop. 00207 if (overlap == none) 00208 { 00209 x_optimal = x; 00210 y_optimal = y; 00211 break; 00212 } 00213 00214 if (first_pass) 00215 { 00216 first_pass = false; 00217 min_overlap = overlap; 00218 } 00219 //CT save the best position and the minimum overlap up to now 00220 else if (overlap >= none && overlap < min_overlap) 00221 { 00222 min_overlap = overlap; 00223 x_optimal = x; 00224 y_optimal = y; 00225 } 00226 00227 // really need to loop? test if there's any overlap 00228 if (overlap > none) 00229 { 00230 00231 possible = maxRect.right(); 00232 if (possible - cw > x) possible -= cw; 00233 00234 // compare to the position of each client on the same desk 00235 ClientList::ConstIterator l; 00236 for(l = m_WorkspacePtr->stackingOrder().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++l) 00237 { 00238 00239 if ((*l)->isOnDesktop(desktop) && 00240 (*l)->isShown( false ) && (*l) != c) 00241 { 00242 00243 xl = (*l)->x(); yt = (*l)->y(); 00244 xr = xl + (*l)->width(); yb = yt + (*l)->height(); 00245 00246 // if not enough room above or under the current tested client 00247 // determine the first non-overlapped x position 00248 if((y < yb) && (yt < ch + y)) 00249 { 00250 00251 if((xr > x) && (possible > xr)) possible = xr; 00252 00253 basket = xl - cw; 00254 if((basket > x) && (possible > basket)) possible = basket; 00255 } 00256 } 00257 } 00258 x = possible; 00259 } 00260 00261 // ... else ==> not enough x dimension (overlap was wrong on horizontal) 00262 else if (overlap == w_wrong) 00263 { 00264 x = maxRect.left(); 00265 possible = maxRect.bottom(); 00266 00267 if (possible - ch > y) possible -= ch; 00268 00269 //test the position of each window on the desk 00270 ClientList::ConstIterator l; 00271 for(l = m_WorkspacePtr->stackingOrder().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++l) 00272 { 00273 if((*l)->isOnDesktop(desktop) && 00274 (*l) != c && c->isShown( false )) 00275 { 00276 00277 xl = (*l)->x(); yt = (*l)->y(); 00278 xr = xl + (*l)->width(); yb = yt + (*l)->height(); 00279 00280 // if not enough room to the left or right of the current tested client 00281 // determine the first non-overlapped y position 00282 if((yb > y) && (possible > yb)) possible = yb; 00283 00284 basket = yt - ch; 00285 if((basket > y) && (possible > basket)) possible = basket; 00286 } 00287 } 00288 y = possible; 00289 } 00290 } 00291 while((overlap != none) && (overlap != h_wrong) && (y < maxRect.bottom())); 00292 00293 if(ch>= maxRect.height()) 00294 y_optimal=maxRect.top(); 00295 00296 // place the window 00297 c->move(x_optimal, y_optimal); 00298 00299 } 00300 00304 void Placement::placeCascaded (Client* c, const QRect& area, bool re_init) 00305 { 00306 /* cascadePlacement by Cristian Tibirna (tibirna@kde.org) (30Jan98) 00307 */ 00308 // work coords 00309 int xp, yp; 00310 00311 //CT how do I get from the 'Client' class the size that NW squarish "handle" 00312 const int delta_x = 24; 00313 const int delta_y = 24; 00314 00315 const int dn = c->desktop() == 0 || c->isOnAllDesktops() ? (m_WorkspacePtr->currentDesktop() - 1) : (c->desktop() - 1); 00316 00317 // get the maximum allowed windows space and desk's origin 00318 QRect maxRect = checkArea( c, area ); 00319 00320 // initialize often used vars: width and height of c; we gain speed 00321 const int ch = c->height(); 00322 const int cw = c->width(); 00323 const int X = maxRect.left(); 00324 const int Y = maxRect.top(); 00325 const int H = maxRect.height(); 00326 const int W = maxRect.width(); 00327 00328 //initialize if needed 00329 if (re_init || cci[dn].pos.x() < X || cci[dn].pos.y() < Y ) 00330 { 00331 cci[dn].pos = QPoint(X, Y); 00332 cci[dn].col = cci[dn].row = 0; 00333 } 00334 00335 00336 xp = cci[dn].pos.x(); 00337 yp = cci[dn].pos.y(); 00338 00339 //here to touch in case people vote for resize on placement 00340 if ((yp + ch) > H) yp = Y; 00341 00342 if ((xp + cw) > W) 00343 if (!yp) 00344 { 00345 placeSmart(c,area); 00346 return; 00347 } 00348 else xp = X; 00349 00350 //if this isn't the first window 00351 if (cci[dn].pos.x() != X && cci[dn].pos.y() != Y) 00352 { 00353 /* The following statements cause an internal compiler error with 00354 * egcs-2.91.66 on SuSE Linux 6.3. The equivalent forms compile fine. 00355 * 22-Dec-1999 CS 00356 * 00357 * if (xp != X && yp == Y) xp = delta_x * (++(cci[dn].col)); 00358 * if (yp != Y && xp == X) yp = delta_y * (++(cci[dn].row)); 00359 */ 00360 if (xp != X && yp == Y) 00361 { 00362 ++(cci[dn].col); 00363 xp = delta_x * cci[dn].col; 00364 } 00365 if (yp != Y && xp == X) 00366 { 00367 ++(cci[dn].row); 00368 yp = delta_y * cci[dn].row; 00369 } 00370 00371 // last resort: if still doesn't fit, smart place it 00372 if (((xp + cw) > W - X) || ((yp + ch) > H - Y)) 00373 { 00374 placeSmart(c,area); 00375 return; 00376 } 00377 } 00378 00379 // place the window 00380 c->move(QPoint(xp, yp)); 00381 00382 // new position 00383 cci[dn].pos = QPoint(xp + delta_x, yp + delta_y); 00384 } 00385 00389 void Placement::placeCentered (Client* c, const QRect& area ) 00390 { 00391 00392 // get the maximum allowed windows space and desk's origin 00393 const QRect maxRect = checkArea( c, area ); 00394 00395 const int xp = maxRect.left() + (maxRect.width() - c->width()) / 2; 00396 const int yp = maxRect.top() + (maxRect.height() - c->height()) / 2; 00397 00398 // place the window 00399 c->move(QPoint(xp, yp)); 00400 } 00401 00405 void Placement::placeZeroCornered(Client* c, const QRect& area ) 00406 { 00407 // get the maximum allowed windows space and desk's origin 00408 const QRect maxRect = checkArea( c, area ); 00409 00410 // place the window 00411 c->move(QPoint(maxRect.left(), maxRect.top())); 00412 } 00413 00414 void Placement::placeUtility(Client* c, QRect& area ) 00415 { 00416 // TODO kwin should try to place utility windows next to their mainwindow, 00417 // preferably at the right edge, and going down if there are more of them 00418 // if there's not enough place outside the mainwindow, it should prefer 00419 // top-right corner 00420 // use the default placement for now 00421 place( c, Default, area ); 00422 } 00423 00424 00425 void Placement::placeDialog(Client* c, QRect& area ) 00426 { 00427 placeOnMainWindow( c, area ); 00428 } 00429 00430 void Placement::placeUnderMouse(Client* c, QRect& area ) 00431 { 00432 area = checkArea( c, area ); 00433 QRect geom = c->geometry(); 00434 geom.moveCenter( QCursor::pos()); 00435 c->move( geom.topLeft()); 00436 c->keepInArea( area ); // make sure it's kept inside workarea 00437 } 00438 00439 void Placement::placeOnMainWindow(Client* c, QRect& area ) 00440 { 00441 area = checkArea( c, area ); 00442 ClientList mainwindows = c->mainClients(); 00443 Client* place_on = NULL; 00444 Client* place_on2 = NULL; 00445 int mains_count = 0; 00446 for( ClientList::ConstIterator it = mainwindows.begin(); 00447 it != mainwindows.end(); 00448 ++it ) 00449 { 00450 if( (*it)->isSpecialWindow() && !(*it)->isOverride()) 00451 continue; // don't consider toolbars etc when placing 00452 ++mains_count; 00453 place_on2 = *it; 00454 if( (*it)->isOnCurrentDesktop()) 00455 { 00456 if( place_on == NULL ) 00457 place_on = *it; 00458 else 00459 { // two or more on current desktop -> center 00460 placeCentered( c, area ); 00461 return; 00462 } 00463 } 00464 } 00465 if( place_on == NULL ) 00466 { // 'mains_count' is used because it doesn't include ignored mainwindows 00467 if( mains_count != 1 ) 00468 { 00469 placeCentered( c, area ); 00470 return; 00471 } 00472 place_on = place_on2; // use the only window filtered together with 'mains_count' 00473 } 00474 QRect geom = c->geometry(); 00475 geom.moveCenter( place_on->geometry().center()); 00476 c->move( geom.topLeft()); 00477 // get area again, because the mainwindow may be on different xinerama screen 00478 area = checkArea( c, QRect()); 00479 c->keepInArea( area ); // make sure it's kept inside workarea 00480 } 00481 00482 QRect Placement::checkArea( const Client* c, const QRect& area ) 00483 { 00484 if( area.isNull()) 00485 return m_WorkspacePtr->clientArea( PlacementArea, c->geometry().center(), c->desktop()); 00486 return area; 00487 } 00488 00489 #endif 00490 00491 00492 Placement::Policy Placement::policyFromString( const QString& policy, bool no_special ) 00493 { 00494 if( policy == "NoPlacement" ) 00495 return NoPlacement; 00496 else if( policy == "Default" && !no_special ) 00497 return Default; 00498 else if( policy == "Random" ) 00499 return Random; 00500 else if( policy == "Cascade" ) 00501 return Cascade; 00502 else if( policy == "Centered" ) 00503 return Centered; 00504 else if( policy == "ZeroCornered" ) 00505 return ZeroCornered; 00506 else if( policy == "UnderMouse" && !no_special) 00507 return UnderMouse; 00508 else if( policy == "OnMainWindow" && !no_special) 00509 return OnMainWindow; 00510 else 00511 return Smart; 00512 } 00513 00514 const char* Placement::policyToString( Policy policy ) 00515 { 00516 const char* const policies[] = 00517 { "NoPlacement", "Default", "Random", "Smart", "Cascade", "Centered", 00518 "ZeroCornered", "UnderMouse", "OnMainWindow" }; 00519 assert( policy < int( sizeof( policies ) / sizeof( policies[ 0 ] ))); 00520 return policies[ policy ]; 00521 } 00522 00523 00524 #ifndef KCMRULES 00525 00526 // ******************** 00527 // Workspace 00528 // ******************** 00529 00533 void Workspace::slotWindowPackLeft() 00534 { 00535 if( active_client && active_client->isMovable()) 00536 active_client->move( packPositionLeft( active_client, active_client->geometry().left(), true ), 00537 active_client->y()); 00538 } 00539 00540 void Workspace::slotWindowPackRight() 00541 { 00542 if( active_client && active_client->isMovable()) 00543 active_client->move( 00544 packPositionRight( active_client, active_client->geometry().right(), true ) 00545 - active_client->width() + 1, active_client->y()); 00546 } 00547 00548 void Workspace::slotWindowPackUp() 00549 { 00550 if( active_client && active_client->isMovable()) 00551 active_client->move( active_client->x(), 00552 packPositionUp( active_client, active_client->geometry().top(), true )); 00553 } 00554 00555 void Workspace::slotWindowPackDown() 00556 { 00557 if( active_client && active_client->isMovable()) 00558 active_client->move( active_client->x(), 00559 packPositionDown( active_client, active_client->geometry().bottom(), true ) - active_client->height() + 1 ); 00560 } 00561 00562 void Workspace::slotWindowGrowHorizontal() 00563 { 00564 if( active_client ) 00565 active_client->growHorizontal(); 00566 } 00567 00568 void Client::growHorizontal() 00569 { 00570 if( !isResizable()) 00571 return; 00572 QRect geom = geometry(); 00573 geom.setRight( workspace()->packPositionRight( this, geom.right(), true )); 00574 QSize adjsize = adjustedSize( geom.size(), SizemodeFixedW ); 00575 if( geometry().size() == adjsize && geom.size() != adjsize && xSizeHint.width_inc > 1 ) // take care of size increments 00576 { 00577 int newright = workspace()->packPositionRight( this, geom.right() + xSizeHint.width_inc - 1, true ); 00578 // check that it hasn't grown outside of the area, due to size increments 00579 // TODO this may be wrong? 00580 if( workspace()->clientArea( MovementArea, 00581 QPoint(( x() + newright ) / 2, geometry().center().y()), desktop()).right() >= newright ) 00582 geom.setRight( newright ); 00583 } 00584 geom.setSize( adjustedSize( geom.size(), SizemodeFixedW )); 00585 setGeometry( geom ); 00586 } 00587 00588 void Workspace::slotWindowShrinkHorizontal() 00589 { 00590 if( active_client ) 00591 active_client->shrinkHorizontal(); 00592 } 00593 00594 void Client::shrinkHorizontal() 00595 { 00596 if( !isResizable()) 00597 return; 00598 QRect geom = geometry(); 00599 geom.setRight( workspace()->packPositionLeft( this, geom.right(), false )); 00600 if( geom.width() <= 1 ) 00601 return; 00602 geom.setSize( adjustedSize( geom.size(), SizemodeFixedW )); 00603 if( geom.width() > 20 ) 00604 setGeometry( geom ); 00605 } 00606 00607 void Workspace::slotWindowGrowVertical() 00608 { 00609 if( active_client ) 00610 active_client->growVertical(); 00611 } 00612 00613 void Client::growVertical() 00614 { 00615 if( !isResizable()) 00616 return; 00617 QRect geom = geometry(); 00618 geom.setBottom( workspace()->packPositionDown( this, geom.bottom(), true )); 00619 QSize adjsize = adjustedSize( geom.size(), SizemodeFixedH ); 00620 if( geometry().size() == adjsize && geom.size() != adjsize && xSizeHint.height_inc > 1 ) // take care of size increments 00621 { 00622 int newbottom = workspace()->packPositionDown( this, geom.bottom() + xSizeHint.height_inc - 1, true ); 00623 // check that it hasn't grown outside of the area, due to size increments 00624 if( workspace()->clientArea( MovementArea, 00625 QPoint( geometry().center().x(), ( y() + newbottom ) / 2 ), desktop()).bottom() >= newbottom ) 00626 geom.setBottom( newbottom ); 00627 } 00628 geom.setSize( adjustedSize( geom.size(), SizemodeFixedH )); 00629 setGeometry( geom ); 00630 } 00631 00632 00633 void Workspace::slotWindowShrinkVertical() 00634 { 00635 if( active_client ) 00636 active_client->shrinkVertical(); 00637 } 00638 00639 void Client::shrinkVertical() 00640 { 00641 if( !isResizable()) 00642 return; 00643 QRect geom = geometry(); 00644 geom.setBottom( workspace()->packPositionUp( this, geom.bottom(), false )); 00645 if( geom.height() <= 1 ) 00646 return; 00647 geom.setSize( adjustedSize( geom.size(), SizemodeFixedH )); 00648 if( geom.height() > 20 ) 00649 setGeometry( geom ); 00650 } 00651 00652 int Workspace::packPositionLeft( const Client* cl, int oldx, bool left_edge ) const 00653 { 00654 int newx = clientArea( MovementArea, cl ).left(); 00655 if( oldx <= newx ) // try another Xinerama screen 00656 newx = clientArea( MovementArea, 00657 QPoint( cl->geometry().left() - 1, cl->geometry().center().y()), cl->desktop()).left(); 00658 if( oldx <= newx ) 00659 return oldx; 00660 for( ClientList::ConstIterator it = clients.begin(); 00661 it != clients.end(); 00662 ++it) 00663 { 00664 if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( active_client->desktop())) 00665 continue; 00666 int x = left_edge ? (*it)->geometry().right() + 1 : (*it)->geometry().left() - 1; 00667 if( x > newx && x < oldx 00668 && !( cl->geometry().top() > (*it)->geometry().bottom() // they overlap in Y direction 00669 || cl->geometry().bottom() < (*it)->geometry().top())) 00670 newx = x; 00671 } 00672 return newx; 00673 } 00674 00675 int Workspace::packPositionRight( const Client* cl, int oldx, bool right_edge ) const 00676 { 00677 int newx = clientArea( MovementArea, cl ).right(); 00678 if( oldx >= newx ) // try another Xinerama screen 00679 newx = clientArea( MovementArea, 00680 QPoint( cl->geometry().right() + 1, cl->geometry().center().y()), cl->desktop()).right(); 00681 if( oldx >= newx ) 00682 return oldx; 00683 for( ClientList::ConstIterator it = clients.begin(); 00684 it != clients.end(); 00685 ++it) 00686 { 00687 if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop())) 00688 continue; 00689 int x = right_edge ? (*it)->geometry().left() - 1 : (*it)->geometry().right() + 1; 00690 if( x < newx && x > oldx 00691 && !( cl->geometry().top() > (*it)->geometry().bottom() 00692 || cl->geometry().bottom() < (*it)->geometry().top())) 00693 newx = x; 00694 } 00695 return newx; 00696 } 00697 00698 int Workspace::packPositionUp( const Client* cl, int oldy, bool top_edge ) const 00699 { 00700 int newy = clientArea( MovementArea, cl ).top(); 00701 if( oldy <= newy ) // try another Xinerama screen 00702 newy = clientArea( MovementArea, 00703 QPoint( cl->geometry().center().x(), cl->geometry().top() - 1 ), cl->desktop()).top(); 00704 if( oldy <= newy ) 00705 return oldy; 00706 for( ClientList::ConstIterator it = clients.begin(); 00707 it != clients.end(); 00708 ++it) 00709 { 00710 if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop())) 00711 continue; 00712 int y = top_edge ? (*it)->geometry().bottom() + 1 : (*it)->geometry().top() - 1; 00713 if( y > newy && y < oldy 00714 && !( cl->geometry().left() > (*it)->geometry().right() // they overlap in X direction 00715 || cl->geometry().right() < (*it)->geometry().left())) 00716 newy = y; 00717 } 00718 return newy; 00719 } 00720 00721 int Workspace::packPositionDown( const Client* cl, int oldy, bool bottom_edge ) const 00722 { 00723 int newy = clientArea( MovementArea, cl ).bottom(); 00724 if( oldy >= newy ) // try another Xinerama screen 00725 newy = clientArea( MovementArea, 00726 QPoint( cl->geometry().center().x(), cl->geometry().bottom() + 1 ), cl->desktop()).bottom(); 00727 if( oldy >= newy ) 00728 return oldy; 00729 for( ClientList::ConstIterator it = clients.begin(); 00730 it != clients.end(); 00731 ++it) 00732 { 00733 if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop())) 00734 continue; 00735 int y = bottom_edge ? (*it)->geometry().top() - 1 : (*it)->geometry().bottom() + 1; 00736 if( y < newy && y > oldy 00737 && !( cl->geometry().left() > (*it)->geometry().right() 00738 || cl->geometry().right() < (*it)->geometry().left())) 00739 newy = y; 00740 } 00741 return newy; 00742 } 00743 00747 void Workspace::place(Client* c, QRect& area) 00748 { 00749 initPositioning->place( c, area ); 00750 } 00751 00752 void Workspace::placeSmart(Client* c, const QRect& area) 00753 { 00754 initPositioning->placeSmart( c, area ); 00755 } 00756 00757 #endif 00758 00759 } // namespace
KDE Logo
This file is part of the documentation for kwin Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 13 21:47:05 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003