• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • twin
 

twin

  • twin
placement.cpp
1 /*****************************************************************
2  KWin - the KDE window manager
3  This file is part of the KDE project.
4 
5 Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
6 Copyright (C) 1997 to 2002 Cristian Tibirna <tibirna@kde.org>
7 Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
8 
9 You can Freely distribute this program under the GNU General Public
10 License. See the file "COPYING" for the exact licensing terms.
11 ******************************************************************/
12 
13 #include "placement.h"
14 
15 #include <tqrect.h>
16 #include <assert.h>
17 
18 #ifndef KCMRULES
19 #include "workspace.h"
20 #include "client.h"
21 #include "options.h"
22 #include "rules.h"
23 #endif
24 
25 namespace KWinInternal
26 {
27 
28 #ifndef KCMRULES
29 
30 Placement::Placement(Workspace* w)
31  {
32  m_WorkspacePtr = w;
33 
34  reinitCascading( 0 );
35  }
36 
40 void Placement::place(Client* c, TQRect& area )
41  {
42  Policy policy = c->rules()->checkPlacement( Default );
43  if( policy != Default )
44  {
45  place( c, area, policy );
46  return;
47  }
48 
49  if( c->isUtility())
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 ); // on mainwindow, if any, otherwise centered
55  else
56  place(c, area, options->placement);
57  }
58 
59 void Placement::place(Client* c, TQRect& area, Policy policy, Policy nextPlacement )
60  {
61  if( policy == Unknown )
62  policy = Default;
63  if( policy == Default )
64  policy = options->placement;
65  if( policy == NoPlacement )
66  return;
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);
81  else
82  placeSmart(c, area, nextPlacement);
83  }
84 
88 void Placement::placeAtRandom(Client* c, const TQRect& area, Policy /*next*/ )
89  {
90  const int step = 24;
91  static int px = step;
92  static int py = 2 * step;
93  int tx,ty;
94 
95  const TQRect maxRect = checkArea( c, area );
96 
97  if (px < maxRect.x())
98  px = maxRect.x();
99  if (py < maxRect.y())
100  py = maxRect.y();
101 
102  px += step;
103  py += 2*step;
104 
105  if (px > maxRect.width()/2)
106  px = maxRect.x() + step;
107  if (py > maxRect.height()/2)
108  py = maxRect.y() + step;
109  tx = px;
110  ty = py;
111  if (tx + c->width() > maxRect.right())
112  {
113  tx = maxRect.right() - c->width();
114  if (tx < 0)
115  tx = 0;
116  px = maxRect.x();
117  }
118  if (ty + c->height() > maxRect.bottom())
119  {
120  ty = maxRect.bottom() - c->height();
121  if (ty < 0)
122  ty = 0;
123  py = maxRect.y();
124  }
125  c->move(tx, ty);
126  }
127 
131 void Placement::placeSmart(Client* c, const TQRect& area, Policy /*next*/ )
132  {
133  /*
134  * SmartPlacement by Cristian Tibirna (tibirna@kde.org)
135  * adapted for kwm (16-19jan98) and for twin (16Nov1999) using (with
136  * permission) ideas from fvwm, authored by
137  * Anthony Martin (amartin@engr.csulb.edu).
138  * Xinerama supported added by Balaji Ramani (balaji@yablibli.com)
139  * with ideas from xfce.
140  */
141 
142  const int none = 0, h_wrong = -1, w_wrong = -2; // overlap types
143  long int overlap, min_overlap = 0;
144  int x_optimal, y_optimal;
145  int possible;
146  int desktop = c->desktop() == 0 || c->isOnAllDesktops() ? m_WorkspacePtr->currentDesktop() : c->desktop();
147 
148  int cxl, cxr, cyt, cyb; //temp coords
149  int xl, xr, yt, yb; //temp coords
150  int basket; //temp holder
151 
152  // get the maximum allowed windows space
153  const TQRect maxRect = checkArea( c, area );
154  int x = maxRect.left(), y = maxRect.top();
155  x_optimal = x; y_optimal = y;
156 
157  //client gabarit
158  int ch = c->height() - 1;
159  int cw = c->width() - 1;
160 
161  bool first_pass = true; //CT lame flag. Don't like it. What else would do?
162 
163  //loop over possible positions
164  do
165  {
166  //test if enough room in x and y directions
167  if (y + ch > maxRect.bottom() && ch < maxRect.height())
168  overlap = h_wrong; // this throws the algorithm to an exit
169  else if(x + cw > maxRect.right())
170  overlap = w_wrong;
171  else
172  {
173  overlap = none; //initialize
174 
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)
179  {
180  if((*l)->isOnDesktop(desktop) &&
181  (*l)->isShown( false ) && (*l) != c)
182  {
183 
184  xl = (*l)->x(); yt = (*l)->y();
185  xr = xl + (*l)->width(); yb = yt + (*l)->height();
186 
187  //if windows overlap, calc the overall overlapping
188  if((cxl < xr) && (cxr > xl) &&
189  (cyt < yb) && (cyb > yt))
190  {
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()) // ignore KeepBelow windows
196  overlap += 0; // for placement (see Client::belongsToLayer() for Dock)
197  else
198  overlap += (xr - xl) * (yb - yt);
199  }
200  }
201  }
202  }
203 
204  //CT first time we get no overlap we stop.
205  if (overlap == none)
206  {
207  x_optimal = x;
208  y_optimal = y;
209  break;
210  }
211 
212  if (first_pass)
213  {
214  first_pass = false;
215  min_overlap = overlap;
216  }
217  //CT save the best position and the minimum overlap up to now
218  else if (overlap >= none && overlap < min_overlap)
219  {
220  min_overlap = overlap;
221  x_optimal = x;
222  y_optimal = y;
223  }
224 
225  // really need to loop? test if there's any overlap
226  if (overlap > none)
227  {
228 
229  possible = maxRect.right();
230  if (possible - cw > x) possible -= cw;
231 
232  // compare to the position of each client on the same desk
233  ClientList::ConstIterator l;
234  for(l = m_WorkspacePtr->stackingOrder().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++l)
235  {
236 
237  if ((*l)->isOnDesktop(desktop) &&
238  (*l)->isShown( false ) && (*l) != c)
239  {
240 
241  xl = (*l)->x(); yt = (*l)->y();
242  xr = xl + (*l)->width(); yb = yt + (*l)->height();
243 
244  // if not enough room above or under the current tested client
245  // determine the first non-overlapped x position
246  if((y < yb) && (yt < ch + y))
247  {
248 
249  if((xr > x) && (possible > xr)) possible = xr;
250 
251  basket = xl - cw;
252  if((basket > x) && (possible > basket)) possible = basket;
253  }
254  }
255  }
256  x = possible;
257  }
258 
259  // ... else ==> not enough x dimension (overlap was wrong on horizontal)
260  else if (overlap == w_wrong)
261  {
262  x = maxRect.left();
263  possible = maxRect.bottom();
264 
265  if (possible - ch > y) possible -= ch;
266 
267  //test the position of each window on the desk
268  ClientList::ConstIterator l;
269  for(l = m_WorkspacePtr->stackingOrder().begin(); l != m_WorkspacePtr->stackingOrder().end() ; ++l)
270  {
271  if((*l)->isOnDesktop(desktop) &&
272  (*l) != c && c->isShown( false ))
273  {
274 
275  xl = (*l)->x(); yt = (*l)->y();
276  xr = xl + (*l)->width(); yb = yt + (*l)->height();
277 
278  // if not enough room to the left or right of the current tested client
279  // determine the first non-overlapped y position
280  if((yb > y) && (possible > yb)) possible = yb;
281 
282  basket = yt - ch;
283  if((basket > y) && (possible > basket)) possible = basket;
284  }
285  }
286  y = possible;
287  }
288  }
289  while((overlap != none) && (overlap != h_wrong) && (y < maxRect.bottom()));
290 
291  if(ch>= maxRect.height())
292  y_optimal=maxRect.top();
293 
294  // place the window
295  c->move(x_optimal, y_optimal);
296 
297  }
298 
299 void Placement::reinitCascading( int desktop )
300  { // desktop == 0 - reinit all
301  if( desktop == 0 )
302  {
303  cci.clear();
304  for( int i = 0; i < m_WorkspacePtr->numberOfDesktops(); i++)
305  {
306  DesktopCascadingInfo inf;
307  inf.pos = TQPoint(-1,-1);
308  inf.col = 0;
309  inf.row = 0;
310  cci.append(inf);
311  }
312  }
313  else
314  {
315  cci[desktop - 1].pos = TQPoint(-1, -1);
316  cci[desktop - 1].col = cci[desktop - 1].row = 0;
317  }
318  }
319 
323 void Placement::placeCascaded (Client* c, TQRect& area, Policy nextPlacement)
324  {
325  /* cascadePlacement by Cristian Tibirna (tibirna@kde.org) (30Jan98)
326  */
327  // work coords
328  int xp, yp;
329 
330  //CT how do I get from the 'Client' class the size that NW squarish "handle"
331  const int delta_x = 24;
332  const int delta_y = 24;
333 
334  const int dn = c->desktop() == 0 || c->isOnAllDesktops() ? (m_WorkspacePtr->currentDesktop() - 1) : (c->desktop() - 1);
335 
336  // get the maximum allowed windows space and desk's origin
337  TQRect maxRect = checkArea( c, area );
338 
339  // initialize often used vars: width and height of c; we gain speed
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();
346 
347  if( nextPlacement == Unknown )
348  nextPlacement = Smart;
349 
350  //initialize if needed
351  if (cci[dn].pos.x() < 0 || cci[dn].pos.x() < X || cci[dn].pos.y() < Y )
352  {
353  cci[dn].pos = TQPoint(X, Y);
354  cci[dn].col = cci[dn].row = 0;
355  }
356 
357 
358  xp = cci[dn].pos.x();
359  yp = cci[dn].pos.y();
360 
361  //here to touch in case people vote for resize on placement
362  if ((yp + ch) > H) yp = Y;
363 
364  if ((xp + cw) > W)
365  {
366  if (!yp)
367  {
368  place(c,area,nextPlacement);
369  return;
370  }
371  }
372  else
373  {
374  xp = X;
375  }
376 
377  //if this isn't the first window
378  if (cci[dn].pos.x() != X && cci[dn].pos.y() != Y)
379  {
380  /* The following statements cause an internal compiler error with
381  * egcs-2.91.66 on SuSE Linux 6.3. The equivalent forms compile fine.
382  * 22-Dec-1999 CS
383  *
384  * if (xp != X && yp == Y) xp = delta_x * (++(cci[dn].col));
385  * if (yp != Y && xp == X) yp = delta_y * (++(cci[dn].row));
386  */
387  if (xp != X && yp == Y)
388  {
389  ++(cci[dn].col);
390  xp = delta_x * cci[dn].col;
391  }
392  if (yp != Y && xp == X)
393  {
394  ++(cci[dn].row);
395  yp = delta_y * cci[dn].row;
396  }
397 
398  // last resort: if still doesn't fit, smart place it
399  if (((xp + cw) > W - X) || ((yp + ch) > H - Y))
400  {
401  place(c,area,nextPlacement);
402  return;
403  }
404  }
405 
406  // place the window
407  c->move(TQPoint(xp, yp));
408 
409  // new position
410  cci[dn].pos = TQPoint(xp + delta_x, yp + delta_y);
411  }
412 
416 void Placement::placeCentered (Client* c, const TQRect& area, Policy /*next*/ )
417  {
418 
419  // get the maximum allowed windows space and desk's origin
420  const TQRect maxRect = checkArea( c, area );
421 
422  const int xp = maxRect.left() + (maxRect.width() - c->width()) / 2;
423  const int yp = maxRect.top() + (maxRect.height() - c->height()) / 2;
424 
425  // place the window
426  c->move(TQPoint(xp, yp));
427  }
428 
432 void Placement::placeZeroCornered(Client* c, const TQRect& area, Policy /*next*/ )
433  {
434  // get the maximum allowed windows space and desk's origin
435  const TQRect maxRect = checkArea( c, area );
436 
437  // place the window
438  c->move(TQPoint(maxRect.left(), maxRect.top()));
439  }
440 
441 void Placement::placeUtility(Client* c, TQRect& area, Policy /*next*/ )
442  {
443 // TODO twin should try to place utility windows next to their mainwindow,
444 // preferably at the right edge, and going down if there are more of them
445 // if there's not enough place outside the mainwindow, it should prefer
446 // top-right corner
447  // use the default placement for now
448  place( c, area, Default );
449  }
450 
451 
452 void Placement::placeDialog(Client* c, TQRect& area, Policy nextPlacement )
453  {
454  placeOnMainWindow( c, area, nextPlacement );
455  }
456 
457 void Placement::placeUnderMouse(Client* c, TQRect& area, Policy /*next*/ )
458  {
459  area = checkArea( c, area );
460  TQRect geom = c->geometry();
461  geom.moveCenter( TQCursor::pos());
462  c->move( geom.topLeft());
463  c->keepInArea( area ); // make sure it's kept inside workarea
464  }
465 
466 void Placement::placeOnMainWindow(Client* c, TQRect& area, Policy nextPlacement )
467  {
468  if( nextPlacement == Unknown )
469  nextPlacement = Centered;
470  if( nextPlacement == Maximizing ) // maximize if needed
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;
476  int mains_count = 0;
477  for( ClientList::ConstIterator it = mainwindows.begin();
478  it != mainwindows.end();
479  ++it )
480  {
481  if( mainwindows.count() > 1 && (*it)->isSpecialWindow())
482  continue; // don't consider toolbars etc when placing
483  ++mains_count;
484  place_on2 = *it;
485  if( (*it)->isOnCurrentDesktop())
486  {
487  if( place_on == NULL )
488  place_on = *it;
489  else
490  { // two or more on current desktop -> center
491  // That's the default at least. However, with maximizing placement
492  // policy as the default, the dialog should be either maximized or
493  // made as large as its maximum size and then placed centered.
494  // So the nextPlacement argument allows chaining. In this case, nextPlacement
495  // is Maximizing and it will call placeCentered().
496  place( c, area, Centered );
497  return;
498  }
499  }
500  }
501  if( place_on == NULL )
502  { // 'mains_count' is used because it doesn't include ignored mainwindows
503  if( mains_count != 1 )
504  {
505  place( c, area, Centered );
506  return;
507  }
508  place_on = place_on2; // use the only window filtered together with 'mains_count'
509  }
510  if( place_on->isDesktop())
511  {
512  place( c, area, Centered );
513  return;
514  }
515  TQRect geom = c->geometry();
516  geom.moveCenter( place_on->geometry().center());
517  c->move( geom.topLeft());
518  // get area again, because the mainwindow may be on different xinerama screen
519  area = checkArea( c, TQRect());
520  c->keepInArea( area ); // make sure it's kept inside workarea
521  }
522 
523 void Placement::placeMaximizing(Client* c, TQRect& area, Policy nextPlacement )
524  {
525  if( nextPlacement == Unknown )
526  nextPlacement = Smart;
527  if( c->isMaximizable() && c->maxSize().width() >= area.width() && c->maxSize().height() >= area.height())
528  {
529  if( m_WorkspacePtr->clientArea( MaximizeArea, c ) == area )
530  c->maximize( Client::MaximizeFull );
531  else // if the geometry doesn't match default maximize area (xinerama case?),
532  { // it's probably better to use the given area
533  c->setGeometry( area );
534  }
535  }
536  else
537  {
538  c->resizeWithChecks( c->maxSize().boundedTo( area.size()));
539  place( c, area, nextPlacement );
540  }
541  }
542 
543 TQRect Placement::checkArea( const Client* c, const TQRect& area )
544  {
545  if( area.isNull())
546  return m_WorkspacePtr->clientArea( PlacementArea, c->geometry().center(), c->desktop());
547  return area;
548  }
549 
550 #endif
551 
552 
553 Placement::Policy Placement::policyFromString( const TQString& policy, bool no_special )
554  {
555  if( policy == "NoPlacement" )
556  return NoPlacement;
557  else if( policy == "Default" && !no_special )
558  return Default;
559  else if( policy == "Random" )
560  return Random;
561  else if( policy == "Cascade" )
562  return Cascade;
563  else if( policy == "Centered" )
564  return Centered;
565  else if( policy == "ZeroCornered" )
566  return ZeroCornered;
567  else if( policy == "UnderMouse" && !no_special)
568  return UnderMouse;
569  else if( policy == "OnMainWindow" && !no_special)
570  return OnMainWindow;
571  else if( policy == "Maximizing" )
572  return Maximizing;
573  else
574  return Smart;
575  }
576 
577 const char* Placement::policyToString( Policy policy )
578  {
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 ];
584  }
585 
586 
587 #ifndef KCMRULES
588 
589 // ********************
590 // Workspace
591 // ********************
592 
596 void Workspace::slotWindowPackLeft()
597  {
598  if( active_client && active_client->isMovable())
599  active_client->move( packPositionLeft( active_client, active_client->geometry().left(), true ),
600  active_client->y());
601  }
602 
603 void Workspace::slotWindowPackRight()
604  {
605  if( active_client && active_client->isMovable())
606  active_client->move(
607  packPositionRight( active_client, active_client->geometry().right(), true )
608  - active_client->width() + 1, active_client->y());
609  }
610 
611 void Workspace::slotWindowPackUp()
612  {
613  if( active_client && active_client->isMovable())
614  active_client->move( active_client->x(),
615  packPositionUp( active_client, active_client->geometry().top(), true ));
616  }
617 
618 void Workspace::slotWindowPackDown()
619  {
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 );
623  }
624 
625 void Workspace::slotWindowGrowHorizontal()
626  {
627  if( active_client )
628  active_client->growHorizontal();
629  }
630 
631 void Client::growHorizontal()
632  {
633  if( !isResizable() || isShade())
634  return;
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 ) // take care of size increments
639  {
640  int newright = workspace()->packPositionRight( this, geom.right() + xSizeHint.width_inc - 1, true );
641  // check that it hasn't grown outside of the area, due to size increments
642  // TODO this may be wrong?
643  if( workspace()->clientArea( MovementArea,
644  TQPoint(( x() + newright ) / 2, geometry().center().y()), desktop()).right() >= newright )
645  geom.setRight( newright );
646  }
647  geom.setSize( adjustedSize( geom.size(), SizemodeFixedW ));
648  setGeometry( geom );
649  }
650 
651 void Workspace::slotWindowShrinkHorizontal()
652  {
653  if( active_client )
654  active_client->shrinkHorizontal();
655  }
656 
657 void Client::shrinkHorizontal()
658  {
659  if( !isResizable() || isShade())
660  return;
661  TQRect geom = geometry();
662  geom.setRight( workspace()->packPositionLeft( this, geom.right(), false ));
663  if( geom.width() <= 1 )
664  return;
665  geom.setSize( adjustedSize( geom.size(), SizemodeFixedW ));
666  if( geom.width() > 20 )
667  setGeometry( geom );
668  }
669 
670 void Workspace::slotWindowGrowVertical()
671  {
672  if( active_client )
673  active_client->growVertical();
674  }
675 
676 void Client::growVertical()
677  {
678  if( !isResizable() || isShade())
679  return;
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 ) // take care of size increments
684  {
685  int newbottom = workspace()->packPositionDown( this, geom.bottom() + xSizeHint.height_inc - 1, true );
686  // check that it hasn't grown outside of the area, due to size increments
687  if( workspace()->clientArea( MovementArea,
688  TQPoint( geometry().center().x(), ( y() + newbottom ) / 2 ), desktop()).bottom() >= newbottom )
689  geom.setBottom( newbottom );
690  }
691  geom.setSize( adjustedSize( geom.size(), SizemodeFixedH ));
692  setGeometry( geom );
693  }
694 
695 
696 void Workspace::slotWindowShrinkVertical()
697  {
698  if( active_client )
699  active_client->shrinkVertical();
700  }
701 
702 void Client::shrinkVertical()
703  {
704  if( !isResizable() || isShade())
705  return;
706  TQRect geom = geometry();
707  geom.setBottom( workspace()->packPositionUp( this, geom.bottom(), false ));
708  if( geom.height() <= 1 )
709  return;
710  geom.setSize( adjustedSize( geom.size(), SizemodeFixedH ));
711  if( geom.height() > 20 )
712  setGeometry( geom );
713  }
714 
715 int Workspace::packPositionLeft( const Client* cl, int oldx, bool left_edge ) const
716  {
717  int newx = clientArea( MovementArea, cl ).left();
718  if( oldx <= newx ) // try another Xinerama screen
719  newx = clientArea( MovementArea,
720  TQPoint( cl->geometry().left() - 1, cl->geometry().center().y()), cl->desktop()).left();
721  if( oldx <= newx )
722  return oldx;
723  for( ClientList::ConstIterator it = clients.begin();
724  it != clients.end();
725  ++it)
726  {
727  if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( active_client->desktop()))
728  continue;
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() // they overlap in Y direction
732  || cl->geometry().bottom() < (*it)->geometry().top()))
733  newx = x;
734  }
735  return newx;
736  }
737 
738 int Workspace::packPositionRight( const Client* cl, int oldx, bool right_edge ) const
739  {
740  int newx = clientArea( MovementArea, cl ).right();
741  if( oldx >= newx ) // try another Xinerama screen
742  newx = clientArea( MovementArea,
743  TQPoint( cl->geometry().right() + 1, cl->geometry().center().y()), cl->desktop()).right();
744  if( oldx >= newx )
745  return oldx;
746  for( ClientList::ConstIterator it = clients.begin();
747  it != clients.end();
748  ++it)
749  {
750  if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
751  continue;
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()))
756  newx = x;
757  }
758  return newx;
759  }
760 
761 int Workspace::packPositionUp( const Client* cl, int oldy, bool top_edge ) const
762  {
763  int newy = clientArea( MovementArea, cl ).top();
764  if( oldy <= newy ) // try another Xinerama screen
765  newy = clientArea( MovementArea,
766  TQPoint( cl->geometry().center().x(), cl->geometry().top() - 1 ), cl->desktop()).top();
767  if( oldy <= newy )
768  return oldy;
769  for( ClientList::ConstIterator it = clients.begin();
770  it != clients.end();
771  ++it)
772  {
773  if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
774  continue;
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() // they overlap in X direction
778  || cl->geometry().right() < (*it)->geometry().left()))
779  newy = y;
780  }
781  return newy;
782  }
783 
784 int Workspace::packPositionDown( const Client* cl, int oldy, bool bottom_edge ) const
785  {
786  int newy = clientArea( MovementArea, cl ).bottom();
787  if( oldy >= newy ) // try another Xinerama screen
788  newy = clientArea( MovementArea,
789  TQPoint( cl->geometry().center().x(), cl->geometry().bottom() + 1 ), cl->desktop()).bottom();
790  if( oldy >= newy )
791  return oldy;
792  for( ClientList::ConstIterator it = clients.begin();
793  it != clients.end();
794  ++it)
795  {
796  if( !(*it)->isShown( false ) || !(*it)->isOnDesktop( cl->desktop()))
797  continue;
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()))
802  newy = y;
803  }
804  return newy;
805  }
806 
810 void Workspace::place(Client* c, TQRect& area)
811  {
812  initPositioning->place( c, area );
813  }
814 
815 void Workspace::placeSmart(Client* c, const TQRect& area)
816  {
817  initPositioning->placeSmart( c, area );
818  }
819 
820 #endif
821 
822 } // namespace
KWinInternal::Client::desktop
int desktop() const
Definition: client.h:751
KWinInternal::Client::setGeometry
void setGeometry(int x, int y, int w, int h, ForceGeometry_t force=NormalGeometrySet)
Definition: geometry.cpp:1714
KWinInternal::Client::isResizable
bool isResizable() const
Definition: geometry.cpp:1665
KWinInternal::Client::adjustedSize
TQSize adjustedSize(const TQSize &, Sizemode mode=SizemodeAny) const
Definition: geometry.cpp:1071

twin

Skip menu "twin"
  • Main Page
  • Alphabetical List
  • Class List
  • File List
  • Class Members

twin

Skip menu "twin"
  • kate
  • libkonq
  • twin
  •   lib
Generated for twin by doxygen 1.9.1
This website is maintained by Timothy Pearson.