• 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
5Copyright (C) 1999, 2000 Matthias Ettrich <ettrich@kde.org>
6Copyright (C) 1997 to 2002 Cristian Tibirna <tibirna@kde.org>
7Copyright (C) 2003 Lubos Lunak <l.lunak@kde.org>
8
9You can Freely distribute this program under the GNU General Public
10License. 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
25namespace KWinInternal
26{
27
28#ifndef KCMRULES
29
30Placement::Placement(Workspace* w)
31 {
32 m_WorkspacePtr = w;
33
34 reinitCascading( 0 );
35 }
36
40void 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
59void 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
88void 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
131void 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
299void 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
323void 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
416void 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
432void 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
441void 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
452void Placement::placeDialog(Client* c, TQRect& area, Policy nextPlacement )
453 {
454 placeOnMainWindow( c, area, nextPlacement );
455 }
456
457void 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
466void 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
523void 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
543TQRect 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
553Placement::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
577const 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
596void 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
603void 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
611void 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
618void 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
625void Workspace::slotWindowGrowHorizontal()
626 {
627 if( active_client )
628 active_client->growHorizontal();
629 }
630
631void 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
651void Workspace::slotWindowShrinkHorizontal()
652 {
653 if( active_client )
654 active_client->shrinkHorizontal();
655 }
656
657void 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
670void Workspace::slotWindowGrowVertical()
671 {
672 if( active_client )
673 active_client->growVertical();
674 }
675
676void 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
696void Workspace::slotWindowShrinkVertical()
697 {
698 if( active_client )
699 active_client->shrinkVertical();
700 }
701
702void 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
715int 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
738int 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
761int 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
784int 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
810void Workspace::place(Client* c, TQRect& area)
811 {
812 initPositioning->place( c, area );
813 }
814
815void 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.4
This website is maintained by Timothy Pearson.