支持嵌套无边框组件

This commit is contained in:
1bbb 2022-12-08 10:23:02 +08:00 committed by Yuhang Zhao
parent d5d1edd690
commit 4844257fc8
11 changed files with 38 additions and 66 deletions

View File

@ -27,6 +27,10 @@ set(SOURCES
../shared/log.cpp
../shared/settings.h
../shared/settings.cpp
../dialog/dialog.h
../dialog/dialog.cpp
../widget/widget.h
../widget/widget.cpp
mainwindow.ui
mainwindow.h
mainwindow.cpp

View File

@ -31,6 +31,8 @@
#include <StandardSystemButton>
#include <FramelessWidgetsHelper>
#include "../shared/settings.h"
#include "../widget/widget.h"
#include "../dialog/dialog.h"
FRAMELESSHELPER_USE_NAMESPACE
@ -106,4 +108,14 @@ QMenuBar::item:pressed {
setWindowTitle(tr("FramelessHelper demo application - Qt MainWindow"));
setWindowIcon(QFileIconProvider().icon(QFileIconProvider::Computer));
connect(m_mainWindow->pushButton, &QPushButton::clicked, this, [this]{
const auto dialog = new Dialog(this);
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->exec();
});
connect(m_mainWindow->pushButton_2, &QPushButton::clicked, this, [this]{
const auto widget = new Widget(this);
widget->setAttribute(Qt::WA_DeleteOnClose);
widget->show();
});
}

View File

@ -85,9 +85,6 @@ public:
Q_NODISCARD static FramelessQuickHelper *findOrCreateFramelessHelper(QObject *object);
protected:
Q_NODISCARD bool eventFilter(QObject *object, QEvent *event) override;
private:
Q_NODISCARD QRect mapItemGeometryToScene(const QQuickItem * const item) const;
Q_NODISCARD bool isInSystemButtons(const QPoint &pos, QuickGlobal::SystemButtonType *button) const;

View File

@ -530,8 +530,6 @@ void FramelessHelperWin::addWindow(const SystemParameters &params)
}
g_win32Helper()->mutex.unlock();
DEBUG.noquote() << "The DPI of window" << hwnd2str(windowId) << "is" << data.dpi;
// Some Qt internals have to be corrected.
Utils::maybeFixupQtInternals(windowId);
// Qt maintains a frame margin internally, we need to update it accordingly
// otherwise we'll get lots of warning messages when we change the window
// geometry, it will also affect the final window geometry because QPA will

View File

@ -186,8 +186,6 @@ void FramelessQuickHelperPrivate::attach()
}
g_quickHelper()->mutex.unlock();
window->installEventFilter(this);
SystemParameters params = {};
params.getWindowId = [window]() -> WId { return window->winId(); };
params.getWindowFlags = [window]() -> Qt::WindowFlags { return window->flags(); };
@ -260,7 +258,6 @@ void FramelessQuickHelperPrivate::detach()
return;
}
g_quickHelper()->data.remove(windowId);
w->removeEventFilter(this);
FramelessManager::instance()->removeWindow(windowId);
}
@ -656,33 +653,6 @@ FramelessQuickHelper *FramelessQuickHelperPrivate::findOrCreateFramelessHelper(Q
return instance;
}
bool FramelessQuickHelperPrivate::eventFilter(QObject *object, QEvent *event)
{
Q_ASSERT(object);
Q_ASSERT(event);
if (!object || !event) {
return false;
}
#ifdef Q_OS_WINDOWS
if (!object->isWindowType() || (event->type() != QEvent::WindowStateChange)
|| FramelessConfig::instance()->isSet(Option::UseCrossPlatformQtImplementation)) {
return QObject::eventFilter(object, event);
}
const auto window = qobject_cast<QQuickWindow *>(object);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
if (Utils::windowStatesToWindowState(window->windowStates()) != Qt::WindowFullScreen) {
#else
if (window->windowState() != Qt::WindowFullScreen) {
#endif
const auto changeEvent = static_cast<QWindowStateChangeEvent *>(event);
if (Utils::windowStatesToWindowState(changeEvent->oldState()) == Qt::WindowFullScreen) {
Utils::maybeFixupQtInternals(window->winId());
}
}
#endif
return QObject::eventFilter(object, event);
}
QRect FramelessQuickHelperPrivate::mapItemGeometryToScene(const QQuickItem * const item) const
{
Q_ASSERT(item);

View File

@ -79,6 +79,12 @@ const FramelessDialogPrivate *FramelessDialogPrivate::get(const FramelessDialog
void FramelessDialogPrivate::initialize()
{
Q_Q(FramelessDialog);
// Without this flag, Qt will always create an invisible native parent window
// for any native widgets which will intercept some win32 messages and confuse
// our own native event filter, so to prevent some weired bugs from happening,
// just disable this feature.
q->setAttribute(Qt::WA_DontCreateNativeAncestors);
q->setAttribute(Qt::WA_NativeWindow);
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
m_sharedHelper = new WidgetsSharedHelper(this);
m_sharedHelper->setup(q);

View File

@ -79,6 +79,12 @@ const FramelessMainWindowPrivate *FramelessMainWindowPrivate::get(const Frameles
void FramelessMainWindowPrivate::initialize()
{
Q_Q(FramelessMainWindow);
// Without this flag, Qt will always create an invisible native parent window
// for any native widgets which will intercept some win32 messages and confuse
// our own native event filter, so to prevent some weired bugs from happening,
// just disable this feature.
q->setAttribute(Qt::WA_DontCreateNativeAncestors);
q->setAttribute(Qt::WA_NativeWindow);
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
m_sharedHelper = new WidgetsSharedHelper(this);
m_sharedHelper->setup(q);

View File

@ -79,6 +79,12 @@ const FramelessWidgetPrivate *FramelessWidgetPrivate::get(const FramelessWidget
void FramelessWidgetPrivate::initialize()
{
Q_Q(FramelessWidget);
// Without this flag, Qt will always create an invisible native parent window
// for any native widgets which will intercept some win32 messages and confuse
// our own native event filter, so to prevent some weired bugs from happening,
// just disable this feature.
q->setAttribute(Qt::WA_DontCreateNativeAncestors);
q->setAttribute(Qt::WA_NativeWindow);
FramelessWidgetsHelper::get(q)->extendsContentIntoTitleBar();
m_sharedHelper = new WidgetsSharedHelper(this);
m_sharedHelper->setup(q);
@ -123,7 +129,7 @@ WidgetsSharedHelper *FramelessWidgetPrivate::widgetsSharedHelper() const
}
FramelessWidget::FramelessWidget(QWidget *parent)
: QWidget(parent), d_ptr(new FramelessWidgetPrivate(this))
: QWidget(parent, Qt::Window), d_ptr(new FramelessWidgetPrivate(this))
{
}

View File

@ -298,8 +298,7 @@ WidgetsSharedHelper *FramelessWidgetsHelperPrivate::findOrCreateSharedHelper(QWi
return dialogPriv->widgetsSharedHelper();
}
}
QWidget * const topLevelWindow = (window->nativeParentWidget()
? window->nativeParentWidget() : window->window());
QWidget * const topLevelWindow = window->window();
WidgetsSharedHelper *helper = topLevelWindow->findChild<WidgetsSharedHelper *>();
if (!helper) {
helper = new WidgetsSharedHelper;
@ -317,11 +316,7 @@ FramelessWidgetsHelper *FramelessWidgetsHelperPrivate::findOrCreateFramelessHelp
}
QObject *parent = nullptr;
if (const auto widget = qobject_cast<QWidget *>(object)) {
if (QWidget * const nativeParent = widget->nativeParentWidget()) {
parent = nativeParent;
} else {
parent = widget->window();
}
parent = widget->window();
} else {
parent = object;
}
@ -435,15 +430,6 @@ void FramelessWidgetsHelperPrivate::attach()
}
g_widgetsHelper()->mutex.unlock();
// Without this flag, Qt will always create an invisible native parent window
// for any native widgets which will intercept some win32 messages and confuse
// our own native event filter, so to prevent some weired bugs from happening,
// just disable this feature.
window->setAttribute(Qt::WA_DontCreateNativeAncestors);
// Force the widget become a native window now so that we can deal with its
// win32 events as soon as possible.
window->setAttribute(Qt::WA_NativeWindow);
SystemParameters params = {};
params.getWindowId = [window]() -> WId { return window->winId(); };
params.getWindowFlags = [window]() -> Qt::WindowFlags { return window->windowFlags(); };
@ -540,9 +526,6 @@ QWidget *FramelessWidgetsHelperPrivate::findTopLevelWindow() const
Q_ASSERT(p);
if (p) {
if (const auto parentWidget = qobject_cast<const QWidget *>(p)) {
if (QWidget * const nativeParent = parentWidget->nativeParentWidget()) {
return nativeParent;
}
return parentWidget->window();
}
}

View File

@ -441,7 +441,7 @@ bool StandardTitleBarPrivate::eventFilter(QObject *object, QEvent *event)
void StandardTitleBarPrivate::initialize()
{
Q_Q(StandardTitleBar);
m_window = (q->nativeParentWidget() ? q->nativeParentWidget() : q->window());
m_window = q->window();
m_chromePalette = new ChromePalette(this);
connect(m_chromePalette, &ChromePalette::titleBarColorChanged,
this, &StandardTitleBarPrivate::updateTitleBarColor);

View File

@ -195,16 +195,6 @@ void WidgetsSharedHelper::changeEventHandler(QEvent *event)
QMetaObject::invokeMethod(m_targetWidget, "zoomedChanged");
}
}
#ifdef Q_OS_WINDOWS
if (!FramelessConfig::instance()->isSet(Option::UseCrossPlatformQtImplementation)) {
if (Utils::windowStatesToWindowState(m_targetWidget->windowState()) != Qt::WindowFullScreen) {
const auto changeEvent = static_cast<QWindowStateChangeEvent *>(event);
if (Utils::windowStatesToWindowState(changeEvent->oldState()) == Qt::WindowFullScreen) {
Utils::maybeFixupQtInternals(m_targetWidget->winId());
}
}
}
#endif
}
void WidgetsSharedHelper::paintEventHandler(QPaintEvent *event)