• Skip to content
  • Skip to link menu
KDE 4.1 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().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++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().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++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().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++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         if (!yp) 
00378         {
00379         place(c,area,nextPlacement);
00380         return;
00381         }
00382     else xp = X;
00383 
00384   //if this isn't the first window
00385     if (cci[dn].pos.x() != X && cci[dn].pos.y() != Y) 
00386         {
00387         /* The following statements cause an internal compiler error with
00388          * egcs-2.91.66 on SuSE Linux 6.3. The equivalent forms compile fine.
00389          * 22-Dec-1999 CS
00390          *
00391          * if (xp != X && yp == Y) xp = delta_x * (++(cci[dn].col));
00392          * if (yp != Y && xp == X) yp = delta_y * (++(cci[dn].row));
00393          */
00394     if (xp != X && yp == Y)
00395             {
00396             ++(cci[dn].col);
00397             xp = delta_x * cci[dn].col;
00398             }
00399         if (yp != Y && xp == X)
00400             {
00401             ++(cci[dn].row);
00402             yp = delta_y * cci[dn].row;
00403             }
00404 
00405         // last resort: if still doesn't fit, smart place it
00406         if (((xp + cw) > W - X) || ((yp + ch) > H - Y)) 
00407             {
00408             place(c,area,nextPlacement);
00409             return;
00410             }
00411         }
00412 
00413     // place the window
00414     c->move(QPoint(xp, yp));
00415 
00416     // new position
00417     cci[dn].pos = QPoint(xp + delta_x, yp + delta_y);
00418     }
00419 
00423 void Placement::placeCentered (Client* c, const QRect& area, Policy /*next*/ )
00424     {
00425 
00426     // get the maximum allowed windows space and desk's origin
00427     const QRect maxRect = checkArea( c, area );
00428 
00429     const int xp = maxRect.left() + (maxRect.width() -  c->width())  / 2;
00430     const int yp = maxRect.top()  + (maxRect.height() - c->height()) / 2;
00431 
00432     // place the window
00433     c->move(QPoint(xp, yp));
00434     }
00435 
00439 void Placement::placeZeroCornered(Client* c, const QRect& area, Policy /*next*/ )
00440     {
00441     // get the maximum allowed windows space and desk's origin
00442     const QRect maxRect = checkArea( c, area );
00443 
00444     // place the window
00445     c->move(QPoint(maxRect.left(), maxRect.top()));
00446     }
00447 
00448 void Placement::placeUtility(Client* c, QRect& area, Policy /*next*/ )
00449     {
00450 // TODO kwin should try to place utility windows next to their mainwindow,
00451 // preferably at the right edge, and going down if there are more of them
00452 // if there's not enough place outside the mainwindow, it should prefer
00453 // top-right corner
00454     // use the default placement for now
00455     place( c, area, Default );
00456     }
00457 
00458 
00459 void Placement::placeDialog(Client* c, QRect& area, Policy nextPlacement )
00460     {
00461     placeOnMainWindow( c, area, nextPlacement );
00462     }
00463 
00464 void Placement::placeUnderMouse(Client* c, QRect& area, Policy /*next*/ )
00465     {
00466     area = checkArea( c, area );
00467     QRect geom = c->geometry();
00468     geom.moveCenter( cursorPos());
00469     c->move( geom.topLeft());
00470     c->keepInArea( area ); // make sure it's kept inside workarea
00471     }
00472 
00473 void Placement::placeOnMainWindow(Client* c, QRect& area, Policy nextPlacement )
00474     {
00475     if( nextPlacement == Unknown )
00476         nextPlacement = Centered;
00477     if( nextPlacement == Maximizing ) // maximize if needed
00478         placeMaximizing( c, area, NoPlacement );
00479     area = checkArea( c, area );
00480     ClientList mainwindows = c->mainClients();
00481     Client* place_on = NULL;
00482     Client* place_on2 = NULL;
00483     int mains_count = 0;
00484     for( ClientList::ConstIterator it = mainwindows.begin();
00485          it != mainwindows.end();
00486          ++it )
00487         {
00488         if( mainwindows.count() > 1 && (*it)->isSpecialWindow())
00489             continue; // don't consider toolbars etc when placing
00490         ++mains_count;
00491         place_on2 = *it;
00492         if( (*it)->isOnCurrentDesktop())
00493             {
00494             if( place_on == NULL )
00495                 place_on = *it;
00496             else
00497                 { // two or more on current desktop -> center
00498                   // That's the default at least. However, with maximizing placement
00499                   // policy as the default, the dialog should be either maximized or
00500                   // made as large as its maximum size and then placed centered.
00501                   // So the nextPlacement argument allows chaining. In this case, nextPlacement
00502                   // is Maximizing and it will call placeCentered().
00503                 place( c, area, Centered );
00504                 return;
00505                 }
00506             }
00507         }
00508     if( place_on == NULL )
00509         { // 'mains_count' is used because it doesn't include ignored mainwindows
00510         if( mains_count != 1 )
00511             {
00512             place( c, area, Centered );
00513             return;
00514             }
00515         place_on = place_on2; // use the only window filtered together with 'mains_count'
00516         }
00517     if( place_on->isDesktop())
00518         {
00519         place( c, area, Centered );
00520         return;
00521         }
00522     QRect geom = c->geometry();
00523     geom.moveCenter( place_on->geometry().center());
00524     c->move( geom.topLeft());
00525     // get area again, because the mainwindow may be on different xinerama screen
00526     area = checkArea( c, QRect()); 
00527     c->keepInArea( area ); // make sure it's kept inside workarea
00528     }
00529 
00530 void Placement::placeMaximizing(Client* c, QRect& area, Policy nextPlacement )
00531     {
00532     if( nextPlacement == Unknown )
00533         nextPlacement = Smart;
00534     if( c->isMaximizable() && c->maxSize().width() >= area.width() && c->maxSize().height() >= area.height())
00535         {
00536         if( m_WorkspacePtr->clientArea( MaximizeArea, c ) == area )
00537             c->maximize( Client::MaximizeFull );
00538         else // if the geometry doesn't match default maximize area (xinerama case?),
00539             { // it's probably better to use the given area
00540             c->setGeometry( area );
00541             }
00542         }
00543     else
00544         {
00545         c->resizeWithChecks( c->maxSize().boundedTo( area.size()));
00546         place( c, area, nextPlacement );
00547         }
00548     }
00549 
00550 QRect Placement::checkArea( const Client* c, const QRect& area )
00551     {
00552     if( area.isNull())
00553         return m_WorkspacePtr->clientArea( PlacementArea, c->geometry().center(), c->desktop());
00554     return area;
00555     }
00556 
00557 #endif
00558 
00559 
00560 Placement::Policy Placement::policyFromString( const QString& policy, bool no_special )
00561     {
00562     if( policy == "NoPlacement" )
00563         return NoPlacement;
00564     else if( policy == "Default" && !no_special )
00565         return Default;
00566     else if( policy == "Random" )
00567         return Random;
00568     else if( policy == "Cascade" )
00569         return Cascade;
00570     else if( policy == "Centered" )
00571         return Centered;
00572     else if( policy == "ZeroCornered" )
00573         return ZeroCornered;
00574     else if( policy == "UnderMouse" && !no_special)
00575         return UnderMouse;
00576     else if( policy == "OnMainWindow" && !no_special)
00577         return OnMainWindow;
00578     else if( policy == "Maximizing" )
00579         return Maximizing;
00580     else
00581         return Smart;
00582     }
00583 
00584 const char* Placement::policyToString( Policy policy )
00585     {
00586     const char* const policies[] =
00587         { "NoPlacement", "Default", "XXX should never see", "Random", "Smart", "Cascade", "Centered",
00588             "ZeroCornered", "UnderMouse", "OnMainWindow", "Maximizing" };
00589     assert( policy < int( sizeof( policies ) / sizeof( policies[ 0 ] )));
00590     return policies[ policy ];
00591     }
00592 
00593 
00594 #ifndef KCMRULES
00595 
00596 // ********************
00597 // Workspace
00598 // ********************
00599 
00603 void Workspace::slotWindowPackLeft()
00604     {
00605     if( active_client && active_client->isMovable())
00606         active_client->move( packPositionLeft( active_client, active_client->geometry().left(), true ),
00607             active_client->y());
00608     }
00609 
00610 void Workspace::slotWindowPackRight()
00611     {
00612     if( active_client && active_client->isMovable())
00613         active_client->move( 
00614             packPositionRight( active_client, active_client->geometry().right(), true )
00615             - active_client->width() + 1, active_client->y());
00616     }
00617 
00618 void Workspace::slotWindowPackUp()
00619     {
00620     if( active_client && active_client->isMovable())
00621         active_client->move( active_client->x(),
00622             packPositionUp( active_client, active_client->geometry().top(), true ));
00623     }
00624 
00625 void Workspace::slotWindowPackDown()
00626     {
00627     if( active_client && active_client->isMovable())
00628         active_client->move( active_client->x(),
00629             packPositionDown( active_client, active_client->geometry().bottom(), true ) - active_client->height() + 1 );
00630     }
00631 
00632 void Workspace::slotWindowGrowHorizontal()
00633     {
00634     if( active_client )
00635         active_client->growHorizontal();
00636     }
00637 
00638 void Client::growHorizontal()
00639     {
00640     if( !isResizable() || isShade())
00641         return;
00642     QRect geom = geometry();
00643     geom.setRight( workspace()->packPositionRight( this, geom.right(), true ));
00644     QSize adjsize = adjustedSize( geom.size(), SizemodeFixedW );
00645     if( geometry().size() == adjsize && geom.size() != adjsize && xSizeHint.width_inc > 1 ) // take care of size increments
00646         {
00647         int newright = workspace()->packPositionRight( this, geom.right() + xSizeHint.width_inc - 1, true );
00648         // check that it hasn't grown outside of the area, due to size increments
00649         // TODO this may be wrong?
00650         if( workspace()->clientArea( MovementArea,
00651             QPoint(( x() + newright ) / 2, geometry().center().y()), desktop()).right() >= newright )
00652             geom.setRight( newright );
00653         }
00654     geom.setSize( adjustedSize( geom.size(), SizemodeFixedW ));
00655     setGeometry( geom );
00656     }
00657 
00658 void Workspace::slotWindowShrinkHorizontal()
00659     {
00660     if( active_client )
00661         active_client->shrinkHorizontal();
00662     }
00663 
00664 void Client::shrinkHorizontal()
00665     {
00666     if( !isResizable() || isShade())
00667         return;
00668     QRect geom = geometry();
00669     geom.setRight( workspace()->packPositionLeft( this, geom.right(), false ));
00670     if( geom.width() <= 1 )
00671         return;
00672     geom.setSize( adjustedSize( geom.size(), SizemodeFixedW ));
00673     if( geom.width() > 20 )
00674         setGeometry( geom );
00675     }
00676 
00677 void Workspace::slotWindowGrowVertical()
00678     {
00679     if( active_client )
00680         active_client->growVertical();
00681     }
00682 
00683 void Client::growVertical()
00684     {
00685     if( !isResizable() || isShade())
00686         return;
00687     QRect geom = geometry();
00688     geom.setBottom( workspace()->packPositionDown( this, geom.bottom(), true ));
00689     QSize adjsize = adjustedSize( geom.size(), SizemodeFixedH );
00690     if( geometry().size() == adjsize && geom.size() != adjsize && xSizeHint.height_inc > 1 ) // take care of size increments
00691         {
00692         int newbottom = workspace()->packPositionDown( this, geom.bottom() + xSizeHint.height_inc - 1, true );
00693         // check that it hasn't grown outside of the area, due to size increments
00694         if( workspace()->clientArea( MovementArea,
00695             QPoint( geometry().center().x(), ( y() + newbottom ) / 2 ), desktop()).bottom() >= newbottom )
00696             geom.setBottom( newbottom );
00697         }
00698     geom.setSize( adjustedSize( geom.size(), SizemodeFixedH ));
00699     setGeometry( geom );
00700     }
00701 
00702 
00703 void Workspace::slotWindowShrinkVertical()
00704     {
00705     if( active_client )
00706         active_client->shrinkVertical();
00707     }
00708 
00709 void Client::shrinkVertical()
00710     {
00711     if( !isResizable() || isShade())
00712         return;
00713     QRect geom = geometry();
00714     geom.setBottom( workspace()->packPositionUp( this, geom.bottom(), false ));
00715     if( geom.height() <= 1 )
00716         return;
00717     geom.setSize( adjustedSize( geom.size(), SizemodeFixedH ));
00718     if( geom.height() > 20 )
00719         setGeometry( geom );
00720     }
00721 
00722 int Workspace::packPositionLeft( const Client* cl, int oldx, bool left_edge ) const
00723     {
00724     int newx = clientArea( MovementArea, cl ).left();
00725     if( oldx <= newx ) // try another Xinerama screen
00726         newx = clientArea( MovementArea,
00727             QPoint( cl->geometry().left() - 1, cl->geometry().center().y()), cl->desktop()).left();
00728     if( oldx <= newx )
00729         return oldx;
00730     for( ClientList::ConstIterator it = clients.begin();
00731          it != clients.end();
00732          ++it)
00733         {
00734         if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( active_client->desktop()))
00735             continue;
00736         int x = left_edge ? (*it)->geometry().right() + 1 : (*it)->geometry().left() - 1;
00737         if( x > newx && x < oldx
00738             && !( cl->geometry().top() > (*it)->geometry().bottom() // they overlap in Y direction
00739                 || cl->geometry().bottom() < (*it)->geometry().top()))
00740             newx = x;
00741         }
00742     return newx;
00743     }
00744 
00745 int Workspace::packPositionRight( const Client* cl, int oldx, bool right_edge ) const
00746     {
00747     int newx = clientArea( MovementArea, cl ).right();
00748     if( oldx >= newx ) // try another Xinerama screen
00749         newx = clientArea( MovementArea,
00750             QPoint( cl->geometry().right() + 1, cl->geometry().center().y()), cl->desktop()).right();
00751     if( oldx >= newx )
00752         return oldx;
00753     for( ClientList::ConstIterator it = clients.begin();
00754          it != clients.end();
00755          ++it)
00756         {
00757         if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
00758             continue;
00759         int x = right_edge ? (*it)->geometry().left() - 1 : (*it)->geometry().right() + 1;
00760         if( x < newx && x > oldx
00761             && !( cl->geometry().top() > (*it)->geometry().bottom()
00762                 || cl->geometry().bottom() < (*it)->geometry().top()))
00763             newx = x;
00764         }
00765     return newx;
00766     }
00767 
00768 int Workspace::packPositionUp( const Client* cl, int oldy, bool top_edge ) const
00769     {
00770     int newy = clientArea( MovementArea, cl ).top();
00771     if( oldy <= newy ) // try another Xinerama screen
00772         newy = clientArea( MovementArea,
00773             QPoint( cl->geometry().center().x(), cl->geometry().top() - 1 ), cl->desktop()).top();
00774     if( oldy <= newy )
00775         return oldy;
00776     for( ClientList::ConstIterator it = clients.begin();
00777          it != clients.end();
00778          ++it)
00779         {
00780         if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
00781             continue;
00782         int y = top_edge ? (*it)->geometry().bottom() + 1 : (*it)->geometry().top() - 1;
00783         if( y > newy && y < oldy
00784             && !( cl->geometry().left() > (*it)->geometry().right() // they overlap in X direction
00785                 || cl->geometry().right() < (*it)->geometry().left()))
00786             newy = y;
00787         }
00788     return newy;
00789     }
00790 
00791 int Workspace::packPositionDown( const Client* cl, int oldy, bool bottom_edge ) const
00792     {
00793     int newy = clientArea( MovementArea, cl ).bottom();
00794     if( oldy >= newy ) // try another Xinerama screen
00795         newy = clientArea( MovementArea,
00796             QPoint( cl->geometry().center().x(), cl->geometry().bottom() + 1 ), cl->desktop()).bottom();
00797     if( oldy >= newy )
00798         return oldy;
00799     for( ClientList::ConstIterator it = clients.begin();
00800          it != clients.end();
00801          ++it)
00802         {
00803         if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
00804             continue;
00805         int y = bottom_edge ? (*it)->geometry().top() - 1 : (*it)->geometry().bottom() + 1;
00806         if( y < newy && y > oldy
00807             && !( cl->geometry().left() > (*it)->geometry().right()
00808                 || cl->geometry().right() < (*it)->geometry().left()))
00809             newy = y;
00810         }
00811     return newy;
00812     }
00813 
00817 void Workspace::place(Client* c, QRect& area)
00818     {
00819     initPositioning->place( c, area );
00820     }
00821 
00822 void Workspace::placeSmart(Client* c, const QRect& area)
00823     {
00824     initPositioning->placeSmart( c, area );
00825     }
00826 
00827 #endif
00828 
00829 } // 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
  •   libplasma
  •   libsolidcontrol
  •   libtaskmanager
  • Plasma
  •   Animators
  •   Applets
  •   Engines
  • Solid Modules
Generated for API Reference by doxygen 1.5.4
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