src/gui/widgets/qmdisubwindow.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 /*!
       
    43     \class QMdiSubWindow
       
    44     \brief The QMdiSubWindow class provides a subwindow class for
       
    45     QMdiArea.
       
    46     \since 4.3
       
    47     \ingroup mainwindow-classes
       
    48 
       
    49 
       
    50     QMdiSubWindow represents a top-level window in a QMdiArea, and consists
       
    51     of a title bar with window decorations, an internal widget, and
       
    52     (depending on the current style) a window frame and a size
       
    53     grip. QMdiSubWindow has its own layout, which consists of the
       
    54     title bar and a center area for the internal widget.
       
    55 
       
    56     \image qmdisubwindowlayout.png
       
    57 
       
    58     The most common way to construct a QMdiSubWindow is to call
       
    59     QMdiArea::addSubWindow() with the internal widget as the argument.
       
    60     You can also create a subwindow yourself, and set an internal
       
    61     widget by calling setWidget().
       
    62 
       
    63     You use the same API when programming with subwindows as with
       
    64     regular top-level windows (e.g., you can call functions such as
       
    65     show(), hide(), showMaximized(), and setWindowTitle()).
       
    66 
       
    67     \section1 Subwindow Handling
       
    68 
       
    69     QMdiSubWindow also supports behavior specific to subwindows in
       
    70     an MDI area.
       
    71 
       
    72     By default, each QMdiSubWindow is visible inside the MDI area
       
    73     viewport when moved around, but it is also possible to specify
       
    74     transparent window movement and resizing behavior, where only
       
    75     the outline of a subwindow is updated during these operations.
       
    76     The setOption() function is used to enable this behavior.
       
    77 
       
    78     The isShaded() function detects whether the subwindow is
       
    79     currently shaded (i.e., the window is collapsed so that only the
       
    80     title bar is visible). To enter shaded mode, call showShaded().
       
    81     QMdiSubWindow emits the windowStateChanged() signal whenever the
       
    82     window state has changed (e.g., when the window becomes minimized,
       
    83     or is restored). It also emits aboutToActivate() before it is
       
    84     activated.
       
    85 
       
    86     In keyboard-interactive mode, the windows are moved and resized
       
    87     with the keyboard. You can enter this mode through the system menu
       
    88     of the window. The keyboardSingleStep and keyboardPageStep
       
    89     properties control the distance the widget is moved or resized for
       
    90     each keypress event. When shift is pressed down page step is used;
       
    91     otherwise single step is used.
       
    92 
       
    93     You can also change the active window with the keyboard. By
       
    94     pressing the control and tab keys at the same time, the next
       
    95     (using the current \l{QMdiArea::}{WindowOrder}) subwindow will be
       
    96     activated. By pressing control, shift, and tab, you will activate
       
    97     the previous window. This is equivalent to calling
       
    98     \l{QMdiArea::}{activateNextSubWindow()} and
       
    99     \l{QMdiArea::}{activatePreviousSubWindow()}. Note that these
       
   100     shortcuts overrides global shortcuts, but not the \l{QMdiArea}s
       
   101     shortcuts.
       
   102 
       
   103     \sa QMdiArea
       
   104 */
       
   105 
       
   106 /*!
       
   107     \enum QMdiSubWindow::SubWindowOption
       
   108 
       
   109     This enum describes options that customize the behavior
       
   110     of QMdiSubWindow.
       
   111 
       
   112     \omitvalue AllowOutsideAreaHorizontally
       
   113     \omitvalue AllowOutsideAreaVertically
       
   114 
       
   115     \value RubberBandResize If you enable this option, a rubber band
       
   116     control is used to represent the subwindow's outline, and the user
       
   117     resizes this instead of the subwindow itself.
       
   118     As a result, the subwindow maintains its original position and size
       
   119     until the resize operation has been completed, at which time it will
       
   120     receive a single QResizeEvent.
       
   121     By default, this option is disabled.
       
   122 
       
   123     \value RubberBandMove If you enable this option, a rubber band
       
   124     control is used to represent the subwindow's outline, and the user
       
   125     moves this instead of the subwindow itself.
       
   126     As a result, the subwindow remains in its original position until
       
   127     the move operation has completed, at which time a QMoveEvent is
       
   128     sent to the window. By default, this option is disabled.
       
   129 */
       
   130 
       
   131 /*!
       
   132     \fn QMdiSubWindow::windowStateChanged(Qt::WindowStates oldState, Qt::WindowStates newState)
       
   133 
       
   134     QMdiSubWindow emits this signal after the window state changes. \a
       
   135     oldState is the window state before it changed, and \a newState is the
       
   136     new, current state.
       
   137 */
       
   138 
       
   139 /*!
       
   140     \fn QMdiSubWindow::aboutToActivate()
       
   141 
       
   142     QMdiSubWindow emits this signal immediately before it is
       
   143     activated. After the subwindow has been activated, the QMdiArea that
       
   144     manages the subwindow will also emit the
       
   145     \l{QMdiArea::}{subWindowActivated()} signal.
       
   146 
       
   147     \sa QMdiArea::subWindowActivated()
       
   148 */
       
   149 
       
   150 #include "qmdisubwindow_p.h"
       
   151 
       
   152 #ifndef QT_NO_MDIAREA
       
   153 
       
   154 #include <QApplication>
       
   155 #include <QStylePainter>
       
   156 #include <QVBoxLayout>
       
   157 #include <QMouseEvent>
       
   158 #include <QWhatsThis>
       
   159 #include <QToolTip>
       
   160 #include <QMainWindow>
       
   161 #include <QScrollBar>
       
   162 #include <QDebug>
       
   163 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
   164 #include <QMacStyle>
       
   165 #endif
       
   166 #include <QMdiArea>
       
   167 
       
   168 QT_BEGIN_NAMESPACE
       
   169 
       
   170 using namespace QMdi;
       
   171 
       
   172 static const QStyle::SubControl SubControls[] =
       
   173 {
       
   174     QStyle::SC_TitleBarLabel, // 1
       
   175     QStyle::SC_TitleBarSysMenu, // 2
       
   176     QStyle::SC_TitleBarMinButton, // 3
       
   177     QStyle::SC_TitleBarMaxButton, // 4
       
   178     QStyle::SC_TitleBarShadeButton, // 5
       
   179     QStyle::SC_TitleBarCloseButton, // 6
       
   180     QStyle::SC_TitleBarNormalButton, // 7
       
   181     QStyle::SC_TitleBarUnshadeButton, // 8
       
   182     QStyle::SC_TitleBarContextHelpButton // 9
       
   183 };
       
   184 static const int NumSubControls = sizeof(SubControls) / sizeof(SubControls[0]);
       
   185 
       
   186 static const QStyle::StandardPixmap ButtonPixmaps[] =
       
   187 {
       
   188     QStyle::SP_TitleBarMinButton,
       
   189     QStyle::SP_TitleBarNormalButton,
       
   190     QStyle::SP_TitleBarCloseButton
       
   191 };
       
   192 static const int NumButtonPixmaps = sizeof(ButtonPixmaps) / sizeof(ButtonPixmaps[0]);
       
   193 
       
   194 static const Qt::WindowFlags CustomizeWindowFlags =
       
   195       Qt::FramelessWindowHint
       
   196     | Qt::CustomizeWindowHint
       
   197     | Qt::WindowTitleHint
       
   198     | Qt::WindowSystemMenuHint
       
   199     | Qt::WindowMinimizeButtonHint
       
   200     | Qt::WindowMaximizeButtonHint
       
   201     | Qt::WindowMinMaxButtonsHint;
       
   202 
       
   203 
       
   204 static const int BoundaryMargin = 5;
       
   205 
       
   206 static inline int getMoveDeltaComponent(uint cflags, uint moveFlag, uint resizeFlag,
       
   207                                         int delta, int maxDelta, int minDelta)
       
   208 {
       
   209     if (cflags & moveFlag) {
       
   210         if (delta > 0)
       
   211             return (cflags & resizeFlag) ? qMin(delta, maxDelta) : delta;
       
   212         return (cflags & resizeFlag) ? qMax(delta, minDelta) : delta;
       
   213     }
       
   214     return 0;
       
   215 }
       
   216 
       
   217 static inline int getResizeDeltaComponent(uint cflags, uint resizeFlag,
       
   218                                           uint resizeReverseFlag, int delta)
       
   219 {
       
   220     if (cflags & resizeFlag) {
       
   221         if (cflags & resizeReverseFlag)
       
   222             return -delta;
       
   223         return delta;
       
   224     }
       
   225     return 0;
       
   226 }
       
   227 
       
   228 static inline bool isChildOfQMdiSubWindow(const QWidget *child)
       
   229 {
       
   230     Q_ASSERT(child);
       
   231     QWidget *parent = child->parentWidget();
       
   232     while (parent) {
       
   233         if (qobject_cast<QMdiSubWindow *>(parent))
       
   234             return true;
       
   235         parent = parent->parentWidget();
       
   236     }
       
   237     return false;
       
   238 }
       
   239 
       
   240 static inline bool isChildOfTabbedQMdiArea(const QMdiSubWindow *child)
       
   241 {
       
   242     Q_ASSERT(child);
       
   243     if (QMdiArea *mdiArea = child->mdiArea()) {
       
   244         if (mdiArea->viewMode() == QMdiArea::TabbedView)
       
   245             return true;
       
   246     }
       
   247     return false;
       
   248 }
       
   249 
       
   250 template<typename T>
       
   251 static inline ControlElement<T> *ptr(QWidget *widget)
       
   252 {
       
   253     if (widget && widget->qt_metacast("ControlElement")
       
   254             && strcmp(widget->metaObject()->className(), T::staticMetaObject.className()) == 0) {
       
   255         return static_cast<ControlElement<T> *>(widget);
       
   256     }
       
   257     return 0;
       
   258 }
       
   259 
       
   260 QString QMdiSubWindowPrivate::originalWindowTitle()
       
   261 {
       
   262     Q_Q(QMdiSubWindow);
       
   263     if (originalTitle.isNull()) {
       
   264         originalTitle = q->window()->windowTitle();
       
   265         if (originalTitle.isNull())
       
   266             originalTitle = QLatin1String("");
       
   267     }
       
   268     return originalTitle;
       
   269 }
       
   270 
       
   271 void QMdiSubWindowPrivate::setNewWindowTitle()
       
   272 {
       
   273     Q_Q(QMdiSubWindow);
       
   274     QString childTitle = q->windowTitle();
       
   275     if (childTitle.isEmpty())
       
   276         return;
       
   277     QString original = originalWindowTitle();
       
   278     if (!original.isEmpty()) {
       
   279         if (!original.contains(QMdiSubWindow::tr("- [%1]").arg(childTitle)))
       
   280             q->window()->setWindowTitle(QMdiSubWindow::tr("%1 - [%2]").arg(original, childTitle));
       
   281 
       
   282     } else {
       
   283         q->window()->setWindowTitle(childTitle);
       
   284     }
       
   285 }
       
   286 
       
   287 static inline bool isHoverControl(QStyle::SubControl control)
       
   288 {
       
   289     return control != QStyle::SC_None && control != QStyle::SC_TitleBarLabel;
       
   290 }
       
   291 
       
   292 #if defined(Q_WS_WIN)
       
   293 static inline QRgb colorref2qrgb(COLORREF col)
       
   294 {
       
   295     return qRgb(GetRValue(col),GetGValue(col),GetBValue(col));
       
   296 }
       
   297 #endif
       
   298 
       
   299 #ifndef QT_NO_TOOLTIP
       
   300 static void showToolTip(QHelpEvent *helpEvent, QWidget *widget, const QStyleOptionComplex &opt,
       
   301                         QStyle::ComplexControl complexControl, QStyle::SubControl subControl)
       
   302 {
       
   303     Q_ASSERT(helpEvent);
       
   304     Q_ASSERT(helpEvent->type() == QEvent::ToolTip);
       
   305     Q_ASSERT(widget);
       
   306 
       
   307 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
   308     // Native Mac windows don't show tool tip.
       
   309     if (qobject_cast<QMacStyle *>(widget->style()))
       
   310         return;
       
   311 #endif
       
   312 
       
   313     // Convert CC_MdiControls to CC_TitleBar. Sub controls of different complex
       
   314     // controls cannot be in the same switch as they might have the same value.
       
   315     if (complexControl == QStyle::CC_MdiControls) {
       
   316         if (subControl == QStyle::SC_MdiMinButton)
       
   317             subControl = QStyle::SC_TitleBarMinButton;
       
   318         else if (subControl == QStyle::SC_MdiCloseButton)
       
   319             subControl = QStyle::SC_TitleBarCloseButton;
       
   320         else if (subControl == QStyle::SC_MdiNormalButton)
       
   321             subControl = QStyle::SC_TitleBarNormalButton;
       
   322         else
       
   323             subControl = QStyle::SC_None;
       
   324     }
       
   325 
       
   326     // Don't change the tooltip for the base widget itself.
       
   327     if (subControl == QStyle::SC_None)
       
   328         return;
       
   329 
       
   330     QString toolTip;
       
   331 
       
   332     switch (subControl) {
       
   333     case QStyle::SC_TitleBarMinButton:
       
   334         toolTip = QMdiSubWindow::tr("Minimize");
       
   335         break;
       
   336     case QStyle::SC_TitleBarMaxButton:
       
   337         toolTip = QMdiSubWindow::tr("Maximize");
       
   338         break;
       
   339     case QStyle::SC_TitleBarUnshadeButton:
       
   340         toolTip = QMdiSubWindow::tr("Unshade");
       
   341         break;
       
   342     case QStyle::SC_TitleBarShadeButton:
       
   343         toolTip = QMdiSubWindow::tr("Shade");
       
   344         break;
       
   345     case QStyle::SC_TitleBarNormalButton:
       
   346         if (widget->isMaximized() || !qobject_cast<QMdiSubWindow *>(widget))
       
   347             toolTip = QMdiSubWindow::tr("Restore Down");
       
   348         else
       
   349             toolTip = QMdiSubWindow::tr("Restore");
       
   350         break;
       
   351     case QStyle::SC_TitleBarCloseButton:
       
   352         toolTip = QMdiSubWindow::tr("Close");
       
   353         break;
       
   354     case QStyle::SC_TitleBarContextHelpButton:
       
   355         toolTip = QMdiSubWindow::tr("Help");
       
   356         break;
       
   357     case QStyle::SC_TitleBarSysMenu:
       
   358         toolTip = QMdiSubWindow::tr("Menu");
       
   359         break;
       
   360     default:
       
   361         break;
       
   362     }
       
   363 
       
   364     const QRect rect = widget->style()->subControlRect(complexControl, &opt, subControl, widget);
       
   365     QToolTip::showText(helpEvent->globalPos(), toolTip, widget, rect);
       
   366 }
       
   367 #endif // QT_NO_TOOLTIP
       
   368 
       
   369 namespace QMdi {
       
   370 /*
       
   371     \class ControlLabel
       
   372     \internal
       
   373 */
       
   374 class ControlLabel : public QWidget
       
   375 {
       
   376     Q_OBJECT
       
   377 public:
       
   378     ControlLabel(QMdiSubWindow *subWindow, QWidget *parent = 0);
       
   379 
       
   380     QSize sizeHint() const;
       
   381 
       
   382 signals:
       
   383     void _q_clicked();
       
   384     void _q_doubleClicked();
       
   385 
       
   386 protected:
       
   387     bool event(QEvent *event);
       
   388     void paintEvent(QPaintEvent *paintEvent);
       
   389     void mousePressEvent(QMouseEvent *mouseEvent);
       
   390     void mouseDoubleClickEvent(QMouseEvent *mouseEvent);
       
   391     void mouseReleaseEvent(QMouseEvent *mouseEvent);
       
   392 
       
   393 private:
       
   394     QPixmap label;
       
   395     bool isPressed;
       
   396     void updateWindowIcon();
       
   397 };
       
   398 } // namespace QMdi
       
   399 
       
   400 ControlLabel::ControlLabel(QMdiSubWindow *subWindow, QWidget *parent)
       
   401     : QWidget(parent), isPressed(false)
       
   402 {
       
   403     Q_UNUSED(subWindow);
       
   404     setFocusPolicy(Qt::NoFocus);
       
   405     updateWindowIcon();
       
   406     setFixedSize(label.size());
       
   407 }
       
   408 
       
   409 /*
       
   410     \internal
       
   411 */
       
   412 QSize ControlLabel::sizeHint() const
       
   413 {
       
   414     return label.size();
       
   415 }
       
   416 
       
   417 /*
       
   418     \internal
       
   419 */
       
   420 bool ControlLabel::event(QEvent *event)
       
   421 {
       
   422     if (event->type() == QEvent::WindowIconChange)
       
   423         updateWindowIcon();
       
   424 #ifndef QT_NO_TOOLTIP
       
   425     else if (event->type() == QEvent::ToolTip) {
       
   426         QStyleOptionTitleBar options;
       
   427         options.initFrom(this);
       
   428         showToolTip(static_cast<QHelpEvent *>(event), this, options,
       
   429                     QStyle::CC_TitleBar, QStyle::SC_TitleBarSysMenu);
       
   430     }
       
   431 #endif
       
   432     return QWidget::event(event);
       
   433 }
       
   434 
       
   435 /*
       
   436     \internal
       
   437 */
       
   438 void ControlLabel::paintEvent(QPaintEvent * /*paintEvent*/)
       
   439 {
       
   440     QPainter painter(this);
       
   441     painter.drawPixmap(0, 0, label);
       
   442 }
       
   443 
       
   444 /*
       
   445     \internal
       
   446 */
       
   447 void ControlLabel::mousePressEvent(QMouseEvent *mouseEvent)
       
   448 {
       
   449     if (mouseEvent->button() != Qt::LeftButton) {
       
   450         mouseEvent->ignore();
       
   451         return;
       
   452     }
       
   453     isPressed = true;
       
   454 }
       
   455 
       
   456 /*
       
   457     \internal
       
   458 */
       
   459 void ControlLabel::mouseDoubleClickEvent(QMouseEvent *mouseEvent)
       
   460 {
       
   461     if (mouseEvent->button() != Qt::LeftButton) {
       
   462         mouseEvent->ignore();
       
   463         return;
       
   464     }
       
   465     isPressed = false;
       
   466     emit _q_doubleClicked();
       
   467 }
       
   468 
       
   469 /*
       
   470     \internal
       
   471 */
       
   472 void ControlLabel::mouseReleaseEvent(QMouseEvent *mouseEvent)
       
   473 {
       
   474     if (mouseEvent->button() != Qt::LeftButton) {
       
   475         mouseEvent->ignore();
       
   476         return;
       
   477     }
       
   478     if (isPressed) {
       
   479         isPressed = false;
       
   480         emit _q_clicked();
       
   481     }
       
   482 }
       
   483 
       
   484 /*
       
   485     \internal
       
   486 */
       
   487 void ControlLabel::updateWindowIcon()
       
   488 {
       
   489     QIcon menuIcon = windowIcon();
       
   490     if (menuIcon.isNull())
       
   491         menuIcon = style()->standardIcon(QStyle::SP_TitleBarMenuButton, 0, parentWidget());
       
   492     label = menuIcon.pixmap(16, 16);
       
   493     update();
       
   494 }
       
   495 
       
   496 namespace QMdi {
       
   497 /*
       
   498     \class ControllerWidget
       
   499     \internal
       
   500 */
       
   501 class ControllerWidget : public QWidget
       
   502 {
       
   503     Q_OBJECT
       
   504 public:
       
   505     ControllerWidget(QMdiSubWindow *subWindow, QWidget *parent = 0);
       
   506     QSize sizeHint() const;
       
   507     void setControlVisible(QMdiSubWindowPrivate::WindowStateAction action, bool visible);
       
   508     inline bool hasVisibleControls() const
       
   509     {
       
   510         return (visibleControls & QStyle::SC_MdiMinButton)
       
   511                || (visibleControls & QStyle::SC_MdiNormalButton)
       
   512                || (visibleControls & QStyle::SC_MdiCloseButton);
       
   513     }
       
   514 
       
   515 signals:
       
   516     void _q_minimize();
       
   517     void _q_restore();
       
   518     void _q_close();
       
   519 
       
   520 protected:
       
   521     void paintEvent(QPaintEvent *event);
       
   522     void mousePressEvent(QMouseEvent *event);
       
   523     void mouseReleaseEvent(QMouseEvent *event);
       
   524     void mouseMoveEvent(QMouseEvent *event);
       
   525     void leaveEvent(QEvent *event);
       
   526     bool event(QEvent *event);
       
   527 
       
   528 private:
       
   529     QStyle::SubControl activeControl;
       
   530     QStyle::SubControl hoverControl;
       
   531     QStyle::SubControls visibleControls;
       
   532     void initStyleOption(QStyleOptionComplex *option) const;
       
   533     QMdiArea *mdiArea;
       
   534     inline QStyle::SubControl getSubControl(const QPoint &pos) const
       
   535     {
       
   536         QStyleOptionComplex opt;
       
   537         initStyleOption(&opt);
       
   538         return style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt, pos, mdiArea);
       
   539     }
       
   540 };
       
   541 } // namespace QMdi
       
   542 
       
   543 /*
       
   544     \internal
       
   545 */
       
   546 ControllerWidget::ControllerWidget(QMdiSubWindow *subWindow, QWidget *parent)
       
   547     : QWidget(parent),
       
   548       activeControl(QStyle::SC_None),
       
   549       hoverControl(QStyle::SC_None),
       
   550       visibleControls(QStyle::SC_None),
       
   551       mdiArea(0)
       
   552 {
       
   553     if (subWindow->parentWidget())
       
   554         mdiArea = qobject_cast<QMdiArea *>(subWindow->parentWidget()->parentWidget());
       
   555     setFocusPolicy(Qt::NoFocus);
       
   556     setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
       
   557     setMouseTracking(true);
       
   558 }
       
   559 
       
   560 /*
       
   561     \internal
       
   562 */
       
   563 QSize ControllerWidget::sizeHint() const
       
   564 {
       
   565     ensurePolished();
       
   566     QStyleOptionComplex opt;
       
   567     initStyleOption(&opt);
       
   568     QSize size(48, 16);
       
   569     return style()->sizeFromContents(QStyle::CT_MdiControls, &opt, size, mdiArea);
       
   570 }
       
   571 
       
   572 void ControllerWidget::setControlVisible(QMdiSubWindowPrivate::WindowStateAction action, bool visible)
       
   573 {
       
   574     QStyle::SubControl subControl = QStyle::SC_None;
       
   575 
       
   576     // Map action from QMdiSubWindowPrivate::WindowStateAction to QStyle::SubControl.
       
   577     if (action == QMdiSubWindowPrivate::MaximizeAction)
       
   578         subControl = QStyle::SC_MdiNormalButton;
       
   579     else if (action == QMdiSubWindowPrivate::CloseAction)
       
   580         subControl = QStyle::SC_MdiCloseButton;
       
   581     else if (action == QMdiSubWindowPrivate::MinimizeAction)
       
   582         subControl = QStyle::SC_MdiMinButton;
       
   583 
       
   584     if (subControl == QStyle::SC_None)
       
   585         return;
       
   586 
       
   587     if (visible && !(visibleControls & subControl))
       
   588         visibleControls |= subControl;
       
   589     else if (!visible && (visibleControls & subControl))
       
   590         visibleControls &= ~subControl;
       
   591 }
       
   592 
       
   593 /*
       
   594     \internal
       
   595 */
       
   596 void ControllerWidget::paintEvent(QPaintEvent * /*paintEvent*/)
       
   597 {
       
   598     QStyleOptionComplex opt;
       
   599     initStyleOption(&opt);
       
   600     if (activeControl == hoverControl) {
       
   601         opt.activeSubControls = activeControl;
       
   602         opt.state |= QStyle::State_Sunken;
       
   603     } else if (hoverControl != QStyle::SC_None && (activeControl == QStyle::SC_None)) {
       
   604         opt.activeSubControls = hoverControl;
       
   605         opt.state |= QStyle::State_MouseOver;
       
   606     }
       
   607     QPainter painter(this);
       
   608     style()->drawComplexControl(QStyle::CC_MdiControls, &opt, &painter, mdiArea);
       
   609 }
       
   610 
       
   611 /*
       
   612     \internal
       
   613 */
       
   614 void ControllerWidget::mousePressEvent(QMouseEvent *event)
       
   615 {
       
   616     if (event->button() != Qt::LeftButton) {
       
   617         event->ignore();
       
   618         return;
       
   619     }
       
   620     activeControl = getSubControl(event->pos());
       
   621     update();
       
   622 }
       
   623 
       
   624 /*
       
   625     \internal
       
   626 */
       
   627 void ControllerWidget::mouseReleaseEvent(QMouseEvent *event)
       
   628 {
       
   629     if (event->button() != Qt::LeftButton) {
       
   630         event->ignore();
       
   631         return;
       
   632     }
       
   633 
       
   634     QStyle::SubControl under_mouse = getSubControl(event->pos());
       
   635     if (under_mouse == activeControl) {
       
   636         switch (activeControl) {
       
   637         case QStyle::SC_MdiCloseButton:
       
   638             emit _q_close();
       
   639             break;
       
   640         case QStyle::SC_MdiNormalButton:
       
   641             emit _q_restore();
       
   642             break;
       
   643         case QStyle::SC_MdiMinButton:
       
   644             emit _q_minimize();
       
   645             break;
       
   646         default:
       
   647             break;
       
   648         }
       
   649     }
       
   650 
       
   651     activeControl = QStyle::SC_None;
       
   652     update();
       
   653 }
       
   654 
       
   655 /*
       
   656     \internal
       
   657 */
       
   658 void ControllerWidget::mouseMoveEvent(QMouseEvent *event)
       
   659 {
       
   660     QStyle::SubControl under_mouse = getSubControl(event->pos());
       
   661     //test if hover state changes
       
   662     if (hoverControl != under_mouse) {
       
   663         hoverControl = under_mouse;
       
   664         update();
       
   665     }
       
   666 }
       
   667 
       
   668 /*
       
   669     \internal
       
   670 */
       
   671 void ControllerWidget::leaveEvent(QEvent * /*event*/)
       
   672 {
       
   673     hoverControl = QStyle::SC_None;
       
   674     update();
       
   675 }
       
   676 
       
   677 /*
       
   678     \internal
       
   679 */
       
   680 bool ControllerWidget::event(QEvent *event)
       
   681 {
       
   682 #ifndef QT_NO_TOOLTIP
       
   683     if (event->type() == QEvent::ToolTip) {
       
   684         QStyleOptionComplex opt;
       
   685         initStyleOption(&opt);
       
   686         QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
       
   687         showToolTip(helpEvent, this, opt, QStyle::CC_MdiControls, getSubControl(helpEvent->pos()));
       
   688     }
       
   689 #endif // QT_NO_TOOLTIP
       
   690     return QWidget::event(event);
       
   691 }
       
   692 
       
   693 /*
       
   694     \internal
       
   695 */
       
   696 void ControllerWidget::initStyleOption(QStyleOptionComplex *option) const
       
   697 {
       
   698     option->initFrom(this);
       
   699     option->subControls = visibleControls;
       
   700     option->activeSubControls = QStyle::SC_None;
       
   701 }
       
   702 
       
   703 /*
       
   704     \internal
       
   705 */
       
   706 ControlContainer::ControlContainer(QMdiSubWindow *mdiChild)
       
   707     : QObject(mdiChild),
       
   708       previousLeft(0),
       
   709       previousRight(0),
       
   710 #ifndef QT_NO_MENUBAR
       
   711       m_menuBar(0),
       
   712 #endif
       
   713       mdiChild(mdiChild)
       
   714 {
       
   715     Q_ASSERT(mdiChild);
       
   716 
       
   717     m_controllerWidget = new ControlElement<ControllerWidget>(mdiChild);
       
   718     connect(m_controllerWidget, SIGNAL(_q_close()), mdiChild, SLOT(close()));
       
   719     connect(m_controllerWidget, SIGNAL(_q_restore()), mdiChild, SLOT(showNormal()));
       
   720     connect(m_controllerWidget, SIGNAL(_q_minimize()), mdiChild, SLOT(showMinimized()));
       
   721 
       
   722     m_menuLabel = new ControlElement<ControlLabel>(mdiChild);
       
   723     m_menuLabel->setWindowIcon(mdiChild->windowIcon());
       
   724 #ifndef QT_NO_MENU
       
   725     connect(m_menuLabel, SIGNAL(_q_clicked()), mdiChild, SLOT(showSystemMenu()));
       
   726 #endif
       
   727     connect(m_menuLabel, SIGNAL(_q_doubleClicked()), mdiChild, SLOT(close()));
       
   728 }
       
   729 
       
   730 ControlContainer::~ControlContainer()
       
   731 {
       
   732 #ifndef QT_NO_MENUBAR
       
   733     removeButtonsFromMenuBar();
       
   734 #endif
       
   735     delete m_menuLabel;
       
   736     m_menuLabel = 0;
       
   737     delete m_controllerWidget;
       
   738     m_controllerWidget = 0;
       
   739 }
       
   740 
       
   741 #ifndef QT_NO_MENUBAR
       
   742 /*
       
   743     \internal
       
   744 */
       
   745 QMenuBar *QMdiSubWindowPrivate::menuBar() const
       
   746 {
       
   747 #if defined(QT_NO_MAINWINDOW)
       
   748     return 0;
       
   749 #else
       
   750     Q_Q(const QMdiSubWindow);
       
   751     if (!q->isMaximized() || drawTitleBarWhenMaximized() || isChildOfTabbedQMdiArea(q))
       
   752         return 0;
       
   753 
       
   754     if (QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q->window()))
       
   755         return mainWindow->menuBar();
       
   756 
       
   757     return 0;
       
   758 #endif
       
   759 }
       
   760 
       
   761 /*
       
   762     \internal
       
   763 */
       
   764 void ControlContainer::showButtonsInMenuBar(QMenuBar *menuBar)
       
   765 {
       
   766     if (!menuBar || !mdiChild || mdiChild->windowFlags() & Qt::FramelessWindowHint)
       
   767         return;
       
   768     m_menuBar = menuBar;
       
   769 
       
   770     if (m_menuLabel && mdiChild->windowFlags() & Qt::WindowSystemMenuHint) {
       
   771         QWidget *currentLeft = menuBar->cornerWidget(Qt::TopLeftCorner);
       
   772         if (currentLeft)
       
   773             currentLeft->hide();
       
   774         if (currentLeft != m_menuLabel) {
       
   775             menuBar->setCornerWidget(m_menuLabel, Qt::TopLeftCorner);
       
   776             previousLeft = currentLeft;
       
   777         }
       
   778         m_menuLabel->show();
       
   779     }
       
   780     ControllerWidget *controllerWidget = qobject_cast<ControllerWidget *>(m_controllerWidget);
       
   781     if (controllerWidget && controllerWidget->hasVisibleControls()) {
       
   782         QWidget *currentRight = menuBar->cornerWidget(Qt::TopRightCorner);
       
   783         if (currentRight)
       
   784             currentRight->hide();
       
   785         if (currentRight != m_controllerWidget) {
       
   786             menuBar->setCornerWidget(m_controllerWidget, Qt::TopRightCorner);
       
   787             previousRight = currentRight;
       
   788         }
       
   789         m_controllerWidget->show();
       
   790     }
       
   791     mdiChild->d_func()->setNewWindowTitle();
       
   792 }
       
   793 
       
   794 /*
       
   795     \internal
       
   796 */
       
   797 void ControlContainer::removeButtonsFromMenuBar(QMenuBar *menuBar)
       
   798 {
       
   799     if (menuBar && menuBar != m_menuBar) {
       
   800         // m_menubar was deleted while sub-window was maximized
       
   801         previousRight = 0;
       
   802         previousLeft = 0;
       
   803         m_menuBar = menuBar;
       
   804     }
       
   805 
       
   806     if (!m_menuBar || !mdiChild || qt_widget_private(mdiChild->window())->data.in_destructor)
       
   807         return;
       
   808 
       
   809     QMdiSubWindow *child = 0;
       
   810     if (m_controllerWidget) {
       
   811         QWidget *currentRight = m_menuBar->cornerWidget(Qt::TopRightCorner);
       
   812         if (currentRight == m_controllerWidget) {
       
   813             if (ControlElement<ControllerWidget> *ce = ptr<ControllerWidget>(previousRight)) {
       
   814                 if (!ce->mdiChild || !ce->mdiChild->isMaximized())
       
   815                     previousRight = 0;
       
   816                 else
       
   817                     child = ce->mdiChild;
       
   818             }
       
   819             m_menuBar->setCornerWidget(previousRight, Qt::TopRightCorner);
       
   820             if (previousRight) {
       
   821                 previousRight->show();
       
   822                 previousRight = 0;
       
   823             }
       
   824         }
       
   825         m_controllerWidget->hide();
       
   826         m_controllerWidget->setParent(0);
       
   827     }
       
   828     if (m_menuLabel) {
       
   829         QWidget *currentLeft = m_menuBar->cornerWidget(Qt::TopLeftCorner);
       
   830         if (currentLeft == m_menuLabel) {
       
   831             if (ControlElement<ControlLabel> *ce = ptr<ControlLabel>(previousLeft)) {
       
   832                 if (!ce->mdiChild || !ce->mdiChild->isMaximized())
       
   833                     previousLeft = 0;
       
   834                 else if (!child)
       
   835                     child = mdiChild;
       
   836             }
       
   837             m_menuBar->setCornerWidget(previousLeft, Qt::TopLeftCorner);
       
   838             if (previousLeft) {
       
   839                 previousLeft->show();
       
   840                 previousLeft = 0;
       
   841             }
       
   842         }
       
   843         m_menuLabel->hide();
       
   844         m_menuLabel->setParent(0);
       
   845     }
       
   846     m_menuBar->update();
       
   847     if (child)
       
   848         child->d_func()->setNewWindowTitle();
       
   849     else if (mdiChild)
       
   850         mdiChild->window()->setWindowTitle(mdiChild->d_func()->originalWindowTitle());
       
   851 }
       
   852 
       
   853 #endif // QT_NO_MENUBAR
       
   854 
       
   855 void ControlContainer::updateWindowIcon(const QIcon &windowIcon)
       
   856 {
       
   857     if (m_menuLabel)
       
   858         m_menuLabel->setWindowIcon(windowIcon);
       
   859 }
       
   860 
       
   861 /*!
       
   862     \internal
       
   863 */
       
   864 QMdiSubWindowPrivate::QMdiSubWindowPrivate()
       
   865     : baseWidget(0),
       
   866       restoreFocusWidget(0),
       
   867       controlContainer(0),
       
   868 #ifndef QT_NO_SIZEGRIP
       
   869       sizeGrip(0),
       
   870 #endif
       
   871 #ifndef QT_NO_RUBBERBAND
       
   872       rubberBand(0),
       
   873 #endif
       
   874       userMinimumSize(0,0),
       
   875       resizeEnabled(true),
       
   876       moveEnabled(true),
       
   877       isInInteractiveMode(false),
       
   878 #ifndef QT_NO_RUBBERBAND
       
   879       isInRubberBandMode(false),
       
   880 #endif
       
   881       isShadeMode(false),
       
   882       ignoreWindowTitleChange(false),
       
   883       ignoreNextActivationEvent(false),
       
   884       activationEnabled(true),
       
   885       isShadeRequestFromMinimizeMode(false),
       
   886       isMaximizeMode(false),
       
   887       isWidgetHiddenByUs(false),
       
   888       isActive(false),
       
   889       isExplicitlyDeactivated(false),
       
   890       keyboardSingleStep(5),
       
   891       keyboardPageStep(20),
       
   892       resizeTimerId(-1),
       
   893       currentOperation(None),
       
   894       hoveredSubControl(QStyle::SC_None),
       
   895       activeSubControl(QStyle::SC_None),
       
   896       focusInReason(Qt::ActiveWindowFocusReason)
       
   897 {
       
   898     initOperationMap();
       
   899 }
       
   900 
       
   901 /*!
       
   902     \internal
       
   903 */
       
   904 void QMdiSubWindowPrivate::_q_updateStaysOnTopHint()
       
   905 {
       
   906 #ifndef QT_NO_ACTION
       
   907     Q_Q(QMdiSubWindow);
       
   908     if (QAction *senderAction = qobject_cast<QAction *>(q->sender())) {
       
   909         if (senderAction->isChecked()) {
       
   910             q->setWindowFlags(q->windowFlags() | Qt::WindowStaysOnTopHint);
       
   911             q->raise();
       
   912         } else {
       
   913             q->setWindowFlags(q->windowFlags() & ~Qt::WindowStaysOnTopHint);
       
   914             q->lower();
       
   915         }
       
   916     }
       
   917 #endif // QT_NO_ACTION
       
   918 }
       
   919 
       
   920 /*!
       
   921     \internal
       
   922 */
       
   923 void QMdiSubWindowPrivate::_q_enterInteractiveMode()
       
   924 {
       
   925 #ifndef QT_NO_ACTION
       
   926     Q_Q(QMdiSubWindow);
       
   927     QAction *action = qobject_cast<QAction *>(q->sender());
       
   928     if (!action)
       
   929         return;
       
   930 
       
   931     QPoint pressPos;
       
   932     if (actions[MoveAction] && actions[MoveAction] == action) {
       
   933         currentOperation = Move;
       
   934         pressPos = QPoint(q->width() / 2, titleBarHeight() - 1);
       
   935     } else if (actions[ResizeAction] && actions[ResizeAction] == action) {
       
   936         currentOperation = q->isLeftToRight() ? BottomRightResize : BottomLeftResize;
       
   937         int offset = q->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, q) / 2;
       
   938         int x = q->isLeftToRight() ? q->width() - offset : offset;
       
   939         pressPos = QPoint(x, q->height() - offset);
       
   940     } else {
       
   941         return;
       
   942     }
       
   943 
       
   944     updateCursor();
       
   945 #ifndef QT_NO_CURSOR
       
   946     q->cursor().setPos(q->mapToGlobal(pressPos));
       
   947 #endif
       
   948     mousePressPosition = q->mapToParent(pressPos);
       
   949     oldGeometry = q->geometry();
       
   950     isInInteractiveMode = true;
       
   951     q->setFocus();
       
   952 #ifndef QT_NO_RUBBERBAND
       
   953     if ((q->testOption(QMdiSubWindow::RubberBandResize)
       
   954             && (currentOperation == BottomRightResize || currentOperation == BottomLeftResize))
       
   955             || (q->testOption(QMdiSubWindow::RubberBandMove) && currentOperation == Move)) {
       
   956         enterRubberBandMode();
       
   957     } else
       
   958 #endif // QT_NO_RUBBERBAND
       
   959     {
       
   960         q->grabMouse();
       
   961     }
       
   962 #endif // QT_NO_ACTION
       
   963 }
       
   964 
       
   965 /*!
       
   966     \internal
       
   967 */
       
   968 void QMdiSubWindowPrivate::_q_processFocusChanged(QWidget *old, QWidget *now)
       
   969 {
       
   970     Q_UNUSED(old);
       
   971     Q_Q(QMdiSubWindow);
       
   972     if (now && (now == q || q->isAncestorOf(now))) {
       
   973         if (now == q && !isInInteractiveMode)
       
   974             setFocusWidget();
       
   975         setActive(true);
       
   976     }
       
   977 }
       
   978 
       
   979 /*!
       
   980     \internal
       
   981 */
       
   982 void QMdiSubWindowPrivate::leaveInteractiveMode()
       
   983 {
       
   984     Q_Q(QMdiSubWindow);
       
   985 #ifndef QT_NO_RUBBERBAND
       
   986     if (isInRubberBandMode)
       
   987         leaveRubberBandMode();
       
   988     else
       
   989 #endif
       
   990         q->releaseMouse();
       
   991     isInInteractiveMode = false;
       
   992     currentOperation = None;
       
   993     updateDirtyRegions();
       
   994     updateCursor();
       
   995     if (baseWidget && baseWidget->focusWidget())
       
   996         baseWidget->focusWidget()->setFocus();
       
   997 }
       
   998 
       
   999 /*!
       
  1000     \internal
       
  1001 */
       
  1002 void QMdiSubWindowPrivate::removeBaseWidget()
       
  1003 {
       
  1004     if (!baseWidget)
       
  1005         return;
       
  1006 
       
  1007     Q_Q(QMdiSubWindow);
       
  1008     baseWidget->removeEventFilter(q);
       
  1009     if (layout)
       
  1010         layout->removeWidget(baseWidget);
       
  1011     if (baseWidget->windowTitle() == q->windowTitle()) {
       
  1012         ignoreWindowTitleChange = true;
       
  1013         q->setWindowTitle(QString());
       
  1014         ignoreWindowTitleChange = false;
       
  1015         q->setWindowModified(false);
       
  1016     }
       
  1017     lastChildWindowTitle.clear();
       
  1018     baseWidget->setParent(0);
       
  1019     baseWidget = 0;
       
  1020     isWidgetHiddenByUs = false;
       
  1021 }
       
  1022 
       
  1023 /*!
       
  1024     \internal
       
  1025 */
       
  1026 void QMdiSubWindowPrivate::initOperationMap()
       
  1027 {
       
  1028     operationMap.insert(Move, OperationInfo(HMove | VMove, Qt::ArrowCursor, false));
       
  1029     operationMap.insert(TopResize, OperationInfo(VMove | VResize | VResizeReverse, Qt::SizeVerCursor));
       
  1030     operationMap.insert(BottomResize, OperationInfo(VResize, Qt::SizeVerCursor));
       
  1031     operationMap.insert(LeftResize, OperationInfo(HMove | HResize | HResizeReverse, Qt::SizeHorCursor));
       
  1032     operationMap.insert(RightResize, OperationInfo(HResize, Qt::SizeHorCursor));
       
  1033     operationMap.insert(TopLeftResize, OperationInfo(HMove | VMove | HResize | VResize | VResizeReverse
       
  1034                                                      | HResizeReverse, Qt::SizeFDiagCursor));
       
  1035     operationMap.insert(TopRightResize, OperationInfo(VMove | HResize | VResize
       
  1036                                                       | VResizeReverse, Qt::SizeBDiagCursor));
       
  1037     operationMap.insert(BottomLeftResize, OperationInfo(HMove | HResize | VResize | HResizeReverse,
       
  1038                                                         Qt::SizeBDiagCursor));
       
  1039     operationMap.insert(BottomRightResize, OperationInfo(HResize | VResize, Qt::SizeFDiagCursor));
       
  1040 }
       
  1041 
       
  1042 #ifndef QT_NO_MENU
       
  1043 
       
  1044 /*!
       
  1045     \internal
       
  1046 */
       
  1047 void QMdiSubWindowPrivate::createSystemMenu()
       
  1048 {
       
  1049     Q_Q(QMdiSubWindow);
       
  1050     Q_ASSERT_X(q, "QMdiSubWindowPrivate::createSystemMenu",
       
  1051                "You can NOT call this function before QMdiSubWindow's ctor");
       
  1052     systemMenu = new QMenu(q);
       
  1053     const QStyle *style = q->style();
       
  1054     addToSystemMenu(RestoreAction, QMdiSubWindow::tr("&Restore"), SLOT(showNormal()));
       
  1055     actions[RestoreAction]->setIcon(style->standardIcon(QStyle::SP_TitleBarNormalButton, 0, q));
       
  1056     actions[RestoreAction]->setEnabled(false);
       
  1057     addToSystemMenu(MoveAction, QMdiSubWindow::tr("&Move"), SLOT(_q_enterInteractiveMode()));
       
  1058     addToSystemMenu(ResizeAction, QMdiSubWindow::tr("&Size"), SLOT(_q_enterInteractiveMode()));
       
  1059     addToSystemMenu(MinimizeAction, QMdiSubWindow::tr("Mi&nimize"), SLOT(showMinimized()));
       
  1060     actions[MinimizeAction]->setIcon(style->standardIcon(QStyle::SP_TitleBarMinButton, 0, q));
       
  1061     addToSystemMenu(MaximizeAction, QMdiSubWindow::tr("Ma&ximize"), SLOT(showMaximized()));
       
  1062     actions[MaximizeAction]->setIcon(style->standardIcon(QStyle::SP_TitleBarMaxButton, 0, q));
       
  1063     addToSystemMenu(StayOnTopAction, QMdiSubWindow::tr("Stay on &Top"), SLOT(_q_updateStaysOnTopHint()));
       
  1064     actions[StayOnTopAction]->setCheckable(true);
       
  1065     systemMenu->addSeparator();
       
  1066     addToSystemMenu(CloseAction, QMdiSubWindow::tr("&Close"), SLOT(close()));
       
  1067     actions[CloseAction]->setIcon(style->standardIcon(QStyle::SP_TitleBarCloseButton, 0, q));
       
  1068 #if !defined(QT_NO_SHORTCUT)
       
  1069     actions[CloseAction]->setShortcuts(QKeySequence::Close);
       
  1070 #endif
       
  1071     updateActions();
       
  1072 }
       
  1073 #endif
       
  1074 
       
  1075 /*!
       
  1076     \internal
       
  1077 */
       
  1078 void QMdiSubWindowPrivate::updateCursor()
       
  1079 {
       
  1080 #ifndef QT_NO_CURSOR
       
  1081     Q_Q(QMdiSubWindow);
       
  1082 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
  1083     if (qobject_cast<QMacStyle *>(q->style()))
       
  1084         return;
       
  1085 #endif
       
  1086 
       
  1087     if (currentOperation == None) {
       
  1088         q->unsetCursor();
       
  1089         return;
       
  1090     }
       
  1091 
       
  1092     if (currentOperation == Move || operationMap.find(currentOperation).value().hover) {
       
  1093         q->setCursor(operationMap.find(currentOperation).value().cursorShape);
       
  1094         return;
       
  1095     }
       
  1096 #endif
       
  1097 }
       
  1098 
       
  1099 /*!
       
  1100     \internal
       
  1101 */
       
  1102 void QMdiSubWindowPrivate::updateDirtyRegions()
       
  1103 {
       
  1104     // No update necessary
       
  1105     if (!parent)
       
  1106         return;
       
  1107 
       
  1108     foreach (Operation operation, operationMap.keys())
       
  1109         operationMap.find(operation).value().region = getRegion(operation);
       
  1110 }
       
  1111 
       
  1112 /*!
       
  1113     \internal
       
  1114 */
       
  1115 void QMdiSubWindowPrivate::updateGeometryConstraints()
       
  1116 {
       
  1117     Q_Q(QMdiSubWindow);
       
  1118     if (!parent)
       
  1119         return;
       
  1120 
       
  1121     internalMinimumSize = (!q->isMinimized() && !q->minimumSize().isNull())
       
  1122                           ? q->minimumSize() : q->minimumSizeHint();
       
  1123     int margin, minWidth;
       
  1124     sizeParameters(&margin, &minWidth);
       
  1125     q->setContentsMargins(margin, titleBarHeight(), margin, margin);
       
  1126     if (q->isMaximized() || (q->isMinimized() && !q->isShaded())) {
       
  1127         moveEnabled = false;
       
  1128         resizeEnabled = false;
       
  1129     } else {
       
  1130         moveEnabled = true;
       
  1131         if ((q->windowFlags() & Qt::MSWindowsFixedSizeDialogHint) || q->isShaded())
       
  1132             resizeEnabled = false;
       
  1133         else
       
  1134             resizeEnabled = true;
       
  1135     }
       
  1136     updateDirtyRegions();
       
  1137 }
       
  1138 
       
  1139 /*!
       
  1140     \internal
       
  1141 */
       
  1142 void QMdiSubWindowPrivate::updateMask()
       
  1143 {
       
  1144     Q_Q(QMdiSubWindow);
       
  1145     if (!q->mask().isEmpty())
       
  1146         q->clearMask();
       
  1147 
       
  1148     if (!parent)
       
  1149         return;
       
  1150 
       
  1151     if ((q->isMaximized() && !drawTitleBarWhenMaximized())
       
  1152         || q->windowFlags() & Qt::FramelessWindowHint)
       
  1153         return;
       
  1154 
       
  1155     if (resizeTimerId == -1)
       
  1156         cachedStyleOptions = titleBarOptions();
       
  1157     cachedStyleOptions.rect = q->rect();
       
  1158     QStyleHintReturnMask frameMask;
       
  1159     q->style()->styleHint(QStyle::SH_WindowFrame_Mask, &cachedStyleOptions, q, &frameMask);
       
  1160     if (!frameMask.region.isEmpty())
       
  1161         q->setMask(frameMask.region);
       
  1162 }
       
  1163 
       
  1164 /*!
       
  1165     \internal
       
  1166 */
       
  1167 void QMdiSubWindowPrivate::setNewGeometry(const QPoint &pos)
       
  1168 {
       
  1169     Q_Q(QMdiSubWindow);
       
  1170     Q_ASSERT(currentOperation != None);
       
  1171     Q_ASSERT(parent);
       
  1172 
       
  1173     uint cflags = operationMap.find(currentOperation).value().changeFlags;
       
  1174     int posX = pos.x();
       
  1175     int posY = pos.y();
       
  1176 
       
  1177     const bool restrictHorizontal = !q->testOption(QMdiSubWindow::AllowOutsideAreaHorizontally);
       
  1178     const bool restrictVertical = !q->testOption(QMdiSubWindow::AllowOutsideAreaVertically);
       
  1179 
       
  1180     if (restrictHorizontal || restrictVertical) {
       
  1181         QRect parentRect = q->parentWidget()->rect();
       
  1182         if (restrictVertical && (cflags & VResizeReverse || currentOperation == Move)) {
       
  1183             posY = qMin(qMax(mousePressPosition.y() - oldGeometry.y(), posY),
       
  1184                         parentRect.height() - BoundaryMargin);
       
  1185         }
       
  1186         if (currentOperation == Move) {
       
  1187             if (restrictHorizontal)
       
  1188                 posX = qMin(qMax(BoundaryMargin, posX), parentRect.width() - BoundaryMargin);
       
  1189             if (restrictVertical)
       
  1190                 posY = qMin(posY, parentRect.height() - BoundaryMargin);
       
  1191         } else {
       
  1192             if (restrictHorizontal) {
       
  1193                 if (cflags & HResizeReverse)
       
  1194                     posX = qMax(mousePressPosition.x() - oldGeometry.x(), posX);
       
  1195                 else
       
  1196                     posX = qMin(parentRect.width() - (oldGeometry.x() + oldGeometry.width()
       
  1197                                                       - mousePressPosition.x()), posX);
       
  1198             }
       
  1199             if (restrictVertical && !(cflags & VResizeReverse)) {
       
  1200                 posY = qMin(parentRect.height() - (oldGeometry.y() + oldGeometry.height()
       
  1201                                                    - mousePressPosition.y()), posY);
       
  1202             }
       
  1203         }
       
  1204     }
       
  1205 
       
  1206     QRect geometry;
       
  1207     if (cflags & (HMove | VMove)) {
       
  1208         int dx = getMoveDeltaComponent(cflags, HMove, HResize, posX - mousePressPosition.x(),
       
  1209                                        oldGeometry.width() - internalMinimumSize.width(),
       
  1210                                        oldGeometry.width() - q->maximumWidth());
       
  1211         int dy = getMoveDeltaComponent(cflags, VMove, VResize, posY - mousePressPosition.y(),
       
  1212                                        oldGeometry.height() - internalMinimumSize.height(),
       
  1213                                        oldGeometry.height() - q->maximumHeight());
       
  1214         geometry.setTopLeft(oldGeometry.topLeft() + QPoint(dx, dy));
       
  1215     } else {
       
  1216         geometry.setTopLeft(q->geometry().topLeft());
       
  1217     }
       
  1218 
       
  1219     if (cflags & (HResize | VResize)) {
       
  1220         int dx = getResizeDeltaComponent(cflags, HResize, HResizeReverse,
       
  1221                                          posX - mousePressPosition.x());
       
  1222         int dy = getResizeDeltaComponent(cflags, VResize, VResizeReverse,
       
  1223                                          posY - mousePressPosition.y());
       
  1224         geometry.setSize(oldGeometry.size() + QSize(dx, dy));
       
  1225     } else {
       
  1226         geometry.setSize(q->geometry().size());
       
  1227     }
       
  1228 
       
  1229     setNewGeometry(&geometry);
       
  1230 }
       
  1231 
       
  1232 /*!
       
  1233     \internal
       
  1234 */
       
  1235 void QMdiSubWindowPrivate::setMinimizeMode()
       
  1236 {
       
  1237     Q_Q(QMdiSubWindow);
       
  1238     Q_ASSERT(parent);
       
  1239 
       
  1240     ensureWindowState(Qt::WindowMinimized);
       
  1241     isShadeRequestFromMinimizeMode = true;
       
  1242     q->showShaded();
       
  1243     isShadeRequestFromMinimizeMode = false;
       
  1244 
       
  1245     moveEnabled = false;
       
  1246 #ifndef QT_NO_ACTION
       
  1247     setEnabled(MoveAction, moveEnabled);
       
  1248 #endif
       
  1249 
       
  1250     Q_ASSERT(q->windowState() & Qt::WindowMinimized);
       
  1251     Q_ASSERT(!(q->windowState() & Qt::WindowMaximized));
       
  1252     // This should be a valid assert, but people can actually re-implement
       
  1253     // setVisible and do crazy stuff, so we're not guaranteed that
       
  1254     // the widget is hidden after calling hide().
       
  1255     // Q_ASSERT(baseWidget ? baseWidget->isHidden() : true);
       
  1256 
       
  1257     setActive(true);
       
  1258 }
       
  1259 
       
  1260 /*!
       
  1261     \internal
       
  1262 */
       
  1263 void QMdiSubWindowPrivate::setNormalMode()
       
  1264 {
       
  1265     Q_Q(QMdiSubWindow);
       
  1266     Q_ASSERT(parent);
       
  1267 
       
  1268     isShadeMode = false;
       
  1269     isMaximizeMode = false;
       
  1270 
       
  1271     ensureWindowState(Qt::WindowNoState);
       
  1272 #ifndef QT_NO_MENUBAR
       
  1273     removeButtonsFromMenuBar();
       
  1274 #endif
       
  1275 
       
  1276     // Hide the window before we change the geometry to avoid multiple resize
       
  1277     // events and wrong window state.
       
  1278     const bool wasVisible = q->isVisible();
       
  1279     if (wasVisible)
       
  1280         q->setVisible(false);
       
  1281 
       
  1282     // Restore minimum size if set by user.
       
  1283     if (!userMinimumSize.isNull()) {
       
  1284         q->setMinimumSize(userMinimumSize);
       
  1285         userMinimumSize = QSize(0, 0);
       
  1286     }
       
  1287 
       
  1288     // Show the internal widget if it was hidden by us,
       
  1289     if (baseWidget && isWidgetHiddenByUs) {
       
  1290         baseWidget->show();
       
  1291         isWidgetHiddenByUs = false;
       
  1292     }
       
  1293 
       
  1294     updateGeometryConstraints();
       
  1295     QRect newGeometry = oldGeometry;
       
  1296     newGeometry.setSize(restoreSize.expandedTo(internalMinimumSize));
       
  1297     q->setGeometry(newGeometry);
       
  1298 
       
  1299     if (wasVisible)
       
  1300         q->setVisible(true);
       
  1301 
       
  1302     // Invalidate the restore size.
       
  1303     restoreSize.setWidth(-1);
       
  1304     restoreSize.setHeight(-1);
       
  1305 
       
  1306 #ifndef QT_NO_SIZEGRIP
       
  1307     setSizeGripVisible(true);
       
  1308 #endif
       
  1309 
       
  1310 #ifndef QT_NO_ACTION
       
  1311     setEnabled(MoveAction, true);
       
  1312     setEnabled(MaximizeAction, true);
       
  1313     setEnabled(MinimizeAction, true);
       
  1314     setEnabled(RestoreAction, false);
       
  1315     setEnabled(ResizeAction, resizeEnabled);
       
  1316 #endif // QT_NO_ACTION
       
  1317 
       
  1318     Q_ASSERT(!(q_func()->windowState() & Qt::WindowMinimized));
       
  1319     // This sub-window can be maximized when shown above if not the
       
  1320     // QMdiArea::DontMaximizeSubWindowOnActionvation is set. Make sure
       
  1321     // the Qt::WindowMaximized flag is set accordingly.
       
  1322     Q_ASSERT((isMaximizeMode && q_func()->windowState() & Qt::WindowMaximized)
       
  1323              || (!isMaximizeMode && !(q_func()->windowState() & Qt::WindowMaximized)));
       
  1324     Q_ASSERT(!isShadeMode);
       
  1325 
       
  1326     setActive(true);
       
  1327     restoreFocus();
       
  1328     updateMask();
       
  1329 }
       
  1330 
       
  1331 /*!
       
  1332     \internal
       
  1333 */
       
  1334 void QMdiSubWindowPrivate::setMaximizeMode()
       
  1335 {
       
  1336     Q_Q(QMdiSubWindow);
       
  1337     Q_ASSERT(parent);
       
  1338 
       
  1339     ensureWindowState(Qt::WindowMaximized);
       
  1340     isShadeMode = false;
       
  1341     isMaximizeMode = true;
       
  1342 
       
  1343     if (!restoreFocusWidget && q->isAncestorOf(QApplication::focusWidget()))
       
  1344         restoreFocusWidget = QApplication::focusWidget();
       
  1345 
       
  1346 #ifndef QT_NO_SIZEGRIP
       
  1347     setSizeGripVisible(false);
       
  1348 #endif
       
  1349 
       
  1350     // Store old geometry and set restore size if not already set.
       
  1351     if (!restoreSize.isValid()) {
       
  1352         oldGeometry = q->geometry();
       
  1353         restoreSize.setWidth(oldGeometry.width());
       
  1354         restoreSize.setHeight(oldGeometry.height());
       
  1355     }
       
  1356 
       
  1357     // Hide the window before we change the geometry to avoid multiple resize
       
  1358     // events and wrong window state.
       
  1359     const bool wasVisible = q->isVisible();
       
  1360     if (wasVisible)
       
  1361         q->setVisible(false);
       
  1362 
       
  1363     // Show the internal widget if it was hidden by us.
       
  1364     if (baseWidget && isWidgetHiddenByUs) {
       
  1365         baseWidget->show();
       
  1366         isWidgetHiddenByUs = false;
       
  1367     }
       
  1368 
       
  1369     updateGeometryConstraints();
       
  1370 
       
  1371     if (wasVisible) {
       
  1372 #ifndef QT_NO_MENUBAR
       
  1373         if (QMenuBar *mBar = menuBar())
       
  1374             showButtonsInMenuBar(mBar);
       
  1375         else
       
  1376 #endif
       
  1377         if (!controlContainer)
       
  1378             controlContainer = new ControlContainer(q);
       
  1379     }
       
  1380 
       
  1381     QWidget *parent = q->parentWidget();
       
  1382     QRect availableRect = parent->contentsRect();
       
  1383 
       
  1384     // Adjust geometry if the sub-window is inside a scroll area.
       
  1385     QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent->parentWidget());
       
  1386     if (scrollArea && scrollArea->viewport() == parent) {
       
  1387         QScrollBar *hbar = scrollArea->horizontalScrollBar();
       
  1388         QScrollBar *vbar = scrollArea->verticalScrollBar();
       
  1389         const int xOffset = hbar ? hbar->value() : 0;
       
  1390         const int yOffset = vbar ? vbar->value() : 0;
       
  1391         availableRect.adjust(-xOffset, -yOffset, -xOffset, -yOffset);
       
  1392         oldGeometry.adjust(xOffset, yOffset, xOffset, yOffset);
       
  1393     }
       
  1394 
       
  1395     setNewGeometry(&availableRect);
       
  1396     // QWidget::setGeometry will reset Qt::WindowMaximized so we have to update it here.
       
  1397     ensureWindowState(Qt::WindowMaximized);
       
  1398 
       
  1399     if (wasVisible)
       
  1400         q->setVisible(true);
       
  1401 
       
  1402     resizeEnabled = false;
       
  1403     moveEnabled = false;
       
  1404 
       
  1405 #ifndef QT_NO_ACTION
       
  1406     setEnabled(MoveAction, moveEnabled);
       
  1407     setEnabled(MaximizeAction, false);
       
  1408     setEnabled(MinimizeAction, true);
       
  1409     setEnabled(RestoreAction, true);
       
  1410     setEnabled(ResizeAction, resizeEnabled);
       
  1411 #endif // QT_NO_ACTION
       
  1412 
       
  1413     Q_ASSERT(q->windowState() & Qt::WindowMaximized);
       
  1414     Q_ASSERT(!(q->windowState() & Qt::WindowMinimized));
       
  1415 
       
  1416     restoreFocus();
       
  1417     updateMask();
       
  1418 }
       
  1419 
       
  1420 /*!
       
  1421     \internal
       
  1422 */
       
  1423 void QMdiSubWindowPrivate::setActive(bool activate, bool changeFocus)
       
  1424 {
       
  1425     Q_Q(QMdiSubWindow);
       
  1426     if (!parent || !activationEnabled)
       
  1427         return;
       
  1428 
       
  1429     if (activate && !isActive && q->isEnabled()) {
       
  1430         isActive = true;
       
  1431         isExplicitlyDeactivated = false;
       
  1432         Qt::WindowStates oldWindowState = q->windowState();
       
  1433         ensureWindowState(Qt::WindowActive);
       
  1434         emit q->aboutToActivate();
       
  1435 #ifndef QT_NO_MENUBAR
       
  1436         if (QMenuBar *mBar = menuBar())
       
  1437             showButtonsInMenuBar(mBar);
       
  1438 #endif
       
  1439         Q_ASSERT(isActive);
       
  1440         emit q->windowStateChanged(oldWindowState, q->windowState());
       
  1441     } else if (!activate && isActive) {
       
  1442         isActive = false;
       
  1443         Qt::WindowStates oldWindowState = q->windowState();
       
  1444         q->overrideWindowState(q->windowState() & ~Qt::WindowActive);
       
  1445         if (changeFocus) {
       
  1446             QWidget *focusWidget = QApplication::focusWidget();
       
  1447             if (focusWidget && (focusWidget == q || q->isAncestorOf(focusWidget)))
       
  1448                 focusWidget->clearFocus();
       
  1449         }
       
  1450         if (baseWidget)
       
  1451             baseWidget->overrideWindowState(baseWidget->windowState() & ~Qt::WindowActive);
       
  1452         Q_ASSERT(!isActive);
       
  1453         emit q->windowStateChanged(oldWindowState, q->windowState());
       
  1454     }
       
  1455 
       
  1456     if (activate && isActive && q->isEnabled() && !q->hasFocus()
       
  1457             && !q->isAncestorOf(QApplication::focusWidget())) {
       
  1458         if (changeFocus)
       
  1459             setFocusWidget();
       
  1460         ensureWindowState(Qt::WindowActive);
       
  1461     }
       
  1462 
       
  1463     int frameWidth = q->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, q);
       
  1464     int titleBarHeight = this->titleBarHeight();
       
  1465     QRegion windowDecoration = QRegion(0, 0, q->width(), q->height());
       
  1466     windowDecoration -= QRegion(frameWidth, titleBarHeight, q->width() - 2 * frameWidth,
       
  1467                                 q->height() - titleBarHeight - frameWidth);
       
  1468 
       
  1469     // Make sure we don't use cached style options if we get
       
  1470     // resize events right before activation/deactivation.
       
  1471     if (resizeTimerId != -1) {
       
  1472         q->killTimer(resizeTimerId);
       
  1473         resizeTimerId = -1;
       
  1474         updateDirtyRegions();
       
  1475     }
       
  1476 
       
  1477     q->update(windowDecoration);
       
  1478 }
       
  1479 
       
  1480 /*!
       
  1481     \internal
       
  1482 */
       
  1483 void QMdiSubWindowPrivate::processClickedSubControl()
       
  1484 {
       
  1485     Q_Q(QMdiSubWindow);
       
  1486     switch (activeSubControl) {
       
  1487     case QStyle::SC_TitleBarContextHelpButton:
       
  1488 #ifndef QT_NO_WHATSTHIS
       
  1489         QWhatsThis::enterWhatsThisMode();
       
  1490 #endif
       
  1491         break;
       
  1492     case QStyle::SC_TitleBarShadeButton:
       
  1493         q->showShaded();
       
  1494         hoveredSubControl = QStyle::SC_TitleBarUnshadeButton;
       
  1495         break;
       
  1496     case QStyle::SC_TitleBarUnshadeButton:
       
  1497         if (q->isShaded())
       
  1498             hoveredSubControl = QStyle::SC_TitleBarShadeButton;
       
  1499         q->showNormal();
       
  1500         break;
       
  1501     case QStyle::SC_TitleBarMinButton:
       
  1502 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
  1503         if (qobject_cast<QMacStyle *>(q->style())) {
       
  1504             if (q->isMinimized())
       
  1505                 q->showNormal();
       
  1506             else
       
  1507                 q->showMinimized();
       
  1508             break;
       
  1509         }
       
  1510 #endif
       
  1511         q->showMinimized();
       
  1512         break;
       
  1513     case QStyle::SC_TitleBarNormalButton:
       
  1514         if (q->isShaded())
       
  1515             hoveredSubControl = QStyle::SC_TitleBarMinButton;
       
  1516         q->showNormal();
       
  1517         break;
       
  1518     case QStyle::SC_TitleBarMaxButton:
       
  1519 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
  1520         if (qobject_cast<QMacStyle *>(q->style())) {
       
  1521             if (q->isMaximized())
       
  1522                 q->showNormal();
       
  1523             else
       
  1524                 q->showMaximized();
       
  1525             break;
       
  1526         }
       
  1527 #endif
       
  1528         q->showMaximized();
       
  1529         break;
       
  1530     case QStyle::SC_TitleBarCloseButton:
       
  1531         q->close();
       
  1532         break;
       
  1533     default:
       
  1534         break;
       
  1535     }
       
  1536 }
       
  1537 
       
  1538 /*!
       
  1539     \internal
       
  1540 */
       
  1541 QRegion QMdiSubWindowPrivate::getRegion(Operation operation) const
       
  1542 {
       
  1543     Q_Q(const QMdiSubWindow);
       
  1544     int width = q->width();
       
  1545     int height = q->height();
       
  1546     int titleBarHeight = this->titleBarHeight();
       
  1547     int frameWidth = q->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, q);
       
  1548     int cornerConst = titleBarHeight - frameWidth;
       
  1549     int titleBarConst = 2 * titleBarHeight;
       
  1550 
       
  1551     if (operation == Move) {
       
  1552         QStyleOptionTitleBar titleBarOptions = this->titleBarOptions();
       
  1553         QRegion move(frameWidth, frameWidth, width - 2 * frameWidth, cornerConst);
       
  1554         // Depending on which window flags are set, activated sub controllers will
       
  1555         // be subtracted from the 'move' region.
       
  1556         for (int i = 0; i < NumSubControls; ++i) {
       
  1557             if (SubControls[i] == QStyle::SC_TitleBarLabel)
       
  1558                 continue;
       
  1559             move -= QRegion(q->style()->subControlRect(QStyle::CC_TitleBar, &titleBarOptions,
       
  1560                             SubControls[i]));
       
  1561         }
       
  1562         return move;
       
  1563     }
       
  1564 
       
  1565     QRegion region;
       
  1566 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
  1567     if (qobject_cast<QMacStyle *>(q->style()))
       
  1568         return region;
       
  1569 #endif
       
  1570 
       
  1571     switch (operation) {
       
  1572     case TopResize:
       
  1573         region = QRegion(titleBarHeight, 0, width - titleBarConst, frameWidth);
       
  1574         break;
       
  1575     case BottomResize:
       
  1576         region = QRegion(titleBarHeight, height - frameWidth, width - titleBarConst, frameWidth);
       
  1577         break;
       
  1578     case LeftResize:
       
  1579         region = QRegion(0, titleBarHeight, frameWidth, height - titleBarConst);
       
  1580         break;
       
  1581     case RightResize:
       
  1582         region = QRegion(width - frameWidth, titleBarHeight, frameWidth, height - titleBarConst);
       
  1583         break;
       
  1584     case TopLeftResize:
       
  1585         region = QRegion(0, 0, titleBarHeight, titleBarHeight)
       
  1586                  - QRegion(frameWidth, frameWidth, cornerConst, cornerConst);
       
  1587         break;
       
  1588     case TopRightResize:
       
  1589         region =  QRegion(width - titleBarHeight, 0, titleBarHeight, titleBarHeight)
       
  1590                   - QRegion(width - titleBarHeight, frameWidth, cornerConst, cornerConst);
       
  1591         break;
       
  1592     case BottomLeftResize:
       
  1593         region = QRegion(0, height - titleBarHeight, titleBarHeight, titleBarHeight)
       
  1594                  - QRegion(frameWidth, height - titleBarHeight, cornerConst, cornerConst);
       
  1595         break;
       
  1596     case BottomRightResize:
       
  1597         region = QRegion(width - titleBarHeight, height - titleBarHeight, titleBarHeight, titleBarHeight)
       
  1598                  - QRegion(width - titleBarHeight, height - titleBarHeight, cornerConst, cornerConst);
       
  1599         break;
       
  1600     default:
       
  1601         break;
       
  1602     }
       
  1603 
       
  1604     return region;
       
  1605 }
       
  1606 
       
  1607 /*!
       
  1608     \internal
       
  1609 */
       
  1610 QMdiSubWindowPrivate::Operation QMdiSubWindowPrivate::getOperation(const QPoint &pos) const
       
  1611 {
       
  1612     OperationInfoMap::const_iterator it;
       
  1613     for (it = operationMap.constBegin(); it != operationMap.constEnd(); ++it)
       
  1614         if (it.value().region.contains(pos))
       
  1615             return it.key();
       
  1616     return None;
       
  1617 }
       
  1618 
       
  1619 extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*);
       
  1620 
       
  1621 /*!
       
  1622     \internal
       
  1623 */
       
  1624 QStyleOptionTitleBar QMdiSubWindowPrivate::titleBarOptions() const
       
  1625 {
       
  1626     Q_Q(const QMdiSubWindow);
       
  1627     QStyleOptionTitleBar titleBarOptions;
       
  1628     titleBarOptions.initFrom(q);
       
  1629     if (activeSubControl != QStyle::SC_None) {
       
  1630         if (hoveredSubControl == activeSubControl) {
       
  1631             titleBarOptions.state |= QStyle::State_Sunken;
       
  1632             titleBarOptions.activeSubControls = activeSubControl;
       
  1633         }
       
  1634     } else if (autoRaise() && hoveredSubControl != QStyle::SC_None
       
  1635                && hoveredSubControl != QStyle::SC_TitleBarLabel) {
       
  1636         titleBarOptions.state |= QStyle::State_MouseOver;
       
  1637         titleBarOptions.activeSubControls = hoveredSubControl;
       
  1638     } else {
       
  1639         titleBarOptions.state &= ~QStyle::State_MouseOver;
       
  1640         titleBarOptions.activeSubControls = QStyle::SC_None;
       
  1641     }
       
  1642 
       
  1643     titleBarOptions.subControls = QStyle::SC_All;
       
  1644     titleBarOptions.titleBarFlags = q->windowFlags();
       
  1645     titleBarOptions.titleBarState = q->windowState();
       
  1646     titleBarOptions.palette = titleBarPalette;
       
  1647     titleBarOptions.icon = menuIcon;
       
  1648 
       
  1649     if (isActive) {
       
  1650         titleBarOptions.state |= QStyle::State_Active;
       
  1651         titleBarOptions.titleBarState |= QStyle::State_Active;
       
  1652         titleBarOptions.palette.setCurrentColorGroup(QPalette::Active);
       
  1653     } else {
       
  1654         titleBarOptions.state &= ~QStyle::State_Active;
       
  1655         titleBarOptions.palette.setCurrentColorGroup(QPalette::Inactive);
       
  1656     }
       
  1657 
       
  1658     int border = hasBorder(titleBarOptions) ? 4 : 0;
       
  1659     int paintHeight = titleBarHeight(titleBarOptions);
       
  1660     paintHeight -= q->isMinimized() ? 2 * border : border;
       
  1661     titleBarOptions.rect = QRect(border, border, q->width() - 2 * border, paintHeight);
       
  1662 
       
  1663     if (!windowTitle.isEmpty()) {
       
  1664         // Set the text here before asking for the width of the title bar label
       
  1665         // in case people uses the actual text to calculate the width.
       
  1666         titleBarOptions.text = windowTitle;
       
  1667         titleBarOptions.fontMetrics = QFontMetrics(font);
       
  1668         int width = q->style()->subControlRect(QStyle::CC_TitleBar, &titleBarOptions,
       
  1669                                                QStyle::SC_TitleBarLabel, q).width();
       
  1670         // Set elided text if we don't have enough space for the entire title.
       
  1671         titleBarOptions.text = titleBarOptions.fontMetrics.elidedText(windowTitle, Qt::ElideRight, width);
       
  1672     }
       
  1673     return titleBarOptions;
       
  1674 }
       
  1675 
       
  1676 /*!
       
  1677     \internal
       
  1678 */
       
  1679 void QMdiSubWindowPrivate::ensureWindowState(Qt::WindowState state)
       
  1680 {
       
  1681     Q_Q(QMdiSubWindow);
       
  1682     Qt::WindowStates windowStates = q->windowState() | state;
       
  1683     switch (state) {
       
  1684     case Qt::WindowMinimized:
       
  1685         windowStates &= ~Qt::WindowMaximized;
       
  1686         windowStates &= ~Qt::WindowNoState;
       
  1687         break;
       
  1688     case Qt::WindowMaximized:
       
  1689         windowStates &= ~Qt::WindowMinimized;
       
  1690         windowStates &= ~Qt::WindowNoState;
       
  1691         break;
       
  1692     case Qt::WindowNoState:
       
  1693         windowStates &= ~Qt::WindowMinimized;
       
  1694         windowStates &= ~Qt::WindowMaximized;
       
  1695         break;
       
  1696     default:
       
  1697         break;
       
  1698     }
       
  1699     if (baseWidget) {
       
  1700         if (!(baseWidget->windowState() & Qt::WindowActive) && windowStates & Qt::WindowActive)
       
  1701             baseWidget->overrideWindowState(windowStates & ~Qt::WindowActive);
       
  1702         else
       
  1703             baseWidget->overrideWindowState(windowStates);
       
  1704     }
       
  1705     q->overrideWindowState(windowStates);
       
  1706 }
       
  1707 
       
  1708 /*!
       
  1709     \internal
       
  1710 */
       
  1711 int QMdiSubWindowPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
       
  1712 {
       
  1713     Q_Q(const QMdiSubWindow);
       
  1714     if (!parent || q->windowFlags() & Qt::FramelessWindowHint
       
  1715         || (q->isMaximized() && !drawTitleBarWhenMaximized())) {
       
  1716         return 0;
       
  1717     }
       
  1718 
       
  1719     int height = q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options, q);
       
  1720 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
  1721     // ### Fix mac style, the +4 pixels hack is not necessary anymore
       
  1722     if (qobject_cast<QMacStyle *>(q->style()))
       
  1723         height -= 4;
       
  1724 #endif
       
  1725     if (hasBorder(options))
       
  1726         height += q->isMinimized() ? 8 : 4;
       
  1727     return height;
       
  1728 }
       
  1729 
       
  1730 /*!
       
  1731     \internal
       
  1732 */
       
  1733 void QMdiSubWindowPrivate::sizeParameters(int *margin, int *minWidth) const
       
  1734 {
       
  1735     Q_Q(const QMdiSubWindow);
       
  1736     Qt::WindowFlags flags = q->windowFlags();
       
  1737     if (!parent || flags & Qt::FramelessWindowHint) {
       
  1738         *margin = 0;
       
  1739         *minWidth = 0;
       
  1740         return;
       
  1741     }
       
  1742 
       
  1743     if (q->isMaximized() && !drawTitleBarWhenMaximized())
       
  1744         *margin = 0;
       
  1745     else
       
  1746         *margin = q->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, q);
       
  1747 
       
  1748     QStyleOptionTitleBar opt = this->titleBarOptions();
       
  1749     int tempWidth = 0;
       
  1750     for (int i = 0; i < NumSubControls; ++i) {
       
  1751         if (SubControls[i] == QStyle::SC_TitleBarLabel) {
       
  1752             tempWidth += 30;
       
  1753             continue;
       
  1754         }
       
  1755         QRect rect = q->style()->subControlRect(QStyle::CC_TitleBar, &opt, SubControls[i], q);
       
  1756         if (!rect.isValid())
       
  1757             continue;
       
  1758         tempWidth += rect.width();
       
  1759     }
       
  1760     *minWidth = tempWidth;
       
  1761 }
       
  1762 
       
  1763 /*!
       
  1764     \internal
       
  1765 */
       
  1766 bool QMdiSubWindowPrivate::drawTitleBarWhenMaximized() const
       
  1767 {
       
  1768     Q_Q(const QMdiSubWindow);
       
  1769     if (q->window()->testAttribute(Qt::WA_CanHostQMdiSubWindowTitleBar))
       
  1770         return false;
       
  1771 
       
  1772     if (isChildOfTabbedQMdiArea(q))
       
  1773         return false;
       
  1774 
       
  1775 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) || defined(Q_WS_WINCE_WM)
       
  1776     return true;
       
  1777 #else
       
  1778     if (q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q))
       
  1779         return true;
       
  1780 #if defined(QT_NO_MENUBAR) || defined(QT_NO_MAINWINDOW)
       
  1781     return true;
       
  1782 #else
       
  1783     QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q->window());
       
  1784     if (!mainWindow || !qobject_cast<QMenuBar *>(mainWindow->menuWidget())
       
  1785         || mainWindow->menuWidget()->isHidden())
       
  1786         return true;
       
  1787 
       
  1788     return isChildOfQMdiSubWindow(q);
       
  1789 #endif
       
  1790 #endif
       
  1791 }
       
  1792 
       
  1793 #ifndef QT_NO_MENUBAR
       
  1794 
       
  1795 /*!
       
  1796     \internal
       
  1797 */
       
  1798 void QMdiSubWindowPrivate::showButtonsInMenuBar(QMenuBar *menuBar)
       
  1799 {
       
  1800     Q_Q(QMdiSubWindow);
       
  1801     Q_ASSERT(q->isMaximized() && !drawTitleBarWhenMaximized());
       
  1802 
       
  1803     if (isChildOfTabbedQMdiArea(q))
       
  1804         return;
       
  1805 
       
  1806     removeButtonsFromMenuBar();
       
  1807     if (!controlContainer)
       
  1808         controlContainer = new ControlContainer(q);
       
  1809 
       
  1810     ignoreWindowTitleChange = true;
       
  1811     controlContainer->showButtonsInMenuBar(menuBar);
       
  1812     ignoreWindowTitleChange = false;
       
  1813 
       
  1814     QWidget *topLevelWindow = q->window();
       
  1815     topLevelWindow->setWindowModified(q->isWindowModified());
       
  1816     topLevelWindow->installEventFilter(q);
       
  1817 
       
  1818     int buttonHeight = 0;
       
  1819     if (controlContainer->controllerWidget())
       
  1820         buttonHeight = controlContainer->controllerWidget()->height();
       
  1821     else if (controlContainer->systemMenuLabel())
       
  1822         buttonHeight = controlContainer->systemMenuLabel()->height();
       
  1823 
       
  1824     // This will rarely happen.
       
  1825     if (menuBar && menuBar->height() < buttonHeight
       
  1826             && topLevelWindow->layout()) {
       
  1827         // Make sure topLevelWindow->contentsRect returns correct geometry.
       
  1828         // topLevelWidget->updateGeoemtry will not do the trick here since it will post the event.
       
  1829         QEvent event(QEvent::LayoutRequest);
       
  1830         QApplication::sendEvent(topLevelWindow, &event);
       
  1831     }
       
  1832 }
       
  1833 
       
  1834 /*!
       
  1835     \internal
       
  1836 */
       
  1837 void QMdiSubWindowPrivate::removeButtonsFromMenuBar()
       
  1838 {
       
  1839     Q_Q(QMdiSubWindow);
       
  1840 
       
  1841     if (!controlContainer || isChildOfTabbedQMdiArea(q))
       
  1842         return;
       
  1843 
       
  1844     QMenuBar *currentMenuBar = 0;
       
  1845 #ifndef QT_NO_MAINWINDOW
       
  1846     if (QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q->window())) {
       
  1847         // NB! We can't use menuBar() here because that one will actually create
       
  1848         // a menubar for us if not set. That's not what we want :-)
       
  1849         currentMenuBar = qobject_cast<QMenuBar *>(mainWindow->menuWidget());
       
  1850     }
       
  1851 #endif
       
  1852 
       
  1853     ignoreWindowTitleChange = true;
       
  1854     controlContainer->removeButtonsFromMenuBar(currentMenuBar);
       
  1855     ignoreWindowTitleChange = false;
       
  1856 
       
  1857     QWidget *topLevelWindow = q->window();
       
  1858     topLevelWindow->removeEventFilter(q);
       
  1859     if (baseWidget && !drawTitleBarWhenMaximized())
       
  1860         topLevelWindow->setWindowModified(false);
       
  1861     originalTitle = QString::null;
       
  1862 }
       
  1863 
       
  1864 #endif // QT_NO_MENUBAR
       
  1865 
       
  1866 void QMdiSubWindowPrivate::updateWindowTitle(bool isRequestFromChild)
       
  1867 {
       
  1868     Q_Q(QMdiSubWindow);
       
  1869     if (isRequestFromChild && !q->windowTitle().isEmpty() && !lastChildWindowTitle.isEmpty()
       
  1870             && lastChildWindowTitle != q->windowTitle()) {
       
  1871         return;
       
  1872     }
       
  1873 
       
  1874     QWidget *titleWidget = 0;
       
  1875     if (isRequestFromChild)
       
  1876         titleWidget = baseWidget;
       
  1877     else
       
  1878         titleWidget = q;
       
  1879     if (!titleWidget || titleWidget->windowTitle().isEmpty())
       
  1880         return;
       
  1881 
       
  1882     ignoreWindowTitleChange = true;
       
  1883     q->setWindowTitle(titleWidget->windowTitle());
       
  1884     if (q->maximizedButtonsWidget())
       
  1885         setNewWindowTitle();
       
  1886     ignoreWindowTitleChange = false;
       
  1887 }
       
  1888 
       
  1889 #ifndef QT_NO_RUBBERBAND
       
  1890 void QMdiSubWindowPrivate::enterRubberBandMode()
       
  1891 {
       
  1892     Q_Q(QMdiSubWindow);
       
  1893     if (q->isMaximized())
       
  1894         return;
       
  1895     Q_ASSERT(oldGeometry.isValid());
       
  1896     Q_ASSERT(parent);
       
  1897     if (!rubberBand) {
       
  1898         rubberBand = new QRubberBand(QRubberBand::Rectangle, q->parentWidget());
       
  1899         // For accessibility to identify this special widget.
       
  1900         rubberBand->setObjectName(QLatin1String("qt_rubberband"));
       
  1901     }
       
  1902     QPoint rubberBandPos = q->mapToParent(QPoint(0, 0));
       
  1903     rubberBand->setGeometry(rubberBandPos.x(), rubberBandPos.y(),
       
  1904                             oldGeometry.width(), oldGeometry.height());
       
  1905     rubberBand->show();
       
  1906     isInRubberBandMode = true;
       
  1907     q->grabMouse();
       
  1908 }
       
  1909 
       
  1910 void QMdiSubWindowPrivate::leaveRubberBandMode()
       
  1911 {
       
  1912     Q_Q(QMdiSubWindow);
       
  1913     Q_ASSERT(rubberBand);
       
  1914     Q_ASSERT(isInRubberBandMode);
       
  1915     q->releaseMouse();
       
  1916     isInRubberBandMode = false;
       
  1917     q->setGeometry(rubberBand->geometry());
       
  1918     rubberBand->hide();
       
  1919     currentOperation = None;
       
  1920 }
       
  1921 #endif // QT_NO_RUBBERBAND
       
  1922 
       
  1923 // Taken from the old QWorkspace (::readColors())
       
  1924 QPalette QMdiSubWindowPrivate::desktopPalette() const
       
  1925 {
       
  1926     Q_Q(const QMdiSubWindow);
       
  1927     QPalette newPalette = q->palette();
       
  1928 
       
  1929     bool colorsInitialized = false;
       
  1930 #ifdef Q_WS_WIN // ask system properties on windows
       
  1931 #ifndef SPI_GETGRADIENTCAPTIONS
       
  1932 #define SPI_GETGRADIENTCAPTIONS 0x1008
       
  1933 #endif
       
  1934 #ifndef COLOR_GRADIENTACTIVECAPTION
       
  1935 #define COLOR_GRADIENTACTIVECAPTION 27
       
  1936 #endif
       
  1937 #ifndef COLOR_GRADIENTINACTIVECAPTION
       
  1938 #define COLOR_GRADIENTINACTIVECAPTION 28
       
  1939 #endif
       
  1940     if (QApplication::desktopSettingsAware()) {
       
  1941         newPalette.setColor(QPalette::Active, QPalette::Highlight,
       
  1942                             colorref2qrgb(GetSysColor(COLOR_ACTIVECAPTION)));
       
  1943         newPalette.setColor(QPalette::Inactive, QPalette::Highlight,
       
  1944                             colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTION)));
       
  1945         newPalette.setColor(QPalette::Active, QPalette::HighlightedText,
       
  1946                             colorref2qrgb(GetSysColor(COLOR_CAPTIONTEXT)));
       
  1947         newPalette.setColor(QPalette::Inactive, QPalette::HighlightedText,
       
  1948                             colorref2qrgb(GetSysColor(COLOR_INACTIVECAPTIONTEXT)));
       
  1949 
       
  1950         colorsInitialized = true;
       
  1951         BOOL hasGradient = false;
       
  1952         SystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, &hasGradient, 0);
       
  1953 
       
  1954         if (hasGradient) {
       
  1955             newPalette.setColor(QPalette::Active, QPalette::Base,
       
  1956                                 colorref2qrgb(GetSysColor(COLOR_GRADIENTACTIVECAPTION)));
       
  1957             newPalette.setColor(QPalette::Inactive, QPalette::Base,
       
  1958                                 colorref2qrgb(GetSysColor(COLOR_GRADIENTINACTIVECAPTION)));
       
  1959         } else {
       
  1960             newPalette.setColor(QPalette::Active, QPalette::Base,
       
  1961                                 newPalette.color(QPalette::Active, QPalette::Highlight));
       
  1962             newPalette.setColor(QPalette::Inactive, QPalette::Base,
       
  1963                                 newPalette.color(QPalette::Inactive, QPalette::Highlight));
       
  1964         }
       
  1965     }
       
  1966 #endif // Q_WS_WIN
       
  1967     if (!colorsInitialized) {
       
  1968         newPalette.setColor(QPalette::Active, QPalette::Highlight,
       
  1969                             newPalette.color(QPalette::Active, QPalette::Highlight));
       
  1970         newPalette.setColor(QPalette::Active, QPalette::Base,
       
  1971                             newPalette.color(QPalette::Active, QPalette::Highlight));
       
  1972         newPalette.setColor(QPalette::Inactive, QPalette::Highlight,
       
  1973                             newPalette.color(QPalette::Inactive, QPalette::Dark));
       
  1974         newPalette.setColor(QPalette::Inactive, QPalette::Base,
       
  1975                             newPalette.color(QPalette::Inactive, QPalette::Dark));
       
  1976         newPalette.setColor(QPalette::Inactive, QPalette::HighlightedText,
       
  1977                             newPalette.color(QPalette::Inactive, QPalette::Window));
       
  1978     }
       
  1979 
       
  1980     return newPalette;
       
  1981 }
       
  1982 
       
  1983 void QMdiSubWindowPrivate::updateActions()
       
  1984 {
       
  1985     Qt::WindowFlags windowFlags = q_func()->windowFlags();
       
  1986     // Hide all
       
  1987     for (int i = 0; i < NumWindowStateActions; ++i)
       
  1988         setVisible(WindowStateAction(i), false);
       
  1989 
       
  1990     if (windowFlags & Qt::FramelessWindowHint)
       
  1991         return;
       
  1992 
       
  1993     setVisible(StayOnTopAction, true);
       
  1994     setVisible(MoveAction, moveEnabled);
       
  1995     setVisible(ResizeAction, resizeEnabled);
       
  1996 
       
  1997     // CloseAction
       
  1998     if (windowFlags & Qt::WindowSystemMenuHint)
       
  1999         setVisible(CloseAction, true);
       
  2000 
       
  2001     // RestoreAction
       
  2002     if (windowFlags & (Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint))
       
  2003         setVisible(RestoreAction, true);
       
  2004 
       
  2005     // MinimizeAction
       
  2006     if (windowFlags & Qt::WindowMinimizeButtonHint)
       
  2007         setVisible(MinimizeAction, true);
       
  2008 
       
  2009     // MaximizeAction
       
  2010     if (windowFlags & Qt::WindowMaximizeButtonHint)
       
  2011         setVisible(MaximizeAction, true);
       
  2012 }
       
  2013 
       
  2014 void QMdiSubWindowPrivate::setFocusWidget()
       
  2015 {
       
  2016     Q_Q(QMdiSubWindow);
       
  2017     if (!baseWidget) {
       
  2018         q->setFocus();
       
  2019         return;
       
  2020     }
       
  2021 
       
  2022     // This will give focus to the next child if possible, otherwise
       
  2023     // do nothing, hence it's not possible to tab between windows with
       
  2024     // just hitting tab (unless Qt::TabFocus is removed from the focus policy).
       
  2025     if (focusInReason == Qt::TabFocusReason) {
       
  2026         q->focusNextChild();
       
  2027         return;
       
  2028     }
       
  2029 
       
  2030     // Same as above, but gives focus to the previous child.
       
  2031     if (focusInReason == Qt::BacktabFocusReason) {
       
  2032         q->focusPreviousChild();
       
  2033         return;
       
  2034     }
       
  2035 
       
  2036     if (QWidget *focusWidget = baseWidget->focusWidget()) {
       
  2037         if (!focusWidget->hasFocus() && q->isAncestorOf(focusWidget)
       
  2038                 && focusWidget->isVisible() && !q->isMinimized()
       
  2039                 && focusWidget->focusPolicy() != Qt::NoFocus) {
       
  2040             focusWidget->setFocus();
       
  2041         } else {
       
  2042             q->setFocus();
       
  2043         }
       
  2044         return;
       
  2045     }
       
  2046 
       
  2047     QWidget *focusWidget = q->nextInFocusChain();
       
  2048     while (focusWidget && focusWidget != q && focusWidget->focusPolicy() == Qt::NoFocus)
       
  2049         focusWidget = focusWidget->nextInFocusChain();
       
  2050     if (focusWidget && q->isAncestorOf(focusWidget))
       
  2051         focusWidget->setFocus();
       
  2052     else if (baseWidget->focusPolicy() != Qt::NoFocus)
       
  2053         baseWidget->setFocus();
       
  2054     else if (!q->hasFocus())
       
  2055         q->setFocus();
       
  2056 }
       
  2057 
       
  2058 void QMdiSubWindowPrivate::restoreFocus()
       
  2059 {
       
  2060     if (!restoreFocusWidget)
       
  2061         return;
       
  2062     if (!restoreFocusWidget->hasFocus() && q_func()->isAncestorOf(restoreFocusWidget)
       
  2063             && restoreFocusWidget->isVisible()
       
  2064             && restoreFocusWidget->focusPolicy() != Qt::NoFocus) {
       
  2065         restoreFocusWidget->setFocus();
       
  2066     }
       
  2067     restoreFocusWidget = 0;
       
  2068 }
       
  2069 
       
  2070 /*!
       
  2071     \internal
       
  2072     ### Please add QEvent::WindowFlagsChange event
       
  2073 */
       
  2074 void QMdiSubWindowPrivate::setWindowFlags(Qt::WindowFlags windowFlags)
       
  2075 {
       
  2076     Q_Q(QMdiSubWindow);
       
  2077     if (!parent) {
       
  2078         q->setWindowFlags(windowFlags);
       
  2079         return;
       
  2080     }
       
  2081 
       
  2082     Qt::WindowFlags windowType = windowFlags & Qt::WindowType_Mask;
       
  2083     if (windowType == Qt::Dialog || windowFlags & Qt::MSWindowsFixedSizeDialogHint)
       
  2084         windowFlags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint;
       
  2085 
       
  2086     // Set standard flags if none of the customize flags are set
       
  2087     if (!(windowFlags & CustomizeWindowFlags))
       
  2088         windowFlags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
       
  2089     else if (windowFlags & Qt::FramelessWindowHint && windowFlags & Qt::WindowStaysOnTopHint)
       
  2090         windowFlags = Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint;
       
  2091     else if (windowFlags & Qt::FramelessWindowHint)
       
  2092         windowFlags = Qt::FramelessWindowHint;
       
  2093 
       
  2094     windowFlags &= ~windowType;
       
  2095     windowFlags |= Qt::SubWindow;
       
  2096 
       
  2097 #ifndef QT_NO_ACTION
       
  2098     if (QAction *stayOnTopAction = actions[QMdiSubWindowPrivate::StayOnTopAction]) {
       
  2099         if (windowFlags & Qt::WindowStaysOnTopHint)
       
  2100             stayOnTopAction->setChecked(true);
       
  2101         else
       
  2102             stayOnTopAction->setChecked(false);
       
  2103     }
       
  2104 #endif
       
  2105 
       
  2106 #ifndef QT_NO_SIZEGRIP
       
  2107     if ((windowFlags & Qt::FramelessWindowHint) && sizeGrip)
       
  2108         delete sizeGrip;
       
  2109 #endif
       
  2110 
       
  2111     q->setWindowFlags(windowFlags);
       
  2112     updateGeometryConstraints();
       
  2113     updateActions();
       
  2114     QSize currentSize = q->size();
       
  2115     if (q->isVisible() && (currentSize.width() < internalMinimumSize.width()
       
  2116             || currentSize.height() < internalMinimumSize.height())) {
       
  2117         q->resize(currentSize.expandedTo(internalMinimumSize));
       
  2118     }
       
  2119 }
       
  2120 
       
  2121 void QMdiSubWindowPrivate::setVisible(WindowStateAction action, bool visible)
       
  2122 {
       
  2123 #ifndef QT_NO_ACTION
       
  2124     if (actions[action])
       
  2125         actions[action]->setVisible(visible);
       
  2126 #endif
       
  2127 
       
  2128     Q_Q(QMdiSubWindow);
       
  2129     if (!controlContainer)
       
  2130         controlContainer = new ControlContainer(q);
       
  2131 
       
  2132     if (ControllerWidget *ctrlWidget = qobject_cast<ControllerWidget *>
       
  2133                                        (controlContainer->controllerWidget())) {
       
  2134         ctrlWidget->setControlVisible(action, visible);
       
  2135     }
       
  2136 }
       
  2137 
       
  2138 #ifndef QT_NO_ACTION
       
  2139 void QMdiSubWindowPrivate::setEnabled(WindowStateAction action, bool enable)
       
  2140 {
       
  2141     if (actions[action])
       
  2142         actions[action]->setEnabled(enable);
       
  2143 }
       
  2144 
       
  2145 #ifndef QT_NO_MENU
       
  2146 void QMdiSubWindowPrivate::addToSystemMenu(WindowStateAction action, const QString &text,
       
  2147                                            const char *slot)
       
  2148 {
       
  2149     if (!systemMenu)
       
  2150         return;
       
  2151     actions[action] = systemMenu->addAction(text, q_func(), slot);
       
  2152 }
       
  2153 #endif
       
  2154 #endif // QT_NO_ACTION
       
  2155 
       
  2156 /*!
       
  2157     \internal
       
  2158 */
       
  2159 QSize QMdiSubWindowPrivate::iconSize() const
       
  2160 {
       
  2161     Q_Q(const QMdiSubWindow);
       
  2162     if (!parent || q->windowFlags() & Qt::FramelessWindowHint)
       
  2163         return QSize(-1, -1);
       
  2164     return QSize(q->style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth, 0, q), titleBarHeight());
       
  2165 }
       
  2166 
       
  2167 #ifndef QT_NO_SIZEGRIP
       
  2168 
       
  2169 /*!
       
  2170     \internal
       
  2171 */
       
  2172 void QMdiSubWindowPrivate::setSizeGrip(QSizeGrip *newSizeGrip)
       
  2173 {
       
  2174     Q_Q(QMdiSubWindow);
       
  2175     if (!newSizeGrip || sizeGrip || q->windowFlags() & Qt::FramelessWindowHint)
       
  2176         return;
       
  2177 
       
  2178     if (layout && layout->indexOf(newSizeGrip) != -1)
       
  2179         return;
       
  2180     newSizeGrip->setFixedSize(newSizeGrip->sizeHint());
       
  2181     bool putSizeGripInLayout = layout ? true : false;
       
  2182 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
  2183     if (qobject_cast<QMacStyle *>(q->style()))
       
  2184         putSizeGripInLayout = false;
       
  2185 #endif
       
  2186     if (putSizeGripInLayout) {
       
  2187         layout->addWidget(newSizeGrip);
       
  2188         layout->setAlignment(newSizeGrip, Qt::AlignBottom | Qt::AlignRight);
       
  2189     } else {
       
  2190         newSizeGrip->setParent(q);
       
  2191         newSizeGrip->move(q->isLeftToRight() ? q->width() - newSizeGrip->width() : 0,
       
  2192                           q->height() - newSizeGrip->height());
       
  2193         sizeGrip = newSizeGrip;
       
  2194     }
       
  2195     newSizeGrip->raise();
       
  2196     updateGeometryConstraints();
       
  2197     newSizeGrip->installEventFilter(q);
       
  2198 }
       
  2199 
       
  2200 /*!
       
  2201     \internal
       
  2202 */
       
  2203 void QMdiSubWindowPrivate::setSizeGripVisible(bool visible) const
       
  2204 {
       
  2205     // See if we can find any size grips
       
  2206     QList<QSizeGrip *> sizeGrips = qFindChildren<QSizeGrip *>(q_func());
       
  2207     foreach (QSizeGrip *grip, sizeGrips)
       
  2208         grip->setVisible(visible);
       
  2209 }
       
  2210 
       
  2211 #endif // QT_NO_SIZEGRIP
       
  2212 
       
  2213 /*!
       
  2214     \internal
       
  2215 */
       
  2216 void QMdiSubWindowPrivate::updateInternalWindowTitle()
       
  2217 {
       
  2218     Q_Q(QMdiSubWindow);
       
  2219     if (q->isWindowModified()) {
       
  2220         windowTitle = q->windowTitle();
       
  2221         windowTitle.replace(QLatin1String("[*]"), QLatin1String("*"));
       
  2222     } else {
       
  2223         windowTitle = qt_setWindowTitle_helperHelper(q->windowTitle(), q);
       
  2224     }
       
  2225     q->update(0, 0, q->width(), titleBarHeight());
       
  2226 }
       
  2227 
       
  2228 /*!
       
  2229     Constructs a new QMdiSubWindow widget. The \a parent and \a
       
  2230     flags arguments are passed to QWidget's constructor.
       
  2231 
       
  2232     Instead of using addSubWindow(), it is also simply possible to
       
  2233     use setParent() when you add the subwindow to a QMdiArea.
       
  2234 
       
  2235     Note that only \l{QMdiSubWindow}s can be set as children of
       
  2236     QMdiArea; you cannot, for instance, write:
       
  2237 
       
  2238     \badcode
       
  2239         QMdiArea mdiArea;
       
  2240         QTextEdit editor(&mdiArea); // invalid child widget
       
  2241     \endcode
       
  2242 
       
  2243     \sa QMdiArea::addSubWindow()
       
  2244 */
       
  2245 QMdiSubWindow::QMdiSubWindow(QWidget *parent, Qt::WindowFlags flags)
       
  2246     : QWidget(*new QMdiSubWindowPrivate, parent, 0)
       
  2247 {
       
  2248     Q_D(QMdiSubWindow);
       
  2249 #ifndef QT_NO_MENU
       
  2250     d->createSystemMenu();
       
  2251     addActions(d->systemMenu->actions());
       
  2252 #endif
       
  2253     d->setWindowFlags(flags);
       
  2254     setBackgroundRole(QPalette::Window);
       
  2255     setAutoFillBackground(true);
       
  2256     setMouseTracking(true);
       
  2257     setLayout(new QVBoxLayout);
       
  2258     setFocusPolicy(Qt::StrongFocus);
       
  2259     layout()->setMargin(0);
       
  2260     d->updateGeometryConstraints();
       
  2261     setAttribute(Qt::WA_Resized, false);
       
  2262     d->titleBarPalette = d->desktopPalette();
       
  2263     d->font = QApplication::font("QWorkspaceTitleBar");
       
  2264     // We don't want the menu icon by default on mac.
       
  2265 #ifndef Q_WS_MAC
       
  2266     if (windowIcon().isNull())
       
  2267         d->menuIcon = style()->standardIcon(QStyle::SP_TitleBarMenuButton, 0, this);
       
  2268     else
       
  2269         d->menuIcon = windowIcon();
       
  2270 #endif
       
  2271     connect(qApp, SIGNAL(focusChanged(QWidget *, QWidget *)),
       
  2272             this, SLOT(_q_processFocusChanged(QWidget *, QWidget *)));
       
  2273 }
       
  2274 
       
  2275 /*!
       
  2276     Destroys the subwindow.
       
  2277 
       
  2278     \sa QMdiArea::removeSubWindow()
       
  2279 */
       
  2280 QMdiSubWindow::~QMdiSubWindow()
       
  2281 {
       
  2282     Q_D(QMdiSubWindow);
       
  2283 #ifndef QT_NO_MENUBAR
       
  2284     d->removeButtonsFromMenuBar();
       
  2285 #endif
       
  2286     d->setActive(false);
       
  2287 }
       
  2288 
       
  2289 /*!
       
  2290     Sets \a widget as the internal widget of this subwindow. The
       
  2291     internal widget is displayed in the center of the subwindow
       
  2292     beneath the title bar.
       
  2293 
       
  2294     QMdiSubWindow takes temporary ownership of \a widget; you do
       
  2295     not have to delete it. Any existing internal widget will be
       
  2296     removed and reparented to the root window.
       
  2297 
       
  2298     \sa widget()
       
  2299 */
       
  2300 void QMdiSubWindow::setWidget(QWidget *widget)
       
  2301 {
       
  2302     Q_D(QMdiSubWindow);
       
  2303     if (!widget) {
       
  2304         d->removeBaseWidget();
       
  2305         return;
       
  2306     }
       
  2307 
       
  2308     if (widget == d->baseWidget) {
       
  2309         qWarning("QMdiSubWindow::setWidget: widget is already set");
       
  2310         return;
       
  2311     }
       
  2312 
       
  2313     bool wasResized = testAttribute(Qt::WA_Resized);
       
  2314     d->removeBaseWidget();
       
  2315 
       
  2316     if (QLayout *layout = this->layout())
       
  2317         layout->addWidget(widget);
       
  2318     else
       
  2319         widget->setParent(this);
       
  2320 
       
  2321 #ifndef QT_NO_SIZEGRIP
       
  2322     QSizeGrip *sizeGrip = qFindChild<QSizeGrip *>(widget);
       
  2323     if (sizeGrip)
       
  2324         sizeGrip->installEventFilter(this);
       
  2325     if (d->sizeGrip)
       
  2326         d->sizeGrip->raise();
       
  2327 #endif
       
  2328 
       
  2329     d->baseWidget = widget;
       
  2330     d->baseWidget->installEventFilter(this);
       
  2331 
       
  2332     d->ignoreWindowTitleChange = true;
       
  2333     bool isWindowModified = this->isWindowModified();
       
  2334     if (windowTitle().isEmpty()) {
       
  2335         d->updateWindowTitle(true);
       
  2336         isWindowModified = d->baseWidget->isWindowModified();
       
  2337     }
       
  2338     if (!this->isWindowModified() && isWindowModified
       
  2339             && windowTitle().contains(QLatin1String("[*]"))) {
       
  2340         setWindowModified(isWindowModified);
       
  2341     }
       
  2342     d->lastChildWindowTitle = d->baseWidget->windowTitle();
       
  2343     d->ignoreWindowTitleChange = false;
       
  2344 
       
  2345     if (windowIcon().isNull() && !d->baseWidget->windowIcon().isNull())
       
  2346         setWindowIcon(d->baseWidget->windowIcon());
       
  2347 
       
  2348     d->updateGeometryConstraints();
       
  2349     if (!wasResized && testAttribute(Qt::WA_Resized))
       
  2350         setAttribute(Qt::WA_Resized, false);
       
  2351 }
       
  2352 
       
  2353 /*!
       
  2354     Returns the current internal widget.
       
  2355 
       
  2356     \sa setWidget()
       
  2357 */
       
  2358 QWidget *QMdiSubWindow::widget() const
       
  2359 {
       
  2360     return d_func()->baseWidget;
       
  2361 }
       
  2362 
       
  2363 
       
  2364 /*!
       
  2365     \internal
       
  2366 */
       
  2367 QWidget *QMdiSubWindow::maximizedButtonsWidget() const
       
  2368 {
       
  2369     Q_D(const QMdiSubWindow);
       
  2370     if (isVisible() && d->controlContainer && isMaximized() && !d->drawTitleBarWhenMaximized()
       
  2371         && !isChildOfTabbedQMdiArea(this)) {
       
  2372         return d->controlContainer->controllerWidget();
       
  2373     }
       
  2374     return 0;
       
  2375 }
       
  2376 
       
  2377 /*!
       
  2378     \internal
       
  2379 */
       
  2380 QWidget *QMdiSubWindow::maximizedSystemMenuIconWidget() const
       
  2381 {
       
  2382     Q_D(const QMdiSubWindow);
       
  2383     if (isVisible() && d->controlContainer && isMaximized() && !d->drawTitleBarWhenMaximized()
       
  2384         && !isChildOfTabbedQMdiArea(this)) {
       
  2385         return d->controlContainer->systemMenuLabel();
       
  2386     }
       
  2387     return 0;
       
  2388 }
       
  2389 
       
  2390 /*!
       
  2391     Returns true if this window is shaded; otherwise returns false.
       
  2392 
       
  2393     A window is shaded if it is collapsed so that only the title bar is
       
  2394     visible.
       
  2395 */
       
  2396 bool QMdiSubWindow::isShaded() const
       
  2397 {
       
  2398     return d_func()->isShadeMode;
       
  2399 }
       
  2400 
       
  2401 /*!
       
  2402     If \a on is true, \a option is enabled on the subwindow; otherwise it is
       
  2403     disabled. See SubWindowOption for the effect of each option.
       
  2404 
       
  2405     \sa SubWindowOption, testOption()
       
  2406 */
       
  2407 void QMdiSubWindow::setOption(SubWindowOption option, bool on)
       
  2408 {
       
  2409     Q_D(QMdiSubWindow);
       
  2410     if (on && !(d->options & option))
       
  2411         d->options |= option;
       
  2412     else if (!on && (d->options & option))
       
  2413         d->options &= ~option;
       
  2414 
       
  2415 #ifndef QT_NO_RUBBERBAND
       
  2416     if ((option & (RubberBandResize | RubberBandMove)) && !on && d->isInRubberBandMode)
       
  2417         d->leaveRubberBandMode();
       
  2418 #endif
       
  2419 }
       
  2420 
       
  2421 /*!
       
  2422     Returns true if \a option is enabled; otherwise returns false.
       
  2423 
       
  2424     \sa SubWindowOption, setOption()
       
  2425 */
       
  2426 bool QMdiSubWindow::testOption(SubWindowOption option) const
       
  2427 {
       
  2428     return d_func()->options & option;
       
  2429 }
       
  2430 
       
  2431 /*!
       
  2432     \property QMdiSubWindow::keyboardSingleStep
       
  2433     \brief sets how far a widget should move or resize when using the
       
  2434     keyboard arrow keys.
       
  2435 
       
  2436     When in keyboard-interactive mode, you can use the arrow and page keys to
       
  2437     either move or resize the window. This property controls the arrow keys.
       
  2438     The common way to enter keyboard interactive mode is to enter the
       
  2439     subwindow menu, and select either "resize" or "move".
       
  2440 
       
  2441     The default keyboard single step value is 5 pixels.
       
  2442 
       
  2443     \sa keyboardPageStep
       
  2444 */
       
  2445 int QMdiSubWindow::keyboardSingleStep() const
       
  2446 {
       
  2447     return d_func()->keyboardSingleStep;
       
  2448 }
       
  2449 
       
  2450 void QMdiSubWindow::setKeyboardSingleStep(int step)
       
  2451 {
       
  2452     // Haven't done any boundary check here since negative step only
       
  2453     // means inverted behavior, which is OK if the user want it.
       
  2454     // A step equal to zero means "do nothing".
       
  2455     d_func()->keyboardSingleStep = step;
       
  2456 }
       
  2457 
       
  2458 /*!
       
  2459     \property QMdiSubWindow::keyboardPageStep
       
  2460     \brief sets how far a widget should move or resize when using the
       
  2461     keyboard page keys.
       
  2462 
       
  2463     When in keyboard-interactive mode, you can use the arrow and page keys to
       
  2464     either move or resize the window. This property controls the page
       
  2465     keys. The common way to enter keyboard interactive mode is to enter the
       
  2466     subwindow menu, and select either "resize" or "move".
       
  2467 
       
  2468     The default keyboard page step value is 20 pixels.
       
  2469 
       
  2470     \sa keyboardSingleStep
       
  2471 */
       
  2472 int QMdiSubWindow::keyboardPageStep() const
       
  2473 {
       
  2474     return d_func()->keyboardPageStep;
       
  2475 }
       
  2476 
       
  2477 void QMdiSubWindow::setKeyboardPageStep(int step)
       
  2478 {
       
  2479     // Haven't done any boundary check here since negative step only
       
  2480     // means inverted behavior, which is OK if the user want it.
       
  2481     // A step equal to zero means "do nothing".
       
  2482     d_func()->keyboardPageStep = step;
       
  2483 }
       
  2484 
       
  2485 #ifndef QT_NO_MENU
       
  2486 /*!
       
  2487     Sets \a systemMenu as the current system menu for this subwindow.
       
  2488 
       
  2489     By default, each QMdiSubWindow has a standard system menu.
       
  2490 
       
  2491     QActions for the system menu created by QMdiSubWindow will
       
  2492     automatically be updated depending on the current window state;
       
  2493     e.g., the minimize action will be disabled after the window is
       
  2494     minimized.
       
  2495 
       
  2496     QActions added by the user are not updated by QMdiSubWindow.
       
  2497 
       
  2498     QMdiSubWindow takes ownership of \a systemMenu; you do not have to
       
  2499     delete it. Any existing menus will be deleted.
       
  2500 
       
  2501     \sa systemMenu(), showSystemMenu()
       
  2502 */
       
  2503 void QMdiSubWindow::setSystemMenu(QMenu *systemMenu)
       
  2504 {
       
  2505     Q_D(QMdiSubWindow);
       
  2506     if (systemMenu && systemMenu == d->systemMenu) {
       
  2507         qWarning("QMdiSubWindow::setSystemMenu: system menu is already set");
       
  2508         return;
       
  2509     }
       
  2510 
       
  2511     if (d->systemMenu) {
       
  2512         delete d->systemMenu;
       
  2513         d->systemMenu = 0;
       
  2514     }
       
  2515 
       
  2516     if (!systemMenu)
       
  2517         return;
       
  2518 
       
  2519     if (systemMenu->parent() != this)
       
  2520         systemMenu->setParent(this);
       
  2521     d->systemMenu = systemMenu;
       
  2522 }
       
  2523 
       
  2524 /*!
       
  2525     Returns a pointer to the current system menu, or zero if no system
       
  2526     menu is set. QMdiSubWindow provides a default system menu, but you can
       
  2527     also set the menu with setSystemMenu().
       
  2528 
       
  2529     \sa setSystemMenu(), showSystemMenu()
       
  2530 */
       
  2531 QMenu *QMdiSubWindow::systemMenu() const
       
  2532 {
       
  2533     return d_func()->systemMenu;
       
  2534 }
       
  2535 
       
  2536 /*!
       
  2537     Shows the system menu below the system menu icon in the title bar.
       
  2538 
       
  2539     \sa setSystemMenu(), systemMenu()
       
  2540 */
       
  2541 void QMdiSubWindow::showSystemMenu()
       
  2542 {
       
  2543     Q_D(QMdiSubWindow);
       
  2544     if (!d->systemMenu)
       
  2545         return;
       
  2546 
       
  2547     QPoint globalPopupPos;
       
  2548     if (QWidget *icon = maximizedSystemMenuIconWidget()) {
       
  2549         if (isLeftToRight())
       
  2550             globalPopupPos = icon->mapToGlobal(QPoint(0, icon->y() + icon->height()));
       
  2551         else
       
  2552             globalPopupPos = icon->mapToGlobal(QPoint(icon->width(), icon->y() + icon->height()));
       
  2553     } else {
       
  2554         if (isLeftToRight())
       
  2555             globalPopupPos = mapToGlobal(contentsRect().topLeft());
       
  2556         else // + QPoint(1, 0) because topRight() == QPoint(left() + width() -1, top())
       
  2557             globalPopupPos = mapToGlobal(contentsRect().topRight()) + QPoint(1, 0);
       
  2558     }
       
  2559 
       
  2560     // Adjust x() with -menuwidth in reverse mode.
       
  2561     if (isRightToLeft())
       
  2562         globalPopupPos -= QPoint(d->systemMenu->sizeHint().width(), 0);
       
  2563     d->systemMenu->installEventFilter(this);
       
  2564     d->systemMenu->popup(globalPopupPos);
       
  2565 }
       
  2566 #endif // QT_NO_MENU
       
  2567 
       
  2568 /*!
       
  2569     \since 4.4
       
  2570 
       
  2571     Returns the area containing this sub-window, or 0 if there is none.
       
  2572 
       
  2573     \sa QMdiArea::addSubWindow()
       
  2574 */
       
  2575 QMdiArea *QMdiSubWindow::mdiArea() const
       
  2576 {
       
  2577     QWidget *parent = parentWidget();
       
  2578     while (parent) {
       
  2579         if (QMdiArea *area = qobject_cast<QMdiArea *>(parent)) {
       
  2580             if (area->viewport() == parentWidget())
       
  2581                 return area;
       
  2582         }
       
  2583         parent = parent->parentWidget();
       
  2584     }
       
  2585     return 0;
       
  2586 }
       
  2587 
       
  2588 /*!
       
  2589     Calling this function makes the subwindow enter the shaded mode.
       
  2590     When the subwindow is shaded, only the title bar is visible.
       
  2591 
       
  2592     Although shading is not supported by all styles, this function will
       
  2593     still show the subwindow as shaded, regardless of whether support
       
  2594     for shading is available. However, when used with styles without
       
  2595     shading support, the user will be unable to return from shaded mode
       
  2596     through the user interface (e.g., through a shade button in the title
       
  2597     bar).
       
  2598 
       
  2599     \sa isShaded()
       
  2600 */
       
  2601 void QMdiSubWindow::showShaded()
       
  2602 {
       
  2603     if (!parent())
       
  2604         return;
       
  2605 
       
  2606     Q_D(QMdiSubWindow);
       
  2607     // setMinimizeMode uses this function.
       
  2608     if (!d->isShadeRequestFromMinimizeMode && isShaded())
       
  2609         return;
       
  2610 
       
  2611     d->isMaximizeMode = false;
       
  2612 
       
  2613     QWidget *currentFocusWidget = QApplication::focusWidget();
       
  2614     if (!d->restoreFocusWidget && isAncestorOf(currentFocusWidget))
       
  2615         d->restoreFocusWidget = currentFocusWidget;
       
  2616 
       
  2617     if (!d->isShadeRequestFromMinimizeMode) {
       
  2618         d->isShadeMode = true;
       
  2619         d->ensureWindowState(Qt::WindowMinimized);
       
  2620     }
       
  2621 
       
  2622 #ifndef QT_NO_MENUBAR
       
  2623     d->removeButtonsFromMenuBar();
       
  2624 #endif
       
  2625 
       
  2626     // showMinimized() will reset Qt::WindowActive, which makes sense
       
  2627     // for top level widgets, but in MDI it makes sense to have an
       
  2628     // active window which is minimized.
       
  2629     if (hasFocus() || isAncestorOf(currentFocusWidget))
       
  2630         d->ensureWindowState(Qt::WindowActive);
       
  2631 
       
  2632 #ifndef QT_NO_SIZEGRIP
       
  2633     d->setSizeGripVisible(false);
       
  2634 #endif
       
  2635 
       
  2636     if (!d->restoreSize.isValid() || d->isShadeMode) {
       
  2637         d->oldGeometry = geometry();
       
  2638         d->restoreSize.setWidth(d->oldGeometry.width());
       
  2639         d->restoreSize.setHeight(d->oldGeometry.height());
       
  2640     }
       
  2641 
       
  2642     // Hide the window before we change the geometry to avoid multiple resize
       
  2643     // events and wrong window state.
       
  2644     const bool wasVisible = isVisible();
       
  2645     if (wasVisible)
       
  2646         setVisible(false);
       
  2647 
       
  2648     d->updateGeometryConstraints();
       
  2649     // Update minimum size to internalMinimumSize if set by user.
       
  2650     if (!minimumSize().isNull()) {
       
  2651         d->userMinimumSize = minimumSize();
       
  2652         setMinimumSize(d->internalMinimumSize);
       
  2653     }
       
  2654     resize(d->internalMinimumSize);
       
  2655 
       
  2656     // Hide the internal widget if not already hidden by the user.
       
  2657     if (d->baseWidget && !d->baseWidget->isHidden()) {
       
  2658         d->baseWidget->hide();
       
  2659         d->isWidgetHiddenByUs = true;
       
  2660     }
       
  2661 
       
  2662     if (wasVisible)
       
  2663         setVisible(true);
       
  2664 
       
  2665     d->setFocusWidget();
       
  2666     d->resizeEnabled = false;
       
  2667     d->moveEnabled = true;
       
  2668     d->updateDirtyRegions();
       
  2669     d->updateMask();
       
  2670 
       
  2671 #ifndef QT_NO_ACTION
       
  2672     d->setEnabled(QMdiSubWindowPrivate::MinimizeAction, false);
       
  2673     d->setEnabled(QMdiSubWindowPrivate::ResizeAction, d->resizeEnabled);
       
  2674     d->setEnabled(QMdiSubWindowPrivate::MaximizeAction, true);
       
  2675     d->setEnabled(QMdiSubWindowPrivate::RestoreAction, true);
       
  2676     d->setEnabled(QMdiSubWindowPrivate::MoveAction, d->moveEnabled);
       
  2677 #endif
       
  2678 }
       
  2679 
       
  2680 /*!
       
  2681     \reimp
       
  2682 */
       
  2683 bool QMdiSubWindow::eventFilter(QObject *object, QEvent *event)
       
  2684 {
       
  2685     Q_D(QMdiSubWindow);
       
  2686     if (!object)
       
  2687         return QWidget::eventFilter(object, event);
       
  2688 
       
  2689 #ifndef QT_NO_MENU
       
  2690     // System menu events.
       
  2691     if (d->systemMenu && d->systemMenu == object) {
       
  2692         if (event->type() == QEvent::MouseButtonDblClick) {
       
  2693             close();
       
  2694         } else if (event->type() == QEvent::MouseMove) {
       
  2695             QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
       
  2696             d->hoveredSubControl = d->getSubControl(mapFromGlobal(mouseEvent->globalPos()));
       
  2697         } else if (event->type() == QEvent::Hide) {
       
  2698             d->systemMenu->removeEventFilter(this);
       
  2699             d->activeSubControl = QStyle::SC_None;
       
  2700             update(QRegion(0, 0, width(), d->titleBarHeight()));
       
  2701         }
       
  2702         return QWidget::eventFilter(object, event);
       
  2703     }
       
  2704 #endif
       
  2705 
       
  2706 #ifndef QT_NO_SIZEGRIP
       
  2707     if (object != d->baseWidget && parent() && qobject_cast<QSizeGrip *>(object)) {
       
  2708         if (event->type() != QEvent::MouseButtonPress || !testOption(QMdiSubWindow::RubberBandResize))
       
  2709             return QWidget::eventFilter(object, event);
       
  2710         const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
       
  2711         d->mousePressPosition = parentWidget()->mapFromGlobal(mouseEvent->globalPos());
       
  2712         d->oldGeometry = geometry();
       
  2713         d->currentOperation = isLeftToRight() ? QMdiSubWindowPrivate::BottomRightResize
       
  2714                                               : QMdiSubWindowPrivate::BottomLeftResize;
       
  2715 #ifndef QT_NO_RUBBERBAND
       
  2716         d->enterRubberBandMode();
       
  2717 #endif
       
  2718         return true;
       
  2719     }
       
  2720 #endif
       
  2721 
       
  2722     if (object != d->baseWidget && event->type() != QEvent::WindowTitleChange)
       
  2723         return QWidget::eventFilter(object, event);
       
  2724 
       
  2725     switch (event->type()) {
       
  2726     case QEvent::Show:
       
  2727         d->setActive(true);
       
  2728         break;
       
  2729     case QEvent::ShowToParent:
       
  2730         if (!d->isWidgetHiddenByUs)
       
  2731             show();
       
  2732         break;
       
  2733     case QEvent::WindowStateChange: {
       
  2734         QWindowStateChangeEvent *changeEvent = static_cast<QWindowStateChangeEvent*>(event);
       
  2735         if (changeEvent->isOverride())
       
  2736             break;
       
  2737         Qt::WindowStates oldState = changeEvent->oldState();
       
  2738         Qt::WindowStates newState = d->baseWidget->windowState();
       
  2739         if (!(oldState & Qt::WindowMinimized) && (newState & Qt::WindowMinimized))
       
  2740             showMinimized();
       
  2741         else if (!(oldState & Qt::WindowMaximized) && (newState & Qt::WindowMaximized))
       
  2742             showMaximized();
       
  2743         else if (!(newState & (Qt::WindowMaximized | Qt::WindowMinimized)))
       
  2744             showNormal();
       
  2745         break;
       
  2746     }
       
  2747     case QEvent::Enter:
       
  2748         d->currentOperation = QMdiSubWindowPrivate::None;
       
  2749         d->updateCursor();
       
  2750         break;
       
  2751     case QEvent::LayoutRequest:
       
  2752         d->updateGeometryConstraints();
       
  2753         break;
       
  2754     case QEvent::WindowTitleChange:
       
  2755         if (d->ignoreWindowTitleChange)
       
  2756             break;
       
  2757         if (object == d->baseWidget) {
       
  2758             d->updateWindowTitle(true);
       
  2759             d->lastChildWindowTitle = d->baseWidget->windowTitle();
       
  2760 #ifndef QT_NO_MENUBAR
       
  2761         } else if (maximizedButtonsWidget() && d->controlContainer->menuBar() && d->controlContainer->menuBar()
       
  2762                    ->cornerWidget(Qt::TopRightCorner) == maximizedButtonsWidget()) {
       
  2763             d->originalTitle = QString::null;
       
  2764             if (d->baseWidget && d->baseWidget->windowTitle() == windowTitle())
       
  2765                 d->updateWindowTitle(true);
       
  2766             else
       
  2767                 d->updateWindowTitle(false);
       
  2768 #endif
       
  2769         }
       
  2770         break;
       
  2771     case QEvent::ModifiedChange: {
       
  2772         if (object != d->baseWidget)
       
  2773             break;
       
  2774         bool windowModified = d->baseWidget->isWindowModified();
       
  2775         if (!windowModified && d->baseWidget->windowTitle() != windowTitle())
       
  2776             break;
       
  2777         if (windowTitle().contains(QLatin1String("[*]")))
       
  2778             setWindowModified(windowModified);
       
  2779         break;
       
  2780     }
       
  2781     default:
       
  2782         break;
       
  2783     }
       
  2784     return QWidget::eventFilter(object, event);
       
  2785 }
       
  2786 
       
  2787 /*!
       
  2788     \reimp
       
  2789 */
       
  2790 bool QMdiSubWindow::event(QEvent *event)
       
  2791 {
       
  2792     Q_D(QMdiSubWindow);
       
  2793     switch (event->type()) {
       
  2794     case QEvent::StyleChange: {
       
  2795         bool wasShaded = isShaded();
       
  2796         bool wasMinimized = isMinimized();
       
  2797         bool wasMaximized = isMaximized();
       
  2798         ensurePolished();
       
  2799         setContentsMargins(0, 0, 0, 0);
       
  2800         if (wasMinimized || wasMaximized || wasShaded)
       
  2801             showNormal();
       
  2802         d->updateGeometryConstraints();
       
  2803         resize(d->internalMinimumSize.expandedTo(size()));
       
  2804         d->updateMask();
       
  2805         d->updateDirtyRegions();
       
  2806         if (wasShaded)
       
  2807             showShaded();
       
  2808         else if (wasMinimized)
       
  2809             showMinimized();
       
  2810         else if (wasMaximized)
       
  2811             showMaximized();
       
  2812         break;
       
  2813     }
       
  2814     case QEvent::ParentAboutToChange:
       
  2815         d->setActive(false);
       
  2816         break;
       
  2817     case QEvent::ParentChange: {
       
  2818         bool wasResized = testAttribute(Qt::WA_Resized);
       
  2819 #ifndef QT_NO_MENUBAR
       
  2820         d->removeButtonsFromMenuBar();
       
  2821 #endif
       
  2822         d->currentOperation = QMdiSubWindowPrivate::None;
       
  2823         d->activeSubControl = QStyle::SC_None;
       
  2824         d->hoveredSubControl = QStyle::SC_None;
       
  2825 #ifndef QT_NO_RUBBERBAND
       
  2826         if (d->isInRubberBandMode)
       
  2827             d->leaveRubberBandMode();
       
  2828 #endif
       
  2829         d->isShadeMode = false;
       
  2830         d->isMaximizeMode = false;
       
  2831         d->isWidgetHiddenByUs = false;
       
  2832         if (!parent()) {
       
  2833 #if !defined(QT_NO_SIZEGRIP) && defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
  2834             if (qobject_cast<QMacStyle *>(style()))
       
  2835                 delete d->sizeGrip;
       
  2836 #endif
       
  2837             setOption(RubberBandResize, false);
       
  2838             setOption(RubberBandMove, false);
       
  2839         } else {
       
  2840             d->setWindowFlags(windowFlags());
       
  2841         }
       
  2842         setContentsMargins(0, 0, 0, 0);
       
  2843         d->updateGeometryConstraints();
       
  2844         d->updateCursor();
       
  2845         d->updateMask();
       
  2846         d->updateDirtyRegions();
       
  2847         d->updateActions();
       
  2848         if (!wasResized && testAttribute(Qt::WA_Resized))
       
  2849             setAttribute(Qt::WA_Resized, false);
       
  2850         break;
       
  2851     }
       
  2852     case QEvent::WindowActivate:
       
  2853         if (d->ignoreNextActivationEvent) {
       
  2854             d->ignoreNextActivationEvent = false;
       
  2855             break;
       
  2856         }
       
  2857         d->isExplicitlyDeactivated = false;
       
  2858         d->setActive(true);
       
  2859         break;
       
  2860     case QEvent::WindowDeactivate:
       
  2861         if (d->ignoreNextActivationEvent) {
       
  2862             d->ignoreNextActivationEvent = false;
       
  2863             break;
       
  2864         }
       
  2865         d->isExplicitlyDeactivated = true;
       
  2866         d->setActive(false);
       
  2867         break;
       
  2868     case QEvent::WindowTitleChange:
       
  2869         if (!d->ignoreWindowTitleChange)
       
  2870             d->updateWindowTitle(false);
       
  2871         d->updateInternalWindowTitle();
       
  2872         break;
       
  2873     case QEvent::ModifiedChange:
       
  2874         if (!windowTitle().contains(QLatin1String("[*]")))
       
  2875             break;
       
  2876 #ifndef QT_NO_MENUBAR
       
  2877         if (maximizedButtonsWidget() && d->controlContainer->menuBar() && d->controlContainer->menuBar()
       
  2878                 ->cornerWidget(Qt::TopRightCorner) == maximizedButtonsWidget()) {
       
  2879             window()->setWindowModified(isWindowModified());
       
  2880         }
       
  2881 #endif // QT_NO_MENUBAR
       
  2882         d->updateInternalWindowTitle();
       
  2883         break;
       
  2884     case QEvent::LayoutDirectionChange:
       
  2885         d->updateDirtyRegions();
       
  2886         break;
       
  2887     case QEvent::LayoutRequest:
       
  2888         d->updateGeometryConstraints();
       
  2889         break;
       
  2890     case QEvent::WindowIconChange:
       
  2891         d->menuIcon = windowIcon();
       
  2892         if (d->menuIcon.isNull())
       
  2893             d->menuIcon = style()->standardIcon(QStyle::SP_TitleBarMenuButton, 0, this);
       
  2894         if (d->controlContainer)
       
  2895             d->controlContainer->updateWindowIcon(d->menuIcon);
       
  2896         if (!maximizedSystemMenuIconWidget())
       
  2897             update(0, 0, width(), d->titleBarHeight());
       
  2898         break;
       
  2899     case QEvent::PaletteChange:
       
  2900         d->titleBarPalette = d->desktopPalette();
       
  2901         break;
       
  2902     case QEvent::FontChange:
       
  2903         d->font = font();
       
  2904         break;
       
  2905 #ifndef QT_NO_TOOLTIP
       
  2906     case QEvent::ToolTip:
       
  2907         showToolTip(static_cast<QHelpEvent *>(event), this, d->titleBarOptions(),
       
  2908                     QStyle::CC_TitleBar, d->hoveredSubControl);
       
  2909         break;
       
  2910 #endif
       
  2911     default:
       
  2912         break;
       
  2913     }
       
  2914     return QWidget::event(event);
       
  2915 }
       
  2916 
       
  2917 /*!
       
  2918     \reimp
       
  2919 */
       
  2920 void QMdiSubWindow::showEvent(QShowEvent *showEvent)
       
  2921 {
       
  2922     Q_D(QMdiSubWindow);
       
  2923     if (!parent()) {
       
  2924         QWidget::showEvent(showEvent);
       
  2925         return;
       
  2926     }
       
  2927 
       
  2928 #if !defined(QT_NO_SIZEGRIP) && defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
  2929     if (qobject_cast<QMacStyle *>(style()) && !d->sizeGrip
       
  2930             && !(windowFlags() & Qt::FramelessWindowHint)) {
       
  2931         d->setSizeGrip(new QSizeGrip(0));
       
  2932         Q_ASSERT(d->sizeGrip);
       
  2933         if (isMinimized())
       
  2934             d->setSizeGripVisible(false);
       
  2935         else
       
  2936             d->setSizeGripVisible(true);
       
  2937         resize(size().expandedTo(d->internalMinimumSize));
       
  2938     }
       
  2939 #endif
       
  2940 
       
  2941     d->updateDirtyRegions();
       
  2942     // Show buttons in the menu bar if they're already not there.
       
  2943     // We want to do this when QMdiSubWindow becomes visible after being hidden.
       
  2944 #ifndef QT_NO_MENUBAR
       
  2945     if (d->controlContainer) {
       
  2946         if (QMenuBar *menuBar = d->menuBar()) {
       
  2947             if (menuBar->cornerWidget(Qt::TopRightCorner) != maximizedButtonsWidget())
       
  2948                 d->showButtonsInMenuBar(menuBar);
       
  2949         }
       
  2950     }
       
  2951 #endif
       
  2952     d->setActive(true);
       
  2953 }
       
  2954 
       
  2955 /*!
       
  2956     \reimp
       
  2957 */
       
  2958 void QMdiSubWindow::hideEvent(QHideEvent * /*hideEvent*/)
       
  2959 {
       
  2960 #ifndef QT_NO_MENUBAR
       
  2961     d_func()->removeButtonsFromMenuBar();
       
  2962 #endif
       
  2963 }
       
  2964 
       
  2965 /*!
       
  2966     \reimp
       
  2967 */
       
  2968 void QMdiSubWindow::changeEvent(QEvent *changeEvent)
       
  2969 {
       
  2970     if (!parent()) {
       
  2971         QWidget::changeEvent(changeEvent);
       
  2972         return;
       
  2973     }
       
  2974 
       
  2975     if (changeEvent->type() != QEvent::WindowStateChange) {
       
  2976         QWidget::changeEvent(changeEvent);
       
  2977         return;
       
  2978     }
       
  2979 
       
  2980     QWindowStateChangeEvent *event = static_cast<QWindowStateChangeEvent *>(changeEvent);
       
  2981     if (event->isOverride()) {
       
  2982         event->ignore();
       
  2983         return;
       
  2984     }
       
  2985 
       
  2986     Qt::WindowStates oldState = event->oldState();
       
  2987     Qt::WindowStates newState = windowState();
       
  2988     if (oldState == newState) {
       
  2989         changeEvent->ignore();
       
  2990         return;
       
  2991     }
       
  2992 
       
  2993     // QWidget ensures that the widget is visible _after_ setWindowState(),
       
  2994     // but we need to ensure that the widget is visible _before_
       
  2995     // setWindowState() returns.
       
  2996     Q_D(QMdiSubWindow);
       
  2997     if (!isVisible()) {
       
  2998         d->ensureWindowState(Qt::WindowNoState);
       
  2999         setVisible(true);
       
  3000     }
       
  3001 
       
  3002     if (!d->oldGeometry.isValid())
       
  3003         d->oldGeometry = geometry();
       
  3004 
       
  3005     if ((oldState & Qt::WindowActive) && (newState & Qt::WindowActive))
       
  3006         d->currentOperation = QMdiSubWindowPrivate::None;
       
  3007 
       
  3008     if (!(oldState & Qt::WindowMinimized) && (newState & Qt::WindowMinimized))
       
  3009         d->setMinimizeMode();
       
  3010     else if (!(oldState & Qt::WindowMaximized) && (newState & Qt::WindowMaximized))
       
  3011         d->setMaximizeMode();
       
  3012     else if (!(newState & (Qt::WindowMaximized | Qt::WindowMinimized)))
       
  3013         d->setNormalMode();
       
  3014 
       
  3015     if (d->isActive)
       
  3016         d->ensureWindowState(Qt::WindowActive);
       
  3017     emit windowStateChanged(oldState, windowState());
       
  3018 }
       
  3019 
       
  3020 /*!
       
  3021     \reimp
       
  3022 */
       
  3023 void QMdiSubWindow::closeEvent(QCloseEvent *closeEvent)
       
  3024 {
       
  3025     Q_D(QMdiSubWindow);
       
  3026     bool acceptClose = true;
       
  3027     if (d->baseWidget)
       
  3028         acceptClose = d->baseWidget->close();
       
  3029     if (!acceptClose) {
       
  3030         closeEvent->ignore();
       
  3031         return;
       
  3032     }
       
  3033 #ifndef QT_NO_MENUBAR
       
  3034     d->removeButtonsFromMenuBar();
       
  3035 #endif
       
  3036     d->setActive(false);
       
  3037     if (parentWidget() && testAttribute(Qt::WA_DeleteOnClose)) {
       
  3038         QChildEvent childRemoved(QEvent::ChildRemoved, this);
       
  3039         QApplication::sendEvent(parentWidget(), &childRemoved);
       
  3040     }
       
  3041     closeEvent->accept();
       
  3042 }
       
  3043 
       
  3044 /*!
       
  3045     \reimp
       
  3046 */
       
  3047 void QMdiSubWindow::leaveEvent(QEvent * /*leaveEvent*/)
       
  3048 {
       
  3049     Q_D(QMdiSubWindow);
       
  3050     if (d->hoveredSubControl != QStyle::SC_None) {
       
  3051         d->hoveredSubControl = QStyle::SC_None;
       
  3052         update(QRegion(0, 0, width(), d->titleBarHeight()));
       
  3053     }
       
  3054 }
       
  3055 
       
  3056 /*!
       
  3057     \reimp
       
  3058 */
       
  3059 void QMdiSubWindow::resizeEvent(QResizeEvent *resizeEvent)
       
  3060 {
       
  3061     Q_D(QMdiSubWindow);
       
  3062 #ifndef QT_NO_SIZEGRIP
       
  3063     if (d->sizeGrip) {
       
  3064         d->sizeGrip->move(isLeftToRight() ? width() - d->sizeGrip->width() : 0,
       
  3065                           height() - d->sizeGrip->height());
       
  3066     }
       
  3067 #endif
       
  3068 
       
  3069     if (!parent()) {
       
  3070         QWidget::resizeEvent(resizeEvent);
       
  3071         return;
       
  3072     }
       
  3073 
       
  3074     if (d->isMaximizeMode)
       
  3075         d->ensureWindowState(Qt::WindowMaximized);
       
  3076 
       
  3077     d->updateMask();
       
  3078     if (!isVisible())
       
  3079         return;
       
  3080 
       
  3081     if (d->resizeTimerId <= 0)
       
  3082         d->cachedStyleOptions = d->titleBarOptions();
       
  3083     else
       
  3084         killTimer(d->resizeTimerId);
       
  3085     d->resizeTimerId = startTimer(200);
       
  3086 }
       
  3087 
       
  3088 /*!
       
  3089     \reimp
       
  3090 */
       
  3091 void QMdiSubWindow::timerEvent(QTimerEvent *timerEvent)
       
  3092 {
       
  3093     Q_D(QMdiSubWindow);
       
  3094     if (timerEvent->timerId() == d->resizeTimerId) {
       
  3095         killTimer(d->resizeTimerId);
       
  3096         d->resizeTimerId = -1;
       
  3097         d->updateDirtyRegions();
       
  3098     }
       
  3099 }
       
  3100 
       
  3101 /*!
       
  3102     \reimp
       
  3103 */
       
  3104 void QMdiSubWindow::moveEvent(QMoveEvent *moveEvent)
       
  3105 {
       
  3106     if (!parent()) {
       
  3107         QWidget::moveEvent(moveEvent);
       
  3108         return;
       
  3109     }
       
  3110 
       
  3111     Q_D(QMdiSubWindow);
       
  3112     if (d->isMaximizeMode)
       
  3113         d->ensureWindowState(Qt::WindowMaximized);
       
  3114 }
       
  3115 
       
  3116 /*!
       
  3117     \reimp
       
  3118 */
       
  3119 void QMdiSubWindow::paintEvent(QPaintEvent *paintEvent)
       
  3120 {
       
  3121     if (!parent() || (windowFlags() & Qt::FramelessWindowHint)) {
       
  3122         QWidget::paintEvent(paintEvent);
       
  3123         return;
       
  3124     }
       
  3125 
       
  3126     Q_D(QMdiSubWindow);
       
  3127     if (isMaximized() && !d->drawTitleBarWhenMaximized())
       
  3128         return;
       
  3129 
       
  3130     if (d->resizeTimerId != -1) {
       
  3131         // Only update the style option rect and the window title.
       
  3132         int border = d->hasBorder(d->cachedStyleOptions) ? 4 : 0;
       
  3133         int titleBarHeight = d->titleBarHeight(d->cachedStyleOptions);
       
  3134         titleBarHeight -= isMinimized() ? 2 * border : border;
       
  3135         d->cachedStyleOptions.rect = QRect(border, border, width() - 2 * border, titleBarHeight);
       
  3136         if (!d->windowTitle.isEmpty()) {
       
  3137             int width = style()->subControlRect(QStyle::CC_TitleBar, &d->cachedStyleOptions,
       
  3138                                                 QStyle::SC_TitleBarLabel, this).width();
       
  3139             d->cachedStyleOptions.text = d->cachedStyleOptions.fontMetrics
       
  3140                                          .elidedText(d->windowTitle, Qt::ElideRight, width);
       
  3141         }
       
  3142     } else {
       
  3143         // Force full update.
       
  3144         d->cachedStyleOptions = d->titleBarOptions();
       
  3145     }
       
  3146 
       
  3147     QStylePainter painter(this);
       
  3148     if (!d->windowTitle.isEmpty())
       
  3149         painter.setFont(d->font);
       
  3150     painter.drawComplexControl(QStyle::CC_TitleBar, d->cachedStyleOptions);
       
  3151 
       
  3152     if (isMinimized() && !d->hasBorder(d->cachedStyleOptions))
       
  3153         return;
       
  3154 
       
  3155     QStyleOptionFrame frameOptions;
       
  3156     frameOptions.initFrom(this);
       
  3157     frameOptions.lineWidth = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth, 0, this);
       
  3158     if (d->isActive)
       
  3159         frameOptions.state |= QStyle::State_Active;
       
  3160     else
       
  3161         frameOptions.state &= ~QStyle::State_Active;
       
  3162 
       
  3163     // ### Ensure that we do not require setting the cliprect for 4.4
       
  3164     if (!isMinimized() && !d->hasBorder(d->cachedStyleOptions))
       
  3165         painter.setClipRect(rect().adjusted(0, d->titleBarHeight(d->cachedStyleOptions), 0, 0));
       
  3166     if (!isMinimized() || d->hasBorder(d->cachedStyleOptions))
       
  3167         painter.drawPrimitive(QStyle::PE_FrameWindow, frameOptions);
       
  3168 }
       
  3169 
       
  3170 /*!
       
  3171     \reimp
       
  3172 */
       
  3173 void QMdiSubWindow::mousePressEvent(QMouseEvent *mouseEvent)
       
  3174 {
       
  3175     if (!parent()) {
       
  3176         QWidget::mousePressEvent(mouseEvent);
       
  3177         return;
       
  3178     }
       
  3179 
       
  3180     Q_D(QMdiSubWindow);
       
  3181     if (d->isInInteractiveMode)
       
  3182         d->leaveInteractiveMode();
       
  3183 #ifndef QT_NO_RUBBERBAND
       
  3184     if (d->isInRubberBandMode)
       
  3185         d->leaveRubberBandMode();
       
  3186 #endif
       
  3187 
       
  3188     if (mouseEvent->button() != Qt::LeftButton) {
       
  3189         mouseEvent->ignore();
       
  3190         return;
       
  3191     }
       
  3192 
       
  3193     if (d->currentOperation != QMdiSubWindowPrivate::None) {
       
  3194         d->updateCursor();
       
  3195         d->mousePressPosition = mapToParent(mouseEvent->pos());
       
  3196         if (d->resizeEnabled || d->moveEnabled)
       
  3197             d->oldGeometry = geometry();
       
  3198 #ifndef QT_NO_RUBBERBAND
       
  3199         if ((testOption(QMdiSubWindow::RubberBandResize) && d->isResizeOperation())
       
  3200             || (testOption(QMdiSubWindow::RubberBandMove) && d->isMoveOperation())) {
       
  3201             d->enterRubberBandMode();
       
  3202         }
       
  3203 #endif
       
  3204         return;
       
  3205     }
       
  3206 
       
  3207     d->activeSubControl = d->hoveredSubControl;
       
  3208 #ifndef QT_NO_MENU
       
  3209     if (d->activeSubControl == QStyle::SC_TitleBarSysMenu)
       
  3210         showSystemMenu();
       
  3211     else
       
  3212 #endif
       
  3213     update(QRegion(0, 0, width(), d->titleBarHeight()));
       
  3214 }
       
  3215 
       
  3216 /*!
       
  3217     \reimp
       
  3218 */
       
  3219 void QMdiSubWindow::mouseDoubleClickEvent(QMouseEvent *mouseEvent)
       
  3220 {
       
  3221     if (!parent()) {
       
  3222         QWidget::mouseDoubleClickEvent(mouseEvent);
       
  3223         return;
       
  3224     }
       
  3225 
       
  3226     if (mouseEvent->button() != Qt::LeftButton) {
       
  3227         mouseEvent->ignore();
       
  3228         return;
       
  3229     }
       
  3230 
       
  3231     Q_D(QMdiSubWindow);
       
  3232     if (!d->isMoveOperation()) {
       
  3233 #ifndef QT_NO_MENU
       
  3234         if (d->hoveredSubControl == QStyle::SC_TitleBarSysMenu)
       
  3235             close();
       
  3236 #endif
       
  3237         return;
       
  3238     }
       
  3239 
       
  3240     Qt::WindowFlags flags = windowFlags();
       
  3241     if (isMinimized()) {
       
  3242         if ((isShaded() && (flags & Qt::WindowShadeButtonHint))
       
  3243             || (flags & Qt::WindowMinimizeButtonHint)) {
       
  3244             showNormal();
       
  3245         }
       
  3246         return;
       
  3247     }
       
  3248 
       
  3249     if (isMaximized()) {
       
  3250        if (flags & Qt::WindowMaximizeButtonHint)
       
  3251            showNormal();
       
  3252        return;
       
  3253     }
       
  3254 
       
  3255     if (flags & Qt::WindowShadeButtonHint)
       
  3256         showShaded();
       
  3257     else if (flags & Qt::WindowMaximizeButtonHint)
       
  3258         showMaximized();
       
  3259 }
       
  3260 
       
  3261 /*!
       
  3262     \reimp
       
  3263 */
       
  3264 void QMdiSubWindow::mouseReleaseEvent(QMouseEvent *mouseEvent)
       
  3265 {
       
  3266     if (!parent()) {
       
  3267         QWidget::mouseReleaseEvent(mouseEvent);
       
  3268         return;
       
  3269     }
       
  3270 
       
  3271     if (mouseEvent->button() != Qt::LeftButton) {
       
  3272         mouseEvent->ignore();
       
  3273         return;
       
  3274     }
       
  3275 
       
  3276     Q_D(QMdiSubWindow);
       
  3277     if (d->currentOperation != QMdiSubWindowPrivate::None) {
       
  3278 #ifndef QT_NO_RUBBERBAND
       
  3279         if (d->isInRubberBandMode && !d->isInInteractiveMode)
       
  3280             d->leaveRubberBandMode();
       
  3281 #endif
       
  3282         if (d->resizeEnabled || d->moveEnabled)
       
  3283             d->oldGeometry = geometry();
       
  3284     }
       
  3285 
       
  3286     d->currentOperation = d->getOperation(mouseEvent->pos());
       
  3287     d->updateCursor();
       
  3288 
       
  3289     d->hoveredSubControl = d->getSubControl(mouseEvent->pos());
       
  3290     if (d->activeSubControl != QStyle::SC_None
       
  3291             && d->activeSubControl == d->hoveredSubControl) {
       
  3292         d->processClickedSubControl();
       
  3293     }
       
  3294     d->activeSubControl = QStyle::SC_None;
       
  3295     update(QRegion(0, 0, width(), d->titleBarHeight()));
       
  3296 }
       
  3297 
       
  3298 /*!
       
  3299     \reimp
       
  3300 */
       
  3301 void QMdiSubWindow::mouseMoveEvent(QMouseEvent *mouseEvent)
       
  3302 {
       
  3303     if (!parent()) {
       
  3304         QWidget::mouseMoveEvent(mouseEvent);
       
  3305         return;
       
  3306     }
       
  3307 
       
  3308     Q_D(QMdiSubWindow);
       
  3309     // No update needed if we're in a move/resize operation.
       
  3310     if (!d->isMoveOperation() && !d->isResizeOperation()) {
       
  3311         // Find previous and current hover region.
       
  3312         const QStyleOptionTitleBar options = d->titleBarOptions();
       
  3313         QStyle::SubControl oldHover = d->hoveredSubControl;
       
  3314         d->hoveredSubControl = d->getSubControl(mouseEvent->pos());
       
  3315         QRegion hoverRegion;
       
  3316         if (isHoverControl(oldHover) && oldHover != d->hoveredSubControl)
       
  3317             hoverRegion += style()->subControlRect(QStyle::CC_TitleBar, &options, oldHover, this);
       
  3318         if (isHoverControl(d->hoveredSubControl) && d->hoveredSubControl != oldHover) {
       
  3319             hoverRegion += style()->subControlRect(QStyle::CC_TitleBar, &options,
       
  3320                     d->hoveredSubControl, this);
       
  3321         }
       
  3322 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
  3323         if (qobject_cast<QMacStyle *>(style()) && !hoverRegion.isEmpty())
       
  3324             hoverRegion += QRegion(0, 0, width(), d->titleBarHeight(options));
       
  3325 #endif
       
  3326         if (!hoverRegion.isEmpty())
       
  3327             update(hoverRegion);
       
  3328     }
       
  3329 
       
  3330     if ((mouseEvent->buttons() & Qt::LeftButton) || d->isInInteractiveMode) {
       
  3331         if ((d->isResizeOperation() && d->resizeEnabled) || (d->isMoveOperation() && d->moveEnabled))
       
  3332             d->setNewGeometry(mapToParent(mouseEvent->pos()));
       
  3333         return;
       
  3334     }
       
  3335 
       
  3336     // Do not resize/move if not allowed.
       
  3337     d->currentOperation = d->getOperation(mouseEvent->pos());
       
  3338     if ((d->isResizeOperation() && !d->resizeEnabled) || (d->isMoveOperation() && !d->moveEnabled))
       
  3339         d->currentOperation = QMdiSubWindowPrivate::None;
       
  3340     d->updateCursor();
       
  3341 }
       
  3342 
       
  3343 /*!
       
  3344     \reimp
       
  3345 */
       
  3346 void QMdiSubWindow::keyPressEvent(QKeyEvent *keyEvent)
       
  3347 {
       
  3348     Q_D(QMdiSubWindow);
       
  3349     if (!d->isInInteractiveMode || !parent()) {
       
  3350         keyEvent->ignore();
       
  3351         return;
       
  3352     }
       
  3353 
       
  3354     QPoint delta;
       
  3355     switch (keyEvent->key()) {
       
  3356     case Qt::Key_Right:
       
  3357         if (keyEvent->modifiers() & Qt::ShiftModifier)
       
  3358             delta = QPoint(d->keyboardPageStep, 0);
       
  3359         else
       
  3360             delta = QPoint(d->keyboardSingleStep, 0);
       
  3361         break;
       
  3362     case Qt::Key_Up:
       
  3363         if (keyEvent->modifiers() & Qt::ShiftModifier)
       
  3364             delta = QPoint(0, -d->keyboardPageStep);
       
  3365         else
       
  3366             delta = QPoint(0, -d->keyboardSingleStep);
       
  3367         break;
       
  3368     case Qt::Key_Left:
       
  3369         if (keyEvent->modifiers() & Qt::ShiftModifier)
       
  3370             delta = QPoint(-d->keyboardPageStep, 0);
       
  3371         else
       
  3372             delta = QPoint(-d->keyboardSingleStep, 0);
       
  3373         break;
       
  3374     case Qt::Key_Down:
       
  3375         if (keyEvent->modifiers() & Qt::ShiftModifier)
       
  3376             delta = QPoint(0, d->keyboardPageStep);
       
  3377         else
       
  3378             delta = QPoint(0, d->keyboardSingleStep);
       
  3379         break;
       
  3380     case Qt::Key_Escape:
       
  3381     case Qt::Key_Return:
       
  3382     case Qt::Key_Enter:
       
  3383         d->leaveInteractiveMode();
       
  3384         return;
       
  3385     default:
       
  3386         keyEvent->ignore();
       
  3387         return;
       
  3388     }
       
  3389 
       
  3390 #ifndef QT_NO_CURSOR
       
  3391     QPoint newPosition = parentWidget()->mapFromGlobal(cursor().pos() + delta);
       
  3392     QRect oldGeometry =
       
  3393 #ifndef QT_NO_RUBBERBAND
       
  3394         d->isInRubberBandMode ? d->rubberBand->geometry() :
       
  3395 #endif
       
  3396         geometry();
       
  3397     d->setNewGeometry(newPosition);
       
  3398     QRect currentGeometry =
       
  3399 #ifndef QT_NO_RUBBERBAND
       
  3400         d->isInRubberBandMode ? d->rubberBand->geometry() :
       
  3401 #endif
       
  3402         geometry();
       
  3403     if (currentGeometry == oldGeometry)
       
  3404         return;
       
  3405 
       
  3406     // Update cursor position
       
  3407 
       
  3408     QPoint actualDelta;
       
  3409     if (d->isMoveOperation()) {
       
  3410         actualDelta = QPoint(currentGeometry.x() - oldGeometry.x(),
       
  3411                              currentGeometry.y() - oldGeometry.y());
       
  3412     } else {
       
  3413         int dx = isLeftToRight() ? currentGeometry.width() - oldGeometry.width()
       
  3414                                  : currentGeometry.x() - oldGeometry.x();
       
  3415         actualDelta = QPoint(dx, currentGeometry.height() - oldGeometry.height());
       
  3416     }
       
  3417 
       
  3418     // Adjust in case we weren't able to move as long as wanted.
       
  3419     if (actualDelta != delta)
       
  3420         newPosition += (actualDelta - delta);
       
  3421     cursor().setPos(parentWidget()->mapToGlobal(newPosition));
       
  3422 #endif
       
  3423 }
       
  3424 
       
  3425 #ifndef QT_NO_CONTEXTMENU
       
  3426 /*!
       
  3427     \reimp
       
  3428 */
       
  3429 void QMdiSubWindow::contextMenuEvent(QContextMenuEvent *contextMenuEvent)
       
  3430 {
       
  3431     Q_D(QMdiSubWindow);
       
  3432     if (!d->systemMenu) {
       
  3433         contextMenuEvent->ignore();
       
  3434         return;
       
  3435     }
       
  3436 
       
  3437     if (d->hoveredSubControl == QStyle::SC_TitleBarSysMenu
       
  3438             || d->getRegion(QMdiSubWindowPrivate::Move).contains(contextMenuEvent->pos())) {
       
  3439         d->systemMenu->exec(contextMenuEvent->globalPos());
       
  3440     } else {
       
  3441         contextMenuEvent->ignore();
       
  3442     }
       
  3443 }
       
  3444 #endif // QT_NO_CONTEXTMENU
       
  3445 
       
  3446 /*!
       
  3447     \reimp
       
  3448 */
       
  3449 void QMdiSubWindow::focusInEvent(QFocusEvent *focusInEvent)
       
  3450 {
       
  3451     d_func()->focusInReason = focusInEvent->reason();
       
  3452 }
       
  3453 
       
  3454 /*!
       
  3455     \reimp
       
  3456 */
       
  3457 void QMdiSubWindow::focusOutEvent(QFocusEvent * /*focusOutEvent*/)
       
  3458 {
       
  3459     // To avoid update() in QWidget::focusOutEvent.
       
  3460 }
       
  3461 
       
  3462 /*!
       
  3463     \reimp
       
  3464 */
       
  3465 void QMdiSubWindow::childEvent(QChildEvent *childEvent)
       
  3466 {
       
  3467     if (childEvent->type() != QEvent::ChildPolished)
       
  3468         return;
       
  3469 #ifndef QT_NO_SIZEGRIP
       
  3470     if (QSizeGrip *sizeGrip = qobject_cast<QSizeGrip *>(childEvent->child()))
       
  3471         d_func()->setSizeGrip(sizeGrip);
       
  3472 #endif
       
  3473 }
       
  3474 
       
  3475 /*!
       
  3476     \reimp
       
  3477 */
       
  3478 QSize QMdiSubWindow::sizeHint() const
       
  3479 {
       
  3480     Q_D(const QMdiSubWindow);
       
  3481     int margin, minWidth;
       
  3482     d->sizeParameters(&margin, &minWidth);
       
  3483     QSize size(2 * margin, d->titleBarHeight() + margin);
       
  3484     if (d->baseWidget && d->baseWidget->sizeHint().isValid())
       
  3485         size += d->baseWidget->sizeHint();
       
  3486     return size.expandedTo(minimumSizeHint());
       
  3487 }
       
  3488 
       
  3489 /*!
       
  3490     \reimp
       
  3491 */
       
  3492 QSize QMdiSubWindow::minimumSizeHint() const
       
  3493 {
       
  3494     Q_D(const QMdiSubWindow);
       
  3495     if (isVisible())
       
  3496         ensurePolished();
       
  3497 
       
  3498     // Minimized window.
       
  3499     if (parent() && isMinimized() && !isShaded())
       
  3500         return d->iconSize();
       
  3501 
       
  3502     // Calculate window decoration.
       
  3503     int margin, minWidth;
       
  3504     d->sizeParameters(&margin, &minWidth);
       
  3505     int decorationHeight = margin + d->titleBarHeight();
       
  3506     int minHeight = decorationHeight;
       
  3507 
       
  3508     // Shaded window.
       
  3509     if (parent() && isShaded())
       
  3510         return QSize(qMax(minWidth, width()), d->titleBarHeight());
       
  3511 
       
  3512     // Content
       
  3513     if (layout()) {
       
  3514         QSize minLayoutSize = layout()->minimumSize();
       
  3515         if (minLayoutSize.isValid()) {
       
  3516             minWidth = qMax(minWidth, minLayoutSize.width() + 2 * margin);
       
  3517             minHeight += minLayoutSize.height();
       
  3518         }
       
  3519     } else if (d->baseWidget && d->baseWidget->isVisible()) {
       
  3520         QSize minBaseWidgetSize = d->baseWidget->minimumSizeHint();
       
  3521         if (minBaseWidgetSize.isValid()) {
       
  3522             minWidth = qMax(minWidth, minBaseWidgetSize.width() + 2 * margin);
       
  3523             minHeight += minBaseWidgetSize.height();
       
  3524         }
       
  3525     }
       
  3526 
       
  3527 #ifndef QT_NO_SIZEGRIP
       
  3528     // SizeGrip
       
  3529     int sizeGripHeight = 0;
       
  3530     if (d->sizeGrip && d->sizeGrip->isVisibleTo(const_cast<QMdiSubWindow *>(this)))
       
  3531         sizeGripHeight = d->sizeGrip->height();
       
  3532 #if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
       
  3533     else if (parent() && qobject_cast<QMacStyle *>(style()) && !d->sizeGrip)
       
  3534         sizeGripHeight = style()->pixelMetric(QStyle::PM_SizeGripSize, 0, this);
       
  3535 #endif
       
  3536     minHeight = qMax(minHeight, decorationHeight + sizeGripHeight);
       
  3537 #endif
       
  3538 
       
  3539     return QSize(minWidth, minHeight).expandedTo(QApplication::globalStrut());
       
  3540 }
       
  3541 
       
  3542 QT_END_NAMESPACE
       
  3543 
       
  3544 #include "moc_qmdisubwindow.cpp"
       
  3545 #include "qmdisubwindow.moc"
       
  3546 
       
  3547 #endif //QT_NO_MDIAREA