qtbase/tests/manual/windowflags/controls.cpp

317 lines
14 KiB
C++
Raw Normal View History

// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses
#include "controls.h"
#include <QGridLayout>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QRadioButton>
#include <QCheckBox>
#include <QRadioButton>
#include <QButtonGroup>
#include <QDebug>
HintControl::HintControl(QWidget *parent)
: QGroupBox(tr("Hints"), parent)
, msWindowsFixedSizeDialogCheckBox(new QCheckBox(tr("MS Windows fixed size dialog")))
, x11BypassWindowManagerCheckBox(new QCheckBox(tr("X11 bypass window manager")))
, framelessWindowCheckBox(new QCheckBox(tr("Frameless window")))
, windowTitleCheckBox(new QCheckBox(tr("Window title")))
, windowSystemMenuCheckBox(new QCheckBox(tr("Window system menu")))
, windowMinimizeButtonCheckBox(new QCheckBox(tr("Window minimize button")))
, windowMaximizeButtonCheckBox(new QCheckBox(tr("Window maximize button")))
, windowFullscreenButtonCheckBox(new QCheckBox(tr("Window fullscreen button")))
, windowCloseButtonCheckBox(new QCheckBox(tr("Window close button")))
, windowContextHelpButtonCheckBox(new QCheckBox(tr("Window context help button")))
, windowShadeButtonCheckBox(new QCheckBox(tr("Window shade button")))
, windowStaysOnTopCheckBox(new QCheckBox(tr("Window stays on top")))
, windowStaysOnBottomCheckBox(new QCheckBox(tr("Window stays on bottom")))
, customizeWindowGroup(new QGroupBox(tr("Customize window title bar controls")))
, transparentForInputCheckBox(new QCheckBox(tr("Transparent for input")))
, noDropShadowCheckBox(new QCheckBox(tr("No drop shadow")))
Introduce Qt::ExpandedClientAreaHint The hint requests that the window's client area is expanded to fill parts of the window that might be (partially) covered by, or conflicting with, other (system) UI elements, such as the window's title bar, resize controls, or a status bar. The safe area margins of the window will reflect any areas that may have conflicting UI elements. If the client area is expanded into the area previously covered by the frame margins, the frame margins are reduced accordingly, as the frame margins represent the non-client-area parts of the window. This new flag replaces, and overlaps in value, with the existing Qt::MaximizeUsingFullscreenGeometryHint, as the latter was added to cover this exact use-case for mobile platforms. Now that we have the use-case on desktop platforms as well we want to use a more generic flag, so the old flag has been deprecated. Semantically, on iOS and Android, without the flags set, the window can be seen as being maximized to take up the entire screen, but with a frameMargin() that reflects the system status bar and resize controls. That's not technically how we implement things right now, but this is an implementation detail that will be changed in a follow-up. On macOS the flag maps to NSWindowStyleMaskFullSizeContentView, and on Windows we have an implementation cooking that uses the DwmExtendFrameIntoClientArea function. Task-number: QTBUG-127634 Change-Id: I9b6863b1550ccc056c16bce235d87b26a7d239b9 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> Reviewed-by: Wladimir Leuschner <wladimir.leuschner@qt.io>
2024-11-11 21:55:36 +00:00
, expandedClientAreaCheckBox(new QCheckBox(tr("Expanded client area")))
{
connect(msWindowsFixedSizeDialogCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(x11BypassWindowManagerCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(framelessWindowCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(windowTitleCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(windowSystemMenuCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(windowMinimizeButtonCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(windowMaximizeButtonCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(windowFullscreenButtonCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(windowCloseButtonCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(windowContextHelpButtonCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(windowShadeButtonCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(windowStaysOnTopCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(windowStaysOnBottomCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(customizeWindowGroup, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(transparentForInputCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
connect(noDropShadowCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
Introduce Qt::ExpandedClientAreaHint The hint requests that the window's client area is expanded to fill parts of the window that might be (partially) covered by, or conflicting with, other (system) UI elements, such as the window's title bar, resize controls, or a status bar. The safe area margins of the window will reflect any areas that may have conflicting UI elements. If the client area is expanded into the area previously covered by the frame margins, the frame margins are reduced accordingly, as the frame margins represent the non-client-area parts of the window. This new flag replaces, and overlaps in value, with the existing Qt::MaximizeUsingFullscreenGeometryHint, as the latter was added to cover this exact use-case for mobile platforms. Now that we have the use-case on desktop platforms as well we want to use a more generic flag, so the old flag has been deprecated. Semantically, on iOS and Android, without the flags set, the window can be seen as being maximized to take up the entire screen, but with a frameMargin() that reflects the system status bar and resize controls. That's not technically how we implement things right now, but this is an implementation detail that will be changed in a follow-up. On macOS the flag maps to NSWindowStyleMaskFullSizeContentView, and on Windows we have an implementation cooking that uses the DwmExtendFrameIntoClientArea function. Task-number: QTBUG-127634 Change-Id: I9b6863b1550ccc056c16bce235d87b26a7d239b9 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> Reviewed-by: Wladimir Leuschner <wladimir.leuschner@qt.io>
2024-11-11 21:55:36 +00:00
connect(expandedClientAreaCheckBox, SIGNAL(clicked()), this, SLOT(slotCheckBoxChanged()));
auto *layout = new QHBoxLayout(this);
layout->setSpacing(0);
layout->setContentsMargins(ControlLayoutMargin, ControlLayoutMargin,
ControlLayoutMargin, ControlLayoutMargin);
auto *basicHintsLayout = new QVBoxLayout;
basicHintsLayout->setSpacing(0);
basicHintsLayout->setContentsMargins(ControlLayoutMargin, ControlLayoutMargin,
ControlLayoutMargin, ControlLayoutMargin);
basicHintsLayout->addWidget(framelessWindowCheckBox);
basicHintsLayout->addWidget(noDropShadowCheckBox);
basicHintsLayout->addWidget(windowStaysOnTopCheckBox);
basicHintsLayout->addWidget(windowStaysOnBottomCheckBox);
basicHintsLayout->addWidget(transparentForInputCheckBox);
basicHintsLayout->addWidget(msWindowsFixedSizeDialogCheckBox);
basicHintsLayout->addWidget(x11BypassWindowManagerCheckBox);
Introduce Qt::ExpandedClientAreaHint The hint requests that the window's client area is expanded to fill parts of the window that might be (partially) covered by, or conflicting with, other (system) UI elements, such as the window's title bar, resize controls, or a status bar. The safe area margins of the window will reflect any areas that may have conflicting UI elements. If the client area is expanded into the area previously covered by the frame margins, the frame margins are reduced accordingly, as the frame margins represent the non-client-area parts of the window. This new flag replaces, and overlaps in value, with the existing Qt::MaximizeUsingFullscreenGeometryHint, as the latter was added to cover this exact use-case for mobile platforms. Now that we have the use-case on desktop platforms as well we want to use a more generic flag, so the old flag has been deprecated. Semantically, on iOS and Android, without the flags set, the window can be seen as being maximized to take up the entire screen, but with a frameMargin() that reflects the system status bar and resize controls. That's not technically how we implement things right now, but this is an implementation detail that will be changed in a follow-up. On macOS the flag maps to NSWindowStyleMaskFullSizeContentView, and on Windows we have an implementation cooking that uses the DwmExtendFrameIntoClientArea function. Task-number: QTBUG-127634 Change-Id: I9b6863b1550ccc056c16bce235d87b26a7d239b9 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> Reviewed-by: Wladimir Leuschner <wladimir.leuschner@qt.io>
2024-11-11 21:55:36 +00:00
basicHintsLayout->addWidget(expandedClientAreaCheckBox);
layout->addLayout(basicHintsLayout);
customizeWindowGroup->setCheckable(true);
customizeWindowGroup->setChecked(false);
auto *customizeWindowLayout = new QVBoxLayout(customizeWindowGroup);
customizeWindowLayout->setSpacing(0);
customizeWindowLayout->setContentsMargins(ControlLayoutMargin, ControlLayoutMargin,
ControlLayoutMargin, ControlLayoutMargin);
customizeWindowLayout->addWidget(windowTitleCheckBox);
customizeWindowLayout->addWidget(windowSystemMenuCheckBox);
customizeWindowLayout->addWidget(windowMinimizeButtonCheckBox);
customizeWindowLayout->addWidget(windowShadeButtonCheckBox);
customizeWindowLayout->addWidget(windowMaximizeButtonCheckBox);
customizeWindowLayout->addWidget(windowFullscreenButtonCheckBox);
customizeWindowLayout->addWidget(windowCloseButtonCheckBox);
customizeWindowLayout->addWidget(windowContextHelpButtonCheckBox);
layout->addWidget(customizeWindowGroup);
}
Qt::WindowFlags HintControl::hints() const
{
Qt::WindowFlags flags;
if (msWindowsFixedSizeDialogCheckBox->isChecked())
flags |= Qt::MSWindowsFixedSizeDialogHint;
if (x11BypassWindowManagerCheckBox->isChecked())
flags |= Qt::X11BypassWindowManagerHint;
if (framelessWindowCheckBox->isChecked())
flags |= Qt::FramelessWindowHint;
if (windowTitleCheckBox->isChecked())
flags |= Qt::WindowTitleHint;
if (windowSystemMenuCheckBox->isChecked())
flags |= Qt::WindowSystemMenuHint;
if (windowMinimizeButtonCheckBox->isChecked())
flags |= Qt::WindowMinimizeButtonHint;
if (windowMaximizeButtonCheckBox->isChecked())
flags |= Qt::WindowMaximizeButtonHint;
if (windowFullscreenButtonCheckBox->isChecked())
flags |= Qt::WindowFullscreenButtonHint;
if (windowCloseButtonCheckBox->isChecked())
flags |= Qt::WindowCloseButtonHint;
if (windowContextHelpButtonCheckBox->isChecked())
flags |= Qt::WindowContextHelpButtonHint;
if (windowShadeButtonCheckBox->isChecked())
flags |= Qt::WindowShadeButtonHint;
if (windowStaysOnTopCheckBox->isChecked())
flags |= Qt::WindowStaysOnTopHint;
if (windowStaysOnBottomCheckBox->isChecked())
flags |= Qt::WindowStaysOnBottomHint;
if (customizeWindowGroup->isChecked())
flags |= Qt::CustomizeWindowHint;
if (transparentForInputCheckBox->isChecked())
flags |= Qt::WindowTransparentForInput;
if (noDropShadowCheckBox->isChecked())
flags |= Qt::NoDropShadowWindowHint;
Introduce Qt::ExpandedClientAreaHint The hint requests that the window's client area is expanded to fill parts of the window that might be (partially) covered by, or conflicting with, other (system) UI elements, such as the window's title bar, resize controls, or a status bar. The safe area margins of the window will reflect any areas that may have conflicting UI elements. If the client area is expanded into the area previously covered by the frame margins, the frame margins are reduced accordingly, as the frame margins represent the non-client-area parts of the window. This new flag replaces, and overlaps in value, with the existing Qt::MaximizeUsingFullscreenGeometryHint, as the latter was added to cover this exact use-case for mobile platforms. Now that we have the use-case on desktop platforms as well we want to use a more generic flag, so the old flag has been deprecated. Semantically, on iOS and Android, without the flags set, the window can be seen as being maximized to take up the entire screen, but with a frameMargin() that reflects the system status bar and resize controls. That's not technically how we implement things right now, but this is an implementation detail that will be changed in a follow-up. On macOS the flag maps to NSWindowStyleMaskFullSizeContentView, and on Windows we have an implementation cooking that uses the DwmExtendFrameIntoClientArea function. Task-number: QTBUG-127634 Change-Id: I9b6863b1550ccc056c16bce235d87b26a7d239b9 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> Reviewed-by: Wladimir Leuschner <wladimir.leuschner@qt.io>
2024-11-11 21:55:36 +00:00
if (expandedClientAreaCheckBox->isChecked())
flags |= Qt::ExpandedClientAreaHint;
return flags;
}
void HintControl::setHints(Qt::WindowFlags flags)
{
msWindowsFixedSizeDialogCheckBox->setChecked(flags & Qt::MSWindowsFixedSizeDialogHint);
x11BypassWindowManagerCheckBox->setChecked(flags & Qt::X11BypassWindowManagerHint);
framelessWindowCheckBox->setChecked(flags & Qt::FramelessWindowHint);
windowTitleCheckBox->setChecked(flags & Qt::WindowTitleHint);
windowSystemMenuCheckBox->setChecked(flags & Qt::WindowSystemMenuHint);
windowMinimizeButtonCheckBox->setChecked(flags & Qt::WindowMinimizeButtonHint);
windowMaximizeButtonCheckBox->setChecked(flags & Qt::WindowMaximizeButtonHint);
windowFullscreenButtonCheckBox->setChecked(flags & Qt::WindowFullscreenButtonHint);
windowCloseButtonCheckBox->setChecked(flags & Qt::WindowCloseButtonHint);
windowContextHelpButtonCheckBox->setChecked(flags & Qt::WindowContextHelpButtonHint);
windowShadeButtonCheckBox->setChecked(flags & Qt::WindowShadeButtonHint);
windowStaysOnTopCheckBox->setChecked(flags & Qt::WindowStaysOnTopHint);
windowStaysOnBottomCheckBox->setChecked(flags & Qt::WindowStaysOnBottomHint);
customizeWindowGroup->setChecked(flags & Qt::CustomizeWindowHint);
transparentForInputCheckBox->setChecked(flags & Qt::WindowTransparentForInput);
noDropShadowCheckBox->setChecked(flags & Qt::NoDropShadowWindowHint);
Introduce Qt::ExpandedClientAreaHint The hint requests that the window's client area is expanded to fill parts of the window that might be (partially) covered by, or conflicting with, other (system) UI elements, such as the window's title bar, resize controls, or a status bar. The safe area margins of the window will reflect any areas that may have conflicting UI elements. If the client area is expanded into the area previously covered by the frame margins, the frame margins are reduced accordingly, as the frame margins represent the non-client-area parts of the window. This new flag replaces, and overlaps in value, with the existing Qt::MaximizeUsingFullscreenGeometryHint, as the latter was added to cover this exact use-case for mobile platforms. Now that we have the use-case on desktop platforms as well we want to use a more generic flag, so the old flag has been deprecated. Semantically, on iOS and Android, without the flags set, the window can be seen as being maximized to take up the entire screen, but with a frameMargin() that reflects the system status bar and resize controls. That's not technically how we implement things right now, but this is an implementation detail that will be changed in a follow-up. On macOS the flag maps to NSWindowStyleMaskFullSizeContentView, and on Windows we have an implementation cooking that uses the DwmExtendFrameIntoClientArea function. Task-number: QTBUG-127634 Change-Id: I9b6863b1550ccc056c16bce235d87b26a7d239b9 Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io> Reviewed-by: Wladimir Leuschner <wladimir.leuschner@qt.io>
2024-11-11 21:55:36 +00:00
expandedClientAreaCheckBox->setChecked(flags & Qt::ExpandedClientAreaHint);
}
void HintControl::slotCheckBoxChanged()
{
emit changed(hints());
}
WindowStateControl::WindowStateControl(QWidget *parent)
: QWidget(parent)
, group(new QButtonGroup)
, restoreButton(new QCheckBox(tr("Normal")))
, minimizeButton(new QCheckBox(tr("Minimized")))
, maximizeButton(new QCheckBox(tr("Maximized")))
, fullscreenButton(new QCheckBox(tr("Fullscreen")))
{
QHBoxLayout *layout = new QHBoxLayout(this);
group->setExclusive(false);
layout->setContentsMargins(ControlLayoutMargin, ControlLayoutMargin,
ControlLayoutMargin, ControlLayoutMargin);
group->addButton(restoreButton, Qt::WindowNoState);
restoreButton->setEnabled(false);
layout->addWidget(restoreButton);
group->addButton(minimizeButton, Qt::WindowMinimized);
layout->addWidget(minimizeButton);
group->addButton(maximizeButton, Qt::WindowMaximized);
layout->addWidget(maximizeButton);
group->addButton(fullscreenButton, Qt::WindowFullScreen);
layout->addWidget(fullscreenButton);
connect(group, &QButtonGroup::idReleased, this, &WindowStateControl::stateChanged);
}
Qt::WindowStates WindowStateControl::state() const
{
Qt::WindowStates states;
foreach (QAbstractButton *button, group->buttons()) {
if (button->isChecked())
states |= Qt::WindowState(group->id(button));
}
return states;
}
void WindowStateControl::setState(Qt::WindowStates s)
{
group->blockSignals(true);
foreach (QAbstractButton *button, group->buttons())
button->setChecked(s & Qt::WindowState(group->id(button)));
if (!(s & (Qt::WindowMaximized | Qt::WindowFullScreen)))
restoreButton->setChecked(true);
group->blockSignals(false);
}
WindowStatesControl::WindowStatesControl(QWidget *parent)
: QGroupBox(tr("States"), parent)
, visibleCheckBox(new QCheckBox(tr("Visible")))
, activeCheckBox(new QCheckBox(tr("Active")))
, stateControl(new WindowStateControl)
{
QHBoxLayout *layout = new QHBoxLayout(this);
layout->setSpacing(0);
layout->setContentsMargins(ControlLayoutMargin, ControlLayoutMargin,
ControlLayoutMargin, ControlLayoutMargin);
connect(visibleCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
layout->addWidget(visibleCheckBox);
connect(activeCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(changed()));
layout->addWidget(activeCheckBox);
layout->addWidget(stateControl);
connect(stateControl, SIGNAL(stateChanged(int)), this, SIGNAL(changed()));
}
Qt::WindowStates WindowStatesControl::states() const
{
Qt::WindowStates s = stateControl->state();
if (activeValue())
s |= Qt::WindowActive;
return s;
}
void WindowStatesControl::setStates(Qt::WindowStates s)
{
stateControl->setState(s);
setActiveValue(s & Qt::WindowActive);
}
bool WindowStatesControl::visibleValue() const
{
return visibleCheckBox && visibleCheckBox->isChecked();
}
void WindowStatesControl::setVisibleValue(bool v)
{
if (visibleCheckBox) {
visibleCheckBox->blockSignals(true);
visibleCheckBox->setChecked(v);
visibleCheckBox->blockSignals(false);
}
}
bool WindowStatesControl::activeValue() const
{
return activeCheckBox && activeCheckBox->isChecked();
}
void WindowStatesControl::setActiveValue(bool v)
{
if (activeCheckBox) {
activeCheckBox->blockSignals(true);
activeCheckBox->setChecked(v);
activeCheckBox->blockSignals(false);
}
}
TypeControl::TypeControl(QWidget *parent)
: QGroupBox(tr("Type"), parent)
, group(new QButtonGroup)
, windowRadioButton(new QRadioButton(tr("Window")))
, dialogRadioButton(new QRadioButton(tr("Dialog")))
, sheetRadioButton(new QRadioButton(tr("Sheet")))
, drawerRadioButton(new QRadioButton(tr("Drawer")))
, popupRadioButton(new QRadioButton(tr("Popup")))
, toolRadioButton(new QRadioButton(tr("Tool")))
, toolTipRadioButton(new QRadioButton(tr("Tooltip")))
, splashScreenRadioButton(new QRadioButton(tr("Splash screen")))
{
group->setExclusive(true);
QGridLayout *layout = new QGridLayout(this);
layout->setSpacing(0);
layout->setContentsMargins(ControlLayoutMargin, ControlLayoutMargin,
ControlLayoutMargin, ControlLayoutMargin);
group->addButton(windowRadioButton, Qt::Window);
layout->addWidget(windowRadioButton, 0, 0);
group->addButton(dialogRadioButton, Qt::Dialog);
layout->addWidget(dialogRadioButton, 1, 0);
group->addButton(sheetRadioButton, Qt::Sheet);
layout->addWidget(sheetRadioButton, 2, 0);
group->addButton(drawerRadioButton, Qt::Drawer);
layout->addWidget(drawerRadioButton, 3, 0);
group->addButton(popupRadioButton, Qt::Popup);
layout->addWidget(popupRadioButton, 0, 1);
group->addButton(toolRadioButton, Qt::Tool);
layout->addWidget(toolRadioButton, 1, 1);
group->addButton(toolTipRadioButton, Qt::ToolTip);
layout->addWidget(toolTipRadioButton, 2, 1);
group->addButton(splashScreenRadioButton, Qt::SplashScreen);
layout->addWidget(splashScreenRadioButton, 3, 1);
connect(group, &QButtonGroup::idReleased, this, &TypeControl::slotChanged);
}
Qt::WindowFlags TypeControl::type() const
{
return Qt::WindowFlags(group->checkedId());
}
void TypeControl::setType(Qt::WindowFlags s)
{
if (QAbstractButton *b = group->button(s & Qt::WindowType_Mask))
b->setChecked(true);
}
void TypeControl::slotChanged()
{
emit changed(type());
}