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