30Placement::Placement(Workspace* w)
 
   40void Placement::place(Client* c, TQRect& area )
 
   42    Policy policy = c->rules()->checkPlacement( Default );
 
   43    if( policy != Default )
 
   45        place( c, area, policy );
 
   50        placeUtility(c, area, options->placement );
 
   51    else if( c->isDialog())
 
   52        placeDialog(c, area, options->placement );
 
   53    else if( c->isSplash())
 
   54        placeOnMainWindow( c, area ); 
 
   56        place(c, area, options->placement);
 
   59void Placement::place(Client* c, TQRect& area, Policy policy, Policy nextPlacement )
 
   61    if( policy == Unknown )
 
   63    if( policy == Default )
 
   64        policy = options->placement;
 
   65    if( policy == NoPlacement )
 
   67    else if (policy == Random)
 
   68        placeAtRandom(c, area, nextPlacement);
 
   69    else if (policy == Cascade)
 
   70        placeCascaded(c, area, nextPlacement);
 
   71    else if (policy == Centered)
 
   72        placeCentered(c, area, nextPlacement);
 
   73    else if (policy == ZeroCornered)
 
   74        placeZeroCornered(c, area, nextPlacement);
 
   75    else if (policy == UnderMouse)
 
   76        placeUnderMouse(c, area, nextPlacement);
 
   77    else if (policy == OnMainWindow)
 
   78        placeOnMainWindow(c, area, nextPlacement);
 
   79    else if( policy == Maximizing )
 
   80        placeMaximizing(c, area, nextPlacement);
 
   82        placeSmart(c, area, nextPlacement);
 
   88void Placement::placeAtRandom(Client* c, 
const TQRect& area, Policy  )
 
   92    static int py = 2 * step;
 
   95    const TQRect maxRect = checkArea( c, area );
 
  105    if (px > maxRect.width()/2)
 
  106        px =  maxRect.x() + step;
 
  107    if (py > maxRect.height()/2)
 
  108        py =  maxRect.y() + step;
 
  111    if (tx + c->width() > maxRect.right())
 
  113        tx = maxRect.right() - c->width();
 
  118    if (ty + c->height() > maxRect.bottom())
 
  120        ty = maxRect.bottom() - c->height();
 
  131void Placement::placeSmart(Client* c, 
const TQRect& area, Policy  )
 
  142    const int none = 0, h_wrong = -1, w_wrong = -2; 
 
  143    long int overlap, min_overlap = 0;
 
  144    int x_optimal, y_optimal;
 
  146    int desktop = c->desktop() == 0 || c->isOnAllDesktops() ? m_WorkspacePtr->currentDesktop() : c->desktop();
 
  148    int cxl, cxr, cyt, cyb;     
 
  153    const TQRect maxRect = checkArea( c, area );
 
  154    int x = maxRect.left(), y = maxRect.top();
 
  155    x_optimal = x; y_optimal = y;
 
  158    int ch = c->height() - 1;
 
  159    int cw = c->width()  - 1;
 
  161    bool first_pass = 
true; 
 
  167        if (y + ch > maxRect.bottom() && ch < maxRect.height())
 
  169        else if(x + cw > maxRect.right())
 
  175            cxl = x; cxr = x + cw;
 
  176            cyt = y; cyb = y + ch;
 
  177            ClientList::ConstIterator l;
 
  178            for(l = m_WorkspacePtr->stackingOrder().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++l) 
 
  180                if((*l)->isOnDesktop(desktop) &&
 
  181                   (*l)->isShown( 
false ) && (*l) != c) 
 
  184                    xl = (*l)->x();          yt = (*l)->y();
 
  185                    xr = xl + (*l)->width(); yb = yt + (*l)->height();
 
  188                    if((cxl < xr) && (cxr > xl) &&
 
  189                       (cyt < yb) && (cyb > yt)) 
 
  191                        xl = TQMAX(cxl, xl); xr = TQMIN(cxr, xr);
 
  192                        yt = TQMAX(cyt, yt); yb = TQMIN(cyb, yb);
 
  193                        if((*l)->keepAbove())
 
  194                            overlap += 16 * (xr - xl) * (yb - yt);
 
  195                        else if((*l)->keepBelow() && !(*l)->isDock()) 
 
  198                            overlap += (xr - xl) * (yb - yt);
 
  215            min_overlap = overlap;
 
  218        else if (overlap >= none && overlap < min_overlap) 
 
  220            min_overlap = overlap;
 
  229            possible = maxRect.right();
 
  230            if (possible - cw > x) possible -= cw;
 
  233            ClientList::ConstIterator l;
 
  234            for(l = m_WorkspacePtr->stackingOrder().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++l) 
 
  237                if ((*l)->isOnDesktop(desktop) &&
 
  238                     (*l)->isShown( 
false ) &&  (*l) != c) 
 
  241                    xl = (*l)->x();          yt = (*l)->y();
 
  242                    xr = xl + (*l)->width(); yb = yt + (*l)->height();
 
  246                    if((y < yb) && (yt < ch + y)) 
 
  249                        if((xr > x) && (possible > xr)) possible = xr;
 
  252                        if((basket > x) && (possible > basket)) possible = basket;
 
  260        else if (overlap == w_wrong) 
 
  263            possible = maxRect.bottom();
 
  265            if (possible - ch > y) possible -= ch;
 
  268            ClientList::ConstIterator l;
 
  269            for(l = m_WorkspacePtr->stackingOrder().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++l) 
 
  271                if((*l)->isOnDesktop(desktop) &&
 
  272                    (*l) != c   &&  c->isShown( 
false )) 
 
  275                    xl = (*l)->x();          yt = (*l)->y();
 
  276                    xr = xl + (*l)->width(); yb = yt + (*l)->height();
 
  280                    if((yb > y) && (possible > yb)) possible = yb;
 
  283                    if((basket > y) && (possible > basket)) possible = basket;
 
  289    while((overlap != none) && (overlap != h_wrong) && (y < maxRect.bottom()));
 
  291    if(ch>= maxRect.height())
 
  292        y_optimal=maxRect.top();
 
  295    c->move(x_optimal, y_optimal);
 
  299void Placement::reinitCascading( 
int desktop )
 
  304        for( 
int i = 0; i < m_WorkspacePtr->numberOfDesktops(); i++) 
 
  306            DesktopCascadingInfo inf;
 
  307            inf.pos = TQPoint(-1,-1);
 
  315        cci[desktop - 1].pos = TQPoint(-1, -1);
 
  316        cci[desktop - 1].col = cci[desktop - 1].row = 0;
 
  323void Placement::placeCascaded (Client* c, TQRect& area, Policy nextPlacement)
 
  331    const int delta_x = 24;
 
  332    const int delta_y = 24;
 
  334    const int dn = c->desktop() == 0 || c->isOnAllDesktops() ? (m_WorkspacePtr->currentDesktop() - 1) : (c->desktop() - 1);
 
  337    TQRect maxRect = checkArea( c, area );
 
  340    const int ch = c->height();
 
  341    const int cw = c->width();
 
  342    const int X = maxRect.left();
 
  343    const int Y = maxRect.top();
 
  344    const int H = maxRect.height();
 
  345    const int W = maxRect.width();
 
  347    if( nextPlacement == Unknown )
 
  348        nextPlacement = Smart;
 
  351    if (cci[dn].pos.x() < 0 || cci[dn].pos.x() < X || cci[dn].pos.y() < Y )
 
  353        cci[dn].pos = TQPoint(X, Y);
 
  354        cci[dn].col = cci[dn].row = 0;
 
  358    xp = cci[dn].pos.x();
 
  359    yp = cci[dn].pos.y();
 
  362    if ((yp + ch) > H) yp = Y;
 
  368        place(c,area,nextPlacement);
 
  378    if (cci[dn].pos.x() != X && cci[dn].pos.y() != Y) 
 
  387    if (xp != X && yp == Y)
 
  390            xp = delta_x * cci[dn].col;
 
  392        if (yp != Y && xp == X)
 
  395            yp = delta_y * cci[dn].row;
 
  399        if (((xp + cw) > W - X) || ((yp + ch) > H - Y)) 
 
  401            place(c,area,nextPlacement);
 
  407    c->move(TQPoint(xp, yp));
 
  410    cci[dn].pos = TQPoint(xp + delta_x,  yp + delta_y);
 
  416void Placement::placeCentered (Client* c, 
const TQRect& area, Policy  )
 
  420    const TQRect maxRect = checkArea( c, area );
 
  422    const int xp = maxRect.left() + (maxRect.width() -  c->width())  / 2;
 
  423    const int yp = maxRect.top()  + (maxRect.height() - c->height()) / 2;
 
  426    c->move(TQPoint(xp, yp));
 
  432void Placement::placeZeroCornered(Client* c, 
const TQRect& area, Policy  )
 
  435    const TQRect maxRect = checkArea( c, area );
 
  438    c->move(TQPoint(maxRect.left(), maxRect.top()));
 
  441void Placement::placeUtility(Client* c, TQRect& area, Policy  )
 
  448    place( c, area, Default );
 
  452void Placement::placeDialog(Client* c, TQRect& area, Policy nextPlacement )
 
  454    placeOnMainWindow( c, area, nextPlacement );
 
  457void Placement::placeUnderMouse(Client* c, TQRect& area, Policy  )
 
  459    area = checkArea( c, area );
 
  460    TQRect geom = c->geometry();
 
  461    geom.moveCenter( TQCursor::pos());
 
  462    c->move( geom.topLeft());
 
  463    c->keepInArea( area ); 
 
  466void Placement::placeOnMainWindow(Client* c, TQRect& area, Policy nextPlacement )
 
  468    if( nextPlacement == Unknown )
 
  469        nextPlacement = Centered;
 
  470    if( nextPlacement == Maximizing ) 
 
  471        placeMaximizing( c, area, NoPlacement );
 
  472    area = checkArea( c, area );
 
  473    ClientList mainwindows = c->mainClients();
 
  474    Client* place_on = NULL;
 
  475    Client* place_on2 = NULL;
 
  477    for( ClientList::ConstIterator it = mainwindows.begin();
 
  478         it != mainwindows.end();
 
  481        if( mainwindows.count() > 1 && (*it)->isSpecialWindow())
 
  485        if( (*it)->isOnCurrentDesktop())
 
  487            if( place_on == NULL )
 
  496                place( c, area, Centered );
 
  501    if( place_on == NULL )
 
  503        if( mains_count != 1 )
 
  505            place( c, area, Centered );
 
  508        place_on = place_on2; 
 
  510    if( place_on->isDesktop())
 
  512        place( c, area, Centered );
 
  515    TQRect geom = c->geometry();
 
  516    geom.moveCenter( place_on->geometry().center());
 
  517    c->move( geom.topLeft());
 
  519    area = checkArea( c, TQRect()); 
 
  520    c->keepInArea( area ); 
 
  523void Placement::placeMaximizing(Client* c, TQRect& area, Policy nextPlacement )
 
  525    if( nextPlacement == Unknown )
 
  526        nextPlacement = Smart;
 
  527    if( c->isMaximizable() && c->maxSize().width() >= area.width() && c->maxSize().height() >= area.height())
 
  529        if( m_WorkspacePtr->clientArea( MaximizeArea, c ) == area )
 
  530            c->maximize( Client::MaximizeFull );
 
  533            c->setGeometry( area );
 
  538        c->resizeWithChecks( c->maxSize().boundedTo( area.size()));
 
  539        place( c, area, nextPlacement );
 
  543TQRect Placement::checkArea( 
const Client* c, 
const TQRect& area )
 
  546        return m_WorkspacePtr->clientArea( PlacementArea, c->geometry().center(), c->desktop());
 
  553Placement::Policy Placement::policyFromString( 
const TQString& policy, 
bool no_special )
 
  555    if( policy == 
"NoPlacement" )
 
  557    else if( policy == 
"Default" && !no_special )
 
  559    else if( policy == 
"Random" )
 
  561    else if( policy == 
"Cascade" )
 
  563    else if( policy == 
"Centered" )
 
  565    else if( policy == 
"ZeroCornered" )
 
  567    else if( policy == 
"UnderMouse" && !no_special)
 
  569    else if( policy == 
"OnMainWindow" && !no_special)
 
  571    else if( policy == 
"Maximizing" )
 
  577const char* Placement::policyToString( Policy policy )
 
  579    const char* 
const policies[] =
 
  580        { 
"NoPlacement", 
"Default", 
"XXX should never see", 
"Random", 
"Smart", 
"Cascade", 
"Centered",
 
  581            "ZeroCornered", 
"UnderMouse", 
"OnMainWindow", 
"Maximizing" };
 
  582    assert( policy < 
int( 
sizeof( policies ) / 
sizeof( policies[ 0 ] )));
 
  583    return policies[ policy ];
 
  596void Workspace::slotWindowPackLeft()
 
  598    if( active_client && active_client->isMovable())
 
  599        active_client->move( packPositionLeft( active_client, active_client->geometry().left(), 
true ),
 
  603void Workspace::slotWindowPackRight()
 
  605    if( active_client && active_client->isMovable())
 
  607            packPositionRight( active_client, active_client->geometry().right(), 
true )
 
  608            - active_client->width() + 1, active_client->y());
 
  611void Workspace::slotWindowPackUp()
 
  613    if( active_client && active_client->isMovable())
 
  614        active_client->move( active_client->x(),
 
  615            packPositionUp( active_client, active_client->geometry().top(), 
true ));
 
  618void Workspace::slotWindowPackDown()
 
  620    if( active_client && active_client->isMovable())
 
  621        active_client->move( active_client->x(),
 
  622            packPositionDown( active_client, active_client->geometry().bottom(), 
true ) - active_client->height() + 1 );
 
  625void Workspace::slotWindowGrowHorizontal()
 
  628        active_client->growHorizontal();
 
  631void Client::growHorizontal()
 
  635    TQRect geom = geometry();
 
  636    geom.setRight( workspace()->packPositionRight( 
this, geom.right(), 
true ));
 
  637    TQSize adjsize = 
adjustedSize( geom.size(), SizemodeFixedW );
 
  638    if( geometry().size() == adjsize && geom.size() != adjsize && xSizeHint.width_inc > 1 ) 
 
  640        int newright = workspace()->packPositionRight( 
this, geom.right() + xSizeHint.width_inc - 1, 
true );
 
  643        if( workspace()->clientArea( MovementArea,
 
  644            TQPoint(( x() + newright ) / 2, geometry().center().y()), 
desktop()).right() >= newright )
 
  645            geom.setRight( newright );
 
  647    geom.setSize( 
adjustedSize( geom.size(), SizemodeFixedW ));
 
  651void Workspace::slotWindowShrinkHorizontal()
 
  654        active_client->shrinkHorizontal();
 
  657void Client::shrinkHorizontal()
 
  661    TQRect geom = geometry();
 
  662    geom.setRight( workspace()->packPositionLeft( 
this, geom.right(), 
false ));
 
  663    if( geom.width() <= 1 )
 
  665    geom.setSize( 
adjustedSize( geom.size(), SizemodeFixedW ));
 
  666    if( geom.width() > 20 )
 
  670void Workspace::slotWindowGrowVertical()
 
  673        active_client->growVertical();
 
  676void Client::growVertical()
 
  680    TQRect geom = geometry();
 
  681    geom.setBottom( workspace()->packPositionDown( 
this, geom.bottom(), 
true ));
 
  682    TQSize adjsize = 
adjustedSize( geom.size(), SizemodeFixedH );
 
  683    if( geometry().size() == adjsize && geom.size() != adjsize && xSizeHint.height_inc > 1 ) 
 
  685        int newbottom = workspace()->packPositionDown( 
this, geom.bottom() + xSizeHint.height_inc - 1, 
true );
 
  687        if( workspace()->clientArea( MovementArea,
 
  688            TQPoint( geometry().center().x(), ( y() + newbottom ) / 2 ), 
desktop()).bottom() >= newbottom )
 
  689            geom.setBottom( newbottom );
 
  691    geom.setSize( 
adjustedSize( geom.size(), SizemodeFixedH ));
 
  696void Workspace::slotWindowShrinkVertical()
 
  699        active_client->shrinkVertical();
 
  702void Client::shrinkVertical()
 
  706    TQRect geom = geometry();
 
  707    geom.setBottom( workspace()->packPositionUp( 
this, geom.bottom(), 
false ));
 
  708    if( geom.height() <= 1 )
 
  710    geom.setSize( 
adjustedSize( geom.size(), SizemodeFixedH ));
 
  711    if( geom.height() > 20 )
 
  715int Workspace::packPositionLeft( 
const Client* cl, 
int oldx, 
bool left_edge )
 const 
  717    int newx = clientArea( MovementArea, cl ).left();
 
  719        newx = clientArea( MovementArea,
 
  720            TQPoint( cl->geometry().left() - 1, cl->geometry().center().y()), cl->desktop()).left();
 
  723    for( ClientList::ConstIterator it = clients.begin();
 
  727        if( !(*it)->isShown( 
false ) || !(*it)->isOnDesktop( active_client->desktop()))
 
  729        int x = left_edge ? (*it)->geometry().right() + 1 : (*it)->geometry().left() - 1;
 
  730        if( x > newx && x < oldx
 
  731            && !( cl->geometry().top() > (*it)->geometry().bottom() 
 
  732                || cl->geometry().bottom() < (*it)->geometry().top()))
 
  738int Workspace::packPositionRight( 
const Client* cl, 
int oldx, 
bool right_edge )
 const 
  740    int newx = clientArea( MovementArea, cl ).right();
 
  742        newx = clientArea( MovementArea,
 
  743            TQPoint( cl->geometry().right() + 1, cl->geometry().center().y()), cl->desktop()).right();
 
  746    for( ClientList::ConstIterator it = clients.begin();
 
  750        if( !(*it)->isShown( 
false ) || !(*it)->isOnDesktop( cl->desktop()))
 
  752        int x = right_edge ? (*it)->geometry().left() - 1 : (*it)->geometry().right() + 1;
 
  753        if( x < newx && x > oldx
 
  754            && !( cl->geometry().top() > (*it)->geometry().bottom()
 
  755                || cl->geometry().bottom() < (*it)->geometry().top()))
 
  761int Workspace::packPositionUp( 
const Client* cl, 
int oldy, 
bool top_edge )
 const 
  763    int newy = clientArea( MovementArea, cl ).top();
 
  765        newy = clientArea( MovementArea,
 
  766            TQPoint( cl->geometry().center().x(), cl->geometry().top() - 1 ), cl->desktop()).top();
 
  769    for( ClientList::ConstIterator it = clients.begin();
 
  773        if( !(*it)->isShown( 
false ) || !(*it)->isOnDesktop( cl->desktop()))
 
  775        int y = top_edge ? (*it)->geometry().bottom() + 1 : (*it)->geometry().top() - 1;
 
  776        if( y > newy && y < oldy
 
  777            && !( cl->geometry().left() > (*it)->geometry().right() 
 
  778                || cl->geometry().right() < (*it)->geometry().left()))
 
  784int Workspace::packPositionDown( 
const Client* cl, 
int oldy, 
bool bottom_edge )
 const 
  786    int newy = clientArea( MovementArea, cl ).bottom();
 
  788        newy = clientArea( MovementArea,
 
  789            TQPoint( cl->geometry().center().x(), cl->geometry().bottom() + 1 ), cl->desktop()).bottom();
 
  792    for( ClientList::ConstIterator it = clients.begin();
 
  796        if( !(*it)->isShown( 
false ) || !(*it)->isOnDesktop( cl->desktop()))
 
  798        int y = bottom_edge ? (*it)->geometry().top() - 1 : (*it)->geometry().bottom() + 1;
 
  799        if( y < newy && y > oldy
 
  800            && !( cl->geometry().left() > (*it)->geometry().right()
 
  801                || cl->geometry().right() < (*it)->geometry().left()))
 
  810void Workspace::place(Client* c, TQRect& area)
 
  812    initPositioning->place( c, area );
 
  815void Workspace::placeSmart(Client* c, 
const TQRect& area)
 
  817    initPositioning->placeSmart( c, area );
 
void setGeometry(int x, int y, int w, int h, ForceGeometry_t force=NormalGeometrySet)
 
TQSize adjustedSize(const TQSize &, Sizemode mode=SizemodeAny) const