From d6d9f4ff3d4523de9119f0aa4f072d75b4a889b9 Mon Sep 17 00:00:00 2001 From: zccrs Date: Mon, 9 Apr 2018 20:00:22 +0800 Subject: [PATCH] feat: add DWindowGroupLeader Change-Id: I9bf91ada334038107123655b36576132e18eb33f --- src/widgets/DWindowGroupLeader | 1 + src/widgets/dwindowgroupleader.cpp | 157 +++++++++++++++++++++++++++++ src/widgets/dwindowgroupleader.h | 52 ++++++++++ src/widgets/widgets.pri | 9 +- 4 files changed, 216 insertions(+), 3 deletions(-) create mode 100644 src/widgets/DWindowGroupLeader create mode 100644 src/widgets/dwindowgroupleader.cpp create mode 100644 src/widgets/dwindowgroupleader.h diff --git a/src/widgets/DWindowGroupLeader b/src/widgets/DWindowGroupLeader new file mode 100644 index 000000000..06639585d --- /dev/null +++ b/src/widgets/DWindowGroupLeader @@ -0,0 +1 @@ +#include "dwindowgroupleader.h" diff --git a/src/widgets/dwindowgroupleader.cpp b/src/widgets/dwindowgroupleader.cpp new file mode 100644 index 000000000..7479a014a --- /dev/null +++ b/src/widgets/dwindowgroupleader.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: zccrs + * + * Maintainer: zccrs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "dwindowgroupleader.h" + +#include +#include +#include +#include + +DWIDGET_BEGIN_NAMESPACE + +#define DEFINE_CONST_CHAR(Name) const char _##Name[] = "_d_" #Name + +DEFINE_CONST_CHAR(groupLeader); +DEFINE_CONST_CHAR(createGroupWindow); +DEFINE_CONST_CHAR(destoryGroupWindow); +DEFINE_CONST_CHAR(setWindowGroup); +DEFINE_CONST_CHAR(clientLeader); + +class DWindowGroupLeaderPrivate +{ +public: + DWindowGroupLeaderPrivate(quint32 groupLeader) + : groupLeader(groupLeader) { + QFunctionPointer clientLeaderFun = qApp->platformFunction(_clientLeader); + + if (clientLeaderFun) { + clientLeader = reinterpret_cast(clientLeaderFun)(); + } + } + + quint32 groupLeader; + quint32 clientLeader = 0; + bool groupLeaderFromUser = false; + + QList> windowList; + + void ensureGroupLeader(); + bool setWindowGroupLeader(quint32 window, quint32 groupLeader); +}; + +void DWindowGroupLeaderPrivate::ensureGroupLeader() +{ + if (groupLeader != 0) + return; + + QFunctionPointer createGroupWindow = qApp->platformFunction(_createGroupWindow); + + if (!createGroupWindow) + return; + + groupLeader = reinterpret_cast(createGroupWindow)(); +} + +bool DWindowGroupLeaderPrivate::setWindowGroupLeader(quint32 window, quint32 groupLeader) +{ + QFunctionPointer setWindowGroup = qApp->platformFunction(_setWindowGroup); + + if (!setWindowGroup) { + return false; + } + + reinterpret_cast(setWindowGroup)(window, groupLeader); + + return true; +} + +DWindowGroupLeader::DWindowGroupLeader(quint32 groupId) + : d_ptr(new DWindowGroupLeaderPrivate(groupId)) +{ + if (groupId != 0) + d_ptr->groupLeaderFromUser = true; +} + +DWindowGroupLeader::~DWindowGroupLeader() +{ + Q_D(DWindowGroupLeader); + + for (auto window : d->windowList) + removeWindow(window); + + if (!d->groupLeaderFromUser) { + QFunctionPointer destoryGroupWindow = qApp->platformFunction(_destoryGroupWindow); + + if (!destoryGroupWindow) + return; + + reinterpret_cast(destoryGroupWindow)(d->groupLeader); + } +} + +void DWindowGroupLeader::addWindow(QWindow *window) +{ + Q_ASSERT(window); + Q_D(DWindowGroupLeader); + + d->ensureGroupLeader(); + + window->setProperty(_groupLeader, d->groupLeader); + + if (window->handle()) { + d->setWindowGroupLeader(window->winId(), d->groupLeader); + } + + d->windowList << window; +} + +void DWindowGroupLeader::removeWindow(QWindow *window) +{ + if (!window) + return; + + window->setProperty(_groupLeader, QVariant()); + + Q_D(DWindowGroupLeader); + + if (window->handle()) { + d->setWindowGroupLeader(window->winId(), d->clientLeader); + } +} + +void DWindowGroupLeader::addWindow(QWidget *window) +{ + Q_ASSERT(window); + Q_ASSERT(window->isWindow()); + + if (!window->windowHandle()) { + window->setAttribute(Qt::WA_NativeWindow); + } + + return addWindow(window->windowHandle()); +} + +void DWindowGroupLeader::removeWindow(QWidget *window) +{ + return removeWindow(window->windowHandle()); +} + +DWIDGET_END_NAMESPACE diff --git a/src/widgets/dwindowgroupleader.h b/src/widgets/dwindowgroupleader.h new file mode 100644 index 000000000..05f6b2f3a --- /dev/null +++ b/src/widgets/dwindowgroupleader.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2017 ~ 2018 Deepin Technology Co., Ltd. + * + * Author: zccrs + * + * Maintainer: zccrs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef DWINDOWGROUPLEADER_H +#define DWINDOWGROUPLEADER_H + +#include + +QT_BEGIN_NAMESPACE +class QWindow; +QT_END_NAMESPACE + +DWIDGET_BEGIN_NAMESPACE + +class DWindowGroupLeaderPrivate; +class DWindowGroupLeader +{ +public: + explicit DWindowGroupLeader(quint32 groupId = 0); + ~DWindowGroupLeader(); + + void addWindow(QWindow *window); + void removeWindow(QWindow *window); + void addWindow(QWidget *window); + void removeWindow(QWidget *window); + +private: + QScopedPointer d_ptr; + + Q_DECLARE_PRIVATE(DWindowGroupLeader) +}; + +DWIDGET_END_NAMESPACE + +#endif // DWINDOWGROUPLEADER_H diff --git a/src/widgets/widgets.pri b/src/widgets/widgets.pri index be1ac1bba..5b06b4e3d 100644 --- a/src/widgets/widgets.pri +++ b/src/widgets/widgets.pri @@ -123,7 +123,8 @@ HEADERS += $$PWD/dslider.h\ $$PWD/dsuggestbutton.h \ $$PWD/dstyleoption.h \ $$PWD/dtoast.h \ - $$PWD/danchors.h + $$PWD/danchors.h \ + $$PWD/dwindowgroupleader.h SOURCES += $$PWD/dslider.cpp \ $$PWD/dthememanager.cpp \ @@ -203,7 +204,8 @@ SOURCES += $$PWD/dslider.cpp \ $$PWD/dsuggestbutton.cpp \ $$PWD/dstyleoption.cpp \ $$PWD/dtoast.cpp \ - $$PWD/danchors.cpp + $$PWD/danchors.cpp \ + $$PWD/dwindowgroupleader.cpp RESOURCES += \ $$PWD/themes/dui_theme_dark.qrc \ @@ -244,6 +246,7 @@ includes.files += \ $$PWD/DToast \ $$PWD/DFileDialog \ $$PWD/DLineEdit \ - $$PWD/DStyleOptionLineEdit + $$PWD/DStyleOptionLineEdit \ + $$PWD/DWindowGroupLeader