Add a cross-platform frameless window example

Written in pure Qt. Cross-platform.
Lacking the system features on Windows of course.

Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
Yuhang Zhao 2020-11-18 11:32:04 +08:00
parent e5cd434500
commit 8e78e275e4
7 changed files with 423 additions and 12 deletions

View File

@ -0,0 +1,6 @@
TARGET = QWidget2
TEMPLATE = app
QT += widgets
HEADERS += widget.h
SOURCES += widget.cpp main.cpp
include($$PWD/../common.pri)

View File

@ -0,0 +1,63 @@
/*
* MIT License
*
* Copyright (C) 2020 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "widget.h"
#include <QApplication>
#include <QStyleOption>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
// High DPI scaling is enabled by default from Qt 6
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
// Windows: we are using the manifest file to get maximum compatibility
// because some APIs are not supprted on old systems such as Windows 7
// and Windows 8. And once we have set the DPI awareness level in the
// manifest file, any attemptation to try to change it through API will
// fail. In other words, Qt won't be able to enable or disable high DPI
// scaling or change the DPI awareness level once we have set it in the
// manifest file. So the following two lines are uesless actually (However,
// they are still useful on other platforms).
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
// Don't round the scale factor.
// This will break QWidget applications because they can't render correctly.
// Qt Quick applications won't have this issue.
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(
Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
#endif
QApplication application(argc, argv);
Widget widget;
QStyleOption option;
option.initFrom(&widget);
const QIcon icon = widget.style()->standardIcon(QStyle::SP_ComputerIcon, &option);
widget.setWindowIcon(icon);
widget.setWindowTitle(QObject::tr("Hello, World!"));
widget.resize(800, 600);
widget.show();
return QApplication::exec();
}

View File

@ -0,0 +1,259 @@
/*
* MIT License
*
* Copyright (C) 2020 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "widget.h"
#include "../../framelesshelper.h"
#include <QEvent>
#include <QGraphicsDropShadowEffect>
#include <QHBoxLayout>
#include <QLabel>
#include <QPainter>
#include <QPushButton>
#include <QSpacerItem>
#include <QVBoxLayout>
Q_GLOBAL_STATIC(FramelessHelper, framelessHelper)
ContentsWidget::ContentsWidget(QWidget *parent) : QWidget(parent)
{
setAttribute(Qt::WA_StyledBackground);
}
void ContentsWidget::setShouldDrawWindowBorder(const bool val)
{
m_bShouldDrawWindowBorder = val;
update();
}
bool ContentsWidget::getShouldDrawWindowBorder() const
{
return m_bShouldDrawWindowBorder;
}
void ContentsWidget::paintEvent(QPaintEvent *event)
{
QWidget::paintEvent(event);
if (m_bShouldDrawWindowBorder) {
QPainter painter(this);
painter.save();
painter.setPen({Qt::black, 1.5});
painter.drawLine(0, 0, width(), 0);
painter.drawLine(0, height(), width(), height());
painter.drawLine(0, 0, 0, height());
painter.drawLine(width(), 0, width(), height());
painter.restore();
}
}
Widget::Widget(QWidget *parent) : QWidget(parent)
{
titleBarHeight = framelessHelper()->getTitleBarHeight();
createWinId();
setupUi();
initBackgroundWindow();
installEventFilter(this);
}
bool Widget::isNormal() const
{
return (!isMinimized() && !isMaximized() && !isFullScreen());
}
void Widget::setupUi()
{
contentsWidget = new ContentsWidget(this);
contentsWidget->setObjectName(QLatin1String("contentsWidget"));
contentsWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
const QSize systemButtonSize = {qRound(titleBarHeight * 1.5), titleBarHeight};
const QSize systemIconSize = {17, 17};
titleBarWidget = new QWidget(contentsWidget);
titleBarWidget->setObjectName(QLatin1String("titleBarWidget"));
titleBarWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
titleBarWidget->setFixedHeight(titleBarHeight);
windowIconButton = new QPushButton(this);
windowIconButton->setObjectName(QLatin1String("windowIconButton"));
windowIconButton->setFixedSize(systemIconSize);
windowIconButton->setIconSize(systemIconSize);
connect(this, &Widget::windowIconChanged, windowIconButton, &QPushButton::setIcon);
windowTitleLabel = new QLabel(this);
QFont f = font();
f.setPointSizeF(8.63);
windowTitleLabel->setFont(f);
connect(this, &Widget::windowTitleChanged, windowTitleLabel, &QLabel::setText);
minimizeButton = new QPushButton(this);
minimizeButton->setObjectName(QLatin1String("minimizeButton"));
minimizeButton->setFixedSize(systemButtonSize);
minimizeButton->setIconSize(systemButtonSize);
minimizeButton->setIcon(QIcon(QLatin1String(":/images/button_minimize_black.svg")));
connect(minimizeButton, &QPushButton::clicked, this, &Widget::showMinimized);
maximizeButton = new QPushButton(this);
maximizeButton->setObjectName(QLatin1String("maximizeButton"));
maximizeButton->setFixedSize(systemButtonSize);
maximizeButton->setIconSize(systemButtonSize);
maximizeButton->setIcon(QIcon(QLatin1String(":/images/button_maximize_black.svg")));
connect(maximizeButton, &QPushButton::clicked, this, [this]() {
if (isMaximized()) {
showNormal();
} else {
showMaximized();
}
});
closeButton = new QPushButton(this);
closeButton->setObjectName(QLatin1String("closeButton"));
closeButton->setFixedSize(systemButtonSize);
closeButton->setIconSize(systemButtonSize);
closeButton->setIcon(QIcon(QLatin1String(":/images/button_close_black.svg")));
connect(closeButton, &QPushButton::clicked, this, &Widget::close);
const auto titleBarWidgetLayout = new QHBoxLayout(titleBarWidget);
titleBarWidgetLayout->setSpacing(0);
titleBarWidgetLayout->setContentsMargins(0, 0, 0, 0);
titleBarWidgetLayout->addSpacerItem(
new QSpacerItem(7, 20, QSizePolicy::Fixed, QSizePolicy::Fixed));
titleBarWidgetLayout->addWidget(windowIconButton);
titleBarWidgetLayout->addSpacerItem(
new QSpacerItem(3, 20, QSizePolicy::Fixed, QSizePolicy::Fixed));
titleBarWidgetLayout->addWidget(windowTitleLabel);
titleBarWidgetLayout->addStretch();
titleBarWidgetLayout->addWidget(minimizeButton);
titleBarWidgetLayout->addWidget(maximizeButton);
titleBarWidgetLayout->addWidget(closeButton);
titleBarWidget->setLayout(titleBarWidgetLayout);
const auto contentsWidgetLayout = new QVBoxLayout(contentsWidget);
contentsWidgetLayout->setSpacing(0);
contentsWidgetLayout->setContentsMargins(1, 1, 1, 0);
contentsWidgetLayout->addWidget(titleBarWidget);
contentsWidgetLayout->addStretch();
contentsWidget->setLayout(contentsWidgetLayout);
const auto backgroundWindowLayout = new QVBoxLayout(this);
backgroundWindowLayout->setSpacing(0);
backgroundWindowLayout->addWidget(contentsWidget);
setLayout(backgroundWindowLayout);
setStyleSheet(QLatin1String(R"(
#contentsWidget {
background-color: #f0f0f0;
}
#titleBarWidget {
background-color: white;
}
#windowIconButton, #minimizeButton, #maximizeButton, #closeButton {
border-style: none;
background-color: transparent;
}
#minimizeButton:hover, #maximizeButton:hover {
background-color: #80c7c7c7;
}
#minimizeButton:pressed, #maximizeButton:pressed {
background-color: #80808080;
}
#closeButton:hover {
background-color: #e81123;
}
#closeButton:pressed {
background-color: #8c0a15;
}
)"));
}
void Widget::initBackgroundWindow()
{
QWindow *win = windowHandle();
framelessHelper()->removeWindowFrame(win);
framelessHelper()->addIgnoreObject(win, windowIconButton);
framelessHelper()->addIgnoreObject(win, minimizeButton);
framelessHelper()->addIgnoreObject(win, maximizeButton);
framelessHelper()->addIgnoreObject(win, closeButton);
framelessHelper()->setTitleBarHeight(titleBarHeight + framelessHelper()->getBorderHeight());
//setAttribute(Qt::WA_Hover);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_TranslucentBackground);
shadowEffect = new QGraphicsDropShadowEffect(this);
shadowEffect->setOffset(0, 0);
contentsWidget->setGraphicsEffect(shadowEffect);
setFrameShadowEnabled();
setFrameShadowActive();
}
void Widget::setFrameShadowEnabled(const bool enable)
{
if (enable) {
const int bw = framelessHelper()->getBorderWidth();
const int bh = framelessHelper()->getBorderHeight();
layout()->setContentsMargins(bw, bh, bw, bh);
shadowEffect->setEnabled(true);
} else {
shadowEffect->setEnabled(false);
layout()->setContentsMargins(0, 0, 0, 0);
}
}
void Widget::setFrameShadowActive(const bool active)
{
if (active) {
shadowEffect->setColor({0, 0, 0, 80});
shadowEffect->setBlurRadius(25);
} else {
shadowEffect->setColor({0, 0, 0, 60});
shadowEffect->setBlurRadius(20);
}
}
bool Widget::eventFilter(QObject *object, QEvent *event)
{
Q_ASSERT(object);
Q_ASSERT(event);
if (object == this) {
switch (event->type()) {
case QEvent::WindowStateChange: {
const bool normal = isNormal();
contentsWidget->setShouldDrawWindowBorder(normal);
setFrameShadowEnabled(normal);
framelessHelper()->setTitleBarHeight(
titleBarHeight + (normal ? framelessHelper()->getBorderHeight() : 0));
const QLatin1String maxIconPath = QLatin1String{":/images/button_maximize_black.svg"};
const QLatin1String restoreIconPath = QLatin1String{
":/images/button_restore_black.svg"};
maximizeButton->setIcon(QIcon(normal ? maxIconPath : restoreIconPath));
} break;
case QEvent::WindowActivate: {
if (isNormal()) {
setFrameShadowActive();
}
} break;
case QEvent::WindowDeactivate: {
if (isNormal()) {
setFrameShadowActive(false);
}
} break;
default:
break;
}
}
return QWidget::eventFilter(object, event);
}

View File

@ -0,0 +1,82 @@
/*
* MIT License
*
* Copyright (C) 2020 by wangwenx190 (Yuhang Zhao)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#include <QWidget>
class QGraphicsDropShadowEffect;
class QPushButton;
class QLabel;
class ContentsWidget : public QWidget
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(ContentsWidget)
public:
explicit ContentsWidget(QWidget *parent = nullptr);
~ContentsWidget() override = default;
void setShouldDrawWindowBorder(const bool val);
bool getShouldDrawWindowBorder() const;
protected:
void paintEvent(QPaintEvent *event) override;
private:
bool m_bShouldDrawWindowBorder = true;
};
class Widget : public QWidget
{
Q_OBJECT
Q_DISABLE_COPY_MOVE(Widget)
public:
explicit Widget(QWidget *parent = nullptr);
~Widget() override = default;
bool isNormal() const;
protected:
bool eventFilter(QObject *object, QEvent *event) override;
private:
void setupUi();
void initBackgroundWindow();
void setFrameShadowEnabled(const bool enable = true);
void setFrameShadowActive(const bool active = true);
private:
int titleBarHeight = 30;
ContentsWidget *contentsWidget = nullptr;
QGraphicsDropShadowEffect *shadowEffect = nullptr;
QWidget *titleBarWidget = nullptr;
QPushButton *windowIconButton = nullptr;
QLabel *windowTitleLabel = nullptr;
QPushButton *minimizeButton = nullptr;
QPushButton *maximizeButton = nullptr;
QPushButton *closeButton = nullptr;
};

View File

@ -175,12 +175,12 @@ void Widget::setupUi()
horizontalLayout->setSpacing(0); horizontalLayout->setSpacing(0);
horizontalLayout->setContentsMargins(0, 0, 0, 0); horizontalLayout->setContentsMargins(0, 0, 0, 0);
horizontalSpacer_7 = new QSpacerItem(3, 20, QSizePolicy::Fixed, QSizePolicy::Minimum); horizontalSpacer_7 = new QSpacerItem(3, 20, QSizePolicy::Fixed, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer_7); horizontalLayout->addSpacerItem(horizontalSpacer_7);
iconButton = new QPushButton(titleBarWidget); iconButton = new QPushButton(titleBarWidget);
iconButton->setObjectName(QLatin1String("iconButton")); iconButton->setObjectName(QLatin1String("iconButton"));
horizontalLayout->addWidget(iconButton); horizontalLayout->addWidget(iconButton);
horizontalSpacer = new QSpacerItem(3, 20, QSizePolicy::Fixed, QSizePolicy::Minimum); horizontalSpacer = new QSpacerItem(3, 20, QSizePolicy::Fixed, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer); horizontalLayout->addSpacerItem(horizontalSpacer);
titleLabel = new QLabel(titleBarWidget); titleLabel = new QLabel(titleBarWidget);
titleLabel->setObjectName(QLatin1String("titleLabel")); titleLabel->setObjectName(QLatin1String("titleLabel"));
QFont font; QFont font;
@ -188,7 +188,7 @@ void Widget::setupUi()
titleLabel->setFont(font); titleLabel->setFont(font);
horizontalLayout->addWidget(titleLabel); horizontalLayout->addWidget(titleLabel);
horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalSpacer_2 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout->addItem(horizontalSpacer_2); horizontalLayout->addSpacerItem(horizontalSpacer_2);
minimizeButton = new QPushButton(titleBarWidget); minimizeButton = new QPushButton(titleBarWidget);
minimizeButton->setObjectName(QLatin1String("minimizeButton")); minimizeButton->setObjectName(QLatin1String("minimizeButton"));
QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Fixed); QSizePolicy sizePolicy1(QSizePolicy::Fixed, QSizePolicy::Fixed);
@ -235,10 +235,10 @@ void Widget::setupUi()
contentsWidget->setSizePolicy(sizePolicy2); contentsWidget->setSizePolicy(sizePolicy2);
verticalLayout_2 = new QVBoxLayout(contentsWidget); verticalLayout_2 = new QVBoxLayout(contentsWidget);
verticalSpacer_2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); verticalSpacer_2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
verticalLayout_2->addItem(verticalSpacer_2); verticalLayout_2->addSpacerItem(verticalSpacer_2);
horizontalLayout_2 = new QHBoxLayout(); horizontalLayout_2 = new QHBoxLayout();
horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalSpacer_3 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_2->addItem(horizontalSpacer_3); horizontalLayout_2->addSpacerItem(horizontalSpacer_3);
controlPanelWidget = new QWidget(contentsWidget); controlPanelWidget = new QWidget(contentsWidget);
QSizePolicy sizePolicy3(QSizePolicy::Maximum, QSizePolicy::Maximum); QSizePolicy sizePolicy3(QSizePolicy::Maximum, QSizePolicy::Maximum);
sizePolicy3.setHorizontalStretch(0); sizePolicy3.setHorizontalStretch(0);
@ -275,18 +275,18 @@ void Widget::setupUi()
verticalLayout->addWidget(resizableCB); verticalLayout->addWidget(resizableCB);
horizontalLayout_2->addWidget(controlPanelWidget); horizontalLayout_2->addWidget(controlPanelWidget);
horizontalSpacer_4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalSpacer_4 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_2->addItem(horizontalSpacer_4); horizontalLayout_2->addSpacerItem(horizontalSpacer_4);
verticalLayout_2->addLayout(horizontalLayout_2); verticalLayout_2->addLayout(horizontalLayout_2);
verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding);
verticalLayout_2->addItem(verticalSpacer); verticalLayout_2->addSpacerItem(verticalSpacer);
horizontalLayout_3 = new QHBoxLayout(); horizontalLayout_3 = new QHBoxLayout();
horizontalSpacer_5 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalSpacer_5 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_3->addItem(horizontalSpacer_5); horizontalLayout_3->addSpacerItem(horizontalSpacer_5);
moveCenterButton = new QPushButton(contentsWidget); moveCenterButton = new QPushButton(contentsWidget);
moveCenterButton->setFont(font1); moveCenterButton->setFont(font1);
horizontalLayout_3->addWidget(moveCenterButton); horizontalLayout_3->addWidget(moveCenterButton);
horizontalSpacer_6 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalSpacer_6 = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum);
horizontalLayout_3->addItem(horizontalSpacer_6); horizontalLayout_3->addSpacerItem(horizontalSpacer_6);
verticalLayout_2->addLayout(horizontalLayout_3); verticalLayout_2->addLayout(horizontalLayout_3);
verticalLayout_3->addWidget(contentsWidget); verticalLayout_3->addWidget(contentsWidget);
if (shouldDrawBorder()) { if (shouldDrawBorder()) {
@ -425,7 +425,7 @@ void Widget::paintEvent(QPaintEvent *event)
if (shouldDrawBorder()) { if (shouldDrawBorder()) {
QPainter painter(this); QPainter painter(this);
painter.save(); painter.save();
painter.setPen({borderColor(), 2.0}); painter.setPen({borderColor(), 1.5});
painter.drawLine(0, 0, width(), 0); painter.drawLine(0, 0, width(), 0);
painter.drawLine(0, height(), width(), height()); painter.drawLine(0, height(), width(), height());
painter.drawLine(0, 0, 0, height()); painter.drawLine(0, 0, 0, height());

View File

@ -1,5 +1,5 @@
TEMPLATE = subdirs TEMPLATE = subdirs
CONFIG -= ordered CONFIG -= ordered
qtHaveModule(widgets): SUBDIRS += QWidget QMainWindow qtHaveModule(widgets): SUBDIRS += QWidget QWidget2 QMainWindow
qtHaveModule(quick): SUBDIRS += Quick qtHaveModule(quick): SUBDIRS += Quick
win32: qtHaveModule(widgets): SUBDIRS += Win32Demo win32: qtHaveModule(widgets): SUBDIRS += Win32Demo

View File

@ -217,7 +217,8 @@ void FramelessHelper::setTitleBarEnabled(const QWindow *window, const bool val)
void FramelessHelper::removeWindowFrame(QWindow *window, const bool center) void FramelessHelper::removeWindowFrame(QWindow *window, const bool center)
{ {
Q_ASSERT(window); Q_ASSERT(window);
window->setFlags(window->flags() | Qt::FramelessWindowHint); window->setFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowSystemMenuHint
| Qt::WindowMinMaxButtonsHint | Qt::WindowTitleHint);
// MouseTracking is always enabled for QWindow. // MouseTracking is always enabled for QWindow.
window->installEventFilter(this); window->installEventFilter(this);
if (center) { if (center) {