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