Salome HOME
Moved some functionality to VTKViewer_Utilities.h
[modules/kernel.git] / src / PatchQt / qworkspaceP.cxx
1 /////////////////////////////////////////////////////////////////////////////
2 // Module      : PatchQt
3 // File        : qworkspaceP.cxx
4 // Description : the patch for Qt's QWorkspace class (qworkspace.cpp)
5 /////////////////////////////////////////////////////////////////////////////
6
7 /****************************************************************************
8 ** $Id$
9 **
10 ** Implementation of the QWorkspace class
11 **
12 ** Created : 931107
13 **
14 ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
15 **
16 ** This file is part of the workspace module of the Qt GUI Toolkit.
17 **
18 ** This file may be distributed under the terms of the Q Public License
19 ** as defined by Trolltech AS of Norway and appearing in the file
20 ** LICENSE.QPL included in the packaging of this file.
21 **
22 ** This file may be distributed and/or modified under the terms of the
23 ** GNU General Public License version 2 as published by the Free Software
24 ** Foundation and appearing in the file LICENSE.GPL included in the
25 ** packaging of this file.
26 **
27 ** Licensees holding valid Qt Enterprise Edition licenses may use this
28 ** file in accordance with the Qt Commercial License Agreement provided
29 ** with the Software.
30 **
31 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
32 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
33 **
34 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
35 **   information about Qt Commercial License Agreements.
36 ** See http://www.trolltech.com/qpl/ for QPL licensing information.
37 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
38 **
39 ** Contact info@trolltech.com if any conditions of this licensing are
40 ** not clear to you.
41 **
42 **********************************************************************/
43
44 #include "qworkspaceP.h"
45
46 #include <qapplication.h>
47 #include <qobjectlist.h>
48 #include <qlayout.h>
49 #include <qtoolbutton.h>
50 #include <qlabel.h>
51 #include <qvbox.h>
52 #include <qaccel.h>
53 #include <qcursor.h>
54 #include <qpopupmenu.h>
55 #include <qmenubar.h>
56 #include <qguardedptr.h>
57 #include <qiconset.h>
58 #include <qfocusdata.h>
59 #include <qdatetime.h>
60 #include <qtooltip.h>
61 #include <qwmatrix.h>
62 #include <qimage.h>
63 #include <qscrollbar.h>
64 #include <qstyle.h>
65 #include <qframe.h>
66 #if defined(Q_WS_WIN)
67 #include <qt_windows.h>
68 #endif
69 #include <qplatformdefs.h>
70 #include <qtimer.h>
71 #include <qpainter.h>
72
73 #include <private/qapplication_p.h>
74 #include <private/qinternal_p.h>
75 using namespace std;
76
77 #define BUTTON_WIDTH    16
78 #define BUTTON_HEIGHT   14
79
80
81 /*!
82     \class QWorkspaceP qworkspace.h
83     \brief The QWorkspaceP widget provides a workspace window that can
84     contain decorated windows, e.g. for MDI.
85
86     \module workspace
87
88     \ingroup application
89     \ingroup organizers
90     \mainclass
91
92     An MDI (multiple document interface) application has one main
93     window with a menu bar. The central widget of this window is a
94     workspace. The workspace itself contains zero, one or more
95     document windows, each of which displays a document.
96
97     The workspace itself is an ordinary Qt widget. It has a standard
98     constructor that takes a parent widget and an object name. The
99     parent window is usually a QMainWindow, but it need not be.
100
101     Document windows (i.e. MDI windows) are also ordinary Qt widgets
102     which have the workspace as parent widget. When you call show(),
103     hide(), showMaximized(), setCaption(), etc. on a document window,
104     it is shown, hidden, etc. with a frame, caption, icon and icon
105     text, just as you'd expect. You can provide widget flags which
106     will be used for the layout of the decoration or the behaviour of
107     the widget itself.
108
109     To change the geometry of the MDI windows it is necessary to make
110     the function calls to the parentWidget() of the widget, as this
111     will move or resize the decorated window.
112
113     A document window becomes active when it gets the keyboard focus.
114     You can activate it using setFocus(), and the user can activate it
115     by moving focus in the normal ways. The workspace emits a signal
116     windowActivated() when it detects the activation change, and the
117     function activeWindow() always returns a pointer to the active
118     document window.
119
120     The convenience function windowList() returns a list of all
121     document windows. This is useful to create a popup menu
122     "<u>W</u>indows" on the fly, for example.
123
124     QWorkspaceP provides two built-in layout strategies for child
125     windows: cascade() and tile(). Both are slots so you can easily
126     connect menu entries to them.
127
128     If you want your users to be able to work with document windows
129     larger than the actual workspace, set the scrollBarsEnabled
130     property to TRUE.
131
132     If the top-level window contains a menu bar and a document window
133     is maximised, QWorkspaceP moves the document window's minimize,
134     restore and close buttons from the document window's frame to the
135     workspace window's menu bar. It then inserts a window operations
136     menu at the far left of the menu bar.
137 */
138
139 static bool inCaptionChange = FALSE;
140
141 class QWorkspacePPrivate {
142 public:
143     QWorkspacePChild* active;
144     QPtrList<QWorkspacePChild> windows;
145     QPtrList<QWorkspacePChild> focus;
146     QPtrList<QWidget> icons;
147     QWorkspacePChild* maxWindow;
148     QRect maxRestore;
149     QGuardedPtr<QFrame> maxcontrols;
150     QGuardedPtr<QMenuBar> maxmenubar;
151
152     int px;
153     int py;
154     QWidget *becomeActive;
155     QGuardedPtr<QLabel> maxtools;
156     QPopupMenu* popup;
157     QPopupMenu* toolPopup;
158     int menuId;
159     int controlId;
160     QString topCaption;
161     bool autoFocusChange;
162
163     QScrollBar *vbar, *hbar;
164     QWidget *corner;
165     int yoffset, xoffset;
166 };
167
168 /*!
169   Constructs a workspace with a \a parent and a \a name.
170  */
171 QWorkspaceP::QWorkspaceP( QWidget *parent, const char *name )
172     : QWidget( parent, name, WNoMousePropagation )
173 {
174     d = new QWorkspacePPrivate;
175     d->maxcontrols = 0;
176     d->active = 0;
177     d->maxWindow = 0;
178     d->maxtools = 0;
179     d->px = 0;
180     d->py = 0;
181     d->becomeActive = 0;
182     d->autoFocusChange = FALSE;
183 #if defined(Q_WS_WIN)
184     d->popup = new QPopupMenu( this, "qt_internal_mdi_popup" );
185     d->toolPopup = new QPopupMenu( this, "qt_internal_mdi_popup" );
186 #else
187     d->popup = new QPopupMenu( parentWidget(), "qt_internal_mdi_popup" );
188     d->toolPopup = new QPopupMenu( parentWidget(), "qt_internal_mdi_popup" );
189 #endif
190
191     d->menuId = -1;
192     d->controlId = -1;
193     connect( d->popup, SIGNAL( aboutToShow() ), this, SLOT(operationMenuAboutToShow() ));
194     connect( d->popup, SIGNAL( activated(int) ), this, SLOT( operationMenuActivated(int) ) );
195     d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarNormalButton)), tr("&Restore"), 1);
196     d->popup->insertItem(tr("&Move"), 2);
197     d->popup->insertItem(tr("&Size"), 3);
198     d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarMinButton)), tr("Mi&nimize"), 4);
199     d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarMaxButton)), tr("Ma&ximize"), 5);
200     d->popup->insertSeparator();
201     d->popup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarCloseButton)),
202                                   tr("&Close")
203 #ifndef QT_NO_ACCEL
204                                         +"\t"+QAccel::keyToString(CTRL+Key_F4)
205 #endif
206                     , this, SLOT( closeActiveWindow() ) );
207
208     connect( d->toolPopup, SIGNAL( aboutToShow() ), this, SLOT(toolMenuAboutToShow() ));
209     connect( d->toolPopup, SIGNAL( activated(int) ), this, SLOT( operationMenuActivated(int) ) );
210     d->toolPopup->insertItem(tr("&Move"), 2);
211     d->toolPopup->insertItem(tr("&Size"), 3);
212     d->toolPopup->insertItem(tr("Stay on &Top"), 7);
213     d->toolPopup->setItemChecked( 7, TRUE );
214     d->toolPopup->setCheckable( TRUE );
215     d->toolPopup->insertSeparator();
216     d->toolPopup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarShadeButton)), tr("Sh&ade"), 6);
217     d->toolPopup->insertItem(QIconSet(style().stylePixmap(QStyle::SP_TitleBarCloseButton)),
218                                       tr("&Close")
219 #ifndef QT_NO_ACCEL
220                                         +"\t"+QAccel::keyToString( CTRL+Key_F4)
221 #endif
222                 , this, SLOT( closeActiveWindow() ) );
223
224 #ifndef QT_NO_ACCEL
225     QAccel* a = new QAccel( this );
226     a->connectItem( a->insertItem( ALT + Key_Minus),
227                     this, SLOT( showOperationMenu() ) );
228
229     a->connectItem( a->insertItem( CTRL + Key_F6),
230                     this, SLOT( activateNextWindow() ) );
231     a->connectItem( a->insertItem( CTRL + Key_Tab),
232                     this, SLOT( activateNextWindow() ) );
233
234     a->connectItem( a->insertItem( CTRL + SHIFT + Key_F6),
235                     this, SLOT( activatePreviousWindow() ) );
236     a->connectItem( a->insertItem( CTRL + SHIFT + Key_Tab),
237                     this, SLOT( activatePreviousWindow() ) );
238
239     a->connectItem( a->insertItem( CTRL + Key_F4 ),
240                     this, SLOT( closeActiveWindow() ) );
241 #endif
242
243     setBackgroundMode( PaletteDark );
244     setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) );
245
246 #ifndef QT_NO_WIDGET_TOPEXTRA
247     d->topCaption = topLevelWidget()->caption();
248 #endif
249
250     d->hbar = d->vbar = 0;
251     d->corner = 0;
252     d->xoffset = d->yoffset = 0;
253
254     updateWorkspace();
255
256     topLevelWidget()->installEventFilter( this );
257 }
258
259 /*!  Destroys the workspace and frees any allocated resources. */
260
261 QWorkspaceP::~QWorkspaceP()
262 {
263     delete d;
264     d = 0;
265 }
266
267 /*!\reimp */
268 QSize QWorkspaceP::sizeHint() const
269 {
270     QSize s( QApplication::desktop()->size() );
271     return QSize( s.width()*2/3, s.height()*2/3);
272 }
273
274 /*! \reimp */
275 void QWorkspaceP::setPaletteBackgroundColor( const QColor & c )
276 {
277     setEraseColor( c );
278 }
279
280
281 /*! \reimp */
282 void QWorkspaceP::setPaletteBackgroundPixmap( const QPixmap & pm )
283 {
284     setErasePixmap( pm );
285 }
286
287 /*! \reimp */
288 void QWorkspaceP::childEvent( QChildEvent * e)
289 {
290     if (e->inserted() && e->child()->isWidgetType()) {
291         QWidget* w = (QWidget*) e->child();
292         if ( !w || !w->testWFlags( WStyle_Title | WStyle_NormalBorder | WStyle_DialogBorder )
293              || d->icons.contains( w ) || w == d->vbar || w == d->hbar || w == d->corner )
294             return;         // nothing to do
295
296         bool hasBeenHidden = w->isHidden();
297         bool hasSize = w->testWState( WState_Resized );
298         int x = w->x();
299         int y = w->y();
300         bool hasPos = x != 0 || y != 0;
301         QSize s = w->size().expandedTo( w->minimumSizeHint() );
302         if ( !hasSize && w->sizeHint().isValid() )
303             w->adjustSize();
304
305         QWorkspacePChild* child = new QWorkspacePChild( w, this, "qt_workspacechild" );
306         child->installEventFilter( this );
307
308         connect( child, SIGNAL( popupOperationMenu( const QPoint& ) ),
309                  this, SLOT( popupOperationMenu( const QPoint& ) ) );
310         connect( child, SIGNAL( showOperationMenu() ),
311                  this, SLOT( showOperationMenu() ) );
312         d->windows.append( child );
313         if ( child->isVisibleTo( this ) )
314             d->focus.append( child );
315         child->internalRaise();
316
317         if ( hasBeenHidden )
318             w->hide();
319         else if ( !isVisible() )  // that's a case were we don't receive a showEvent in time. Tricky.
320             child->show();
321
322         if ( !hasPos )
323             place( child );
324         if ( hasSize )
325             child->resize( s + child->baseSize() );
326         else
327             child->adjustSize();
328         if ( hasPos )
329             child->move( x, y );
330
331         activateWindow( w );
332         updateWorkspace();
333     } else if (e->removed() ) {
334         if ( d->windows.contains( (QWorkspacePChild*)e->child() ) ) {
335             d->windows.removeRef( (QWorkspacePChild*)e->child() );
336             d->focus.removeRef( (QWorkspacePChild*)e->child() );
337             if (d->windows.count() <= 0) { // VSR+ 26/03/03 -->
338               activateWindow( 0 );         
339               d->maxWindow = 0;            
340               hideMaximizeControls();      
341             }                              // <-- VSR+ 26/03/03
342             updateWorkspace();
343         }
344     }
345 }
346
347 /*! \reimp
348 */
349 #ifndef QT_NO_WHEELEVENT
350 void QWorkspaceP::wheelEvent( QWheelEvent *e )
351 {
352     if ( !scrollBarsEnabled() )
353         return;
354     if ( d->vbar && d->vbar->isVisible() && !( e->state() & AltButton ) )
355         QApplication::sendEvent( d->vbar, e );
356     else if ( d->hbar && d->hbar->isVisible() )
357         QApplication::sendEvent( d->hbar, e );
358 }
359 #endif
360
361 void QWorkspaceP::activateWindow( QWidget* w, bool change_focus )
362 {
363     if ( !w ) {
364         d->active = 0;
365         emit windowActivated( 0 );
366         return;
367     }
368     if ( !isVisibleTo( 0 ) ) {
369         d->becomeActive = w;
370         return;
371     }
372     if ( d->active && d->active->windowWidget() == w )
373         return;
374     QPtrListIterator<QWorkspacePChild> it( d->windows );
375     while ( it.current () ) {
376         QWorkspacePChild* c = it.current();
377         ++it;
378         c->setActive( c->windowWidget() == w );
379         if (c->windowWidget() == w)
380             d->active = c;
381     }
382
383     if (!d->active)
384         return;
385
386     if ( d->maxWindow && d->maxWindow != d->active && d->active->windowWidget() &&
387          d->active->windowWidget()->testWFlags( WStyle_MinMax ) &&
388          !d->active->windowWidget()->testWFlags( WStyle_Tool ) ) {
389         maximizeWindow( d->active->windowWidget() );
390         if ( d->maxtools ) {
391 #ifndef QT_NO_WIDGET_TOPEXTRA
392             if ( w->icon() ) {
393                 QPixmap pm(*w->icon());
394                 if(pm.width() != 14 || pm.height() != 14) {
395                     QImage im;
396                     im = pm;
397                     pm = im.smoothScale( 14, 14 );
398                 }
399                 d->maxtools->setPixmap( pm );
400             } else
401 #endif
402             {
403                 QPixmap pm(14,14);
404                 pm.fill( white );
405                 d->maxtools->setPixmap( pm );
406             }
407         }
408     }
409
410     d->active->internalRaise();
411
412     if ( change_focus ) {
413         if ( d->focus.find( d->active ) >=0 ) {
414             d->focus.removeRef( d->active );
415 //          d->focus.append( d->active ); //VSR-
416         }
417         d->focus.append( d->active ); //VSR+
418     }
419
420     updateWorkspace();
421     emit windowActivated( w );
422 }
423
424
425 /*!
426   Returns the active window, or 0 if no window is active.
427  */
428 QWidget* QWorkspaceP::activeWindow() const
429 {
430     return d->active?d->active->windowWidget():0;
431 }
432
433
434 void QWorkspaceP::place( QWidget* w)
435 {
436     int overlap, minOverlap = 0;
437     int possible;
438
439     QRect r1(0, 0, 0, 0);
440     QRect r2(0, 0, 0, 0);
441     QRect maxRect = rect();
442     int x = maxRect.left(), y = maxRect.top();
443     QPoint wpos(maxRect.left(), maxRect.top());
444
445     bool firstPass = TRUE;
446
447     do {
448         if ( y + w->height() > maxRect.bottom() ) {
449             overlap = -1;
450         } else if( x + w->width() > maxRect.right() ) {
451             overlap = -2;
452         } else {
453             overlap = 0;
454
455             r1.setRect(x, y, w->width(), w->height());
456
457             QWidget *l;
458             QPtrListIterator<QWorkspacePChild> it( d->windows );
459             while ( it.current () ) {
460                 l = it.current();
461                 ++it;
462                 if (! d->icons.contains(l) && ! l->isHidden() && l != w ) {
463                     if ( d->maxWindow == l )
464                         r2 = d->maxRestore;
465                     else
466                         r2.setRect(l->x(), l->y(), l->width(), l->height());
467
468                     if (r2.intersects(r1)) {
469                         r2.setCoords(QMAX(r1.left(), r2.left()),
470                                      QMAX(r1.top(), r2.top()),
471                                      QMIN(r1.right(), r2.right()),
472                                      QMIN(r1.bottom(), r2.bottom())
473                                      );
474
475                         overlap += (r2.right() - r2.left()) *
476                                    (r2.bottom() - r2.top());
477                     }
478                 }
479             }
480         }
481
482         if (overlap == 0) {
483             wpos = QPoint(x, y);
484             break;
485         }
486
487         if (firstPass) {
488             firstPass = FALSE;
489             minOverlap = overlap;
490         } else if ( overlap >= 0 && overlap < minOverlap) {
491             minOverlap = overlap;
492             wpos = QPoint(x, y);
493         }
494
495         if ( overlap > 0 ) {
496             possible = maxRect.right();
497             if ( possible - w->width() > x) possible -= w->width();
498
499             QWidget *l;
500             QPtrListIterator<QWorkspacePChild> it( d->windows );
501             while ( it.current () ) {
502                 l = it.current();
503                 ++it;
504                 if (! d->icons.contains(l) && ! l->isHidden() && l != w ) {
505                     if ( d->maxWindow == l )
506                         r2 = d->maxRestore;
507                     else
508                         r2.setRect(l->x(), l->y(), l->width(), l->height());
509
510                     if( ( y < r2.bottom() ) && ( r2.top() < w->height() + y ) ) {
511                         if( r2.right() > x )
512                             possible = possible < r2.right() ?
513                                        possible : r2.right();
514
515                         if( r2.left() - w->width() > x )
516                             possible = possible < r2.left() - w->width() ?
517                                        possible : r2.left() - w->width();
518                     }
519                 }
520             }
521
522             x = possible;
523         } else if ( overlap == -2 ) {
524             x = maxRect.left();
525             possible = maxRect.bottom();
526
527             if ( possible - w->height() > y ) possible -= w->height();
528
529             QWidget *l;
530             QPtrListIterator<QWorkspacePChild> it( d->windows );
531             while ( it.current () ) {
532                 l = it.current();
533                 ++it;
534                 if (l != w && ! d->icons.contains(w)) {
535                     if ( d->maxWindow == l )
536                         r2 = d->maxRestore;
537                     else
538                         r2.setRect(l->x(), l->y(), l->width(), l->height());
539
540                     if( r2.bottom() > y)
541                         possible = possible < r2.bottom() ?
542                                    possible : r2.bottom();
543
544                     if( r2.top() - w->height() > y )
545                         possible = possible < r2.top() - w->height() ?
546                                    possible : r2.top() - w->height();
547                 }
548             }
549
550             y = possible;
551         }
552     }
553     while( overlap != 0 && overlap != -1 );
554
555     w->move(wpos);
556     updateWorkspace();
557 }
558
559
560 void QWorkspaceP::insertIcon( QWidget* w )
561 {
562     if ( !w || d->icons.contains( w ) )
563         return;
564     d->icons.append( w );
565     if (w->parentWidget() != this )
566         w->reparent( this, 0, QPoint(0,0), FALSE);
567
568
569     QRect cr = updateWorkspace();
570     int x = 0;
571     int y = cr.height() - w->height();
572
573     QPtrListIterator<QWidget> it( d->icons );
574     while ( it.current () ) {
575         QWidget* i = it.current();
576         ++it;
577         if ( x > 0 && x + i->width() > cr.width() ){
578             x = 0;
579             y -= i->height();
580         }
581
582         if ( i != w &&
583             i->geometry().intersects( QRect( x, y, w->width(), w->height() ) ) )
584             x += i->width();
585     }
586     w->move( x, y );
587
588     if ( isVisibleTo( parentWidget() ) ) {
589         w->show();
590         w->lower();
591     }
592     updateWorkspace();
593 }
594
595
596 void QWorkspaceP::removeIcon( QWidget* w)
597 {
598     if ( !d->icons.contains( w ) )
599         return;
600     d->icons.remove( w );
601     w->hide();
602 }
603
604
605 /*! \reimp  */
606 void QWorkspaceP::resizeEvent( QResizeEvent * )
607 {
608     if ( d->maxWindow ) {
609         d->maxWindow->adjustToFullscreen();
610         ((QWorkspaceP*)d->maxWindow->windowWidget())->setWState( WState_Maximized );
611     }
612
613     QRect cr = updateWorkspace();
614
615     QPtrListIterator<QWorkspacePChild> it( d->windows );
616     while ( it.current () ) {
617         QWorkspacePChild* c = it.current();
618         ++it;
619         if ( c->windowWidget() && !c->windowWidget()->testWFlags( WStyle_Tool ) )
620             continue;
621
622         int x = c->x();
623         int y = c->y();
624         if ( c->snappedDown )
625             y =  cr.height() - c->height();
626         if ( c->snappedRight )
627             x =  cr.width() - c->width();
628
629         if ( x != c->x() || y != c->y() )
630             c->move( x, y );
631     }
632
633 }
634
635 /*! \reimp */
636 void QWorkspaceP::showEvent( QShowEvent *e )
637 {
638     if ( d->maxWindow && !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this))
639         showMaximizeControls();
640     QWidget::showEvent( e );
641     if ( d->becomeActive ) {
642         activateWindow( d->becomeActive );
643         d->becomeActive = 0;
644     }
645     else if ( d->windows.count() > 0 && !d->active )
646         activateWindow( d->windows.first()->windowWidget() );
647
648     updateWorkspace();
649 }
650
651 /*! \reimp */
652 void QWorkspaceP::hideEvent( QHideEvent * )
653 {
654
655     if ( !isVisibleTo(0) && !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this))
656         hideMaximizeControls();
657 }
658
659 void QWorkspaceP::minimizeWindow( QWidget* w)
660 {
661     QWorkspacePChild* c = findChild( w );
662     QWorkspacePChild* oldActive = d->active;    //VSR+
663
664     if ( !w || w && (!w->testWFlags( WStyle_Minimize ) || w->testWFlags( WStyle_Tool) ) )
665         return;
666
667     if ( c ) {
668         QWorkspaceP *fake = (QWorkspaceP*)w;
669
670         setUpdatesEnabled( FALSE );
671         bool wasMax = FALSE;
672         if ( c == d->maxWindow ) {
673             wasMax = TRUE;
674             d->maxWindow = 0;
675             inCaptionChange = TRUE;
676 #ifndef QT_NO_WIDGET_TOPEXTRA
677             if ( !!d->topCaption )
678                 topLevelWidget()->setCaption( d->topCaption );
679 #endif
680             inCaptionChange = FALSE;
681             if ( !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this) )
682                 hideMaximizeControls();
683             for (QPtrListIterator<QWorkspacePChild> it( d->windows ); it.current(); ++it ) {
684                 QWorkspacePChild* c = it.current();
685                 if ( c->titlebar )
686                     c->titlebar->setMovable( TRUE );
687                 c->widgetResizeHandler->setActive( TRUE );
688             }
689         }
690         insertIcon( c->iconWidget() );
691         bool wasFocused = c->titlebar->isActive();
692         blockSignals( TRUE );//VSR+
693         c->hide();
694         blockSignals( FALSE );//VSR+
695         if ( wasFocused && ( !d->active || d->active && d->active->testWState( WState_Minimized ) ) ) { //VSR+
696 //      if ( wasFocused && d->active && d->active->testWState( WState_Minimized ) ) {                   //VSR-
697 //VSR-      blockSignals( TRUE ); 
698             activateWindow( w, FALSE );
699 //VSR-      blockSignals( FALSE );
700         }
701         else if ( oldActive != d->active ) { //VSR+
702            emit ( windowActivated( d->active ? d->active->windowWidget() : 0 ) ); //VSR+
703         } //VSR+
704         if ( wasMax )
705             c->setGeometry( d->maxRestore );
706         if ( d->focus.find( c ) < 0 ) // VSR+
707             d->focus.append( c );
708
709         setUpdatesEnabled( TRUE );
710         updateWorkspace();
711
712         fake->clearWState( WState_Maximized );
713         fake->setWState( WState_Minimized );
714         c->clearWState( WState_Maximized );
715         c->setWState( WState_Minimized );
716     }
717 }
718
719 void QWorkspaceP::normalizeWindow( QWidget* w)
720 {
721     QWorkspacePChild* c = findChild( w );
722     if ( !w )
723         return;
724     if ( c ) {
725         QWorkspaceP *fake = (QWorkspaceP*)w;
726         fake->clearWState( WState_Minimized | WState_Maximized );
727         if ( !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this) && d->maxWindow ) {
728             hideMaximizeControls();
729         } else {
730             c->widgetResizeHandler->setActive( TRUE );
731             if ( c->titlebar )
732                 c->titlebar->setMovable(TRUE);
733         }
734         fake->clearWState( WState_Minimized | WState_Maximized );
735         c->clearWState( WState_Minimized | WState_Maximized );
736
737         if ( c == d->maxWindow ) {
738             c->setGeometry( d->maxRestore );
739             d->maxWindow = 0;
740 #ifndef QT_NO_WIDGET_TOPEXTRA
741             inCaptionChange = TRUE;
742             if ( !!d->topCaption )
743                 topLevelWidget()->setCaption( d->topCaption );
744             inCaptionChange = FALSE;
745 #endif
746         } else {
747             if ( c->iconw )
748                 removeIcon( c->iconw->parentWidget() );
749             c->show();
750         }
751
752         if ( !style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this))
753             hideMaximizeControls();
754         for (QPtrListIterator<QWorkspacePChild> it( d->windows ); it.current(); ++it ) {
755             QWorkspacePChild* c = it.current();
756             if ( c->titlebar )
757                 c->titlebar->setMovable( TRUE );
758             c->widgetResizeHandler->setActive( TRUE );
759         }
760         activateWindow( w, TRUE );
761
762         updateWorkspace();
763     }
764 }
765
766 void QWorkspaceP::maximizeWindow( QWidget* w)
767 {
768     QWorkspacePChild* c = findChild( w );
769
770     if ( !w || w && (!w->testWFlags( WStyle_Maximize ) || w->testWFlags( WStyle_Tool) ) )
771         return;
772     if ( w->maximumSize().isValid() && ( w->maximumWidth() < width() || w->maximumHeight() < height() ) ) {
773         w->resize( w->maximumSize() );
774         return;
775     }
776
777     if ( c ) {
778         setUpdatesEnabled( FALSE );
779         if (c->iconw && d->icons.contains( c->iconw->parentWidget() ) )
780             normalizeWindow( w );
781         QWorkspaceP *fake = (QWorkspaceP*)w;
782
783         QRect r( c->geometry() );
784         c->adjustToFullscreen();
785         c->show();
786         c->internalRaise();
787         qApp->sendPostedEvents( c, QEvent::Resize );
788         qApp->sendPostedEvents( c, QEvent::Move );
789         qApp->sendPostedEvents( c, QEvent::ShowWindowRequest );
790         if ( d->maxWindow != c ) {
791             if ( d->maxWindow )
792                 d->maxWindow->setGeometry( d->maxRestore );
793             d->maxWindow = c;
794             d->maxRestore = r;
795         }
796
797         activateWindow( w );
798         if(!style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this)) {
799             showMaximizeControls();
800         } else {
801             c->widgetResizeHandler->setActive( FALSE );
802             if ( c->titlebar )
803                 c->titlebar->setMovable( FALSE );
804         }
805 #ifndef QT_NO_WIDGET_TOPEXTRA
806         inCaptionChange = TRUE;
807         if ( !!d->topCaption )
808             topLevelWidget()->setCaption( tr("%1 - [%2]")
809                 .arg(d->topCaption).arg(c->caption()) );
810         inCaptionChange = FALSE;
811 #endif
812         setUpdatesEnabled( TRUE );
813
814         updateWorkspace();
815
816         fake->clearWState( WState_Minimized );
817         fake->setWState( WState_Maximized );
818         c->clearWState( WState_Minimized );
819         c->setWState( WState_Maximized );
820     }
821 }
822
823 void QWorkspaceP::showWindow( QWidget* w)
824 {
825     if ( d->maxWindow && w->testWFlags( WStyle_Maximize ) && !w->testWFlags( WStyle_Tool) )
826         maximizeWindow( w );
827     else if ( !w->testWFlags( WStyle_Tool ) )
828         normalizeWindow( w );
829     else
830         w->parentWidget()->show();
831     if ( d->maxWindow )
832         d->maxWindow->raise();
833     updateWorkspace();
834 }
835
836
837 QWorkspacePChild* QWorkspaceP::findChild( QWidget* w)
838 {
839     QPtrListIterator<QWorkspacePChild> it( d->windows );
840     while ( it.current () ) {
841         QWorkspacePChild* c = it.current();
842         ++it;
843         if (c->windowWidget() == w)
844             return c;
845     }
846     return 0;
847 }
848
849 /*!
850   Returns a list of all windows.
851  */
852 QWidgetList QWorkspaceP::windowList() const
853 {
854     QWidgetList windows;
855     QPtrListIterator<QWorkspacePChild> it( d->windows );
856     while ( it.current () ) {
857         QWorkspacePChild* c = it.current();
858         ++it;
859         if ( c->windowWidget() )
860             windows.append( c->windowWidget() );
861     }
862     return windows;
863 }
864
865 /*!\reimp*/
866 bool QWorkspaceP::eventFilter( QObject *o, QEvent * e)
867 {
868     static QTime* t = 0;
869     static QWorkspaceP* tc = 0;
870 #ifndef QT_NO_MENUBAR
871     if ( o == d->maxtools && d->menuId != -1 ) {
872         switch ( e->type() ) {
873         case QEvent::MouseButtonPress:
874             {
875                 QMenuBar* b = (QMenuBar*)o->parent();
876                 if ( !t )
877                     t = new QTime;
878                 if ( tc != this || t->elapsed() > QApplication::doubleClickInterval() ) {
879                     if ( QApplication::reverseLayout() ) {
880                         QPoint p = b->mapToGlobal( QPoint( b->x() + b->width(), b->y() + b->height() ) );
881                         p.rx() -= d->popup->sizeHint().width();
882                         popupOperationMenu( p );
883                     } else {
884                         popupOperationMenu( b->mapToGlobal( QPoint( b->x(), b->y() + b->height() ) ) );
885                     }
886                     t->start();
887                     tc = this;
888                 } else {
889                     tc = 0;
890                     closeActiveWindow();
891                 }
892                 return TRUE;
893             }
894         default:
895             break;
896         }
897         return QWidget::eventFilter( o, e );
898     }
899 #endif
900     switch ( e->type() ) {
901     case QEvent::Hide:
902     case QEvent::HideToParent:
903         if ( !o->isA( "QWorkspacePChild" ) || !isVisible() )
904             break;
905         d->focus.removeRef( (QWorkspacePChild*)o );
906         if ( d->active != o )
907             break;
908         if ( d->focus.isEmpty() ) {
909             activateWindow( 0 );
910         } else {
911             d->autoFocusChange = TRUE;
912             activatePreviousWindow();
913             QWorkspacePChild* c = d->active;
914             while ( d->active &&
915                     d->active->windowWidget() &&
916                     d->active->windowWidget()->testWFlags( WStyle_Tool ) ) {
917                 activatePreviousWindow();
918                 if ( d->active == c )
919                     break;
920             }
921             d->autoFocusChange = FALSE;
922         }
923         if ( d->maxWindow == o && d->maxWindow->isHidden() ) {
924             d->maxWindow->setGeometry( d->maxRestore );
925             d->maxWindow = 0;
926             if ( d->active )
927                 maximizeWindow( d->active );
928
929             if ( !d->maxWindow ) {
930
931                 if ( style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this)) {
932                     QWorkspacePChild *wc = (QWorkspacePChild *)o;
933                     wc->widgetResizeHandler->setActive( TRUE );
934                     if ( wc->titlebar )
935                         wc->titlebar->setMovable( TRUE );
936                 } else {
937                     hideMaximizeControls();
938                 }
939 #ifndef QT_NO_WIDGET_TOPEXTRA
940                 inCaptionChange = TRUE;
941                 if ( !!d->topCaption )
942                     topLevelWidget()->setCaption( d->topCaption );
943                 inCaptionChange = FALSE;
944 #endif
945             }
946         }
947         break;
948     case QEvent::Show:
949         if ( o->isA("QWorkspacePChild") && !d->focus.containsRef( (QWorkspacePChild*)o ) )
950             d->focus.append( (QWorkspacePChild*)o );
951         updateWorkspace();
952         break;
953     case QEvent::CaptionChange:
954         if ( inCaptionChange )
955             break;
956
957 #ifndef QT_NO_WIDGET_TOPEXTRA
958         inCaptionChange = TRUE;
959         if ( o == topLevelWidget() )
960             d->topCaption = ((QWidget*)o)->caption();
961
962         if ( d->maxWindow && !!d->topCaption )
963             topLevelWidget()->setCaption( tr("%1 - [%2]")
964                 .arg(d->topCaption).arg(d->maxWindow->caption()));
965         inCaptionChange = FALSE;
966 #endif
967
968         break;
969     case QEvent::Close:
970         if ( o == topLevelWidget() )
971         {
972             QPtrListIterator<QWorkspacePChild> it( d->windows );
973             while ( it.current () ) {
974                 QWorkspacePChild* c = it.current();
975                 ++it;
976                 if ( c->shademode )
977                     c->showShaded();
978             }
979         } else if ( o->inherits("QWorkspacePChild") ) {
980             d->popup->hide();
981         }
982         if ( d->windows.count() > 1 || d->windows.first() && d->active != d->windows.first() )
983           activatePreviousWindow();
984         updateWorkspace();
985         break;
986     default:
987         break;
988     }
989     return QWidget::eventFilter( o, e);
990 }
991
992 void QWorkspaceP::showMaximizeControls()
993 {
994 #ifndef QT_NO_MENUBAR
995     Q_ASSERT(d->maxWindow);
996     QMenuBar* b = 0;
997     
998     // Do a breadth-first search first on every parent, 
999     QWidget* w = parentWidget();
1000     QObjectList * l = 0;
1001     while ( !l && w ) {
1002         l = w->queryList( "QMenuBar", 0, FALSE, FALSE );
1003         w = w->parentWidget();  
1004         if ( l && !l->count() ) {
1005             delete l;
1006             l = 0;
1007         }
1008     } 
1009     
1010     // and query recursively if nothing is found.
1011     if ( !l || !l->count() ) {
1012         if ( l )
1013             delete l;
1014         l = topLevelWidget()->queryList( "QMenuBar", 0, 0, TRUE );
1015     }
1016     if ( l && l->count() )
1017         b = (QMenuBar *)l->first();
1018     delete l;
1019
1020     if ( !b )
1021         return;
1022
1023     if ( !d->maxcontrols ) {
1024         d->maxmenubar = b;
1025         d->maxcontrols = new QFrame( topLevelWidget(), "qt_maxcontrols" );
1026         QHBoxLayout* l = new QHBoxLayout( d->maxcontrols,
1027                                           d->maxcontrols->frameWidth(), 0 );
1028         if ( d->maxWindow->windowWidget()->testWFlags(WStyle_Minimize) ) {
1029             QToolButton* iconB = new QToolButton( d->maxcontrols, "iconify" );
1030 #ifndef QT_NO_TOOLTIP
1031             QToolTip::add( iconB, tr( "Minimize" ) );
1032 #endif
1033             l->addWidget( iconB );
1034             iconB->setFocusPolicy( NoFocus );
1035             iconB->setIconSet(style().stylePixmap(QStyle::SP_TitleBarMinButton));
1036             iconB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
1037             connect( iconB, SIGNAL( clicked() ),
1038                      this, SLOT( minimizeActiveWindow() ) );
1039         }
1040
1041         QToolButton* restoreB = new QToolButton( d->maxcontrols, "restore" );
1042 #ifndef QT_NO_TOOLTIP
1043         QToolTip::add( restoreB, tr( "Restore Down" ) );
1044 #endif
1045         l->addWidget( restoreB );
1046         restoreB->setFocusPolicy( NoFocus );
1047         restoreB->setIconSet( style().stylePixmap(QStyle::SP_TitleBarNormalButton));
1048         restoreB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
1049         connect( restoreB, SIGNAL( clicked() ),
1050                  this, SLOT( normalizeActiveWindow() ) );
1051
1052         l->addSpacing( 2 );
1053         QToolButton* closeB = new QToolButton( d->maxcontrols, "close" );
1054 #ifndef QT_NO_TOOLTIP
1055         QToolTip::add( closeB, tr( "Close" ) );
1056 #endif
1057         l->addWidget( closeB );
1058         closeB->setFocusPolicy( NoFocus );
1059         closeB->setIconSet( style().stylePixmap(QStyle::SP_TitleBarCloseButton) );
1060         closeB->setFixedSize(BUTTON_WIDTH, BUTTON_HEIGHT);
1061         connect( closeB, SIGNAL( clicked() ),
1062                  this, SLOT( closeActiveWindow() ) );
1063
1064         d->maxcontrols->setFixedSize( d->maxcontrols->minimumSizeHint() );
1065     }
1066
1067     if ( d->controlId == -1 || b->indexOf( d->controlId ) == -1 ) {
1068         QFrame* dmaxcontrols = d->maxcontrols;
1069         d->controlId = b->insertItem( dmaxcontrols, -1, b->count() );
1070     }
1071     if ( d->active && ( d->menuId == -1 || b->indexOf( d->menuId ) == -1 ) ) {
1072         if ( !d->maxtools ) {
1073             d->maxtools = new QLabel( topLevelWidget(), "qt_maxtools" );
1074             d->maxtools->installEventFilter( this );
1075         }
1076 #ifndef QT_NO_WIDGET_TOPEXTRA
1077         if ( d->active->windowWidget() && d->active->windowWidget()->icon() ) {
1078             QPixmap pm(*d->active->windowWidget()->icon());
1079             if(pm.width() != 14 || pm.height() != 14) {
1080                 QImage im;
1081                 im = pm;
1082                 pm = im.smoothScale( 14, 14 );
1083             }
1084             d->maxtools->setPixmap( pm );
1085         } else
1086 #endif
1087         {
1088             QPixmap pm(14,14);
1089             pm.fill( white );
1090             d->maxtools->setPixmap( pm );
1091         }
1092         d->menuId = b->insertItem( d->maxtools, -1, 0 );
1093     }
1094 #endif
1095 }
1096
1097
1098 void QWorkspaceP::hideMaximizeControls()
1099 {
1100 #ifndef QT_NO_MENUBAR
1101     if ( d->maxmenubar ) {
1102         int mi = d->menuId;
1103         if ( mi != -1 ) {
1104             if ( d->maxmenubar->indexOf( mi ) != -1 )
1105                 d->maxmenubar->removeItem( mi );
1106             d->maxtools = 0;
1107         }
1108         int ci = d->controlId;
1109         if ( ci != -1 && d->maxmenubar->indexOf( ci ) != -1 )
1110             d->maxmenubar->removeItem( ci );
1111     }
1112     d->maxcontrols = 0;
1113     d->menuId = -1;
1114     d->controlId = -1;
1115 #endif
1116 }
1117
1118 void QWorkspaceP::closeActiveWindow()
1119 {
1120     setUpdatesEnabled( FALSE );
1121     if ( d->maxWindow && d->maxWindow->windowWidget() )
1122         d->maxWindow->windowWidget()->close();
1123     else if ( d->active && d->active->windowWidget() )
1124         d->active->windowWidget()->close();
1125     setUpdatesEnabled( TRUE );
1126     updateWorkspace();
1127 }
1128
1129 void QWorkspaceP::closeAllWindows()
1130 {
1131     QPtrListIterator<QWorkspacePChild> it( d->windows );
1132     QWorkspacePChild *c = 0;
1133     while ( ( c = it.current() ) != 0 ) {
1134         ++it;
1135         if ( c->windowWidget() )
1136             c->windowWidget()->close();
1137     }
1138 }
1139
1140 void QWorkspaceP::normalizeActiveWindow()
1141 {
1142     if  ( d->maxWindow )
1143         d->maxWindow->showNormal();
1144     else if ( d->active )
1145         d->active->showNormal();
1146 }
1147
1148 void QWorkspaceP::minimizeActiveWindow()
1149 {
1150     if ( d->maxWindow )
1151         d->maxWindow->showMinimized();
1152     else if ( d->active )
1153         d->active->showMinimized();
1154 }
1155
1156 void QWorkspaceP::showOperationMenu()
1157 {
1158     if  ( !d->active || !d->active->windowWidget() )
1159         return;
1160     Q_ASSERT( d->active->windowWidget()->testWFlags( WStyle_SysMenu ) );
1161     QPoint p;
1162     QPopupMenu *popup = d->active->windowWidget()->testWFlags( WStyle_Tool ) ? d->toolPopup : d->popup;
1163     if ( QApplication::reverseLayout() ) {
1164         p = QPoint( d->active->windowWidget()->mapToGlobal( QPoint(d->active->windowWidget()->width(),0) ) );
1165         p.rx() -= popup->sizeHint().width();
1166     } else {
1167         p = QPoint( d->active->windowWidget()->mapToGlobal( QPoint(0,0) ) );
1168     }
1169     if ( !d->active->isVisible() ) {
1170         p = d->active->iconWidget()->mapToGlobal( QPoint(0,0) );
1171         p.ry() -= popup->sizeHint().height();
1172     }
1173     popupOperationMenu( p );
1174 }
1175
1176 void QWorkspaceP::popupOperationMenu( const QPoint&  p)
1177 {
1178     if ( !d->active || !d->active->windowWidget() || !d->active->windowWidget()->testWFlags( WStyle_SysMenu ) )
1179         return;
1180     if ( d->active->windowWidget()->testWFlags( WStyle_Tool ))
1181         d->toolPopup->popup( p );
1182     else
1183         d->popup->popup( p );
1184 }
1185
1186 void QWorkspaceP::operationMenuAboutToShow()
1187 {
1188     for ( int i = 1; i < 6; i++ ) {
1189         bool enable = d->active != 0;
1190         d->popup->setItemEnabled( i, enable );
1191     }
1192
1193     if ( !d->active || !d->active->windowWidget() )
1194         return;
1195
1196     d->popup->setItemEnabled( 4, d->active->windowWidget()->testWFlags( WStyle_Minimize ) );
1197     d->popup->setItemEnabled( 5, d->active->windowWidget()->testWFlags( WStyle_Maximize ) );
1198
1199     if ( d->active == d->maxWindow ) {
1200         d->popup->setItemEnabled( 2, FALSE );
1201         d->popup->setItemEnabled( 3, FALSE );
1202         d->popup->setItemEnabled( 5, FALSE );
1203     } else if ( d->active->isVisible() ){
1204         d->popup->setItemEnabled( 1, FALSE );
1205     } else {
1206         d->popup->setItemEnabled( 2, FALSE );
1207         d->popup->setItemEnabled( 3, FALSE );
1208         d->popup->setItemEnabled( 4, FALSE );
1209     }
1210 }
1211
1212 void QWorkspaceP::toolMenuAboutToShow()
1213 {
1214     if ( !d->active || !d->active->windowWidget() )
1215         return;
1216
1217     d->toolPopup->setItemEnabled( 3, !d->active->shademode );
1218     if ( d->active->shademode )
1219         d->toolPopup->changeItem( 6,
1220                                   QIconSet(style().stylePixmap(QStyle::SP_TitleBarUnshadeButton)), tr("&Unshade") );
1221     else
1222         d->toolPopup->changeItem( 6, QIconSet(style().stylePixmap(QStyle::SP_TitleBarShadeButton)), tr("Sh&ade") );
1223     d->toolPopup->setItemEnabled( 6, d->active->windowWidget()->testWFlags( WStyle_MinMax ) );
1224     d->toolPopup->setItemChecked( 7, d->active->windowWidget()->testWFlags( WStyle_StaysOnTop ) );
1225 }
1226
1227 void QWorkspaceP::operationMenuActivated( int a )
1228 {
1229     if ( !d->active )
1230         return;
1231     switch ( a ) {
1232     case 1:
1233         d->active->showNormal();
1234         break;
1235     case 2:
1236         d->active->doMove();
1237         break;
1238     case 3:
1239         if ( d->active->shademode )
1240             d->active->showShaded();
1241         d->active->doResize();
1242         break;
1243     case 4:
1244         d->active->showMinimized();
1245         break;
1246     case 5:
1247         d->active->showMaximized();
1248         break;
1249     case 6:
1250         d->active->showShaded();
1251         break;
1252     case 7:
1253         {
1254             QWorkspaceP* w = (QWorkspaceP*)d->active->windowWidget();
1255             if ( !w )
1256                 break;
1257             if ( w->testWFlags( WStyle_StaysOnTop ) ) {
1258                 w->clearWFlags( WStyle_StaysOnTop );
1259             } else {
1260                 w->setWFlags( WStyle_StaysOnTop );
1261                 w->parentWidget()->raise();
1262             }
1263         }
1264         break;
1265     default:
1266         break;
1267     }
1268 }
1269
1270 void QWorkspaceP::activateNextWindow()
1271 {
1272     if ( d->focus.isEmpty() )
1273         return;
1274     if ( !d->active ) {
1275         if ( d->focus.first() )
1276             activateWindow( d->focus.first()->windowWidget(), FALSE );
1277         return;
1278     }
1279
1280     int a = d->focus.find( d->active ) + 1;
1281
1282     a = a % d->focus.count();
1283
1284     if ( d->focus.at( a ) )
1285         activateWindow( d->focus.at( a )->windowWidget(), FALSE );
1286     else
1287         d->active = 0;
1288 }
1289
1290 void QWorkspaceP::activatePreviousWindow()
1291 {
1292     if ( d->focus.isEmpty() ) {
1293         if ( d->windows.count() > 0 ) { //VSR+
1294             activateWindow( d->windows.last()->windowWidget() ); //VSR+
1295         } //VSR+
1296         return;
1297     }
1298     if ( !d->active ) {
1299         if ( d->focus.last() )
1300             activateWindow( d->focus.first()->windowWidget(), FALSE );
1301         else
1302             activateWindow( 0 );
1303
1304         return;
1305     }
1306
1307     int a = d->focus.find( d->active ) - 1;
1308
1309     if ( a < 0 )
1310         a = d->focus.count()-1;
1311
1312     if ( d->autoFocusChange ) {
1313         QWidget *widget = 0;
1314         while ( a >= 0 && d->focus.at( a ) && ( widget = d->focus.at( a )->windowWidget() ) && !widget->isVisible() )
1315             a--;
1316         if ( a < 0 )
1317             a = d->focus.count() - 1;
1318     }
1319
1320     if ( d->focus.at( a ) )
1321         activateWindow( d->focus.at( a )->windowWidget(), FALSE );
1322     else
1323         activateWindow( 0 );
1324 }
1325
1326
1327 /*!
1328   \fn void QWorkspaceP::windowActivated( QWidget* w )
1329
1330   This signal is emitted when the window widget \a w becomes active.
1331   Note that \a w can be null, and that more than one signal may be
1332   fired for one activation event.
1333
1334   \sa activeWindow(), windowList()
1335 */
1336
1337
1338
1339 /*!
1340   Arranges all child windows in a cascade pattern.
1341
1342   \sa tile()
1343  */
1344 void QWorkspaceP::cascade()
1345 {
1346     if  ( d->maxWindow )
1347         d->maxWindow->showNormal();
1348
1349     if ( d->vbar ) {
1350         d->vbar->blockSignals( TRUE );
1351         d->vbar->setValue( 0 );
1352         d->vbar->blockSignals( FALSE );
1353         d->hbar->blockSignals( TRUE );
1354         d->hbar->setValue( 0 );
1355         d->hbar->blockSignals( FALSE );
1356         scrollBarChanged();
1357     }
1358
1359     const int xoffset = 13;
1360     const int yoffset = 20;
1361
1362     // make a list of all relevant mdi clients
1363     QPtrList<QWorkspacePChild> widgets;
1364     QWorkspacePChild* wc = 0;
1365     for ( wc = d->windows.first(); wc; wc = d->windows.next() )
1366         if ( wc->iconw )
1367             normalizeWindow( wc->windowWidget() );
1368     for ( wc = d->focus.first(); wc; wc = d->focus.next() )
1369         if ( wc->windowWidget()->isVisibleTo( this ) && !wc->windowWidget()->testWFlags( WStyle_Tool ) )
1370             widgets.append( wc );
1371
1372     int x = 0;
1373     int y = 0;
1374
1375     setUpdatesEnabled( FALSE );
1376     QPtrListIterator<QWorkspacePChild> it( widgets );
1377     int children = d->windows.count() - 1;
1378     while ( it.current () ) {
1379         QWorkspacePChild *child = it.current();
1380         ++it;
1381         child->setUpdatesEnabled( FALSE );
1382         bool hasSizeHint = FALSE;
1383         QSize prefSize = child->windowWidget()->sizeHint().expandedTo( child->windowWidget()->minimumSizeHint() );
1384
1385         if ( !prefSize.isValid() )
1386             prefSize = QSize( width() - children * xoffset, height() - children * yoffset );
1387         else
1388             hasSizeHint = TRUE;
1389         prefSize = prefSize.expandedTo( child->windowWidget()->minimumSize() ).boundedTo( child->windowWidget()->maximumSize() );
1390         if ( hasSizeHint )
1391             prefSize += QSize( child->baseSize().width(), child->baseSize().height() );
1392
1393         int w = prefSize.width();
1394         int h = prefSize.height();
1395
1396         child->showNormal();
1397         qApp->sendPostedEvents( 0, QEvent::ShowNormal );
1398         if ( y + h > height() )
1399             y = 0;
1400         if ( x + w > width() )
1401             x = 0;
1402         child->setGeometry( x, y, w, h );
1403         x += xoffset;
1404         y += yoffset;
1405         child->internalRaise();
1406         child->setUpdatesEnabled( TRUE );
1407     }
1408     setUpdatesEnabled( TRUE );
1409     updateWorkspace();
1410 }
1411
1412 /*!
1413   Arranges all child windows in a tile pattern.
1414
1415   \sa cascade()
1416  */
1417 void QWorkspaceP::tile()
1418 {
1419     if  ( d->maxWindow )
1420         d->maxWindow->showNormal();
1421
1422     if ( d->vbar ) {
1423         d->vbar->blockSignals( TRUE );
1424         d->vbar->setValue( 0 );
1425         d->vbar->blockSignals( FALSE );
1426         d->hbar->blockSignals( TRUE );
1427         d->hbar->setValue( 0 );
1428         d->hbar->blockSignals( FALSE );
1429         scrollBarChanged();
1430     }
1431
1432     int rows = 1;
1433     int cols = 1;
1434     int n = 0;
1435     QWorkspacePChild* c;
1436
1437     QPtrListIterator<QWorkspacePChild> it( d->windows );
1438     while ( it.current () ) {
1439         c = it.current();
1440         ++it;
1441         if ( !c->windowWidget()->isHidden() &&
1442              !c->windowWidget()->testWFlags( WStyle_StaysOnTop ) &&
1443              !c->windowWidget()->testWFlags( WStyle_Tool ) )
1444             n++;
1445     }
1446
1447     while ( rows * cols < n ) {
1448         if ( cols <= rows )
1449             cols++;
1450         else
1451             rows++;
1452     }
1453     int add = cols * rows - n;
1454     bool* used = new bool[ cols*rows ];
1455     for ( int i = 0; i < rows*cols; i++ )
1456         used[i] = FALSE;
1457
1458     int row = 0;
1459     int col = 0;
1460     int w = width() / cols;
1461     int h = height() / rows;
1462
1463     it.toFirst();
1464     while ( it.current () ) {
1465         c = it.current();
1466         ++it;
1467         if ( c->windowWidget()->isHidden() || c->windowWidget()->testWFlags( WStyle_Tool ) )
1468             continue;
1469         if ( c->windowWidget()->testWFlags( WStyle_StaysOnTop ) ) {
1470             QPoint p = c->pos();
1471             if ( p.x()+c->width() < 0 )
1472                 p.setX( 0 );
1473             if ( p.x() > width() )
1474                 p.setX( width() - c->width() );
1475             if ( p.y() + 10 < 0 )
1476                 p.setY( 0 );
1477             if ( p.y() > height() )
1478                 p.setY( height() - c->height() );
1479
1480
1481             if ( p != c->pos() )
1482                 c->QFrame::move( p );
1483         } else {
1484             c->showNormal();
1485             qApp->sendPostedEvents( 0, QEvent::ShowNormal );
1486             used[row*cols+col] = TRUE;
1487             if ( add ) {
1488                 c->setGeometry( col*w, row*h, QMIN( w, c->windowWidget()->maximumWidth()+c->baseSize().width() ),
1489                                               QMIN( 2*h, c->windowWidget()->maximumHeight()+c->baseSize().height() ) );
1490                 used[(row+1)*cols+col] = TRUE;
1491                 add--;
1492             } else {
1493                 c->setGeometry( col*w, row*h, QMIN( w, c->windowWidget()->maximumWidth()+c->baseSize().width() ),
1494                                               QMIN( h, c->windowWidget()->maximumHeight()+c->baseSize().height() ) );
1495             }
1496             while( row < rows && col < cols && used[row*cols+col] ) {
1497                 col++;
1498                 if ( col == cols ) {
1499                     col = 0;
1500                     row++;
1501                 }
1502             }
1503         }
1504     }
1505     delete [] used;
1506     updateWorkspace();
1507 }
1508
1509 QWorkspacePChild::QWorkspacePChild( QWidget* window, QWorkspaceP *parent,
1510                                   const char *name )
1511     : QFrame( parent, name,
1512               WStyle_Customize | WStyle_NoBorder  | WDestructiveClose | WNoMousePropagation | WSubWindow )
1513 {
1514     setMouseTracking( TRUE );
1515     act = FALSE;
1516     iconw = 0;
1517     lastfocusw = 0;
1518     shademode = FALSE;
1519     titlebar = 0;
1520     snappedRight = FALSE;
1521     snappedDown = FALSE;
1522
1523     if (window) {
1524         switch (window->focusPolicy()) {
1525         case QWidget::NoFocus:
1526             window->setFocusPolicy(QWidget::ClickFocus);
1527             break;
1528         case QWidget::TabFocus:
1529             window->setFocusPolicy(QWidget::StrongFocus);
1530             break;
1531         default:
1532             break;
1533         }
1534     }
1535
1536     if ( window && window->testWFlags( WStyle_Title ) ) {
1537         titlebar = new QTitleBarP( window, this, "qt_ws_titlebar" );
1538         connect( titlebar, SIGNAL( doActivate() ),
1539                  this, SLOT( activate() ) );
1540         connect( titlebar, SIGNAL( doClose() ),
1541                  window, SLOT( close() ) );
1542         connect( titlebar, SIGNAL( doMinimize() ),
1543                  this, SLOT( showMinimized() ) );
1544         connect( titlebar, SIGNAL( doNormal() ),
1545                  this, SLOT( showNormal() ) );
1546         connect( titlebar, SIGNAL( doMaximize() ),
1547                  this, SLOT( showMaximized() ) );
1548         connect( titlebar, SIGNAL( popupOperationMenu( const QPoint& ) ),
1549                  this, SIGNAL( popupOperationMenu( const QPoint& ) ) );
1550         connect( titlebar, SIGNAL( showOperationMenu() ),
1551                  this, SIGNAL( showOperationMenu() ) );
1552         connect( titlebar, SIGNAL( doShade() ),
1553                  this, SLOT( showShaded() ) );
1554         connect( titlebar, SIGNAL( doubleClicked() ),
1555                  this, SLOT( titleBarDoubleClicked() ) );
1556     }
1557
1558     if ( window && window->testWFlags( WStyle_Tool ) ) {
1559         setFrameStyle( QFrame::StyledPanel | QFrame::Raised );
1560         setLineWidth( 2 );
1561         setMinimumSize( 128, 0 );
1562     } else {
1563         setFrameStyle( QFrame::StyledPanel | QFrame::Raised );
1564         setLineWidth( 2 );
1565         setMinimumSize( 128, 0 );
1566     }
1567
1568     childWidget = window;
1569     if (!childWidget)
1570         return;
1571
1572 #ifndef QT_NO_WIDGET_TOPEXTRA
1573     setCaption( childWidget->caption() );
1574 #endif
1575
1576     QPoint p;
1577     QSize s;
1578     QSize cs;
1579
1580     bool hasBeenResized = childWidget->testWState( WState_Resized );
1581
1582     if ( !hasBeenResized )
1583         cs = childWidget->sizeHint().expandedTo( childWidget->minimumSizeHint() );
1584     else
1585         cs = childWidget->size();
1586
1587     int th = titlebar ? titlebar->sizeHint().height() : 0;
1588     if ( titlebar ) {
1589 #ifndef QT_NO_WIDGET_TOPEXTRA
1590         if( childWidget->icon() ) {
1591             QPixmap pm(*childWidget->icon());
1592             if(pm.width() != 14 || pm.height() != 14) {
1593                 QImage im;
1594                 im = pm;
1595                 pm = im.smoothScale( 14, 14 );
1596             }
1597             titlebar->setIcon( pm );
1598         }
1599 #endif
1600         p = QPoint( contentsRect().x(),
1601                     th + contentsRect().y() );
1602         s = QSize( cs.width() + 2*frameWidth(),
1603                    cs.height() + 2*frameWidth() + th + 2 );
1604     } else {
1605         p = QPoint( contentsRect().x(), contentsRect().y() );
1606         s = QSize( cs.width() + 2*frameWidth(),
1607                    cs.height() + 2*frameWidth() );
1608     }
1609
1610     childWidget->reparent( this, p);
1611     resize( s );
1612
1613     childWidget->installEventFilter( this );
1614
1615     widgetResizeHandler = new QWidgetResizeHandlerP( this, window );
1616     widgetResizeHandler->setMovingEnabled( FALSE );
1617     widgetResizeHandler->setSizeProtection( !parent->scrollBarsEnabled() );
1618     connect( widgetResizeHandler, SIGNAL( activate() ),
1619              this, SLOT( activate() ) );
1620     widgetResizeHandler->setExtraHeight( th + 2 );
1621
1622     setBaseSize( baseSize() );
1623 }
1624
1625 QWorkspacePChild::~QWorkspacePChild()
1626 {
1627     if ( iconw )
1628         delete iconw->parentWidget();
1629 }
1630
1631 void QWorkspacePChild::moveEvent( QMoveEvent * )
1632 {
1633     ((QWorkspaceP*) parentWidget() )->updateWorkspace();
1634 }
1635
1636 void QWorkspacePChild::resizeEvent( QResizeEvent * )
1637 {
1638     QRect r = contentsRect();
1639     QRect cr;
1640
1641     if ( titlebar ) {
1642         int th = titlebar->sizeHint().height();
1643         QRect tbrect( 0, 0, width(), th );
1644         if ( !style().styleHint( QStyle::SH_TitleBar_NoBorder ) )
1645             tbrect = QRect( r.x(), r.y(), r.width(), th );
1646         titlebar->setGeometry( tbrect );
1647         cr = QRect( r.x(), r.y() + titlebar->height() + (shademode ? 5 : 1),
1648             r.width(), r.height() - titlebar->height() - 2 );
1649     } else {
1650         cr = r;
1651     }
1652
1653     if (!childWidget)
1654         return;
1655
1656     windowSize = cr.size();
1657     childWidget->setGeometry( cr );
1658     ((QWorkspaceP*) parentWidget() )->updateWorkspace();
1659 }
1660
1661 QSize QWorkspacePChild::baseSize() const
1662 {
1663     int th = titlebar ? titlebar->sizeHint().height() : 0;
1664     return QSize( 2*frameWidth(), 2*frameWidth() + th + 2 );
1665 }
1666
1667 QSize QWorkspacePChild::sizeHint() const
1668 {
1669     if ( !childWidget )
1670         return QFrame::sizeHint() + baseSize();
1671     return childWidget->sizeHint().expandedTo( childWidget->minimumSizeHint() ) + baseSize();
1672 }
1673
1674 QSize QWorkspacePChild::minimumSizeHint() const
1675 {
1676     if ( !childWidget )
1677         return QFrame::minimumSizeHint() + baseSize();
1678     QSize s = childWidget->minimumSize();
1679     if ( s.isEmpty() )
1680         s = childWidget->minimumSizeHint();
1681     return s + baseSize();
1682 }
1683
1684 void QWorkspacePChild::activate()
1685 {
1686     ((QWorkspaceP*)parentWidget())->activateWindow( windowWidget() );
1687 }
1688
1689 bool QWorkspacePChild::eventFilter( QObject * o, QEvent * e)
1690 {
1691     if ( !isActive() && ( e->type() == QEvent::MouseButtonPress ||
1692         e->type() == QEvent::FocusIn ) ) {
1693         if ( iconw ) {
1694             ((QWorkspaceP*)parentWidget())->normalizeWindow( windowWidget() );
1695             if ( iconw ) {
1696                 ((QWorkspaceP*)parentWidget())->removeIcon( iconw->parentWidget() );
1697                 delete iconw->parentWidget();
1698                 iconw = 0;
1699             }
1700         }
1701         activate();
1702     }
1703
1704     // for all widgets except the window, we that's the only thing we
1705     // process, and if we have no childWidget we skip totally
1706     if ( o != childWidget || childWidget == 0 )
1707         return FALSE;
1708
1709     switch ( e->type() ) {
1710     case QEvent::Show:
1711         if ( ((QWorkspaceP*)parentWidget())->d->focus.find( this ) < 0 )
1712             ((QWorkspaceP*)parentWidget())->d->focus.append( this );
1713         if ( isVisibleTo( parentWidget() ) )
1714             break;
1715         if (( (QShowEvent*)e)->spontaneous() )
1716             break;
1717         // fall through
1718     case QEvent::ShowToParent:
1719         if ( windowWidget() && windowWidget()->testWFlags( WStyle_StaysOnTop ) ) {
1720             internalRaise();
1721             show();
1722         }
1723         ((QWorkspaceP*)parentWidget())->showWindow( windowWidget() );
1724         break;
1725     case QEvent::ShowMaximized:
1726         if ( windowWidget()->maximumSize().isValid() &&
1727              ( windowWidget()->maximumWidth() < parentWidget()->width() ||
1728                windowWidget()->maximumHeight() < parentWidget()->height() ) ) {
1729             windowWidget()->resize( windowWidget()->maximumSize() );
1730             break;
1731         }
1732         if ( windowWidget()->testWFlags( WStyle_Maximize ) && !windowWidget()->testWFlags( WStyle_Tool ) )
1733             ((QWorkspaceP*)parentWidget())->maximizeWindow( windowWidget() );
1734         else
1735             ((QWorkspaceP*)parentWidget())->normalizeWindow( windowWidget() );
1736         break;
1737     case QEvent::ShowMinimized:
1738         ((QWorkspaceP*)parentWidget())->minimizeWindow( windowWidget() );
1739         break;
1740     case QEvent::ShowNormal:
1741         ((QWorkspaceP*)parentWidget())->normalizeWindow( windowWidget() );
1742         if (iconw) {
1743             ((QWorkspaceP*)parentWidget())->removeIcon( iconw->parentWidget() );
1744             delete iconw->parentWidget();
1745         }
1746         break;
1747     case QEvent::Hide:
1748     case QEvent::HideToParent:
1749         if ( !childWidget->isVisibleTo( this ) ) {
1750             QWidget * w = iconw;
1751             if ( w && ( w = w->parentWidget() ) ) {
1752                 ((QWorkspaceP*)parentWidget())->removeIcon( w );
1753                 delete w;
1754             }
1755             hide();
1756         }
1757         break;
1758     case QEvent::CaptionChange:
1759 #ifndef QT_NO_WIDGET_TOPEXTRA
1760         setCaption( childWidget->caption() );
1761         if ( iconw )
1762             iconw->setCaption( childWidget->caption() );
1763 #endif
1764         break;
1765     case QEvent::IconChange:
1766         {
1767             QWorkspaceP* ws = (QWorkspaceP*)parentWidget();
1768             if ( !titlebar )
1769                 break;
1770 #ifndef QT_NO_WIDGET_TOPEXTRA
1771             if ( childWidget->icon() ) {
1772                 titlebar->setIcon( *childWidget->icon() );
1773             } else
1774 #endif
1775             {
1776                 QPixmap pm;
1777                 titlebar->setIcon( pm );
1778             }
1779
1780             if ( ws->d->maxWindow != this )
1781                 break;
1782
1783             if ( ws->d->maxtools ) {
1784 #ifndef QT_NO_WIDGET_TOPEXTRA
1785                 if ( childWidget->icon() ) {
1786                     QPixmap pm(*childWidget->icon());
1787                     if(pm.width() != 14 || pm.height() != 14) {
1788                         QImage im;
1789                         im = pm;
1790                         pm = im.smoothScale( 14, 14 );
1791                     }
1792                     ws->d->maxtools->setPixmap( pm );
1793                 } else
1794 #endif
1795                 {
1796                     QPixmap pm(14,14);
1797                     pm.fill( white );
1798                     ws->d->maxtools->setPixmap( pm );
1799                 }
1800             }
1801         }
1802         break;
1803     case QEvent::Resize:
1804         {
1805             QResizeEvent* re = (QResizeEvent*)e;
1806             if ( re->size() != windowSize && !shademode )
1807                 resize( re->size() + baseSize() );
1808         }
1809         break;
1810
1811     case QEvent::WindowDeactivate:
1812         if ( titlebar )
1813             titlebar->setActive( FALSE );
1814         break;
1815
1816     case QEvent::WindowActivate:
1817         if ( titlebar )
1818             titlebar->setActive( act );
1819         break;
1820
1821     default:
1822         break;
1823     }
1824
1825     return QFrame::eventFilter(o, e);
1826 }
1827
1828 bool QWorkspacePChild::focusNextPrevChild( bool next )
1829 {
1830     QFocusData *f = focusData();
1831
1832     QWidget *startingPoint = f->home();
1833     QWidget *candidate = 0;
1834     QWidget *w = next ? f->next() : f->prev();
1835     while( !candidate && w != startingPoint ) {
1836         if ( w != startingPoint &&
1837              (w->focusPolicy() & TabFocus) == TabFocus
1838              && w->isEnabled() &&!w->focusProxy() && w->isVisible() )
1839             candidate = w;
1840         w = next ? f->next() : f->prev();
1841     }
1842
1843     if ( candidate ) {
1844         QObjectList *ol = queryList();
1845         bool ischild = ol->findRef( candidate ) != -1;
1846         delete ol;
1847         if ( !ischild ) {
1848             startingPoint = f->home();
1849             QWidget *nw = next ? f->prev() : f->next();
1850             QObjectList *ol2 = queryList();
1851             QWidget *lastValid = 0;
1852             candidate = startingPoint;
1853             while ( nw != startingPoint ) {
1854                 if ( ( candidate->focusPolicy() & TabFocus ) == TabFocus
1855                     && candidate->isEnabled() &&!candidate->focusProxy() && candidate->isVisible() )
1856                     lastValid = candidate;
1857                 if ( ol2->findRef( nw ) == -1 ) {
1858                     candidate = lastValid;
1859                     break;
1860                 }
1861                 candidate = nw;
1862                 nw = next ? f->prev() : f->next();
1863             }
1864             delete ol2;
1865         }
1866     }
1867
1868     if ( !candidate )
1869         return FALSE;
1870
1871     candidate->setFocus();
1872     return TRUE;
1873 }
1874
1875 void QWorkspacePChild::childEvent( QChildEvent*  e)
1876 {
1877     if ( e->type() == QEvent::ChildRemoved && e->child() == childWidget ) {
1878         childWidget = 0;
1879         if ( iconw ) {
1880             ((QWorkspaceP*)parentWidget())->removeIcon( iconw->parentWidget() );
1881             delete iconw->parentWidget();
1882         }
1883         close();
1884     }
1885 }
1886
1887
1888 void QWorkspacePChild::doResize()
1889 {
1890     widgetResizeHandler->doResize();
1891 }
1892
1893 void QWorkspacePChild::doMove()
1894 {
1895     widgetResizeHandler->doMove();
1896 }
1897
1898 void QWorkspacePChild::enterEvent( QEvent * )
1899 {
1900 }
1901
1902 void QWorkspacePChild::leaveEvent( QEvent * )
1903 {
1904 #ifndef QT_NO_CURSOR
1905     if ( !widgetResizeHandler->isButtonDown() )
1906         setCursor( arrowCursor );
1907 #endif
1908 }
1909
1910 void QWorkspacePChild::drawFrame( QPainter *p )
1911 {
1912     QStyle::SFlags flags = QStyle::Style_Default;
1913     QStyleOption opt(lineWidth(),midLineWidth());
1914
1915     if ( act )
1916         flags |= QStyle::Style_Active;
1917
1918     style().drawPrimitive( QStyle::PE_WindowFrame, p, rect(), colorGroup(), flags, opt );
1919 }
1920
1921 void QWorkspacePChild::styleChange( QStyle & )
1922 {
1923     resizeEvent( 0 );
1924     if ( iconw ) {
1925         QVBox *vbox = (QVBox*)iconw->parentWidget()->qt_cast( "QVBox" );
1926         Q_ASSERT(vbox);
1927         if ( !style().styleHint( QStyle::SH_TitleBar_NoBorder ) ) {
1928             vbox->setFrameStyle( QFrame::WinPanel | QFrame::Raised );
1929             vbox->resize( 196+2*vbox->frameWidth(), 20 + 2*vbox->frameWidth() );
1930         } else {
1931             vbox->resize( 196, 20 );
1932         }
1933     }
1934 }
1935
1936 static bool isChildOf( QWidget * child, QWidget * parent )
1937 {
1938     if ( !parent || !child )
1939         return FALSE;
1940     QWidget * w = child;
1941     while( w && w != parent )
1942         w = w->parentWidget();
1943     return w != 0;
1944 }
1945
1946
1947 void QWorkspacePChild::setActive( bool b )
1948 {
1949     if ( !childWidget )
1950         return;
1951
1952     if ( act == b )
1953         return;
1954
1955     act = b;
1956     repaint( FALSE );
1957
1958     if ( titlebar )
1959         titlebar->setActive( act );
1960     if ( iconw )
1961         iconw->setActive( act );
1962
1963     QObjectList* ol = childWidget->queryList( "QWidget" );
1964     if ( act ) {
1965         QObject *o;
1966         for ( o = ol->first(); o; o = ol->next() )
1967             o->removeEventFilter( this );
1968         bool hasFocus = isChildOf( focusWidget(), childWidget );
1969         if ( !hasFocus ) {
1970             if ( lastfocusw && ol->contains( lastfocusw ) &&
1971                  lastfocusw->focusPolicy() != NoFocus ) {
1972                 // this is a bug if lastfocusw has been deleted, a new
1973                 // widget has been created, and the new one is a child
1974                 // of the same window as the old one. but even though
1975                 // it's a bug the behaviour is reasonable
1976                 lastfocusw->setFocus();
1977             } else if ( childWidget->focusPolicy() != NoFocus ) {
1978                 childWidget->setFocus();
1979             } else {
1980                 // find something, anything, that accepts focus, and use that.
1981                 o = ol->first();
1982                 while( o && ((QWidget*)o)->focusPolicy() == NoFocus )
1983                     o = ol->next();
1984                 if ( o )
1985                     ((QWidget*)o)->setFocus();
1986             }
1987         }
1988     } else {
1989         lastfocusw = 0;
1990         if ( isChildOf( focusWidget(), childWidget ) )
1991             lastfocusw = focusWidget();
1992         QObject * o;
1993         for ( o = ol->first(); o; o = ol->next() ) {
1994             o->removeEventFilter( this );
1995             o->installEventFilter( this );
1996         }
1997     }
1998     delete ol;
1999 }
2000
2001 bool QWorkspacePChild::isActive() const
2002 {
2003     return act;
2004 }
2005
2006 QWidget* QWorkspacePChild::windowWidget() const
2007 {
2008     return childWidget;
2009 }
2010
2011
2012 QWidget* QWorkspacePChild::iconWidget() const
2013 {
2014     if ( !iconw ) {
2015         QWorkspacePChild* that = (QWorkspacePChild*) this;
2016         QVBox* vbox = new QVBox(0, "qt_vbox" );
2017         if ( !style().styleHint( QStyle::SH_TitleBar_NoBorder ) ) {
2018             vbox->setFrameStyle( QFrame::WinPanel | QFrame::Raised );
2019             vbox->resize( 196+2*vbox->frameWidth(), 20 + 2*vbox->frameWidth() );
2020         } else {
2021             vbox->resize( 196, 20 );
2022         }
2023         QTitleBarP *tb = new QTitleBarP( windowWidget(), vbox, "_workspacechild_icon_");
2024         ((QWorkspacePChild*)tb)->setWState( WState_Minimized );
2025         that->iconw = tb;
2026         iconw->setActive( isActive() );
2027         connect( iconw, SIGNAL( doActivate() ),
2028                  this, SLOT( activate() ) );
2029         connect( iconw, SIGNAL( doClose() ),
2030                  windowWidget(), SLOT( close() ) );
2031         connect( iconw, SIGNAL( doNormal() ),
2032                  this, SLOT( showNormal() ) );
2033         connect( iconw, SIGNAL( doMaximize() ),
2034                  this, SLOT( showMaximized() ) );
2035         connect( iconw, SIGNAL( popupOperationMenu( const QPoint& ) ),
2036                  this, SIGNAL( popupOperationMenu( const QPoint& ) ) );
2037         connect( iconw, SIGNAL( showOperationMenu() ),
2038                  this, SIGNAL( showOperationMenu() ) );
2039         connect( iconw, SIGNAL( doubleClicked() ),
2040                  this, SLOT( titleBarDoubleClicked() ) );
2041     }
2042 #ifndef QT_NO_WIDGET_TOPEXTRA
2043     if ( windowWidget() ) {
2044         iconw->setCaption( windowWidget()->caption() );
2045         if ( windowWidget()->icon() )
2046             iconw->setIcon( *windowWidget()->icon() );
2047     }
2048 #endif
2049     return iconw->parentWidget();
2050 }
2051
2052 void QWorkspacePChild::showMinimized()
2053 {
2054     QApplication::postEvent( windowWidget(), new QEvent( QEvent::ShowMinimized ) );
2055 }
2056
2057 void QWorkspacePChild::showMaximized()
2058 {
2059     QApplication::postEvent( windowWidget(), new QEvent( QEvent::ShowMaximized ) );
2060 }
2061
2062 void QWorkspacePChild::showNormal()
2063 {
2064     QApplication::postEvent( windowWidget(), new QEvent( QEvent::ShowNormal ) );
2065 }
2066
2067 void QWorkspacePChild::showShaded()
2068 {
2069     if ( !titlebar)
2070         return;
2071     Q_ASSERT( windowWidget()->testWFlags( WStyle_MinMax ) && windowWidget()->testWFlags( WStyle_Tool ) );
2072     ((QWorkspaceP*)parentWidget())->activateWindow( windowWidget() );
2073     if ( shademode ) {
2074         QWorkspacePChild* fake = (QWorkspacePChild*)windowWidget();
2075         fake->clearWState( WState_Minimized );
2076         clearWState( WState_Minimized );
2077
2078         shademode = FALSE;
2079         resize( shadeRestore );
2080         setMinimumSize( shadeRestoreMin );
2081     } else {
2082         shadeRestore = size();
2083         shadeRestoreMin = minimumSize();
2084         setMinimumHeight(0);
2085         shademode = TRUE;
2086         QWorkspacePChild* fake = (QWorkspacePChild*)windowWidget();
2087         fake->setWState( WState_Minimized );
2088         setWState( WState_Minimized );
2089
2090         resize( width(), titlebar->height() + 2*lineWidth() + 1 );
2091     }
2092     titlebar->update();
2093 }
2094
2095 void QWorkspacePChild::titleBarDoubleClicked()
2096 {
2097     if ( !windowWidget() )
2098         return;
2099     if ( windowWidget()->testWFlags( WStyle_MinMax ) ) {
2100         if ( windowWidget()->testWFlags( WStyle_Tool ) )
2101             showShaded();
2102         else if ( iconw )
2103             showNormal();
2104         else if ( windowWidget()->testWFlags( WStyle_Maximize ) )
2105             showMaximized();
2106     }
2107 }
2108
2109 void QWorkspacePChild::adjustToFullscreen()
2110 {
2111     qApp->sendPostedEvents( this, QEvent::Resize );
2112     qApp->sendPostedEvents( childWidget, QEvent::Resize );
2113     qApp->sendPostedEvents( childWidget, QEvent::Move );
2114     if(style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this)) {
2115         setGeometry( 0, 0, parentWidget()->width(), parentWidget()->height());
2116     } else {
2117         setGeometry( -childWidget->x(), -childWidget->y(),
2118                      parentWidget()->width() + width() - childWidget->width(),
2119                      parentWidget()->height() + height() - childWidget->height() );
2120     }
2121     setWState( WState_Maximized );
2122     ((QWorkspacePChild*)childWidget)->setWState( WState_Maximized );
2123 }
2124
2125 void QWorkspacePChild::adjustSize()
2126 {
2127     if ( !testWState(WState_Polished) )
2128         polish();
2129
2130     QSize prefSize = windowWidget()->sizeHint().expandedTo( windowWidget()->minimumSizeHint() );
2131     prefSize = prefSize.expandedTo( windowWidget()->minimumSize() ).boundedTo( windowWidget()->maximumSize() );
2132     prefSize += baseSize();
2133
2134     resize( prefSize );
2135 }
2136
2137 void QWorkspacePChild::setCaption( const QString& cap )
2138 {
2139     if ( titlebar )
2140         titlebar->setCaption( cap );
2141 #ifndef QT_NO_WIDGET_TOPEXTRA
2142     QWidget::setCaption( cap );
2143 #endif
2144 }
2145
2146 void QWorkspacePChild::internalRaise()
2147 {
2148     setUpdatesEnabled( FALSE );
2149     if ( iconw )
2150         iconw->parentWidget()->raise();
2151     raise();
2152
2153     if ( !windowWidget() || windowWidget()->testWFlags( WStyle_StaysOnTop ) ) {
2154         setUpdatesEnabled( TRUE );
2155         return;
2156     }
2157
2158     QPtrListIterator<QWorkspacePChild> it( ((QWorkspaceP*)parent())->d->windows );
2159     while ( it.current () ) {
2160         QWorkspacePChild* c = it.current();
2161         ++it;
2162         if ( c->windowWidget() &&
2163             !c->windowWidget()->isHidden() &&
2164              c->windowWidget()->testWFlags( WStyle_StaysOnTop ) )
2165              c->raise();
2166     }
2167
2168     setUpdatesEnabled( TRUE );
2169 }
2170
2171 void QWorkspacePChild::move( int x, int y )
2172 {
2173     int nx = x;
2174     int ny = y;
2175
2176     if ( windowWidget() && windowWidget()->testWFlags( WStyle_Tool ) ) {
2177         int dx = 10;
2178         int dy = 10;
2179
2180         if ( QABS( x ) < dx )
2181             nx = 0;
2182         if ( QABS( y ) < dy )
2183             ny = 0;
2184         if ( QABS( x + width() - parentWidget()->width() ) < dx ) {
2185             nx = parentWidget()->width() - width();
2186             snappedRight = TRUE;
2187         } else
2188             snappedRight = FALSE;
2189
2190         if ( QABS( y + height() - parentWidget()->height() ) < dy ) {
2191             ny = parentWidget()->height() - height();
2192             snappedDown = TRUE;
2193         } else
2194             snappedDown = FALSE;
2195     }
2196     QFrame::move( nx, ny );
2197 }
2198
2199 bool QWorkspaceP::scrollBarsEnabled() const
2200 {
2201     return d->vbar != 0;
2202 }
2203
2204 /*! \property QWorkspaceP::scrollBarsEnabled
2205     \brief whether the workspace provides scrollbars
2206
2207     If this property is set to TRUE, it is possible to resize child
2208     windows over the right or the bottom edge out of the visible area
2209     of the workspace. The workspace shows scrollbars to make it
2210     possible for the user to access those windows. If this property is
2211     set to FALSE (the default), resizing windows out of the visible
2212     area of the workspace is not permitted.
2213 */
2214 void QWorkspaceP::setScrollBarsEnabled( bool enable )
2215 {
2216     if ( (d->vbar != 0) == enable )
2217         return;
2218
2219     d->xoffset = d->yoffset = 0;
2220     if ( enable ) {
2221         d->vbar = new QScrollBar( Vertical, this, "vertical scrollbar" );
2222         connect( d->vbar, SIGNAL( valueChanged(int) ), this, SLOT( scrollBarChanged() ) );
2223         d->hbar = new QScrollBar( Horizontal, this, "horizontal scrollbar" );
2224         connect( d->hbar, SIGNAL( valueChanged(int) ), this, SLOT( scrollBarChanged() ) );
2225         d->corner = new QWidget( this, "qt_corner" );
2226         updateWorkspace();
2227     } else {
2228         delete d->vbar;
2229         delete d->hbar;
2230         delete d->corner;
2231         d->vbar = d->hbar = 0;
2232         d->corner = 0;
2233     }
2234
2235     QPtrListIterator<QWorkspacePChild> it( d->windows );
2236     while ( it.current () ) {
2237         QWorkspacePChild *child = it.current();
2238         ++it;
2239         child->widgetResizeHandler->setSizeProtection( !enable );
2240     }
2241 }
2242
2243 QRect QWorkspaceP::updateWorkspace()
2244 {
2245     if ( !isUpdatesEnabled() )
2246         return rect();
2247
2248     QRect cr( rect() );
2249
2250     if ( scrollBarsEnabled() && !d->maxWindow ) {
2251         d->corner->raise();
2252         d->vbar->raise();
2253         d->hbar->raise();
2254         if ( d->maxWindow )
2255             d->maxWindow->raise();
2256
2257         QRect r( 0, 0, 0, 0 );
2258         QPtrListIterator<QWorkspacePChild> it( d->windows );
2259         while ( it.current () ) {
2260             QWorkspacePChild *child = it.current();
2261             ++it;
2262             if ( !child->isHidden() )
2263                 r = r.unite( child->geometry() );
2264         }
2265         d->vbar->blockSignals( TRUE );
2266         d->hbar->blockSignals( TRUE );
2267
2268         int hsbExt = d->hbar->sizeHint().height();
2269         int vsbExt = d->vbar->sizeHint().width();
2270
2271
2272         bool showv = d->yoffset || d->yoffset + r.bottom() - height() + 1 > 0 || d->yoffset + r.top() < 0;
2273         bool showh = d->xoffset || d->xoffset + r.right() - width() + 1 > 0 || d->xoffset + r.left() < 0;
2274
2275         if ( showh && !showv)
2276             showv = d->yoffset + r.bottom() - height() + hsbExt + 1 > 0;
2277         if ( showv && !showh )
2278             showh = d->xoffset + r.right() - width() + vsbExt  + 1 > 0;
2279
2280         if ( !showh )
2281             hsbExt = 0;
2282         if ( !showv )
2283             vsbExt = 0;
2284
2285         if ( showv ) {
2286             d->vbar->setSteps( QMAX( height() / 12, 30 ), height()  - hsbExt );
2287             d->vbar->setRange( QMIN( 0, d->yoffset + QMIN( 0, r.top() ) ), QMAX( 0, d->yoffset + QMAX( 0, r.bottom() - height() + hsbExt + 1) ) );
2288             d->vbar->setGeometry( width() - vsbExt, 0, vsbExt, height() - hsbExt );
2289             d->vbar->setValue( d->yoffset );
2290             d->vbar->show();
2291         } else {
2292             d->vbar->hide();
2293         }
2294
2295         if ( showh ) {
2296             d->hbar->setSteps( QMAX( width() / 12, 30 ), width() - vsbExt );
2297             d->hbar->setRange( QMIN( 0, d->xoffset + QMIN( 0, r.left() ) ), QMAX( 0, d->xoffset + QMAX( 0, r.right() - width() + vsbExt  + 1) ) );
2298             d->hbar->setGeometry( 0, height() - hsbExt, width() - vsbExt, hsbExt );
2299             d->hbar->setValue( d->xoffset );
2300             d->hbar->show();
2301         } else {
2302             d->hbar->hide();
2303         }
2304
2305         if ( showh && showv ) {
2306             d->corner->setGeometry( width() - vsbExt, height() - hsbExt, vsbExt, hsbExt );
2307             d->corner->show();
2308         } else {
2309             d->corner->hide();
2310         }
2311
2312         d->vbar->blockSignals( FALSE );
2313         d->hbar->blockSignals( FALSE );
2314
2315         cr.setRect( 0, 0, width() - vsbExt, height() - hsbExt );
2316     }
2317
2318     QPtrListIterator<QWidget> ii( d->icons );
2319     while ( ii.current() ) {
2320         QWorkspacePChild* w = (QWorkspacePChild*)ii.current();
2321         ++ii;
2322         int x = w->x();
2323         int y = w->y();
2324         bool m = FALSE;
2325         if ( x+w->width() > cr.width() ) {
2326             m = TRUE;
2327             x =  cr.width() - w->width();
2328         }
2329         if ( y+w->height() >  cr.height() ) {
2330             y =  cr.height() - w->height();
2331             m = TRUE;
2332         }
2333         if ( m )
2334             w->move( x, y );
2335     }
2336
2337     return cr;
2338
2339 }
2340
2341 void QWorkspaceP::scrollBarChanged()
2342 {
2343     int ver = d->yoffset - d->vbar->value();
2344     int hor = d->xoffset - d->hbar->value();
2345     d->yoffset = d->vbar->value();
2346     d->xoffset = d->hbar->value();
2347
2348     QPtrListIterator<QWorkspacePChild> it( d->windows );
2349     while ( it.current () ) {
2350         QWorkspacePChild *child = it.current();
2351         ++it;
2352         // we do not use move() due to the reimplementation in QWorkspacePChild
2353         child->setGeometry( child->x() + hor, child->y() + ver, child->width(), child->height() );
2354     }
2355     updateWorkspace();
2356 }
2357
2358 #ifndef QT_NO_STYLE
2359 /*!\reimp */
2360 void QWorkspaceP::styleChange( QStyle &olds )
2361 {
2362     int fs = style().styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this);
2363     if ( isVisibleTo(0) && d->maxWindow &&
2364          fs != olds.styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, this)) {
2365         if( fs )
2366             hideMaximizeControls();
2367         else
2368             showMaximizeControls();
2369     }
2370     QWidget::styleChange(olds);
2371 }
2372 #endif
2373
2374 #define RANGE 4
2375
2376 static bool resizeHorizontalDirectionFixed = FALSE;
2377 static bool resizeVerticalDirectionFixed = FALSE;
2378
2379 QWidgetResizeHandlerP::QWidgetResizeHandlerP( QWidget *parent, QWidget *cw, const char *name )
2380     : QObject( parent, name ), widget( parent ), childWidget( cw ? cw : parent ),
2381       extrahei( 0 ), buttonDown( FALSE ), moveResizeMode( FALSE ), sizeprotect( TRUE ), moving( TRUE )
2382 {
2383     mode = Nowhere;
2384     widget->setMouseTracking( TRUE );
2385     range = widget->inherits( "QFrame" ) ? ((QFrame*)widget)->frameWidth() : RANGE;
2386     range = QMAX( RANGE, range );
2387     active = TRUE;
2388     qApp->installEventFilter( this );
2389 }
2390
2391 static QWidget *childOf( QWidget *w, QWidget *child )
2392 {
2393     while ( child ) {
2394         if ( child == w )
2395             return child;
2396         child = child->parentWidget();
2397     }
2398     return 0;
2399 }
2400
2401 bool QWidgetResizeHandlerP::eventFilter( QObject *o, QEvent *ee )
2402 {
2403     if ( !active || !o->isWidgetType() )
2404         return FALSE;
2405
2406     QWidget *w = childOf( widget, (QWidget*)o );
2407     if ( !w || o->inherits( "QSizeGrip" ) )
2408         return FALSE;
2409
2410     QMouseEvent *e = (QMouseEvent*)ee;
2411     switch ( e->type() ) {
2412     case QEvent::MouseButtonPress: {
2413         if ( w->isMaximized() )
2414             break;
2415         if ( !widget->rect().contains( widget->mapFromGlobal( e->globalPos() ) ) )
2416             return FALSE;
2417         if ( e->button() == LeftButton ) {
2418             emit activate();
2419             bool me = isMovingEnabled();
2420             setMovingEnabled( me && o == widget );
2421             mouseMoveEvent( e );
2422             setMovingEnabled( me );
2423             buttonDown = TRUE;
2424             moveOffset = widget->mapFromGlobal( e->globalPos() );
2425             invertedMoveOffset = widget->rect().bottomRight() - moveOffset;
2426         }
2427     } break;
2428     case QEvent::MouseButtonRelease:
2429         if ( w->isMaximized() )
2430             break;
2431         if ( e->button() == LeftButton ) {
2432             moveResizeMode = FALSE;
2433             buttonDown = FALSE;
2434             widget->releaseMouse();
2435             widget->releaseKeyboard();
2436         }
2437         break;
2438     case QEvent::MouseMove: {
2439         if ( w->isMaximized() )
2440             break;
2441         bool me = isMovingEnabled();
2442         setMovingEnabled( me && o == widget );
2443         mouseMoveEvent( e );
2444         setMovingEnabled( me );
2445         if ( buttonDown && mode != Center )
2446             return TRUE;
2447     } break;
2448     case QEvent::KeyPress:
2449         keyPressEvent( (QKeyEvent*)e );
2450         break;
2451     case QEvent::AccelOverride:
2452         if ( buttonDown ) {
2453             ((QKeyEvent*)ee)->accept();
2454             return TRUE;
2455         }
2456         break;
2457     default:
2458         break;
2459     }
2460     return FALSE;
2461 }
2462
2463 void QWidgetResizeHandlerP::mouseMoveEvent( QMouseEvent *e )
2464 {
2465     QPoint pos = widget->mapFromGlobal( e->globalPos() );
2466     if ( !moveResizeMode && ( !buttonDown || ( e->state() & LeftButton ) == 0 ) ) {
2467         if ( pos.y() <= range && pos.x() <= range)
2468             mode = TopLeft;
2469         else if ( pos.y() >= widget->height()-range && pos.x() >= widget->width()-range)
2470             mode = BottomRight;
2471         else if ( pos.y() >= widget->height()-range && pos.x() <= range)
2472             mode = BottomLeft;
2473         else if ( pos.y() <= range && pos.x() >= widget->width()-range)
2474             mode = TopRight;
2475         else if ( pos.y() <= range )
2476             mode = Top;
2477         else if ( pos.y() >= widget->height()-range )
2478             mode = Bottom;
2479         else if ( pos.x() <= range )
2480             mode = Left;
2481         else if (  pos.x() >= widget->width()-range )
2482             mode = Right;
2483         else
2484             mode = Center;
2485
2486         if ( widget->isMinimized() )
2487             mode = Center;
2488 #ifndef QT_NO_CURSOR
2489         setMouseCursor( mode );
2490 #endif
2491         return;
2492     }
2493
2494     if ( buttonDown && !isMovingEnabled() && mode == Center && !moveResizeMode )
2495         return;
2496
2497     if ( widget->testWState( WState_ConfigPending ) )
2498         return;
2499
2500     QPoint globalPos = widget->parentWidget( TRUE ) ?
2501                        widget->parentWidget( TRUE )->mapFromGlobal( e->globalPos() ) : e->globalPos();
2502     if ( widget->parentWidget( TRUE ) && !widget->parentWidget( TRUE )->rect().contains( globalPos ) ) {
2503         if ( globalPos.x() < 0 )
2504             globalPos.rx() = 0;
2505         if ( globalPos.y() < 0 )
2506             globalPos.ry() = 0;
2507         if ( sizeprotect && globalPos.x() > widget->parentWidget()->width() )
2508             globalPos.rx() = widget->parentWidget()->width();
2509         if ( sizeprotect && globalPos.y() > widget->parentWidget()->height() )
2510             globalPos.ry() = widget->parentWidget()->height();
2511     }
2512
2513     QPoint p = globalPos + invertedMoveOffset;
2514     QPoint pp = globalPos - moveOffset;
2515
2516     int fw = 0;
2517     int mw = QMAX( childWidget->minimumSizeHint().width(),
2518                    childWidget->minimumWidth() );
2519     int mh = QMAX( childWidget->minimumSizeHint().height(),
2520                    childWidget->minimumHeight() );
2521     if ( childWidget != widget ) {
2522         if ( widget->inherits( "QFrame" ) )
2523             fw = ( (QFrame *) widget )->frameWidth();
2524         mw += 2 * fw;
2525         mh += 2 * fw + extrahei;
2526     }
2527
2528     QSize mpsize( widget->geometry().right() - pp.x() + 1,
2529                   widget->geometry().bottom() - pp.y() + 1 );
2530     mpsize = mpsize.expandedTo( widget->minimumSize() ).expandedTo( QSize(mw, mh) );
2531     QPoint mp( widget->geometry().right() - mpsize.width() + 1,
2532                widget->geometry().bottom() - mpsize.height() + 1 );
2533
2534     QRect geom = widget->geometry();
2535
2536     switch ( mode ) {
2537     case TopLeft:
2538         geom = QRect( mp, widget->geometry().bottomRight() ) ;
2539         break;
2540     case BottomRight:
2541         geom = QRect( widget->geometry().topLeft(), p ) ;
2542         break;
2543     case BottomLeft:
2544         geom = QRect( QPoint(mp.x(), widget->geometry().y() ), QPoint( widget->geometry().right(), p.y()) ) ;
2545         break;
2546     case TopRight:
2547         geom = QRect( QPoint( widget->geometry().x(), mp.y() ), QPoint( p.x(), widget->geometry().bottom()) ) ;
2548         break;
2549     case Top:
2550         geom = QRect( QPoint( widget->geometry().left(), mp.y() ), widget->geometry().bottomRight() ) ;
2551         break;
2552     case Bottom:
2553         geom = QRect( widget->geometry().topLeft(), QPoint( widget->geometry().right(), p.y() ) ) ;
2554         break;
2555     case Left:
2556         geom = QRect( QPoint( mp.x(), widget->geometry().top() ), widget->geometry().bottomRight() ) ;
2557         break;
2558     case Right:
2559         geom = QRect( widget->geometry().topLeft(), QPoint( p.x(), widget->geometry().bottom() ) ) ;
2560         break;
2561     case Center:
2562         if ( isMovingEnabled() || moveResizeMode )
2563             geom.moveTopLeft( pp );
2564         break;
2565     default:
2566         break;
2567     }
2568
2569     QSize maxsize( childWidget->maximumSize() );
2570     if ( childWidget != widget )
2571         maxsize += QSize( 2 * fw, 2 * fw + extrahei );
2572
2573     geom = QRect( geom.topLeft(),
2574                   geom.size().expandedTo( widget->minimumSize() )
2575                              .expandedTo( QSize(mw, mh) )
2576                              .boundedTo( maxsize ) );
2577
2578     if ( geom != widget->geometry() &&
2579         ( widget->isTopLevel() || widget->parentWidget()->rect().intersects( geom ) ) ) {
2580         if ( widget->isMinimized() )
2581             widget->move( geom.topLeft() );
2582         else
2583             widget->setGeometry( geom );
2584     }
2585
2586 #if defined(Q_WS_WIN)
2587     MSG msg;
2588 #if defined(UNICODE)
2589 #  ifndef Q_OS_TEMP
2590     if ( qWinVersion() & WV_NT_based ) {
2591 #  endif
2592         while(PeekMessageW( &msg, widget->winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE ))
2593             ;
2594 #  ifndef Q_OS_TEMP
2595     } else
2596 #  endif
2597 #endif
2598 #ifndef Q_OS_TEMP
2599     {
2600         while(PeekMessageA( &msg, widget->winId(), WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE ))
2601             ;
2602     }
2603 #endif
2604 #endif
2605
2606     QApplication::syncX();
2607 }
2608
2609 void QWidgetResizeHandlerP::setMouseCursor( MousePosition m )
2610 {
2611 #ifndef QT_NO_CURSOR
2612     switch ( m ) {
2613     case TopLeft:
2614     case BottomRight:
2615         widget->setCursor( sizeFDiagCursor );
2616         break;
2617     case BottomLeft:
2618     case TopRight:
2619         widget->setCursor( sizeBDiagCursor );
2620         break;
2621     case Top:
2622     case Bottom:
2623         widget->setCursor( sizeVerCursor );
2624         break;
2625     case Left:
2626     case Right:
2627         widget->setCursor( sizeHorCursor );
2628         break;
2629     default:
2630         widget->setCursor( arrowCursor );
2631         break;
2632     }
2633 #endif
2634 }
2635
2636 void QWidgetResizeHandlerP::keyPressEvent( QKeyEvent * e )
2637 {
2638     if ( !isMove() && !isResize() )
2639         return;
2640     bool is_control = e->state() & ControlButton;
2641     int delta = is_control?1:8;
2642     QPoint pos = QCursor::pos();
2643     switch ( e->key() ) {
2644     case Key_Left:
2645         pos.rx() -= delta;
2646         if ( pos.x() <= QApplication::desktop()->geometry().left() ) {
2647             if ( mode == TopLeft || mode == BottomLeft ) {
2648                 moveOffset.rx() += delta;
2649                 invertedMoveOffset.rx() += delta;
2650             } else {
2651                 moveOffset.rx() -= delta;
2652                 invertedMoveOffset.rx() -= delta;
2653             }
2654         }
2655         if ( isResize() && !resizeHorizontalDirectionFixed ) {
2656             resizeHorizontalDirectionFixed = TRUE;
2657             if ( mode == BottomRight )
2658                 mode = BottomLeft;
2659             else if ( mode == TopRight )
2660                 mode = TopLeft;
2661 #ifndef QT_NO_CURSOR
2662             setMouseCursor( mode );
2663             widget->grabMouse( widget->cursor() );
2664 #else
2665             widget->grabMouse();
2666 #endif
2667         }
2668         break;
2669     case Key_Right:
2670         pos.rx() += delta;
2671         if ( pos.x() >= QApplication::desktop()->geometry().right() ) {
2672             if ( mode == TopRight || mode == BottomRight ) {
2673                 moveOffset.rx() += delta;
2674                 invertedMoveOffset.rx() += delta;
2675             } else {
2676                 moveOffset.rx() -= delta;
2677                 invertedMoveOffset.rx() -= delta;
2678             }
2679         }
2680         if ( isResize() && !resizeHorizontalDirectionFixed ) {
2681             resizeHorizontalDirectionFixed = TRUE;
2682             if ( mode == BottomLeft )
2683                 mode = BottomRight;
2684             else if ( mode == TopLeft )
2685                 mode = TopRight;
2686 #ifndef QT_NO_CURSOR
2687             setMouseCursor( mode );
2688             widget->grabMouse( widget->cursor() );
2689 #else
2690             widget->grabMouse();
2691 #endif
2692         }
2693         break;
2694     case Key_Up:
2695         pos.ry() -= delta;
2696         if ( pos.y() <= QApplication::desktop()->geometry().top() ) {
2697             if ( mode == TopLeft || mode == TopRight ) {
2698                 moveOffset.ry() += delta;
2699                 invertedMoveOffset.ry() += delta;
2700             } else {
2701                 moveOffset.ry() -= delta;
2702                 invertedMoveOffset.ry() -= delta;
2703             }
2704         }
2705         if ( isResize() && !resizeVerticalDirectionFixed ) {
2706             resizeVerticalDirectionFixed = TRUE;
2707             if ( mode == BottomLeft )
2708                 mode = TopLeft;
2709             else if ( mode == BottomRight )
2710                 mode = TopRight;
2711 #ifndef QT_NO_CURSOR
2712             setMouseCursor( mode );
2713             widget->grabMouse( widget->cursor() );
2714 #else
2715             widget->grabMouse();
2716 #endif
2717         }
2718         break;
2719     case Key_Down:
2720         pos.ry() += delta;
2721         if ( pos.y() >= QApplication::desktop()->geometry().bottom() ) {
2722             if ( mode == BottomLeft || mode == BottomRight ) {
2723                 moveOffset.ry() += delta;
2724                 invertedMoveOffset.ry() += delta;
2725             } else {
2726                 moveOffset.ry() -= delta;
2727                 invertedMoveOffset.ry() -= delta;
2728             }
2729         }
2730         if ( isResize() && !resizeVerticalDirectionFixed ) {
2731             resizeVerticalDirectionFixed = TRUE;
2732             if ( mode == TopLeft )
2733                 mode = BottomLeft;
2734             else if ( mode == TopRight )
2735                 mode = BottomRight;
2736 #ifndef QT_NO_CURSOR
2737             setMouseCursor( mode );
2738             widget->grabMouse( widget->cursor() );
2739 #else
2740             widget->grabMouse();
2741 #endif
2742         }
2743         break;
2744     case Key_Space:
2745     case Key_Return:
2746     case Key_Enter:
2747     case Key_Escape:
2748         moveResizeMode = FALSE;
2749         widget->releaseMouse();
2750         widget->releaseKeyboard();
2751         buttonDown = FALSE;
2752         break;
2753     default:
2754         return;
2755     }
2756     QCursor::setPos( pos );
2757 }
2758
2759
2760 void QWidgetResizeHandlerP::doResize()
2761 {
2762     if ( !active )
2763         return;
2764
2765     moveResizeMode = TRUE;
2766     buttonDown = TRUE;
2767     moveOffset = widget->mapFromGlobal( QCursor::pos() );
2768     if ( moveOffset.x() < widget->width()/2) {
2769         if ( moveOffset.y() < widget->height()/2)
2770             mode = TopLeft;
2771         else
2772             mode = BottomLeft;
2773     } else {
2774         if ( moveOffset.y() < widget->height()/2)
2775             mode = TopRight;
2776         else
2777             mode = BottomRight;
2778     }
2779     invertedMoveOffset = widget->rect().bottomRight() - moveOffset;
2780 #ifndef QT_NO_CURSOR
2781     setMouseCursor( mode );
2782     widget->grabMouse( widget->cursor()  );
2783 #else
2784     widget->grabMouse();
2785 #endif
2786     widget->grabKeyboard();
2787     resizeHorizontalDirectionFixed = FALSE;
2788     resizeVerticalDirectionFixed = FALSE;
2789 }
2790
2791 void QWidgetResizeHandlerP::doMove()
2792 {
2793     if ( !active )
2794         return;
2795
2796     mode = Center;
2797     moveResizeMode = TRUE;
2798     buttonDown = TRUE;
2799     moveOffset = widget->mapFromGlobal( QCursor::pos() );
2800     invertedMoveOffset = widget->rect().bottomRight() - moveOffset;
2801 #ifndef QT_NO_CURSOR
2802     widget->grabMouse( SizeAllCursor );
2803 #else
2804     widget->grabMouse();
2805 #endif
2806     widget->grabKeyboard();
2807 }
2808
2809 #ifndef QT_NO_TOOLTIP
2810 class QTitleBarPTip : public QToolTip
2811 {
2812 public:
2813     QTitleBarPTip( QWidget * parent ) : QToolTip( parent ) { }
2814
2815     void maybeTip( const QPoint &pos )
2816     {
2817         if ( !parentWidget()->inherits( "QTitleBarP" ) )
2818             return;
2819         QTitleBarP *t = (QTitleBarP *)parentWidget();
2820
2821         QString tipstring;
2822         QStyle::SubControl ctrl = t->style().querySubControl(QStyle::CC_TitleBar, t, pos);
2823         QSize controlSize = t->style().querySubControlMetrics(QStyle::CC_TitleBar, t, ctrl).size();
2824
2825         QWidget *window = t->window();
2826         if ( window ) {
2827             switch(ctrl) {
2828             case QStyle::SC_TitleBarSysMenu:
2829                 if ( t->testWFlags( WStyle_SysMenu ) )
2830                     tipstring = QTitleBarP::tr( "System Menu" );
2831                 break;
2832
2833             case QStyle::SC_TitleBarShadeButton:
2834                 if ( t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_MinMax ) )
2835                     tipstring = QTitleBarP::tr( "Shade" );
2836                 break;
2837
2838             case QStyle::SC_TitleBarUnshadeButton:
2839                 if ( t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_MinMax ) )
2840                     tipstring = QTitleBarP::tr( "Unshade" );
2841                 break;
2842
2843             case QStyle::SC_TitleBarNormalButton:
2844             case QStyle::SC_TitleBarMinButton:
2845                 if ( !t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_Minimize ) ) {
2846                     if( window->isMinimized() )
2847                         tipstring = QTitleBarP::tr( "Normalize" );
2848                     else
2849                         tipstring = QTitleBarP::tr( "Minimize" );
2850                 }
2851                 break;
2852
2853             case QStyle::SC_TitleBarMaxButton:
2854                 if ( !t->testWFlags( WStyle_Tool ) && t->testWFlags( WStyle_Maximize ) )
2855                     tipstring = QTitleBarP::tr( "Maximize" );
2856                 break;
2857
2858             case QStyle::SC_TitleBarCloseButton:
2859                 if ( t->testWFlags( WStyle_SysMenu ) )
2860                     tipstring = QTitleBarP::tr( "Close" );
2861                 break;
2862
2863             default:
2864                 break;
2865             }
2866         }
2867 #ifndef QT_NO_WIDGET_TOPEXTRA
2868         if ( tipstring.isEmpty() ) {
2869             if ( t->visibleText() != t->caption() )
2870                 tipstring = t->caption();
2871         }
2872 #endif
2873         if(!tipstring.isEmpty())
2874             tip( QRect(pos, controlSize), tipstring );
2875     }
2876 };
2877 #endif
2878
2879 class QTitleBarPPrivate
2880 {
2881 public:
2882     QTitleBarPPrivate()
2883         : toolTip( 0 ), act( 0 ), window( 0 ), movable( 1 ), pressed( 0 ), autoraise(0)
2884     {
2885     }
2886
2887     QStyle::SCFlags buttonDown;
2888     QPoint moveOffset;
2889     QToolTip *toolTip;
2890     bool act                :1;
2891     QWidget* window;
2892     bool movable            :1;
2893     bool pressed            :1;
2894     bool autoraise          :1;
2895     QString cuttext;
2896 };
2897
2898 QTitleBarP::QTitleBarP(QWidget* w, QWidget* parent, const char* name)
2899     : QWidget( parent, name, WStyle_Customize | WStyle_NoBorder | WResizeNoErase | WRepaintNoErase )
2900 {
2901     d = new QTitleBarPPrivate();
2902
2903 #ifndef QT_NO_TOOLTIP
2904     d->toolTip = new QTitleBarPTip( this );
2905 #endif
2906     d->window = w;
2907     d->buttonDown = QStyle::SC_None;
2908     d->act = 0;
2909     if ( w ) {
2910         setWFlags( ((QTitleBarP*)w)->getWFlags() | WResizeNoErase | WRepaintNoErase );
2911 #ifndef QT_NO_WIDGET_TOPEXTRA
2912         setCaption( w->caption() );
2913 #endif
2914     } else {
2915         setWFlags( WStyle_Customize | WResizeNoErase | WRepaintNoErase );
2916     }
2917
2918     readColors();
2919     setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed ) );
2920     setMouseTracking(TRUE);
2921 }
2922
2923 QTitleBarP::~QTitleBarP()
2924 {
2925 #ifndef QT_NO_TOOLTIP
2926     delete d->toolTip;
2927 #endif
2928
2929     delete d;
2930     d = 0;
2931 }
2932
2933 #ifdef Q_WS_WIN
2934 extern QRgb qt_colorref2qrgb(COLORREF col);
2935 #endif
2936
2937 void QTitleBarP::readColors()
2938 {
2939     QPalette pal = palette();
2940
2941 #ifdef Q_WS_WIN // ask system properties on windows
2942 #ifndef SPI_GETGRADIENTCAPTIONS
2943 #define SPI_GETGRADIENTCAPTIONS 0x1008
2944 #endif
2945 #ifndef COLOR_GRADIENTACTIVECAPTION
2946 #define COLOR_GRADIENTACTIVECAPTION 27
2947 #endif
2948 #ifndef COLOR_GRADIENTINACTIVECAPTION
2949 #define COLOR_GRADIENTINACTIVECAPTION 28
2950 #endif
2951     if ( QApplication::desktopSettingsAware() ) {
2952         pal.setColor( QPalette::Active, QColorGroup::Highlight, qt_colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION)) );
2953         pal.setColor( QPalette::Inactive, QColorGroup::Highlight, qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION)) );
2954         pal.setColor( QPalette::Active, QColorGroup::HighlightedText, qt_colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)) );
2955         pal.setColor( QPalette::Inactive, QColorGroup::HighlightedText, qt_colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)) );
2956         if ( qt_winver != Qt::WV_95 && qt_winver != WV_NT ) {
2957             BOOL gradient;
2958 #ifdef Q_OS_TEMP
2959             SystemParametersInfo( SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0 );
2960 #else
2961 #if defined(UNICODE)
2962             if ( qt_winver & Qt::WV_NT_based )
2963                 SystemParametersInfo( SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0 );
2964             else
2965 #endif
2966                 SystemParametersInfoA( SPI_GETGRADIENTCAPTIONS, 0, &gradient, 0 );
2967 #endif
2968             if ( gradient ) {
2969                 pal.setColor( QPalette::Active, QColorGroup::Base, qt_colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)) );
2970                 pal.setColor( QPalette::Inactive, QColorGroup::Base, qt_colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)) );
2971             } else {
2972                 pal.setColor( QPalette::Active, QColorGroup::Base, palette().active().highlight() );
2973                 pal.setColor( QPalette::Inactive, QColorGroup::Base, palette().inactive().highlight() );
2974             }
2975         }
2976     } else
2977 #endif // Q_WS_WIN
2978     {
2979         pal.setColor( QPalette::Active, QColorGroup::Highlight, palette().active().highlight() );
2980         pal.setColor( QPalette::Active, QColorGroup::Base, palette().active().highlight() );
2981         pal.setColor( QPalette::Inactive, QColorGroup::Highlight, palette().inactive().dark() );
2982         pal.setColor( QPalette::Inactive, QColorGroup::Base, palette().inactive().dark() );
2983         pal.setColor( QPalette::Inactive, QColorGroup::HighlightedText, palette().inactive().background() );
2984     }
2985
2986     setPalette( pal );
2987     setActive( d->act );
2988 }
2989
2990 void QTitleBarP::mousePressEvent( QMouseEvent * e)
2991 {
2992     emit doActivate();
2993     if ( e->button() == LeftButton ) {
2994         d->pressed = TRUE;
2995         QStyle::SCFlags ctrl = style().querySubControl(QStyle::CC_TitleBar, this, e->pos());
2996         switch (ctrl) {
2997         case QStyle::SC_TitleBarSysMenu:
2998             if ( testWFlags( WStyle_SysMenu ) && !testWFlags( WStyle_Tool ) ) {
2999                 d->buttonDown = QStyle::SC_None;
3000                 static QTime* t = 0;
3001                 static QTitleBarP* tc = 0;
3002                 if ( !t )
3003                     t = new QTime;
3004                 if ( tc != this || t->elapsed() > QApplication::doubleClickInterval() ) {
3005                     emit showOperationMenu();
3006                     t->start();
3007                     tc = this;
3008                 } else {
3009                     tc = 0;
3010                     emit doClose();
3011                     return;
3012                 }
3013             }
3014             break;
3015
3016         case QStyle::SC_TitleBarShadeButton:
3017         case QStyle::SC_TitleBarUnshadeButton:
3018             if ( testWFlags( WStyle_MinMax ) && testWFlags( WStyle_Tool ) )
3019                 d->buttonDown = ctrl;
3020             break;
3021
3022         case QStyle::SC_TitleBarNormalButton:
3023             if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) )
3024                 d->buttonDown = ctrl;
3025             break;
3026
3027         case QStyle::SC_TitleBarMinButton:
3028             if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) )
3029                 d->buttonDown = ctrl;
3030             break;
3031
3032         case QStyle::SC_TitleBarMaxButton:
3033             if ( testWFlags( WStyle_Maximize ) && !testWFlags( WStyle_Tool ) )
3034                 d->buttonDown = ctrl;
3035             break;
3036
3037         case QStyle::SC_TitleBarCloseButton:
3038             if ( testWFlags( WStyle_SysMenu ) )
3039                 d->buttonDown = ctrl;
3040             break;
3041
3042         case QStyle::SC_TitleBarLabel:
3043             d->buttonDown = ctrl;
3044             d->moveOffset = mapToParent( e->pos() );
3045             break;
3046         
3047         default:
3048             break;
3049         }
3050         repaint( FALSE );
3051     } else {
3052         d->pressed = FALSE;
3053     }
3054 }
3055
3056 void QTitleBarP::contextMenuEvent( QContextMenuEvent *e )
3057 {
3058     QStyle::SCFlags ctrl = style().querySubControl(QStyle::CC_TitleBar, this, e->pos());
3059     if( ctrl == QStyle::SC_TitleBarLabel || ctrl == QStyle::SC_TitleBarSysMenu ) {
3060         emit popupOperationMenu(e->globalPos());
3061         e->accept();
3062     }
3063 }
3064
3065 void QTitleBarP::mouseReleaseEvent( QMouseEvent * e)
3066 {
3067     if ( e->button() == LeftButton && d->pressed) {
3068         QStyle::SCFlags ctrl = style().querySubControl(QStyle::CC_TitleBar, this, e->pos());
3069
3070         if (ctrl == d->buttonDown) {
3071             switch(ctrl) {
3072             case QStyle::SC_TitleBarShadeButton:
3073             case QStyle::SC_TitleBarUnshadeButton:
3074                 if( testWFlags( WStyle_MinMax ) && testWFlags( WStyle_Tool ) )
3075                     emit doShade();
3076                 break;
3077         
3078             case QStyle::SC_TitleBarNormalButton:
3079                 if( testWFlags( WStyle_MinMax ) && !testWFlags( WStyle_Tool ) )
3080                     emit doNormal();
3081                 break;
3082
3083             case QStyle::SC_TitleBarMinButton:
3084                 if( testWFlags( WStyle_Minimize ) && !testWFlags( WStyle_Tool ) )
3085                     emit doMinimize();
3086                 break;
3087
3088             case QStyle::SC_TitleBarMaxButton:
3089                 if( d->window && testWFlags( WStyle_Maximize ) && !testWFlags( WStyle_Tool ) ) {
3090                     if(d->window->isMaximized())
3091                         emit doNormal();
3092                     else
3093                         emit doMaximize();
3094                 }
3095                 break;
3096
3097             case QStyle::SC_TitleBarCloseButton:
3098                 if( testWFlags( WStyle_SysMenu ) ) {
3099                     d->buttonDown = QStyle::SC_None;
3100                     repaint(FALSE);
3101                     emit doClose();             
3102                     return;
3103                 }
3104                 break;
3105
3106             default:
3107                 break;
3108             }
3109         }
3110         d->buttonDown = QStyle::SC_None;
3111         repaint(FALSE);
3112         d->pressed = FALSE;
3113     }
3114 }
3115
3116 void QTitleBarP::mouseMoveEvent( QMouseEvent * e)
3117 {
3118     switch (d->buttonDown) {
3119     case QStyle::SC_None:
3120         if(autoRaise())
3121             repaint( FALSE );
3122         break;
3123     case QStyle::SC_TitleBarSysMenu:
3124         break;
3125     case QStyle::SC_TitleBarShadeButton:
3126     case QStyle::SC_TitleBarUnshadeButton:
3127     case QStyle::SC_TitleBarNormalButton:
3128     case QStyle::SC_TitleBarMinButton:
3129     case QStyle::SC_TitleBarMaxButton:
3130     case QStyle::SC_TitleBarCloseButton:
3131         {
3132             QStyle::SCFlags last_ctrl = d->buttonDown;
3133             d->buttonDown = style().querySubControl(QStyle::CC_TitleBar, this, e->pos());
3134             if( d->buttonDown != last_ctrl)
3135                 d->buttonDown = QStyle::SC_None;
3136             repaint(FALSE);
3137             d->buttonDown = last_ctrl;
3138         }
3139         break;
3140
3141     case QStyle::SC_TitleBarLabel:
3142         if ( d->buttonDown == QStyle::SC_TitleBarLabel && d->movable && d->pressed ) {
3143             if ( (d->moveOffset - mapToParent( e->pos() ) ).manhattanLength() >= 4 ) {
3144                 QPoint p = mapFromGlobal(e->globalPos());
3145 #ifndef QT_NO_WORKSPACE
3146                 if(d->window && d->window->parentWidget()->inherits("QWorkspacePChild")) {
3147                     QWidget *w = d->window->parentWidget()->parentWidget();
3148                     if(w && w->inherits("QWorkspaceP")) {
3149                         QWorkspaceP *workspace = (QWorkspaceP*)w;
3150                         p = workspace->mapFromGlobal( e->globalPos() );
3151                         if ( !workspace->rect().contains(p) ) {
3152                             if ( p.x() < 0 )
3153                                 p.rx() = 0;
3154                             if ( p.y() < 0 )
3155                                 p.ry() = 0;
3156                             if ( p.x() > workspace->width() )
3157                                 p.rx() = workspace->width();
3158                             if ( p.y() > workspace->height() )
3159                                 p.ry() = workspace->height();
3160                         }
3161                     }
3162                 }
3163 #endif
3164                 QPoint pp = p - d->moveOffset;
3165                 parentWidget()->move( pp );
3166             }
3167         } else {
3168             QStyle::SCFlags last_ctrl = d->buttonDown;
3169             d->buttonDown = QStyle::SC_None;
3170             if( d->buttonDown != last_ctrl)
3171                 repaint(FALSE);
3172         }
3173         break;
3174     }
3175 }
3176
3177 void QTitleBarP::resizeEvent( QResizeEvent *r)
3178 {
3179     QWidget::resizeEvent(r);
3180     cutText();
3181 }
3182
3183 void QTitleBarP::paintEvent(QPaintEvent *)
3184 {
3185     QStyle::SCFlags ctrls = QStyle::SC_TitleBarLabel;
3186     if ( testWFlags( WStyle_SysMenu) ) {
3187         if ( testWFlags( WStyle_Tool ) ) {
3188             ctrls |= QStyle::SC_TitleBarCloseButton;
3189             if ( d->window && testWFlags( WStyle_MinMax ) ) {
3190                 if ( d->window->isMinimized() )
3191                     ctrls |= QStyle::SC_TitleBarUnshadeButton;
3192                 else
3193                     ctrls |= QStyle::SC_TitleBarShadeButton;
3194             }
3195         } else {
3196             ctrls |= QStyle::SC_TitleBarSysMenu | QStyle::SC_TitleBarCloseButton;
3197             if ( d->window && testWFlags( WStyle_Minimize ) ) {
3198                 if( d->window && d->window->isMinimized() )
3199                     ctrls |= QStyle::SC_TitleBarNormalButton;
3200                 else
3201                     ctrls |= QStyle::SC_TitleBarMinButton;
3202             }
3203             if ( d->window && testWFlags( WStyle_Maximize ) && !d->window->isMaximized() )
3204                 ctrls |= QStyle::SC_TitleBarMaxButton;
3205         }
3206     }
3207
3208     QStyle::SCFlags under_mouse = QStyle::SC_None;
3209     if( autoRaise() && hasMouse() ) {
3210         QPoint p(mapFromGlobal(QCursor::pos()));
3211         under_mouse = style().querySubControl(QStyle::CC_TitleBar, this, p);
3212         ctrls ^= under_mouse;
3213     }
3214
3215     // QSharedDoubleBuffer buffer( (bool)FALSE, (bool)FALSE );
3216     // buffer.begin( this, rect() );
3217     QSharedDoubleBuffer buffer( this, rect() );
3218     style().drawComplexControl(QStyle::CC_TitleBar, buffer.painter(), this, rect(),
3219                                colorGroup(),
3220                                isEnabled() ? QStyle::Style_Enabled :
3221                                QStyle::Style_Default, ctrls, d->buttonDown);
3222     if(under_mouse != QStyle::SC_None)
3223         style().drawComplexControl(QStyle::CC_TitleBar, buffer.painter(), this, rect(),
3224                                    colorGroup(),
3225                                    QStyle::Style_MouseOver |
3226                                    (isEnabled() ? QStyle::Style_Enabled : 0),
3227                                    under_mouse, d->buttonDown);
3228 }
3229
3230 void QTitleBarP::mouseDoubleClickEvent( QMouseEvent *e )
3231 {
3232     if ( e->button() != LeftButton )
3233         return;
3234
3235     switch(style().querySubControl(QStyle::CC_TitleBar, this, e->pos())) {
3236     case QStyle::SC_TitleBarLabel:
3237         emit doubleClicked();
3238         break;
3239
3240     case QStyle::SC_TitleBarSysMenu:
3241         if ( testWFlags( WStyle_SysMenu ) )
3242             emit doClose();
3243         break;
3244
3245     default:
3246         break;
3247     }
3248 }
3249
3250 void QTitleBarP::cutText()
3251 {
3252 #ifndef QT_NO_WIDGET_TOPEXTRA
3253     QFontMetrics fm( font() );
3254
3255     int maxw = style().querySubControlMetrics(QStyle::CC_TitleBar, this,
3256                                               QStyle::SC_TitleBarLabel).width();
3257     if ( !d->window )
3258         maxw = width() - 20;
3259     const QString txt = caption();
3260     d->cuttext = txt;
3261     if ( fm.width( txt + "m" ) > maxw ) {
3262         int i = txt.length();
3263         int dotlength = fm.width( "..." );
3264         while ( i>0 && fm.width(txt.left( i )) + dotlength > maxw )
3265             i--;
3266         if(i != (int)txt.length())
3267             d->cuttext = txt.left( i ) + "...";
3268     }
3269 #endif
3270 }
3271
3272 void QTitleBarP::setCaption( const QString& title )
3273 {
3274 #ifndef QT_NO_WIDGET_TOPEXTRA
3275     if( caption() == title)
3276         return;
3277     QWidget::setCaption( title );
3278     cutText();
3279
3280     update();
3281 #endif
3282 }
3283
3284
3285 void QTitleBarP::setIcon( const QPixmap& icon )
3286 {
3287 #ifndef QT_NO_WIDGET_TOPEXTRA
3288 #ifndef QT_NO_IMAGE_SMOOTHSCALE
3289     QRect menur = style().querySubControlMetrics(QStyle::CC_TitleBar, this,
3290                                                   QStyle::SC_TitleBarSysMenu);
3291
3292     QPixmap theIcon;
3293     if (icon.width() > menur.width()) {
3294         // try to keep something close to the same aspect
3295         int aspect = (icon.height() * 100) / icon.width();
3296         int newh = (aspect * menur.width()) / 100;
3297         theIcon.convertFromImage( icon.convertToImage().smoothScale(menur.width(),
3298                                                                    newh) );
3299     } else if (icon.height() > menur.height()) {
3300         // try to keep something close to the same aspect
3301         int aspect = (icon.width() * 100) / icon.height();
3302         int neww = (aspect * menur.height()) / 100;
3303         theIcon.convertFromImage( icon.convertToImage().smoothScale(neww,
3304                                                                    menur.height()) );
3305     } else
3306         theIcon = icon;
3307
3308     QWidget::setIcon( theIcon );
3309 #else
3310     QWidget::setIcon( icon );
3311 #endif
3312
3313     update();
3314 #endif
3315 }
3316
3317 void QTitleBarP::leaveEvent( QEvent * )
3318 {
3319     if(autoRaise() && !d->pressed)
3320         repaint( FALSE );
3321 }
3322
3323 void QTitleBarP::enterEvent( QEvent * )
3324 {
3325     if(autoRaise() && !d->pressed)
3326         repaint( FALSE );
3327     QEvent e( QEvent::Leave );
3328     QApplication::sendEvent( parentWidget(), &e );
3329 }
3330
3331 void QTitleBarP::setActive( bool active )
3332 {
3333     if ( d->act == active )
3334         return ;
3335
3336     d->act = active;
3337     update();
3338 }
3339
3340 bool QTitleBarP::isActive() const
3341 {
3342     return d->act;
3343 }
3344
3345 bool QTitleBarP::usesActiveColor() const
3346 {
3347     return ( isActive() && isActiveWindow() ) ||
3348            ( !window() && topLevelWidget()->isActiveWindow() );
3349 }
3350
3351 QString QTitleBarP::visibleText() const
3352 {
3353     return d->cuttext;
3354 }
3355
3356 QWidget *QTitleBarP::window() const
3357 {
3358     return d->window;
3359 }
3360
3361 bool QTitleBarP::event( QEvent* e )
3362 {
3363     if ( e->type() == QEvent::ApplicationPaletteChange ) {
3364         readColors();
3365         return TRUE;
3366     } else if ( e->type() == QEvent::WindowActivate ) {
3367         setActive( d->act );
3368     } else if ( e->type() == QEvent::WindowDeactivate ) {
3369         bool wasActive = d->act;
3370         setActive( FALSE );
3371         d->act = wasActive;
3372     }
3373
3374     return QWidget::event( e );
3375 }
3376
3377 void QTitleBarP::setMovable(bool b)
3378 {
3379     d->movable = b;
3380 }
3381
3382 bool QTitleBarP::isMovable() const
3383 {
3384     return d->movable;
3385 }
3386
3387 void QTitleBarP::setAutoRaise(bool b)
3388 {
3389     d->autoraise = b;
3390 }
3391
3392 bool QTitleBarP::autoRaise() const
3393 {
3394     return d->autoraise;
3395 }
3396
3397 QSize QTitleBarP::sizeHint() const
3398 {
3399     constPolish();
3400     QRect menur = style().querySubControlMetrics(QStyle::CC_TitleBar, this,
3401                                                  QStyle::SC_TitleBarSysMenu);
3402     return QSize( menur.width(), style().pixelMetric( QStyle::PM_TitleBarHeight, this ) );
3403 }
3404