• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

KWin

placement.cpp

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

KWin

Skip menu "KWin"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • KWin
  •   KWin Libraries
  • Libraries
  •   libkworkspace
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal