6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
96
97
98
99
100
101
104
105
106
107
108
109
110
111
112
116#include <QApplication>
117#include <QStylePainter>
118#include <QVBoxLayout>
119#include <QMouseEvent>
120#if QT_CONFIG(whatsthis)
123#if QT_CONFIG(tooltip)
126#if QT_CONFIG(mainwindow)
127#include <QMainWindow>
132#include <QScopedValueRollback>
139#include <QProxyStyle>
143using namespace Qt::StringLiterals;
144using namespace std::chrono_literals;
150 QStyle::SC_TitleBarLabel,
151 QStyle::SC_TitleBarSysMenu,
152 QStyle::SC_TitleBarMinButton,
153 QStyle::SC_TitleBarMaxButton,
154 QStyle::SC_TitleBarShadeButton,
155 QStyle::SC_TitleBarCloseButton,
156 QStyle::SC_TitleBarNormalButton,
157 QStyle::SC_TitleBarUnshadeButton,
158 QStyle::SC_TitleBarContextHelpButton
163 Qt::FramelessWindowHint
164 | Qt::CustomizeWindowHint
165 | Qt::WindowTitleHint
166 | Qt::WindowSystemMenuHint
167 | Qt::WindowMinimizeButtonHint
168 | Qt::WindowMaximizeButtonHint
169 | Qt::WindowMinMaxButtonsHint;
176 auto proxyStyle = qobject_cast<QProxyStyle *>(style);
177 auto styleToCheck = proxyStyle ? proxyStyle->baseStyle() : style;
178 return styleToCheck->inherits(
"QMacStyle");
182 int delta,
int maxDelta,
int minDelta)
184 if (cflags & moveFlag) {
186 return (cflags & resizeFlag) ? qMin(delta, maxDelta) : delta;
187 return (cflags & resizeFlag) ? qMax(delta, minDelta) : delta;
193 uint resizeReverseFlag,
int delta)
195 if (cflags & resizeFlag) {
196 if (cflags & resizeReverseFlag)
206 QWidget *parent = child->parentWidget();
208 if (qobject_cast<QMdiSubWindow *>(parent))
210 parent = parent->parentWidget();
218 if (QMdiArea *mdiArea = child->mdiArea()) {
219 if (mdiArea->viewMode() == QMdiArea::TabbedView)
228 if (widget && widget->qt_metacast(
"ControlElement")
229 && strcmp(widget->metaObject()->className(), T::staticMetaObject.className()) == 0) {
235QString QMdiSubWindowPrivate::originalWindowTitleHelper()
const
237 Q_Q(
const QMdiSubWindow);
240 if (
auto *mdiArea = q->mdiArea()) {
241 const auto &subWindows = mdiArea->subWindowList();
242 for (
auto *subWindow : subWindows) {
243 if (subWindow != q && subWindow->isMaximized()) {
244 auto *subWindowD =
static_cast<QMdiSubWindowPrivate *>(qt_widget_private(subWindow));
245 if (!subWindowD->originalTitle.isNull())
246 return subWindowD->originalTitle;
250 return q->window()->windowTitle();
253QString QMdiSubWindowPrivate::originalWindowTitle()
255 if (originalTitle.isNull()) {
256 originalTitle = originalWindowTitleHelper();
257 if (originalTitle.isNull())
258 originalTitle =
""_L1;
260 return originalTitle;
263void QMdiSubWindowPrivate::setNewWindowTitle()
266 QString childTitle = q->windowTitle();
267 if (childTitle.isEmpty())
269 QString original = originalWindowTitle();
270 if (!original.isEmpty()) {
271 if (!original.contains(QMdiSubWindow::tr(
"- [%1]").arg(childTitle))) {
272 auto title = QMdiSubWindow::tr(
"%1 - [%2]").arg(original, childTitle);
273 ignoreWindowTitleChange =
true;
274 q->window()->setWindowTitle(title);
275 ignoreWindowTitleChange =
false;
279 ignoreWindowTitleChange =
true;
280 q->window()->setWindowTitle(childTitle);
281 ignoreWindowTitleChange =
false;
287 return control != QStyle::SC_None && control != QStyle::SC_TitleBarLabel;
290#if QT_CONFIG(tooltip)
291static void showToolTip(QHelpEvent *helpEvent, QWidget *widget,
const QStyleOptionComplex &opt,
292 QStyle::ComplexControl complexControl, QStyle::SubControl subControl)
295 Q_ASSERT(helpEvent->type() == QEvent::ToolTip);
298 if (widget->style()->styleHint(QStyle::SH_TitleBar_ShowToolTipsOnButtons, &opt, widget))
303 if (complexControl == QStyle::CC_MdiControls) {
304 if (subControl == QStyle::SC_MdiMinButton)
305 subControl = QStyle::SC_TitleBarMinButton;
306 else if (subControl == QStyle::SC_MdiCloseButton)
307 subControl = QStyle::SC_TitleBarCloseButton;
308 else if (subControl == QStyle::SC_MdiNormalButton)
309 subControl = QStyle::SC_TitleBarNormalButton;
311 subControl = QStyle::SC_None;
315 if (subControl == QStyle::SC_None)
320 switch (subControl) {
321 case QStyle::SC_TitleBarMinButton:
322 toolTip = QMdiSubWindow::tr(
"Minimize");
324 case QStyle::SC_TitleBarMaxButton:
325 toolTip = QMdiSubWindow::tr(
"Maximize");
327 case QStyle::SC_TitleBarUnshadeButton:
328 toolTip = QMdiSubWindow::tr(
"Unshade");
330 case QStyle::SC_TitleBarShadeButton:
331 toolTip = QMdiSubWindow::tr(
"Shade");
333 case QStyle::SC_TitleBarNormalButton:
334 if (widget->isMaximized() || !qobject_cast<QMdiSubWindow *>(widget))
335 toolTip = QMdiSubWindow::tr(
"Restore Down");
337 toolTip = QMdiSubWindow::tr(
"Restore");
339 case QStyle::SC_TitleBarCloseButton:
340 toolTip = QMdiSubWindow::tr(
"Close");
342 case QStyle::SC_TitleBarContextHelpButton:
343 toolTip = QMdiSubWindow::tr(
"Help");
345 case QStyle::SC_TitleBarSysMenu:
346 toolTip = QMdiSubWindow::tr(
"Menu");
352 const QRect rect = widget->style()->subControlRect(complexControl, &opt, subControl, widget);
353 QToolTip::showText(helpEvent->globalPos(), toolTip, widget, rect);
359
360
361
384 void updateWindowIcon();
389 : QWidget(parent), isPressed(
false)
391 setFocusPolicy(Qt::NoFocus);
393 setFixedSize(label.deviceIndependentSize().toSize());
397
398
401 return label.deviceIndependentSize().toSize();
405
406
409 if (event->type() == QEvent::WindowIconChange)
411 else if (event->type() == QEvent::StyleChange) {
413 setFixedSize(label.size());
415#if QT_CONFIG(tooltip)
416 else if (event->type() == QEvent::ToolTip) {
417 QStyleOptionTitleBar options;
418 options.initFrom(
this);
419 showToolTip(
static_cast<QHelpEvent *>(event),
this, options,
420 QStyle::CC_TitleBar, QStyle::SC_TitleBarSysMenu);
423 return QWidget::event(event);
427
428
431 QPainter painter(
this);
432 painter.drawPixmap(0, 0, label);
436
437
440 if (mouseEvent->button() != Qt::LeftButton) {
441 mouseEvent->ignore();
448
449
452 if (mouseEvent->button() != Qt::LeftButton) {
453 mouseEvent->ignore();
457 emit _q_doubleClicked();
461
462
465 if (mouseEvent->button() != Qt::LeftButton) {
466 mouseEvent->ignore();
476
477
480 QIcon menuIcon = windowIcon();
481 if (menuIcon.isNull())
482 menuIcon = style()->standardIcon(QStyle::SP_TitleBarMenuButton,
nullptr, parentWidget());
483 const int iconSize = style()->pixelMetric(QStyle::PM_TitleBarButtonIconSize,
nullptr, parentWidget());
484 label = menuIcon.pixmap(QSize(iconSize, iconSize), devicePixelRatio());
490
491
492
502 return (visibleControls & QStyle::SC_MdiMinButton)
503 || (visibleControls & QStyle::SC_MdiNormalButton)
504 || (visibleControls & QStyle::SC_MdiCloseButton);
521 QStyle::SubControl activeControl;
522 QStyle::SubControl hoverControl;
523 QStyle::SubControls visibleControls;
524 void initStyleOption(QStyleOptionComplex *option)
const;
525 inline QStyle::SubControl getSubControl(
const QPoint &pos)
const
527 QStyleOptionComplex opt;
528 initStyleOption(&opt);
529 return style()->hitTestComplexControl(QStyle::CC_MdiControls, &opt, pos,
this);
535
536
539 activeControl(QStyle::SC_None),
540 hoverControl(QStyle::SC_None),
541 visibleControls(QStyle::SC_None)
543 setFocusPolicy(Qt::NoFocus);
544 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
545 setMouseTracking(
true);
549
550
554 QStyleOptionComplex opt;
555 initStyleOption(&opt);
556 const int buttonSize = style()->pixelMetric(QStyle::PM_TitleBarButtonSize, &opt,
this);
557 QSize size(3 * buttonSize, buttonSize);
558 return style()->sizeFromContents(QStyle::CT_MdiControls, &opt, size,
this);
563 QStyle::SubControl subControl = QStyle::SC_None;
566 if (action == QMdiSubWindowPrivate::MaximizeAction)
567 subControl = QStyle::SC_MdiNormalButton;
568 else if (action == QMdiSubWindowPrivate::CloseAction)
569 subControl = QStyle::SC_MdiCloseButton;
570 else if (action == QMdiSubWindowPrivate::MinimizeAction)
571 subControl = QStyle::SC_MdiMinButton;
573 if (subControl == QStyle::SC_None)
576 visibleControls.setFlag(subControl, visible && !(visibleControls & subControl));
580
581
584 QStyleOptionComplex opt;
585 initStyleOption(&opt);
586 if (activeControl == hoverControl) {
587 opt.activeSubControls = activeControl;
588 opt.state |= QStyle::State_Sunken;
589 }
else if (hoverControl != QStyle::SC_None && (activeControl == QStyle::SC_None)) {
590 opt.activeSubControls = hoverControl;
591 opt.state |= QStyle::State_MouseOver;
593 QPainter painter(
this);
594 style()->drawComplexControl(QStyle::CC_MdiControls, &opt, &painter,
this);
598
599
602 if (event->button() != Qt::LeftButton) {
606 activeControl = getSubControl(event->position().toPoint());
611
612
615 if (event->button() != Qt::LeftButton) {
620 QStyle::SubControl under_mouse = getSubControl(event->position().toPoint());
621 if (under_mouse == activeControl) {
622 switch (activeControl) {
623 case QStyle::SC_MdiCloseButton:
626 case QStyle::SC_MdiNormalButton:
629 case QStyle::SC_MdiMinButton:
637 activeControl = QStyle::SC_None;
642
643
646 QStyle::SubControl under_mouse = getSubControl(event->position().toPoint());
648 if (hoverControl != under_mouse) {
649 hoverControl = under_mouse;
655
656
659 hoverControl = QStyle::SC_None;
664
665
668#if QT_CONFIG(tooltip)
669 if (event->type() == QEvent::ToolTip) {
670 QStyleOptionComplex opt;
671 initStyleOption(&opt);
672 QHelpEvent *helpEvent =
static_cast<QHelpEvent *>(event);
673 showToolTip(helpEvent,
this, opt, QStyle::CC_MdiControls, getSubControl(helpEvent->pos()));
676 return QWidget::event(event);
680
681
684 option->initFrom(
this);
685 option->subControls = visibleControls;
686 option->activeSubControls = QStyle::SC_None;
690
691
696#if QT_CONFIG(menubar)
703 m_controllerWidget =
new ControlElement<ControllerWidget>(mdiChild);
704 connect(m_controllerWidget, SIGNAL(_q_close()), mdiChild, SLOT(close()));
705 connect(m_controllerWidget, SIGNAL(_q_restore()), mdiChild, SLOT(showNormal()));
706 connect(m_controllerWidget, SIGNAL(_q_minimize()), mdiChild, SLOT(showMinimized()));
708 m_menuLabel =
new ControlElement<ControlLabel>(mdiChild);
709 m_menuLabel->setWindowIcon(mdiChild->windowIcon());
711 connect(m_menuLabel, SIGNAL(_q_clicked()), mdiChild, SLOT(showSystemMenu()));
713 connect(m_menuLabel, SIGNAL(_q_doubleClicked()), mdiChild, SLOT(close()));
718#if QT_CONFIG(menubar)
719 removeButtonsFromMenuBar();
722 m_menuLabel =
nullptr;
723 delete m_controllerWidget;
724 m_controllerWidget =
nullptr;
727#if QT_CONFIG(menubar)
729
730
731QMenuBar *QMdiSubWindowPrivate::menuBar()
const
733#if !QT_CONFIG(mainwindow)
736 Q_Q(
const QMdiSubWindow);
737 if (!q->isMaximized() || drawTitleBarWhenMaximized() || isChildOfTabbedQMdiArea(q))
740 if (QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q->window()))
741 return mainWindow->menuBar();
748
749
750void ControlContainer::showButtonsInMenuBar(QMenuBar *menuBar)
752 if (!menuBar || !mdiChild || mdiChild->windowFlags() & Qt::FramelessWindowHint)
756 if (m_menuLabel && mdiChild->windowFlags() & Qt::WindowSystemMenuHint) {
757 QWidget *currentLeft = menuBar->cornerWidget(Qt::TopLeftCorner);
760 if (currentLeft != m_menuLabel) {
761 menuBar->setCornerWidget(m_menuLabel, Qt::TopLeftCorner);
762 previousLeft = currentLeft;
766 ControllerWidget *controllerWidget = qobject_cast<ControllerWidget *>(m_controllerWidget);
767 if (controllerWidget && controllerWidget->hasVisibleControls()) {
768 QWidget *currentRight = menuBar->cornerWidget(Qt::TopRightCorner);
770 currentRight->hide();
771 if (currentRight != m_controllerWidget) {
772 menuBar->setCornerWidget(m_controllerWidget, Qt::TopRightCorner);
773 previousRight = currentRight;
775 m_controllerWidget->show();
777 mdiChild->d_func()->setNewWindowTitle();
781
782
783void ControlContainer::removeButtonsFromMenuBar(QMenuBar *menuBar)
785 if (menuBar && menuBar != m_menuBar) {
787 previousRight =
nullptr;
788 previousLeft =
nullptr;
792 if (!m_menuBar || !mdiChild || qt_widget_private(mdiChild->window())->data.in_destructor)
795 QMdiSubWindow *child =
nullptr;
796 if (m_controllerWidget) {
797 QWidget *currentRight = m_menuBar->cornerWidget(Qt::TopRightCorner);
798 if (currentRight == m_controllerWidget) {
799 if (ControlElement<ControllerWidget> *ce = ptr<ControllerWidget>(previousRight)) {
800 if (!ce->mdiChild || !ce->mdiChild->isMaximized())
801 previousRight =
nullptr;
803 child = ce->mdiChild;
805 m_menuBar->setCornerWidget(previousRight, Qt::TopRightCorner);
807 previousRight->show();
808 previousRight =
nullptr;
811 m_controllerWidget->hide();
812 m_controllerWidget->setParent(
nullptr);
815 QWidget *currentLeft = m_menuBar->cornerWidget(Qt::TopLeftCorner);
816 if (currentLeft == m_menuLabel) {
817 if (ControlElement<ControlLabel> *ce = ptr<ControlLabel>(previousLeft)) {
818 if (!ce->mdiChild || !ce->mdiChild->isMaximized())
819 previousLeft =
nullptr;
823 m_menuBar->setCornerWidget(previousLeft, Qt::TopLeftCorner);
825 previousLeft->show();
826 previousLeft =
nullptr;
830 m_menuLabel->setParent(
nullptr);
834 child->d_func()->setNewWindowTitle();
836 mdiChild->window()->setWindowTitle(mdiChild->d_func()->originalWindowTitle());
844 m_menuLabel->setWindowIcon(windowIcon);
848
849
850QMdiSubWindowPrivate::QMdiSubWindowPrivate()
851 : baseWidget(
nullptr),
852 restoreFocusWidget(
nullptr),
853 controlContainer(
nullptr),
854#if QT_CONFIG(sizegrip)
857#if QT_CONFIG(rubberband)
860 userMinimumSize(0,0),
863 isInInteractiveMode(
false),
864#if QT_CONFIG(rubberband)
865 isInRubberBandMode(
false),
868 ignoreWindowTitleChange(
false),
869 ignoreNextActivationEvent(
false),
870 activationEnabled(
true),
871 isShadeRequestFromMinimizeMode(
false),
872 isMaximizeMode(
false),
873 isWidgetHiddenByUs(
false),
875 isExplicitlyDeactivated(
false),
876 keyboardSingleStep(5),
877 keyboardPageStep(20),
878 currentOperation(None),
879 hoveredSubControl(QStyle::SC_None),
880 activeSubControl(QStyle::SC_None),
881 focusInReason(Qt::ActiveWindowFocusReason)
887
888
889void QMdiSubWindowPrivate::_q_updateStaysOnTopHint()
893 if (QAction *senderAction = qobject_cast<QAction *>(q->sender())) {
894 if (senderAction->isChecked()) {
895 q->setWindowFlags(q->windowFlags() | Qt::WindowStaysOnTopHint);
898 q->setWindowFlags(q->windowFlags() & ~Qt::WindowStaysOnTopHint);
906
907
908void QMdiSubWindowPrivate::_q_enterInteractiveMode()
912 QAction *action = qobject_cast<QAction *>(q->sender());
917 if (actions[MoveAction] && actions[MoveAction] == action) {
918 currentOperation = Move;
919 pressPos = QPoint(q->width() / 2, titleBarHeight() - 1);
920 }
else if (actions[ResizeAction] && actions[ResizeAction] == action) {
921 currentOperation = q->isLeftToRight() ? BottomRightResize : BottomLeftResize;
922 int offset = q->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth,
nullptr, q) / 2;
923 int x = q->isLeftToRight() ? q->width() - offset : offset;
924 pressPos = QPoint(x, q->height() - offset);
931 q->cursor().setPos(q->mapToGlobal(pressPos));
933 mousePressPosition = q->mapToParent(pressPos);
934 oldGeometry = q->geometry();
935 isInInteractiveMode =
true;
937#if QT_CONFIG(rubberband)
938 if ((q->testOption(QMdiSubWindow::RubberBandResize)
939 && (currentOperation == BottomRightResize || currentOperation == BottomLeftResize))
940 || (q->testOption(QMdiSubWindow::RubberBandMove) && currentOperation == Move)) {
941 enterRubberBandMode();
951
952
953void QMdiSubWindowPrivate::_q_processFocusChanged(QWidget *old, QWidget *now)
957 if (now && (now == q || q->isAncestorOf(now))) {
958 if (now == q && !isInInteractiveMode)
965
966
967void QMdiSubWindowPrivate::leaveInteractiveMode()
970#if QT_CONFIG(rubberband)
971 if (isInRubberBandMode)
972 leaveRubberBandMode();
976 isInInteractiveMode =
false;
977 currentOperation = None;
978 updateDirtyRegions();
980 if (baseWidget && baseWidget->focusWidget())
981 baseWidget->focusWidget()->setFocus();
985
986
987void QMdiSubWindowPrivate::removeBaseWidget()
993 baseWidget->removeEventFilter(q);
995 layout->removeWidget(baseWidget);
996 if (baseWidget->windowTitle() == q->windowTitle()) {
997 ignoreWindowTitleChange =
true;
998 q->setWindowTitle(QString());
999 ignoreWindowTitleChange =
false;
1000 q->setWindowModified(
false);
1002 lastChildWindowTitle.clear();
1004 if (baseWidget->parentWidget() == q)
1005 baseWidget->setParent(
nullptr);
1006 baseWidget =
nullptr;
1007 isWidgetHiddenByUs =
false;
1011
1012
1013void QMdiSubWindowPrivate::initOperationMap()
1015 operationMap.insert(Move, OperationInfo(HMove | VMove, Qt::ArrowCursor,
false));
1016 operationMap.insert(TopResize, OperationInfo(VMove | VResize | VResizeReverse, Qt::SizeVerCursor));
1017 operationMap.insert(BottomResize, OperationInfo(VResize, Qt::SizeVerCursor));
1018 operationMap.insert(LeftResize, OperationInfo(HMove | HResize | HResizeReverse, Qt::SizeHorCursor));
1019 operationMap.insert(RightResize, OperationInfo(HResize, Qt::SizeHorCursor));
1020 operationMap.insert(TopLeftResize, OperationInfo(HMove | VMove | HResize | VResize | VResizeReverse
1021 | HResizeReverse, Qt::SizeFDiagCursor));
1022 operationMap.insert(TopRightResize, OperationInfo(VMove | HResize | VResize
1023 | VResizeReverse, Qt::SizeBDiagCursor));
1024 operationMap.insert(BottomLeftResize, OperationInfo(HMove | HResize | VResize | HResizeReverse,
1025 Qt::SizeBDiagCursor));
1026 operationMap.insert(BottomRightResize, OperationInfo(HResize | VResize, Qt::SizeFDiagCursor));
1032
1033
1034void QMdiSubWindowPrivate::createSystemMenu()
1037 Q_ASSERT_X(q,
"QMdiSubWindowPrivate::createSystemMenu",
1038 "You can NOT call this function before QMdiSubWindow's ctor");
1039 systemMenu =
new QMenu(q);
1040 systemMenu->installEventFilter(q);
1041 const QStyle *style = q->style();
1042 addToSystemMenu(RestoreAction, QMdiSubWindow::tr(
"&Restore"), SLOT(showNormal()));
1043 actions[RestoreAction]->setIcon(style->standardIcon(QStyle::SP_TitleBarNormalButton,
nullptr, q));
1044 actions[RestoreAction]->setEnabled(
false);
1045 addToSystemMenu(MoveAction, QMdiSubWindow::tr(
"&Move"), SLOT(_q_enterInteractiveMode()));
1046 addToSystemMenu(ResizeAction, QMdiSubWindow::tr(
"&Size"), SLOT(_q_enterInteractiveMode()));
1047 addToSystemMenu(MinimizeAction, QMdiSubWindow::tr(
"Mi&nimize"), SLOT(showMinimized()));
1048 actions[MinimizeAction]->setIcon(style->standardIcon(QStyle::SP_TitleBarMinButton,
nullptr, q));
1049 addToSystemMenu(MaximizeAction, QMdiSubWindow::tr(
"Ma&ximize"), SLOT(showMaximized()));
1050 actions[MaximizeAction]->setIcon(style->standardIcon(QStyle::SP_TitleBarMaxButton,
nullptr, q));
1051 addToSystemMenu(StayOnTopAction, QMdiSubWindow::tr(
"Stay on &Top"), SLOT(_q_updateStaysOnTopHint()));
1052 actions[StayOnTopAction]->setCheckable(
true);
1053 systemMenu->addSeparator();
1054 addToSystemMenu(CloseAction, QMdiSubWindow::tr(
"&Close"), SLOT(close()));
1055 actions[CloseAction]->setIcon(style->standardIcon(QStyle::SP_TitleBarCloseButton,
nullptr, q));
1056#if !defined(QT_NO_SHORTCUT)
1057 actions[CloseAction]->setShortcuts(QKeySequence::Close);
1064
1065
1066void QMdiSubWindowPrivate::updateCursor()
1070 if (isMacStyle(q->style()))
1073 if (currentOperation == None) {
1078 if (currentOperation == Move || operationMap.find(currentOperation).value().hover) {
1079 q->setCursor(operationMap.find(currentOperation).value().cursorShape);
1086
1087
1088void QMdiSubWindowPrivate::updateDirtyRegions()
1094 for (OperationInfoMap::iterator it = operationMap.begin(), end = operationMap.end(); it != end; ++it)
1095 it.value().region = getRegion(it.key());
1099
1100
1101void QMdiSubWindowPrivate::updateGeometryConstraints()
1107 internalMinimumSize = (!q->isMinimized() && !q->minimumSize().isNull())
1108 ? q->minimumSize() : q->minimumSizeHint();
1109 int margin, minWidth;
1110 sizeParameters(&margin, &minWidth);
1111 q->setContentsMargins(margin, titleBarHeight(), margin, margin);
1112 if (q->isMaximized() || (q->isMinimized() && !q->isShaded())) {
1113 moveEnabled =
false;
1114 resizeEnabled =
false;
1117 if ((q->windowFlags() & Qt::MSWindowsFixedSizeDialogHint) || q->isShaded())
1118 resizeEnabled =
false;
1120 resizeEnabled =
true;
1122 updateDirtyRegions();
1126
1127
1128void QMdiSubWindowPrivate::updateMask()
1131 if (!q->mask().isEmpty())
1137 if ((q->isMaximized() && !drawTitleBarWhenMaximized())
1138 || q->windowFlags() & Qt::FramelessWindowHint)
1141 if (!resizeTimer.isActive())
1142 cachedStyleOptions = titleBarOptions();
1143 cachedStyleOptions.rect = q->rect();
1144 QStyleHintReturnMask frameMask;
1145 q->style()->styleHint(QStyle::SH_WindowFrame_Mask, &cachedStyleOptions, q, &frameMask);
1146 if (!frameMask.region.isEmpty())
1147 q->setMask(frameMask.region);
1151
1152
1153void QMdiSubWindowPrivate::setNewGeometry(
const QPoint &pos)
1156 Q_ASSERT(currentOperation != None);
1159 uint cflags = operationMap.find(currentOperation).value().changeFlags;
1163 const bool restrictHorizontal = !q->testOption(QMdiSubWindow::AllowOutsideAreaHorizontally);
1164 const bool restrictVertical = !q->testOption(QMdiSubWindow::AllowOutsideAreaVertically);
1166 if (restrictHorizontal || restrictVertical) {
1167 QRect parentRect = q->parentWidget()->rect();
1168 if (restrictVertical && (cflags & VResizeReverse || currentOperation == Move)) {
1169 posY = qMin(qMax(mousePressPosition.y() - oldGeometry.y(), posY),
1170 parentRect.height() - BoundaryMargin);
1172 if (currentOperation == Move) {
1173 if (restrictHorizontal)
1174 posX = qMin(qMax(BoundaryMargin, posX), parentRect.width() - BoundaryMargin);
1175 if (restrictVertical)
1176 posY = qMin(posY, parentRect.height() - BoundaryMargin);
1178 if (restrictHorizontal) {
1179 if (cflags & HResizeReverse)
1180 posX = qMax(mousePressPosition.x() - oldGeometry.x(), posX);
1182 posX = qMin(parentRect.width() - (oldGeometry.x() + oldGeometry.width()
1183 - mousePressPosition.x()), posX);
1185 if (restrictVertical && !(cflags & VResizeReverse)) {
1186 posY = qMin(parentRect.height() - (oldGeometry.y() + oldGeometry.height()
1187 - mousePressPosition.y()), posY);
1193 if (cflags & (HMove | VMove)) {
1194 int dx = getMoveDeltaComponent(cflags, HMove, HResize, posX - mousePressPosition.x(),
1195 oldGeometry.width() - internalMinimumSize.width(),
1196 oldGeometry.width() - q->maximumWidth());
1197 int dy = getMoveDeltaComponent(cflags, VMove, VResize, posY - mousePressPosition.y(),
1198 oldGeometry.height() - internalMinimumSize.height(),
1199 oldGeometry.height() - q->maximumHeight());
1200 geometry.setTopLeft(oldGeometry.topLeft() + QPoint(dx, dy));
1202 geometry.setTopLeft(q->geometry().topLeft());
1205 if (cflags & (HResize | VResize)) {
1206 int dx = getResizeDeltaComponent(cflags, HResize, HResizeReverse,
1207 posX - mousePressPosition.x());
1208 int dy = getResizeDeltaComponent(cflags, VResize, VResizeReverse,
1209 posY - mousePressPosition.y());
1210 geometry.setSize(oldGeometry.size() + QSize(dx, dy));
1212 geometry.setSize(q->geometry().size());
1215 setNewGeometry(&geometry);
1219
1220
1221void QMdiSubWindowPrivate::setMinimizeMode()
1226 ensureWindowState(Qt::WindowMinimized);
1227 isShadeRequestFromMinimizeMode =
true;
1229 isShadeRequestFromMinimizeMode =
false;
1231 moveEnabled =
false;
1233 setEnabled(MoveAction, moveEnabled);
1236 Q_ASSERT(q->windowState() & Qt::WindowMinimized);
1237 Q_ASSERT(!(q->windowState() & Qt::WindowMaximized));
1247
1248
1249void QMdiSubWindowPrivate::setNormalMode()
1254 isShadeMode =
false;
1255 isMaximizeMode =
false;
1257 ensureWindowState(Qt::WindowNoState);
1258#if QT_CONFIG(menubar)
1259 removeButtonsFromMenuBar();
1264 const bool wasVisible = q->isVisible();
1266 q->setVisible(
false);
1269 if (!userMinimumSize.isNull()) {
1270 q->setMinimumSize(userMinimumSize);
1271 userMinimumSize = QSize(0, 0);
1275 if (baseWidget && isWidgetHiddenByUs) {
1277 isWidgetHiddenByUs =
false;
1280 updateGeometryConstraints();
1281 QRect newGeometry = oldGeometry;
1282 newGeometry.setSize(restoreSize.expandedTo(internalMinimumSize));
1283 q->setGeometry(newGeometry);
1286 q->setVisible(
true);
1289 restoreSize.setWidth(-1);
1290 restoreSize.setHeight(-1);
1292#if QT_CONFIG(sizegrip)
1293 setSizeGripVisible(
true);
1297 setEnabled(MoveAction,
true);
1298 setEnabled(MaximizeAction,
true);
1299 setEnabled(MinimizeAction,
true);
1300 setEnabled(RestoreAction,
false);
1301 setEnabled(ResizeAction, resizeEnabled);
1304 Q_ASSERT(!(q_func()->windowState() & Qt::WindowMinimized));
1308 Q_ASSERT((isMaximizeMode && q_func()->windowState() & Qt::WindowMaximized)
1309 || (!isMaximizeMode && !(q_func()->windowState() & Qt::WindowMaximized)));
1310 Q_ASSERT(!isShadeMode);
1317inline void QMdiSubWindowPrivate::storeFocusWidget()
1319 if (QWidget *focus = QApplication::focusWidget()) {
1320 if (!restoreFocusWidget && q_func()->isAncestorOf(focus))
1321 restoreFocusWidget = focus;
1326
1327
1328void QMdiSubWindowPrivate::setMaximizeMode()
1333 ensureWindowState(Qt::WindowMaximized);
1334 isShadeMode =
false;
1335 isMaximizeMode =
true;
1339#if QT_CONFIG(sizegrip)
1340 setSizeGripVisible(
false);
1344 if (!restoreSize.isValid()) {
1345 oldGeometry = q->geometry();
1346 restoreSize.setWidth(oldGeometry.width());
1347 restoreSize.setHeight(oldGeometry.height());
1352 const bool wasVisible = q->isVisible();
1354 q->setVisible(
false);
1357 if (baseWidget && isWidgetHiddenByUs) {
1359 isWidgetHiddenByUs =
false;
1362 updateGeometryConstraints();
1365#if QT_CONFIG(menubar)
1366 if (QMenuBar *mBar = menuBar())
1367 showButtonsInMenuBar(mBar);
1370 if (!controlContainer)
1371 controlContainer =
new ControlContainer(q);
1374 QWidget *parent = q->parentWidget();
1375 QRect availableRect = parent->contentsRect();
1378 QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent->parentWidget());
1379 if (scrollArea && scrollArea->viewport() == parent) {
1380 QScrollBar *hbar = scrollArea->horizontalScrollBar();
1381 QScrollBar *vbar = scrollArea->verticalScrollBar();
1382 const int xOffset = hbar ? hbar->value() : 0;
1383 const int yOffset = vbar ? vbar->value() : 0;
1384 availableRect.adjust(-xOffset, -yOffset, -xOffset, -yOffset);
1385 oldGeometry.adjust(xOffset, yOffset, xOffset, yOffset);
1388 setNewGeometry(&availableRect);
1390 ensureWindowState(Qt::WindowMaximized);
1393 q->setVisible(
true);
1395 resizeEnabled =
false;
1396 moveEnabled =
false;
1399 setEnabled(MoveAction, moveEnabled);
1400 setEnabled(MaximizeAction,
false);
1401 setEnabled(MinimizeAction,
true);
1402 setEnabled(RestoreAction,
true);
1403 setEnabled(ResizeAction, resizeEnabled);
1406 Q_ASSERT(q->windowState() & Qt::WindowMaximized);
1407 Q_ASSERT(!(q->windowState() & Qt::WindowMinimized));
1414
1415
1416void QMdiSubWindowPrivate::setActive(
bool activate,
bool changeFocus)
1419 if (!parent || !activationEnabled)
1422 if (activate && !isActive && q->isEnabled()) {
1424 isExplicitlyDeactivated =
false;
1425 Qt::WindowStates oldWindowState = q->windowState();
1426 ensureWindowState(Qt::WindowActive);
1427 emit q->aboutToActivate();
1428#if QT_CONFIG(menubar)
1429 if (QMenuBar *mBar = menuBar())
1430 showButtonsInMenuBar(mBar);
1433 emit q->windowStateChanged(oldWindowState, q->windowState());
1434 }
else if (!activate && isActive) {
1436 Qt::WindowStates oldWindowState = q->windowState();
1437 q->overrideWindowState(q->windowState() & ~Qt::WindowActive);
1440 QWidget *focusWidget = QApplication::focusWidget();
1441 if (focusWidget && (focusWidget == q || q->isAncestorOf(focusWidget)))
1442 focusWidget->clearFocus();
1445 baseWidget->overrideWindowState(baseWidget->windowState() & ~Qt::WindowActive);
1446 Q_ASSERT(!isActive);
1447 emit q->windowStateChanged(oldWindowState, q->windowState());
1450 if (activate && isActive && q->isEnabled() && !q->hasFocus()
1451 && !q->isAncestorOf(QApplication::focusWidget())) {
1454 ensureWindowState(Qt::WindowActive);
1457 int frameWidth = q->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth,
nullptr, q);
1458 int titleBarHeight =
this->titleBarHeight();
1459 QRegion windowDecoration = QRegion(0, 0, q->width(), q->height());
1460 windowDecoration -= QRegion(frameWidth, titleBarHeight, q->width() - 2 * frameWidth,
1461 q->height() - titleBarHeight - frameWidth);
1465 if (resizeTimer.isActive()) {
1467 updateDirtyRegions();
1470 q->update(windowDecoration);
1474
1475
1476void QMdiSubWindowPrivate::processClickedSubControl()
1479 switch (activeSubControl) {
1480 case QStyle::SC_TitleBarContextHelpButton:
1481#if QT_CONFIG(whatsthis)
1482 QWhatsThis::enterWhatsThisMode();
1485 case QStyle::SC_TitleBarShadeButton:
1487 hoveredSubControl = QStyle::SC_TitleBarUnshadeButton;
1489 case QStyle::SC_TitleBarUnshadeButton:
1491 hoveredSubControl = QStyle::SC_TitleBarShadeButton;
1494 case QStyle::SC_TitleBarMinButton:
1495 if (isMacStyle(q->style())) {
1496 if (q->isMinimized())
1505 case QStyle::SC_TitleBarNormalButton:
1507 hoveredSubControl = QStyle::SC_TitleBarMinButton;
1510 case QStyle::SC_TitleBarMaxButton:
1511 if (isMacStyle(q->style())) {
1512 if (q->isMaximized())
1521 case QStyle::SC_TitleBarCloseButton:
1530
1531
1532QRegion QMdiSubWindowPrivate::getRegion(Operation operation)
const
1534 Q_Q(
const QMdiSubWindow);
1535 int width = q->width();
1536 int height = q->height();
1537 int titleBarHeight =
this->titleBarHeight();
1538 int frameWidth = q->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth,
nullptr, q);
1539 int cornerConst = titleBarHeight - frameWidth;
1540 int titleBarConst = 2 * titleBarHeight;
1542 if (operation == Move) {
1543 QStyleOptionTitleBar titleBarOptions =
this->titleBarOptions();
1544 QRegion move(frameWidth, frameWidth, width - 2 * frameWidth, cornerConst);
1547 for (
int i = 0; i < NumSubControls; ++i) {
1548 if (SubControls[i] == QStyle::SC_TitleBarLabel)
1550 move -= QRegion(q->style()->subControlRect(QStyle::CC_TitleBar, &titleBarOptions,
1557 if (isMacStyle(q->style()))
1560 switch (operation) {
1562 region = QRegion(titleBarHeight, 0, width - titleBarConst, frameWidth);
1565 region = QRegion(titleBarHeight, height - frameWidth, width - titleBarConst, frameWidth);
1568 region = QRegion(0, titleBarHeight, frameWidth, height - titleBarConst);
1571 region = QRegion(width - frameWidth, titleBarHeight, frameWidth, height - titleBarConst);
1574 region = QRegion(0, 0, titleBarHeight, titleBarHeight)
1575 - QRegion(frameWidth, frameWidth, cornerConst, cornerConst);
1577 case TopRightResize:
1578 region = QRegion(width - titleBarHeight, 0, titleBarHeight, titleBarHeight)
1579 - QRegion(width - titleBarHeight, frameWidth, cornerConst, cornerConst);
1581 case BottomLeftResize:
1582 region = QRegion(0, height - titleBarHeight, titleBarHeight, titleBarHeight)
1583 - QRegion(frameWidth, height - titleBarHeight, cornerConst, cornerConst);
1585 case BottomRightResize:
1586 region = QRegion(width - titleBarHeight, height - titleBarHeight, titleBarHeight, titleBarHeight)
1587 - QRegion(width - titleBarHeight, height - titleBarHeight, cornerConst, cornerConst);
1597
1598
1599QMdiSubWindowPrivate::Operation QMdiSubWindowPrivate::getOperation(
const QPoint &pos)
const
1601 OperationInfoMap::const_iterator it;
1602 for (it = operationMap.constBegin(); it != operationMap.constEnd(); ++it)
1603 if (it.value().region.contains(pos))
1611
1612
1613QStyleOptionTitleBar QMdiSubWindowPrivate::titleBarOptions()
const
1615 Q_Q(
const QMdiSubWindow);
1616 QStyleOptionTitleBar titleBarOptions;
1617 titleBarOptions.initFrom(q);
1618 if (activeSubControl != QStyle::SC_None) {
1619 if (hoveredSubControl == activeSubControl) {
1620 titleBarOptions.state |= QStyle::State_Sunken;
1621 titleBarOptions.activeSubControls = activeSubControl;
1623 }
else if (autoRaise() && hoveredSubControl != QStyle::SC_None
1624 && hoveredSubControl != QStyle::SC_TitleBarLabel) {
1625 titleBarOptions.state |= QStyle::State_MouseOver;
1626 titleBarOptions.activeSubControls = hoveredSubControl;
1628 titleBarOptions.state &= ~QStyle::State_MouseOver;
1629 titleBarOptions.activeSubControls = QStyle::SC_None;
1632 titleBarOptions.subControls = QStyle::SC_All;
1633 titleBarOptions.titleBarFlags = q->windowFlags();
1634 titleBarOptions.titleBarState = q->windowState();
1635 titleBarOptions.palette = titleBarPalette;
1636 titleBarOptions.icon = menuIcon;
1639 titleBarOptions.state |= QStyle::State_Active;
1640 titleBarOptions.titleBarState |= QStyle::State_Active;
1641 titleBarOptions.palette.setCurrentColorGroup(QPalette::Active);
1643 titleBarOptions.state &= ~QStyle::State_Active;
1644 titleBarOptions.palette.setCurrentColorGroup(QPalette::Inactive);
1647 int border = hasBorder(titleBarOptions) ? 4 : 0;
1648 int paintHeight = titleBarHeight(titleBarOptions);
1649 paintHeight -= q->isMinimized() ? 2 * border : border;
1650 titleBarOptions.rect = QRect(border, border, q->width() - 2 * border, paintHeight);
1652 if (!windowTitle.isEmpty()) {
1655 titleBarOptions.text = windowTitle;
1656 titleBarOptions.fontMetrics = QFontMetrics(font);
1657 int width = q->style()->subControlRect(QStyle::CC_TitleBar, &titleBarOptions,
1658 QStyle::SC_TitleBarLabel, q).width();
1660 titleBarOptions.text = titleBarOptions.fontMetrics.elidedText(windowTitle, Qt::ElideRight, width);
1662 return titleBarOptions;
1666
1667
1668void QMdiSubWindowPrivate::ensureWindowState(Qt::WindowState state)
1671 Qt::WindowStates windowStates = q->windowState() | state;
1673 case Qt::WindowMinimized:
1674 windowStates &= ~Qt::WindowMaximized;
1675 windowStates &= ~Qt::WindowFullScreen;
1676 windowStates &= ~Qt::WindowNoState;
1678 case Qt::WindowMaximized:
1679 windowStates &= ~Qt::WindowMinimized;
1680 windowStates &= ~Qt::WindowFullScreen;
1681 windowStates &= ~Qt::WindowNoState;
1683 case Qt::WindowNoState:
1684 windowStates &= ~Qt::WindowMinimized;
1685 windowStates &= ~Qt::WindowMaximized;
1686 windowStates &= ~Qt::WindowFullScreen;
1692 if (!(baseWidget->windowState() & Qt::WindowActive) && windowStates & Qt::WindowActive)
1693 baseWidget->overrideWindowState(windowStates & ~Qt::WindowActive);
1695 baseWidget->overrideWindowState(windowStates);
1697 q->overrideWindowState(windowStates);
1701
1702
1703int QMdiSubWindowPrivate::titleBarHeight(
const QStyleOptionTitleBar &options)
const
1705 Q_Q(
const QMdiSubWindow);
1706 if (!parent || q->windowFlags() & Qt::FramelessWindowHint
1707 || (q->isMaximized() && !drawTitleBarWhenMaximized())) {
1711 int height = q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &options, q);
1712 if (hasBorder(options))
1713 height += q->isMinimized() ? 8 : 4;
1718
1719
1720void QMdiSubWindowPrivate::sizeParameters(
int *margin,
int *minWidth)
const
1722 Q_Q(
const QMdiSubWindow);
1723 Qt::WindowFlags flags = q->windowFlags();
1724 if (!parent || flags & Qt::FramelessWindowHint) {
1730 if (q->isMaximized() && !drawTitleBarWhenMaximized())
1733 *margin = q->style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth,
nullptr, q);
1735 QStyleOptionTitleBar opt =
this->titleBarOptions();
1737 for (
int i = 0; i < NumSubControls; ++i) {
1738 if (SubControls[i] == QStyle::SC_TitleBarLabel) {
1742 QRect rect = q->style()->subControlRect(QStyle::CC_TitleBar, &opt, SubControls[i], q);
1743 if (!rect.isValid())
1745 tempWidth += rect.width();
1747 *minWidth = tempWidth;
1751
1752
1753bool QMdiSubWindowPrivate::drawTitleBarWhenMaximized()
const
1755 Q_Q(
const QMdiSubWindow);
1756 if (q->window()->testAttribute(Qt::WA_CanHostQMdiSubWindowTitleBar))
1759 if (isChildOfTabbedQMdiArea(q))
1762 if (q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize,
nullptr, q))
1764#if !QT_CONFIG(menubar) || !QT_CONFIG(mainwindow)
1765 Q_UNUSED(isChildOfQMdiSubWindow);
1768 QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q->window());
1769 if (!mainWindow || !qobject_cast<QMenuBar *>(mainWindow->menuWidget())
1770 || mainWindow->menuWidget()->isHidden())
1773 return isChildOfQMdiSubWindow(q);
1777#if QT_CONFIG(menubar)
1780
1781
1782void QMdiSubWindowPrivate::showButtonsInMenuBar(QMenuBar *menuBar)
1785 Q_ASSERT(q->isMaximized() && !drawTitleBarWhenMaximized());
1787 if (isChildOfTabbedQMdiArea(q))
1790 removeButtonsFromMenuBar();
1791 if (!controlContainer)
1792 controlContainer =
new ControlContainer(q);
1794 ignoreWindowTitleChange =
true;
1795 controlContainer->showButtonsInMenuBar(menuBar);
1796 ignoreWindowTitleChange =
false;
1798 QWidget *topLevelWindow = q->window();
1799 topLevelWindow->setWindowModified(q->isWindowModified());
1800 topLevelWindow->installEventFilter(q);
1802 int buttonHeight = 0;
1803 if (controlContainer->controllerWidget())
1804 buttonHeight = controlContainer->controllerWidget()->height();
1805 else if (controlContainer->systemMenuLabel())
1806 buttonHeight = controlContainer->systemMenuLabel()->height();
1809 if (menuBar && menuBar->height() < buttonHeight
1810 && topLevelWindow->layout()) {
1813 QEvent event(QEvent::LayoutRequest);
1814 QCoreApplication::sendEvent(topLevelWindow, &event);
1819
1820
1821void QMdiSubWindowPrivate::removeButtonsFromMenuBar()
1825 if (!controlContainer || isChildOfTabbedQMdiArea(q))
1828 QMenuBar *currentMenuBar =
nullptr;
1829#if QT_CONFIG(mainwindow)
1830 if (QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q->window())) {
1833 currentMenuBar = qobject_cast<QMenuBar *>(mainWindow->menuWidget());
1837 ignoreWindowTitleChange =
true;
1838 controlContainer->removeButtonsFromMenuBar(currentMenuBar);
1839 ignoreWindowTitleChange =
false;
1841 QWidget *topLevelWindow = q->window();
1842 topLevelWindow->removeEventFilter(q);
1843 if (baseWidget && !drawTitleBarWhenMaximized())
1844 topLevelWindow->setWindowModified(
false);
1845 originalTitle.clear();
1850void QMdiSubWindowPrivate::updateWindowTitle(
bool isRequestFromChild)
1853 if (isRequestFromChild && !q->windowTitle().isEmpty() && !lastChildWindowTitle.isEmpty()
1854 && lastChildWindowTitle != q->windowTitle()) {
1858 QWidget *titleWidget =
nullptr;
1859 if (isRequestFromChild)
1860 titleWidget = baseWidget;
1863 if (!titleWidget || titleWidget->windowTitle().isEmpty())
1866 ignoreWindowTitleChange =
true;
1867 q->setWindowTitle(titleWidget->windowTitle());
1868 if (q->maximizedButtonsWidget())
1869 setNewWindowTitle();
1870 ignoreWindowTitleChange =
false;
1873#if QT_CONFIG(rubberband)
1874void QMdiSubWindowPrivate::enterRubberBandMode()
1877 if (q->isMaximized())
1879 Q_ASSERT(oldGeometry.isValid());
1882 rubberBand =
new QRubberBand(QRubberBand::Rectangle, q->parentWidget());
1884 rubberBand->setObjectName(
"qt_rubberband"_L1);
1886 QPoint rubberBandPos = q->mapToParent(QPoint(0, 0));
1887 rubberBand->setGeometry(rubberBandPos.x(), rubberBandPos.y(),
1888 oldGeometry.width(), oldGeometry.height());
1890 isInRubberBandMode =
true;
1894void QMdiSubWindowPrivate::leaveRubberBandMode()
1897 Q_ASSERT(rubberBand);
1898 Q_ASSERT(isInRubberBandMode);
1900 isInRubberBandMode =
false;
1901 q->setGeometry(rubberBand->geometry());
1903 currentOperation = None;
1908QPalette QMdiSubWindowPrivate::desktopPalette()
const
1910 Q_Q(
const QMdiSubWindow);
1911 QPalette newPalette = q->palette();
1913 newPalette.setColor(QPalette::Active, QPalette::Highlight,
1914 newPalette.color(QPalette::Active, QPalette::Highlight));
1915 newPalette.setColor(QPalette::Active, QPalette::Base,
1916 newPalette.color(QPalette::Active, QPalette::Highlight));
1917 newPalette.setColor(QPalette::Inactive, QPalette::Highlight,
1918 newPalette.color(QPalette::Inactive, QPalette::Dark));
1919 newPalette.setColor(QPalette::Inactive, QPalette::Base,
1920 newPalette.color(QPalette::Inactive, QPalette::Dark));
1921 newPalette.setColor(QPalette::Inactive, QPalette::HighlightedText,
1922 newPalette.color(QPalette::Inactive, QPalette::Window));
1927void QMdiSubWindowPrivate::updateActions()
1929 Qt::WindowFlags windowFlags = q_func()->windowFlags();
1931 for (
int i = 0; i < NumWindowStateActions; ++i)
1932 setVisible(WindowStateAction(i),
false);
1934#if defined(Q_OS_MACOS) && QT_CONFIG(action)
1935 if (q_func()->style()->inherits(
"QMacStyle"))
1936 for (
int i = 0; i < NumWindowStateActions; ++i)
1937 if (QAction *action = actions[i])
1938 action->setIconVisibleInMenu(
false);
1941 if (windowFlags & Qt::FramelessWindowHint)
1944 setVisible(StayOnTopAction,
true);
1945 setVisible(MoveAction, moveEnabled);
1946 setVisible(ResizeAction, resizeEnabled);
1949 if (windowFlags & Qt::WindowSystemMenuHint)
1950 setVisible(CloseAction,
true);
1953 if (windowFlags & (Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint))
1954 setVisible(RestoreAction,
true);
1957 if (windowFlags & Qt::WindowMinimizeButtonHint)
1958 setVisible(MinimizeAction,
true);
1961 if (windowFlags & Qt::WindowMaximizeButtonHint)
1962 setVisible(MaximizeAction,
true);
1965void QMdiSubWindowPrivate::setFocusWidget()
1976 if (focusInReason == Qt::TabFocusReason) {
1977 q->focusNextChild();
1982 if (focusInReason == Qt::BacktabFocusReason) {
1983 q->focusPreviousChild();
1987 if (!(q->windowState() & Qt::WindowMinimized) && restoreFocus())
1990 if (QWidget *focusWidget = baseWidget->focusWidget()) {
1991 if (!focusWidget->hasFocus() && q->isAncestorOf(focusWidget)
1992 && focusWidget->isVisible() && !q->isMinimized()
1993 && focusWidget->focusPolicy() != Qt::NoFocus) {
1994 focusWidget->setFocus();
2001 QWidget *focusWidget = q->nextInFocusChain();
2002 while (focusWidget && focusWidget != q && focusWidget->focusPolicy() == Qt::NoFocus)
2003 focusWidget = focusWidget->nextInFocusChain();
2004 if (focusWidget && q->isAncestorOf(focusWidget))
2005 focusWidget->setFocus();
2006 else if (baseWidget->focusPolicy() != Qt::NoFocus)
2007 baseWidget->setFocus();
2008 else if (!q->hasFocus())
2012bool QMdiSubWindowPrivate::restoreFocus()
2014 if (restoreFocusWidget.isNull())
2016 QWidget *candidate = restoreFocusWidget;
2017 restoreFocusWidget.clear();
2018 if (!candidate->hasFocus() && q_func()->isAncestorOf(candidate)
2019 && candidate->isVisible()
2020 && candidate->focusPolicy() != Qt::NoFocus) {
2021 candidate->setFocus();
2024 return candidate->hasFocus();
2028
2029
2030void QMdiSubWindowPrivate::setWindowFlags(Qt::WindowFlags windowFlags)
2035 QWidgetPrivate::setWindowFlags(windowFlags);
2039 Qt::WindowFlags windowType = windowFlags & Qt::WindowType_Mask;
2040 if (windowType == Qt::Dialog || windowFlags & Qt::MSWindowsFixedSizeDialogHint)
2041 windowFlags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint;
2044 if (!(windowFlags & CustomizeWindowFlags))
2045 windowFlags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint;
2046 else if (windowFlags & Qt::FramelessWindowHint && windowFlags & Qt::WindowStaysOnTopHint)
2047 windowFlags = Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint;
2048 else if (windowFlags & Qt::FramelessWindowHint)
2049 windowFlags = Qt::FramelessWindowHint;
2051 windowFlags &= ~windowType;
2052 windowFlags &= ~Qt::WindowFullscreenButtonHint;
2053 windowFlags |= Qt::SubWindow;
2056 if (QAction *stayOnTopAction = actions[QMdiSubWindowPrivate::StayOnTopAction]) {
2057 if (windowFlags & Qt::WindowStaysOnTopHint)
2058 stayOnTopAction->setChecked(
true);
2060 stayOnTopAction->setChecked(
false);
2064#if QT_CONFIG(sizegrip)
2065 if ((windowFlags & Qt::FramelessWindowHint) && sizeGrip)
2069 QWidgetPrivate::setWindowFlags(windowFlags);
2070 updateGeometryConstraints();
2072 QSize currentSize = q->size();
2073 if (q->isVisible() && (currentSize.width() < internalMinimumSize.width()
2074 || currentSize.height() < internalMinimumSize.height())) {
2075 q->resize(currentSize.expandedTo(internalMinimumSize));
2079void QMdiSubWindowPrivate::setVisible(WindowStateAction action,
bool visible)
2082 if (actions[action])
2083 actions[action]->setVisible(visible);
2087 if (!controlContainer)
2088 controlContainer =
new ControlContainer(q);
2090 if (ControllerWidget *ctrlWidget = qobject_cast<ControllerWidget *>
2091 (controlContainer->controllerWidget())) {
2092 ctrlWidget->setControlVisible(action, visible);
2098void QMdiSubWindowPrivate::setEnabled(WindowStateAction action,
bool enable)
2100 if (actions[action])
2101 actions[action]->setEnabled(enable);
2105void QMdiSubWindowPrivate::addToSystemMenu(WindowStateAction action,
const QString &text,
2110 actions[action] = systemMenu->addAction(text, q_func(), slot);
2116
2117
2118QSize QMdiSubWindowPrivate::iconSize()
const
2120 Q_Q(
const QMdiSubWindow);
2121 if (!parent || q->windowFlags() & Qt::FramelessWindowHint)
2122 return QSize(-1, -1);
2123 return QSize(q->style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth,
nullptr, q), titleBarHeight());
2126#if QT_CONFIG(sizegrip)
2129
2130
2131void QMdiSubWindowPrivate::setSizeGrip(QSizeGrip *newSizeGrip)
2134 if (!newSizeGrip || sizeGrip || q->windowFlags() & Qt::FramelessWindowHint)
2137 if (layout && layout->indexOf(newSizeGrip) != -1)
2139 newSizeGrip->setFixedSize(newSizeGrip->sizeHint());
2140 bool putSizeGripInLayout = layout ?
true :
false;
2141 if (isMacStyle(q->style()))
2142 putSizeGripInLayout =
false;
2143 if (putSizeGripInLayout) {
2144 layout->addWidget(newSizeGrip);
2145 layout->setAlignment(newSizeGrip, Qt::AlignBottom | Qt::AlignRight);
2147 newSizeGrip->setParent(q);
2148 newSizeGrip->move(q->isLeftToRight() ? q->width() - newSizeGrip->width() : 0,
2149 q->height() - newSizeGrip->height());
2150 sizeGrip = newSizeGrip;
2152 newSizeGrip->raise();
2153 updateGeometryConstraints();
2154 newSizeGrip->installEventFilter(q);
2158
2159
2160void QMdiSubWindowPrivate::setSizeGripVisible(
bool visible)
const
2163 const QList<QSizeGrip *> sizeGrips = q_func()->findChildren<QSizeGrip *>();
2164 for (QSizeGrip *grip : sizeGrips)
2165 grip->setVisible(visible);
2171
2172
2173void QMdiSubWindowPrivate::updateInternalWindowTitle()
2176 if (q->isWindowModified()) {
2177 windowTitle = q->windowTitle();
2178 windowTitle.replace(
"[*]"_L1,
"*"_L1);
2180 windowTitle = qt_setWindowTitle_helperHelper(q->windowTitle(), q);
2182 q->update(0, 0, q->width(), titleBarHeight());
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203QMdiSubWindow::QMdiSubWindow(QWidget *parent, Qt::WindowFlags flags)
2204 : QWidget(*
new QMdiSubWindowPrivate, parent, { })
2208 d->createSystemMenu();
2209 addActions(d->systemMenu->actions());
2211 d->setWindowFlags(flags);
2212 setBackgroundRole(QPalette::Window);
2213 setAutoFillBackground(
true);
2214 setMouseTracking(
true);
2215 setLayout(
new QVBoxLayout);
2216 setFocusPolicy(Qt::StrongFocus);
2217 layout()->setContentsMargins(QMargins());
2218 d->updateGeometryConstraints();
2219 setAttribute(Qt::WA_Resized,
false);
2220 d->titleBarPalette = d->desktopPalette();
2221 d->font = QApplication::font(
"QMdiSubWindowTitleBar");
2224 if (windowIcon().isNull())
2225 d->menuIcon = style()->standardIcon(QStyle::SP_TitleBarMenuButton,
nullptr,
this);
2227 d->menuIcon = windowIcon();
2229 connect(qApp, SIGNAL(focusChanged(QWidget*,QWidget*)),
2230 this, SLOT(_q_processFocusChanged(QWidget*,QWidget*)));
2234
2235
2236
2237
2238QMdiSubWindow::~QMdiSubWindow()
2241#if QT_CONFIG(menubar)
2242 d->removeButtonsFromMenuBar();
2244 d->setActive(
false);
2245 delete d->controlContainer;
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259void QMdiSubWindow::setWidget(QWidget *widget)
2263 d->removeBaseWidget();
2267 if (Q_UNLIKELY(widget == d->baseWidget)) {
2268 qWarning(
"QMdiSubWindow::setWidget: widget is already set");
2272 bool wasResized = testAttribute(Qt::WA_Resized);
2273 d->removeBaseWidget();
2275 if (QLayout *layout =
this->layout())
2276 layout->addWidget(widget);
2278 widget->setParent(
this);
2280#if QT_CONFIG(sizegrip)
2281 QSizeGrip *sizeGrip = widget->findChild<QSizeGrip *>();
2283 sizeGrip->installEventFilter(
this);
2285 d->sizeGrip->raise();
2288 d->baseWidget = widget;
2289 d->baseWidget->installEventFilter(
this);
2291 d->ignoreWindowTitleChange =
true;
2292 bool isWindowModified =
this->isWindowModified();
2293 if (windowTitle().isEmpty()) {
2294 d->updateWindowTitle(
true);
2295 isWindowModified = d->baseWidget->isWindowModified();
2297 if (!
this->isWindowModified() && isWindowModified && windowTitle().contains(
"[*]"_L1))
2298 setWindowModified(isWindowModified);
2299 d->lastChildWindowTitle = d->baseWidget->windowTitle();
2300 d->ignoreWindowTitleChange =
false;
2302 if (windowIcon().isNull() && !d->baseWidget->windowIcon().isNull())
2303 setWindowIcon(d->baseWidget->windowIcon());
2305 d->updateGeometryConstraints();
2306 if (!wasResized && testAttribute(Qt::WA_Resized))
2307 setAttribute(Qt::WA_Resized,
false);
2311
2312
2313
2314
2315QWidget *QMdiSubWindow::widget()
const
2317 return d_func()->baseWidget;
2322
2323
2324QWidget *QMdiSubWindow::maximizedButtonsWidget()
const
2326 Q_D(
const QMdiSubWindow);
2327 if (isVisible() && d->controlContainer && isMaximized() && !d->drawTitleBarWhenMaximized()
2328 && !isChildOfTabbedQMdiArea(
this)) {
2329 return d->controlContainer->controllerWidget();
2335
2336
2337QWidget *QMdiSubWindow::maximizedSystemMenuIconWidget()
const
2339 Q_D(
const QMdiSubWindow);
2340 if (isVisible() && d->controlContainer && isMaximized() && !d->drawTitleBarWhenMaximized()
2341 && !isChildOfTabbedQMdiArea(
this)) {
2342 return d->controlContainer->systemMenuLabel();
2348
2349
2350
2351
2352
2353bool QMdiSubWindow::isShaded()
const
2355 return d_func()->isShadeMode;
2359
2360
2361
2362
2363
2364void QMdiSubWindow::setOption(SubWindowOption option,
bool on)
2367 d->options.setFlag(option, on);
2369#if QT_CONFIG(rubberband)
2370 if ((option & (RubberBandResize | RubberBandMove)) && !on && d->isInRubberBandMode)
2371 d->leaveRubberBandMode();
2376
2377
2378
2379
2380bool QMdiSubWindow::testOption(SubWindowOption option)
const
2382 return d_func()->options & option;
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399int QMdiSubWindow::keyboardSingleStep()
const
2401 return d_func()->keyboardSingleStep;
2404void QMdiSubWindow::setKeyboardSingleStep(
int step)
2409 d_func()->keyboardSingleStep = step;
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426int QMdiSubWindow::keyboardPageStep()
const
2428 return d_func()->keyboardPageStep;
2431void QMdiSubWindow::setKeyboardPageStep(
int step)
2436 d_func()->keyboardPageStep = step;
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457void QMdiSubWindow::setSystemMenu(QMenu *systemMenu)
2460 if (Q_UNLIKELY(systemMenu && systemMenu == d->systemMenu)) {
2461 qWarning(
"QMdiSubWindow::setSystemMenu: system menu is already set");
2465 if (d->systemMenu) {
2466 delete d->systemMenu;
2467 d->systemMenu =
nullptr;
2473 if (systemMenu->parent() !=
this)
2474 systemMenu->setParent(
this);
2475 d->systemMenu = systemMenu;
2479
2480
2481
2482
2483
2484
2485QMenu *QMdiSubWindow::systemMenu()
const
2487 return d_func()->systemMenu;
2491
2492
2493
2494
2495void QMdiSubWindow::showSystemMenu()
2501 QPoint globalPopupPos;
2502 if (QWidget *icon = maximizedSystemMenuIconWidget()) {
2503 if (isLeftToRight())
2504 globalPopupPos = icon->mapToGlobal(QPoint(0, icon->y() + icon->height()));
2506 globalPopupPos = icon->mapToGlobal(QPoint(icon->width(), icon->y() + icon->height()));
2508 if (isLeftToRight())
2509 globalPopupPos = mapToGlobal(contentsRect().topLeft());
2511 globalPopupPos = mapToGlobal(contentsRect().topRight()) + QPoint(1, 0);
2515 if (isRightToLeft())
2516 globalPopupPos -= QPoint(d->systemMenu->sizeHint().width(), 0);
2517 d->systemMenu->popup(globalPopupPos);
2522
2523
2524
2525
2526
2527
2528
2529QMdiArea *QMdiSubWindow::mdiArea()
const
2531 QWidget *parent = parentWidget();
2533 if (QMdiArea *area = qobject_cast<QMdiArea *>(parent)) {
2534 if (area->viewport() == parentWidget())
2537 parent = parent->parentWidget();
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555void QMdiSubWindow::showShaded()
2562 if (!d->isShadeRequestFromMinimizeMode && isShaded())
2565 d->isMaximizeMode =
false;
2567 d->storeFocusWidget();
2569 if (!d->isShadeRequestFromMinimizeMode) {
2570 d->isShadeMode =
true;
2571 d->ensureWindowState(Qt::WindowMinimized);
2574#if QT_CONFIG(menubar)
2575 d->removeButtonsFromMenuBar();
2581 if (hasFocus() || isAncestorOf(QApplication::focusWidget()))
2582 d->ensureWindowState(Qt::WindowActive);
2584#if QT_CONFIG(sizegrip)
2585 d->setSizeGripVisible(
false);
2588 if (!d->restoreSize.isValid() || d->isShadeMode) {
2589 d->oldGeometry = geometry();
2590 d->restoreSize.setWidth(d->oldGeometry.width());
2591 d->restoreSize.setHeight(d->oldGeometry.height());
2596 const bool wasVisible = isVisible();
2600 d->updateGeometryConstraints();
2602 if (!minimumSize().isNull()) {
2603 d->userMinimumSize = minimumSize();
2604 setMinimumSize(d->internalMinimumSize);
2606 resize(d->internalMinimumSize);
2609 if (d->baseWidget && !d->baseWidget->isHidden() && !(windowFlags() & Qt::FramelessWindowHint)) {
2610 d->baseWidget->hide();
2611 d->isWidgetHiddenByUs =
true;
2617 d->setFocusWidget();
2618 d->resizeEnabled =
false;
2619 d->moveEnabled =
true;
2620 d->updateDirtyRegions();
2624 d->setEnabled(QMdiSubWindowPrivate::MinimizeAction,
false);
2625 d->setEnabled(QMdiSubWindowPrivate::ResizeAction, d->resizeEnabled);
2626 d->setEnabled(QMdiSubWindowPrivate::MaximizeAction,
true);
2627 d->setEnabled(QMdiSubWindowPrivate::RestoreAction,
true);
2628 d->setEnabled(QMdiSubWindowPrivate::MoveAction, d->moveEnabled);
2633
2634
2635bool QMdiSubWindow::eventFilter(QObject *object, QEvent *event)
2639 return QWidget::eventFilter(object, event);
2643 if (d->systemMenu && d->systemMenu == object) {
2644 if (event->type() == QEvent::MouseButtonDblClick) {
2645 const QMouseEvent *mouseEvent =
static_cast<
const QMouseEvent *>(event);
2646 const QAction *action = d->systemMenu->actionAt(mouseEvent->position().toPoint());
2647 if (!action || action->isEnabled())
2649 }
else if (event->type() == QEvent::MouseMove) {
2650 QMouseEvent *mouseEvent =
static_cast<QMouseEvent *>(event);
2651 d->hoveredSubControl = d->getSubControl(mapFromGlobal(mouseEvent->globalPosition().toPoint()));
2652 }
else if (event->type() == QEvent::Hide) {
2653 d->activeSubControl = QStyle::SC_None;
2654 update(QRegion(0, 0, width(), d->titleBarHeight()));
2656 return QWidget::eventFilter(object, event);
2660#if QT_CONFIG(sizegrip)
2661 if (object != d->baseWidget && parent() && qobject_cast<QSizeGrip *>(object)) {
2662 if (event->type() != QEvent::MouseButtonPress || !testOption(QMdiSubWindow::RubberBandResize))
2663 return QWidget::eventFilter(object, event);
2664 const QMouseEvent *mouseEvent =
static_cast<QMouseEvent *>(event);
2665 d->mousePressPosition = parentWidget()->mapFromGlobal(mouseEvent->globalPosition().toPoint());
2666 d->oldGeometry = geometry();
2667 d->currentOperation = isLeftToRight() ? QMdiSubWindowPrivate::BottomRightResize
2668 : QMdiSubWindowPrivate::BottomLeftResize;
2669#if QT_CONFIG(rubberband)
2670 d->enterRubberBandMode();
2676 if (object != d->baseWidget && event->type() != QEvent::WindowTitleChange)
2677 return QWidget::eventFilter(object, event);
2679 switch (event->type()) {
2683 case QEvent::ShowToParent:
2684 if (!d->isWidgetHiddenByUs)
2687 case QEvent::WindowStateChange: {
2688 QWindowStateChangeEvent *changeEvent =
static_cast<QWindowStateChangeEvent*>(event);
2689 if (changeEvent->isOverride())
2691 Qt::WindowStates oldState = changeEvent->oldState();
2692 Qt::WindowStates newState = d->baseWidget->windowState();
2693 if (!(oldState & Qt::WindowMinimized) && (newState & Qt::WindowMinimized))
2695 else if (!(oldState & Qt::WindowMaximized) && (newState & Qt::WindowMaximized))
2697 else if (!(newState & (Qt::WindowMaximized | Qt::WindowMinimized | Qt::WindowFullScreen)))
2702 d->currentOperation = QMdiSubWindowPrivate::None;
2705 case QEvent::LayoutRequest:
2706 d->updateGeometryConstraints();
2708 case QEvent::WindowTitleChange:
2709 if (d->ignoreWindowTitleChange)
2711 if (object == d->baseWidget) {
2712 d->updateWindowTitle(
true);
2713 d->lastChildWindowTitle = d->baseWidget->windowTitle();
2714#if QT_CONFIG(menubar)
2715 }
else if (maximizedButtonsWidget() && d->controlContainer->menuBar() && d->controlContainer->menuBar()
2716 ->cornerWidget(Qt::TopRightCorner) == maximizedButtonsWidget()) {
2717 d->originalTitle.clear();
2718 if (d->baseWidget && d->baseWidget->windowTitle() == windowTitle())
2719 d->updateWindowTitle(
true);
2721 d->updateWindowTitle(
false);
2725 case QEvent::ModifiedChange: {
2726 if (object != d->baseWidget)
2728 bool windowModified = d->baseWidget->isWindowModified();
2729 if (!windowModified && d->baseWidget->windowTitle() != windowTitle())
2731 if (windowTitle().contains(
"[*]"_L1))
2732 setWindowModified(windowModified);
2738 return QWidget::eventFilter(object, event);
2742
2743
2744bool QMdiSubWindow::event(QEvent *event)
2747 switch (event->type()) {
2748 case QEvent::StyleChange: {
2749 bool wasShaded = isShaded();
2750 bool wasMinimized = isMinimized();
2751 bool wasMaximized = isMaximized();
2753 const QScopedValueRollback<
bool> activationEnabledSaver(d->activationEnabled);
2754 d->activationEnabled =
false;
2757 setContentsMargins(0, 0, 0, 0);
2758 if (wasMinimized || wasMaximized || wasShaded)
2760 d->updateGeometryConstraints();
2761 resize(d->internalMinimumSize.expandedTo(size()));
2763 d->updateDirtyRegions();
2766 else if (wasMinimized)
2768 else if (wasMaximized)
2772 case QEvent::ParentAboutToChange:
2773 d->setActive(
false);
2775 case QEvent::ParentChange: {
2776 bool wasResized = testAttribute(Qt::WA_Resized);
2777#if QT_CONFIG(menubar)
2778 d->removeButtonsFromMenuBar();
2780 d->currentOperation = QMdiSubWindowPrivate::None;
2781 d->activeSubControl = QStyle::SC_None;
2782 d->hoveredSubControl = QStyle::SC_None;
2783#if QT_CONFIG(rubberband)
2784 if (d->isInRubberBandMode)
2785 d->leaveRubberBandMode();
2787 d->isShadeMode =
false;
2788 d->isMaximizeMode =
false;
2789 d->isWidgetHiddenByUs =
false;
2791#if QT_CONFIG(sizegrip)
2792 if (isMacStyle(style()))
2795 setOption(RubberBandResize,
false);
2796 setOption(RubberBandMove,
false);
2798 d->setWindowFlags(windowFlags());
2800 setContentsMargins(0, 0, 0, 0);
2801 d->updateGeometryConstraints();
2804 d->updateDirtyRegions();
2806 if (!wasResized && testAttribute(Qt::WA_Resized))
2807 setAttribute(Qt::WA_Resized,
false);
2810 case QEvent::WindowActivate:
2811 if (d->ignoreNextActivationEvent) {
2812 d->ignoreNextActivationEvent =
false;
2815 d->isExplicitlyDeactivated =
false;
2818 case QEvent::WindowDeactivate:
2819 if (d->ignoreNextActivationEvent) {
2820 d->ignoreNextActivationEvent =
false;
2823 d->isExplicitlyDeactivated =
true;
2824 d->setActive(
false);
2826 case QEvent::WindowTitleChange:
2827 if (!d->ignoreWindowTitleChange)
2828 d->updateWindowTitle(
false);
2829 d->updateInternalWindowTitle();
2831 case QEvent::ModifiedChange:
2832 if (!windowTitle().contains(
"[*]"_L1))
2834#if QT_CONFIG(menubar)
2835 if (maximizedButtonsWidget() && d->controlContainer->menuBar() && d->controlContainer->menuBar()
2836 ->cornerWidget(Qt::TopRightCorner) == maximizedButtonsWidget()) {
2837 window()->setWindowModified(isWindowModified());
2840 d->updateInternalWindowTitle();
2842 case QEvent::LayoutDirectionChange:
2843 d->updateDirtyRegions();
2845 case QEvent::LayoutRequest:
2846 d->updateGeometryConstraints();
2848 case QEvent::WindowIconChange:
2849 d->menuIcon = windowIcon();
2850 if (d->menuIcon.isNull())
2851 d->menuIcon = style()->standardIcon(QStyle::SP_TitleBarMenuButton,
nullptr,
this);
2852 if (d->controlContainer)
2853 d->controlContainer->updateWindowIcon(d->menuIcon);
2854 if (!maximizedSystemMenuIconWidget())
2855 update(0, 0, width(), d->titleBarHeight());
2857 case QEvent::PaletteChange:
2858 d->titleBarPalette = d->desktopPalette();
2860 case QEvent::FontChange:
2863#if QT_CONFIG(tooltip)
2864 case QEvent::ToolTip:
2865 showToolTip(
static_cast<QHelpEvent *>(event),
this, d->titleBarOptions(),
2866 QStyle::CC_TitleBar, d->hoveredSubControl);
2870 case QEvent::ActionAdded:
2871 case QEvent::ActionChanged:
2872 case QEvent::ActionRemoved:
2879 return QWidget::event(event);
2883
2884
2885void QMdiSubWindow::showEvent(QShowEvent *showEvent)
2889 QWidget::showEvent(showEvent);
2893#if QT_CONFIG(sizegrip)
2894 if (isMacStyle(style()) && !d->sizeGrip
2895 && !(windowFlags() & Qt::FramelessWindowHint)) {
2896 d->setSizeGrip(
new QSizeGrip(
this));
2897 Q_ASSERT(d->sizeGrip);
2899 d->setSizeGripVisible(
false);
2901 d->setSizeGripVisible(
true);
2902 resize(size().expandedTo(d->internalMinimumSize));
2906 d->updateDirtyRegions();
2909#if QT_CONFIG(menubar)
2910 if (d->controlContainer) {
2911 if (QMenuBar *menuBar = d->menuBar()) {
2912 if (menuBar->cornerWidget(Qt::TopRightCorner) != maximizedButtonsWidget())
2913 d->showButtonsInMenuBar(menuBar);
2921
2922
2923void QMdiSubWindow::hideEvent(QHideEvent * )
2925#if QT_CONFIG(menubar)
2926 d_func()->removeButtonsFromMenuBar();
2931
2932
2933void QMdiSubWindow::changeEvent(QEvent *changeEvent)
2936 QWidget::changeEvent(changeEvent);
2940 if (changeEvent->type() != QEvent::WindowStateChange) {
2941 QWidget::changeEvent(changeEvent);
2945 QWindowStateChangeEvent *event =
static_cast<QWindowStateChangeEvent *>(changeEvent);
2946 if (event->isOverride()) {
2951 Qt::WindowStates oldState = event->oldState();
2952 Qt::WindowStates newState = windowState();
2953 if (oldState == newState) {
2954 changeEvent->ignore();
2963 d->ensureWindowState(Qt::WindowNoState);
2967 if (!d->oldGeometry.isValid())
2968 d->oldGeometry = geometry();
2970 if ((oldState & Qt::WindowActive) && (newState & Qt::WindowActive))
2971 d->currentOperation = QMdiSubWindowPrivate::None;
2973 if (!(oldState & Qt::WindowMinimized) && (newState & Qt::WindowMinimized))
2974 d->setMinimizeMode();
2975 else if (!(oldState & Qt::WindowMaximized) && (newState & Qt::WindowMaximized))
2976 d->setMaximizeMode();
2977 else if (!(newState & (Qt::WindowMaximized | Qt::WindowMinimized | Qt::WindowFullScreen)))
2981 d->ensureWindowState(Qt::WindowActive);
2982 if (d->activationEnabled)
2983 emit windowStateChanged(oldState, windowState());
2987
2988
2989void QMdiSubWindow::closeEvent(QCloseEvent *closeEvent)
2992 bool acceptClose =
true;
2994 acceptClose = d->baseWidget->close();
2996 closeEvent->ignore();
2999#if QT_CONFIG(menubar)
3000 d->removeButtonsFromMenuBar();
3002 d->setActive(
false);
3003 if (parentWidget() && testAttribute(Qt::WA_DeleteOnClose)) {
3004 QChildEvent childRemoved(QEvent::ChildRemoved,
this);
3005 QCoreApplication::sendEvent(parentWidget(), &childRemoved);
3007 closeEvent->accept();
3011
3012
3013void QMdiSubWindow::leaveEvent(QEvent * )
3016 if (d->hoveredSubControl != QStyle::SC_None) {
3017 d->hoveredSubControl = QStyle::SC_None;
3018 update(QRegion(0, 0, width(), d->titleBarHeight()));
3023
3024
3025
3026
3027
3028void QMdiSubWindow::resizeEvent(QResizeEvent *resizeEvent)
3031#if QT_CONFIG(sizegrip)
3033 d->sizeGrip->move(isLeftToRight() ? width() - d->sizeGrip->width() : 0,
3034 height() - d->sizeGrip->height());
3039 QWidget::resizeEvent(resizeEvent);
3043 if (d->isMaximizeMode)
3044 d->ensureWindowState(Qt::WindowMaximized);
3050 if (!d->resizeTimer.isActive())
3051 d->cachedStyleOptions = d->titleBarOptions();
3052 d->resizeTimer.start(200ms,
this);
3056
3057
3058void QMdiSubWindow::timerEvent(QTimerEvent *timerEvent)
3061 if (timerEvent->id() == d->resizeTimer.id()) {
3062 d->resizeTimer.stop();
3063 d->updateDirtyRegions();
3068
3069
3070void QMdiSubWindow::moveEvent(QMoveEvent *moveEvent)
3073 QWidget::moveEvent(moveEvent);
3078 if (d->isMaximizeMode)
3079 d->ensureWindowState(Qt::WindowMaximized);
3083
3084
3085void QMdiSubWindow::paintEvent(QPaintEvent *paintEvent)
3087 if (!parent() || (windowFlags() & Qt::FramelessWindowHint)) {
3088 QWidget::paintEvent(paintEvent);
3094 if (d->resizeTimer.isActive()) {
3096 int border = d->hasBorder(d->cachedStyleOptions) ? 4 : 0;
3097 int titleBarHeight = d->titleBarHeight(d->cachedStyleOptions);
3098 titleBarHeight -= isMinimized() ? 2 * border : border;
3099 d->cachedStyleOptions.rect = QRect(border, border, width() - 2 * border, titleBarHeight);
3100 if (!d->windowTitle.isEmpty()) {
3101 int width = style()->subControlRect(QStyle::CC_TitleBar, &d->cachedStyleOptions,
3102 QStyle::SC_TitleBarLabel,
this).width();
3103 d->cachedStyleOptions.text = d->cachedStyleOptions.fontMetrics
3104 .elidedText(d->windowTitle, Qt::ElideRight, width);
3108 d->cachedStyleOptions = d->titleBarOptions();
3111 QStylePainter painter(
this);
3112 QStyleOptionFrame frameOptions;
3113 frameOptions.initFrom(
this);
3114 frameOptions.state.setFlag(QStyle::State_Active, d->isActive);
3115 if (isMaximized() && !d->drawTitleBarWhenMaximized()) {
3116 if (!autoFillBackground() && (!widget() || !qt_widget_private(widget())->isOpaque)) {
3118 painter.drawPrimitive(QStyle::PE_FrameWindow, frameOptions);
3123 if (!d->windowTitle.isEmpty())
3124 painter.setFont(d->font);
3125 painter.drawComplexControl(QStyle::CC_TitleBar, d->cachedStyleOptions);
3127 if (isMinimized() && !d->hasBorder(d->cachedStyleOptions))
3130 frameOptions.lineWidth = style()->pixelMetric(QStyle::PM_MdiSubWindowFrameWidth,
nullptr,
this);
3133 if (!isMinimized() && !d->hasBorder(d->cachedStyleOptions))
3134 painter.setClipRect(rect().adjusted(0, d->titleBarHeight(d->cachedStyleOptions), 0, 0));
3135 if (!isMinimized() || d->hasBorder(d->cachedStyleOptions))
3136 painter.drawPrimitive(QStyle::PE_FrameWindow, frameOptions);
3140
3141
3142void QMdiSubWindow::mousePressEvent(QMouseEvent *mouseEvent)
3145 QWidget::mousePressEvent(mouseEvent);
3150 if (d->isInInteractiveMode)
3151 d->leaveInteractiveMode();
3152#if QT_CONFIG(rubberband)
3153 if (d->isInRubberBandMode)
3154 d->leaveRubberBandMode();
3157 if (mouseEvent->button() != Qt::LeftButton) {
3158 mouseEvent->ignore();
3162 if (d->currentOperation != QMdiSubWindowPrivate::None) {
3164 d->mousePressPosition = mapToParent(mouseEvent->position().toPoint());
3165 if (d->resizeEnabled || d->moveEnabled)
3166 d->oldGeometry = geometry();
3167#if QT_CONFIG(rubberband)
3168 if ((testOption(QMdiSubWindow::RubberBandResize) && d->isResizeOperation())
3169 || (testOption(QMdiSubWindow::RubberBandMove) && d->isMoveOperation())) {
3170 d->enterRubberBandMode();
3176 d->activeSubControl = d->hoveredSubControl;
3178 if (d->activeSubControl == QStyle::SC_TitleBarSysMenu)
3182 update(QRegion(0, 0, width(), d->titleBarHeight()));
3186
3187
3188void QMdiSubWindow::mouseDoubleClickEvent(QMouseEvent *mouseEvent)
3191 QWidget::mouseDoubleClickEvent(mouseEvent);
3195 if (mouseEvent->button() != Qt::LeftButton) {
3196 mouseEvent->ignore();
3201 if (!d->isMoveOperation()) {
3203 if (d->hoveredSubControl == QStyle::SC_TitleBarSysMenu)
3209 Qt::WindowFlags flags = windowFlags();
3210 if (isMinimized()) {
3211 if ((isShaded() && (flags & Qt::WindowShadeButtonHint))
3212 || (flags & Qt::WindowMinimizeButtonHint)) {
3218 if (isMaximized()) {
3219 if (flags & Qt::WindowMaximizeButtonHint)
3224 if (flags & Qt::WindowShadeButtonHint)
3226 else if (flags & Qt::WindowMaximizeButtonHint)
3231
3232
3233void QMdiSubWindow::mouseReleaseEvent(QMouseEvent *mouseEvent)
3236 QWidget::mouseReleaseEvent(mouseEvent);
3240 if (mouseEvent->button() != Qt::LeftButton) {
3241 mouseEvent->ignore();
3246 if (d->currentOperation != QMdiSubWindowPrivate::None) {
3247#if QT_CONFIG(rubberband)
3248 if (d->isInRubberBandMode && !d->isInInteractiveMode)
3249 d->leaveRubberBandMode();
3251 if (d->resizeEnabled || d->moveEnabled)
3252 d->oldGeometry = geometry();
3255 d->currentOperation = d->getOperation(mouseEvent->position().toPoint());
3258 d->hoveredSubControl = d->getSubControl(mouseEvent->position().toPoint());
3259 if (d->activeSubControl != QStyle::SC_None
3260 && d->activeSubControl == d->hoveredSubControl) {
3261 d->processClickedSubControl();
3263 d->activeSubControl = QStyle::SC_None;
3264 update(QRegion(0, 0, width(), d->titleBarHeight()));
3268
3269
3270void QMdiSubWindow::mouseMoveEvent(QMouseEvent *mouseEvent)
3273 QWidget::mouseMoveEvent(mouseEvent);
3279 if (!d->isMoveOperation() && !d->isResizeOperation()) {
3281 const QStyleOptionTitleBar options = d->titleBarOptions();
3282 QStyle::SubControl oldHover = d->hoveredSubControl;
3283 d->hoveredSubControl = d->getSubControl(mouseEvent->position().toPoint());
3284 QRegion hoverRegion;
3285 if (isHoverControl(oldHover) && oldHover != d->hoveredSubControl)
3286 hoverRegion += style()->subControlRect(QStyle::CC_TitleBar, &options, oldHover,
this);
3287 if (isHoverControl(d->hoveredSubControl) && d->hoveredSubControl != oldHover) {
3288 hoverRegion += style()->subControlRect(QStyle::CC_TitleBar, &options,
3289 d->hoveredSubControl,
this);
3292 if (isMacStyle(style()) && !hoverRegion.isEmpty())
3293 hoverRegion += QRegion(0, 0, width(), d->titleBarHeight(options));
3295 if (!hoverRegion.isEmpty())
3296 update(hoverRegion);
3299 if ((mouseEvent->buttons() & Qt::LeftButton) || d->isInInteractiveMode) {
3300 if ((d->isResizeOperation() && d->resizeEnabled) || (d->isMoveOperation() && d->moveEnabled)) {
3303 d->setNewGeometry(parentWidget()->mapFromGlobal(mouseEvent->globalPosition().toPoint()));
3309 d->currentOperation = d->getOperation(mouseEvent->position().toPoint());
3310 if ((d->isResizeOperation() && !d->resizeEnabled) || (d->isMoveOperation() && !d->moveEnabled))
3311 d->currentOperation = QMdiSubWindowPrivate::None;
3316
3317
3318void QMdiSubWindow::keyPressEvent(QKeyEvent *keyEvent)
3321 if (!d->isInInteractiveMode || !parent()) {
3327 switch (keyEvent->key()) {
3329 if (keyEvent->modifiers() & Qt::ShiftModifier)
3330 delta = QPoint(d->keyboardPageStep, 0);
3332 delta = QPoint(d->keyboardSingleStep, 0);
3335 if (keyEvent->modifiers() & Qt::ShiftModifier)
3336 delta = QPoint(0, -d->keyboardPageStep);
3338 delta = QPoint(0, -d->keyboardSingleStep);
3341 if (keyEvent->modifiers() & Qt::ShiftModifier)
3342 delta = QPoint(-d->keyboardPageStep, 0);
3344 delta = QPoint(-d->keyboardSingleStep, 0);
3347 if (keyEvent->modifiers() & Qt::ShiftModifier)
3348 delta = QPoint(0, d->keyboardPageStep);
3350 delta = QPoint(0, d->keyboardSingleStep);
3352 case Qt::Key_Escape:
3353 case Qt::Key_Return:
3355 d->leaveInteractiveMode();
3363 QPoint newPosition = parentWidget()->mapFromGlobal(cursor().pos() + delta);
3365#if QT_CONFIG(rubberband)
3366 d->isInRubberBandMode ? d->rubberBand->geometry() :
3369 d->setNewGeometry(newPosition);
3370 QRect currentGeometry =
3371#if QT_CONFIG(rubberband)
3372 d->isInRubberBandMode ? d->rubberBand->geometry() :
3375 if (currentGeometry == oldGeometry)
3381 if (d->isMoveOperation()) {
3382 actualDelta = QPoint(currentGeometry.x() - oldGeometry.x(),
3383 currentGeometry.y() - oldGeometry.y());
3385 int dx = isLeftToRight() ? currentGeometry.width() - oldGeometry.width()
3386 : currentGeometry.x() - oldGeometry.x();
3387 actualDelta = QPoint(dx, currentGeometry.height() - oldGeometry.height());
3391 if (actualDelta != delta)
3392 newPosition += (actualDelta - delta);
3393 cursor().setPos(parentWidget()->mapToGlobal(newPosition));
3397#ifndef QT_NO_CONTEXTMENU
3399
3400
3401void QMdiSubWindow::contextMenuEvent(QContextMenuEvent *contextMenuEvent)
3404 if (!d->systemMenu) {
3405 contextMenuEvent->ignore();
3409 if (d->hoveredSubControl == QStyle::SC_TitleBarSysMenu
3410 || d->getRegion(QMdiSubWindowPrivate::Move).contains(contextMenuEvent->pos())) {
3411 d->systemMenu->exec(contextMenuEvent->globalPos());
3413 contextMenuEvent->ignore();
3419
3420
3421void QMdiSubWindow::focusInEvent(QFocusEvent *focusInEvent)
3423 d_func()->focusInReason = focusInEvent->reason();
3427
3428
3429void QMdiSubWindow::focusOutEvent(QFocusEvent * )
3435
3436
3437void QMdiSubWindow::childEvent(QChildEvent *childEvent)
3439 if (childEvent->type() != QEvent::ChildPolished)
3441#if QT_CONFIG(sizegrip)
3442 if (QSizeGrip *sizeGrip = qobject_cast<QSizeGrip *>(childEvent->child()))
3443 d_func()->setSizeGrip(sizeGrip);
3448
3449
3450QSize QMdiSubWindow::sizeHint()
const
3452 Q_D(
const QMdiSubWindow);
3453 int margin, minWidth;
3454 d->sizeParameters(&margin, &minWidth);
3455 QSize size(2 * margin, d->titleBarHeight() + margin);
3456 if (d->baseWidget && d->baseWidget->sizeHint().isValid())
3457 size += d->baseWidget->sizeHint();
3458 return size.expandedTo(minimumSizeHint());
3462
3463
3464QSize QMdiSubWindow::minimumSizeHint()
const
3466 Q_D(
const QMdiSubWindow);
3471 if (parent() && isMinimized() && !isShaded())
3472 return d->iconSize();
3475 int margin, minWidth;
3476 d->sizeParameters(&margin, &minWidth);
3477 int decorationHeight = margin + d->titleBarHeight();
3478 int minHeight = decorationHeight;
3481 if (parent() && isShaded())
3482 return QSize(qMax(minWidth, width()), d->titleBarHeight());
3486 QSize minLayoutSize = layout()->minimumSize();
3487 if (minLayoutSize.isValid()) {
3488 minWidth = qMax(minWidth, minLayoutSize.width() + 2 * margin);
3489 minHeight += minLayoutSize.height();
3491 }
else if (d->baseWidget && d->baseWidget->isVisible()) {
3492 QSize minBaseWidgetSize = d->baseWidget->minimumSizeHint();
3493 if (minBaseWidgetSize.isValid()) {
3494 minWidth = qMax(minWidth, minBaseWidgetSize.width() + 2 * margin);
3495 minHeight += minBaseWidgetSize.height();
3499#if QT_CONFIG(sizegrip)
3501 int sizeGripHeight = 0;
3502 if (d->sizeGrip && d->sizeGrip->isVisibleTo(
const_cast<QMdiSubWindow *>(
this)))
3503 sizeGripHeight = d->sizeGrip->height();
3504 else if (parent() && isMacStyle(style()) && !d->sizeGrip)
3505 sizeGripHeight = style()->pixelMetric(QStyle::PM_SizeGripSize,
nullptr,
this);
3506 minHeight = qMax(minHeight, decorationHeight + sizeGripHeight);
3509 return QSize(minWidth, minHeight);
3514#include "moc_qmdisubwindow.cpp"
3515#include "qmdisubwindow.moc"
void updateWindowIcon(const QIcon &windowIcon)
ControlContainer(QMdiSubWindow *mdiChild)
QSize sizeHint() const override
bool event(QEvent *event) override
This virtual function receives events to an object and should return true if the event e was recogniz...
void mousePressEvent(QMouseEvent *mouseEvent) override
This event handler, for event event, can be reimplemented in a subclass to receive mouse press events...
void mouseReleaseEvent(QMouseEvent *mouseEvent) override
This event handler, for event event, can be reimplemented in a subclass to receive mouse release even...
void mouseDoubleClickEvent(QMouseEvent *mouseEvent) override
This event handler, for event event, can be reimplemented in a subclass to receive mouse double click...
void paintEvent(QPaintEvent *paintEvent) override
This event handler can be reimplemented in a subclass to receive paint events passed in event.
static const int BoundaryMargin
static bool isChildOfQMdiSubWindow(const QWidget *child)
static const int NumSubControls
static const QStyle::SubControl SubControls[]
static int getMoveDeltaComponent(uint cflags, uint moveFlag, uint resizeFlag, int delta, int maxDelta, int minDelta)
static bool isHoverControl(QStyle::SubControl control)
static const Qt::WindowFlags CustomizeWindowFlags
static int getResizeDeltaComponent(uint cflags, uint resizeFlag, uint resizeReverseFlag, int delta)
static bool isMacStyle(QStyle *style)
QString qt_setWindowTitle_helperHelper(const QString &, const QWidget *)
Returns a modified window title with the [*] place holder replaced according to the rules described i...
static ControlElement< T > * ptr(QWidget *widget)
static bool isChildOfTabbedQMdiArea(const QMdiSubWindow *child)