diff --git a/src/kernel/dplatformhandle.cpp b/src/kernel/dplatformhandle.cpp index d21fbd9..837ac21 100644 --- a/src/kernel/dplatformhandle.cpp +++ b/src/kernel/dplatformhandle.cpp @@ -2,122 +2,25 @@ // // SPDX-License-Identifier: LGPL-3.0-or-later - -#include "dguiapplicationhelper.h" #include "dplatformhandle.h" -#include "dplatformtheme.h" -#include "dwindowmanagerhelper.h" - +#include "dplatformwindowinterface_p.h" +#include "dguiapplicationhelper.h" +#ifndef DTK_DISABLE_XCB +#include "plugins/platform/xcb/dxcbplatformwindowinterface.h" +#endif #ifndef DTK_DISABLE_TREELAND #include "plugins/platform/treeland/dtreelandplatformwindowinterface.h" #endif -#include -#include - -#include -#include -#include -#include -#include - DGUI_BEGIN_NAMESPACE -#define DXCB_PLUGIN_KEY "dxcb" -#define DXCB_PLUGIN_SYMBOLIC_PROPERTY "_d_isDxcb" - -#define DEFINE_CONST_CHAR(Name) const char _##Name[] = "_d_" #Name - -DEFINE_CONST_CHAR(useDxcb); -DEFINE_CONST_CHAR(redirectContent); -DEFINE_CONST_CHAR(netWmStates); -DEFINE_CONST_CHAR(windowRadius); -DEFINE_CONST_CHAR(borderWidth); -DEFINE_CONST_CHAR(borderColor); -DEFINE_CONST_CHAR(windowEffect); -DEFINE_CONST_CHAR(windowStartUpEffect); -DEFINE_CONST_CHAR(shadowRadius); -DEFINE_CONST_CHAR(shadowOffset); -DEFINE_CONST_CHAR(shadowColor); -DEFINE_CONST_CHAR(clipPath); -DEFINE_CONST_CHAR(frameMask); -DEFINE_CONST_CHAR(frameMargins); -DEFINE_CONST_CHAR(translucentBackground); -DEFINE_CONST_CHAR(enableSystemResize); -DEFINE_CONST_CHAR(enableSystemMove); -DEFINE_CONST_CHAR(enableBlurWindow); -DEFINE_CONST_CHAR(windowBlurAreas); -DEFINE_CONST_CHAR(windowBlurPaths); -DEFINE_CONST_CHAR(windowWallpaperParas); -DEFINE_CONST_CHAR(autoInputMaskByClipPath); - -DEFINE_CONST_CHAR(resolve_mask); -enum PropRole { - WindowRadius, - - // TO BE CONTINUE -}; - -// functions -DEFINE_CONST_CHAR(setWmBlurWindowBackgroundArea); -DEFINE_CONST_CHAR(setWmBlurWindowBackgroundPathList); -DEFINE_CONST_CHAR(setWmBlurWindowBackgroundMaskImage); -DEFINE_CONST_CHAR(setWmWallpaperParameter); -DEFINE_CONST_CHAR(setWindowProperty); -DEFINE_CONST_CHAR(pluginVersion); -DEFINE_CONST_CHAR(disableOverrideCursor); -DEFINE_CONST_CHAR(enableDxcb); -DEFINE_CONST_CHAR(isEnableDxcb); -DEFINE_CONST_CHAR(setEnableNoTitlebar); -DEFINE_CONST_CHAR(isEnableNoTitlebar); -DEFINE_CONST_CHAR(clientLeader); - -static void resolve(QObject *obj, PropRole role) -{ - int mask = obj->property(_resolve_mask).toInt(); - obj->setProperty(_resolve_mask, (mask |= 1 << role)); -} +static QHash g_platformWindowImpls; -static bool resolved(QObject *obj, PropRole role) +static DPlatformWindowInterface *platformWindowImpl(const DPlatformHandle *platformHandle) { - int mask = obj->property(_resolve_mask).toInt(); - return mask & (1 << role); + return g_platformWindowImpls.value(platformHandle); } -static void setWindowProperty(QWindow *window, const char *name, const QVariant &value) -{ - if (!window) - return; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - static QFunctionPointer setWindowProperty = qApp->platformFunction(_setWindowProperty); -#else - constexpr QFunctionPointer setWindowProperty = nullptr; -#endif - - if (!setWindowProperty) { - window->setProperty(name, value); - - return; - } - - reinterpret_cast(setWindowProperty)(window, name, value); -} - -#ifndef DTK_DISABLE_TREELAND -static QHash g_platformThemeMap; - -static DTreeLandPlatformWindowInterface *dPlatformWindowInterfaceByWindow(QWindow * window) -{ - for (auto it = g_platformThemeMap.cbegin(); it != g_platformThemeMap.cend(); ++it) { - if (it.value()->getWindow() == window) { - return it.value(); - } - } - return nullptr; -} -#endif - /*! \class Dtk::Gui::DPlatformHandle \inmodule dtkgui @@ -394,6 +297,36 @@ static DTreeLandPlatformWindowInterface *dPlatformWindowInterfaceByWindow(QWindo 竖直方向的圆角半径 */ +static DPlatformWindowInterfaceFactory::Creator OutsideWindowInterfaceCreator = nullptr; + +void DPlatformWindowInterfaceFactory::registerInterface(Creator creator) +{ + OutsideWindowInterfaceCreator = creator; +} + +static DPlatformWindowInterface *createWindowInterface(QWindow *window, DPlatformHandle *platformHandle) +{ + DPlatformWindowInterface *impl = nullptr; + if (OutsideWindowInterfaceCreator) { + impl = OutsideWindowInterfaceCreator(window, platformHandle); + } + if (!impl) { +#ifndef DTK_DISABLE_XCB + if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsXWindowPlatform)) { + impl = new DXCBPlatformWindowInterface(window, platformHandle); + } +#endif + +#ifndef DTK_DISABLE_TREELAND + if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { + impl = new DTreeLandPlatformWindowInterface(window, platformHandle); + } +#endif + } + + return impl; +} + /*! \brief DPlatformHandle::DPlatformHandle 将 \a window 对象传递给 enableDXcbForWindow @@ -405,24 +338,21 @@ DPlatformHandle::DPlatformHandle(QWindow *window, QObject *parent) : QObject(parent) , m_window(window) { -#ifndef DTK_DISABLE_TREELAND - if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { - g_platformThemeMap.insert(this, new DTreeLandPlatformWindowInterface(nullptr, window)); + auto impl = createWindowInterface(window, this); + if (!impl) { + qDebug() << "Use default DPlatformWindowInterface for the window" << window->winId(); + impl = new DPlatformWindowInterface(window, this); } -#endif - - enableDXcbForWindow(window); + g_platformWindowImpls.insert(this, impl); - window->installEventFilter(this); + impl->setEnabled(true); } DPlatformHandle::~DPlatformHandle() { -#ifndef DTK_DISABLE_TREELAND - if (auto item = g_platformThemeMap.take(this)) { - item->deleteLater(); + if (auto item = g_platformWindowImpls.take(this)) { + delete item; } -#endif } /*! @@ -432,16 +362,11 @@ DPlatformHandle::~DPlatformHandle() */ QString DPlatformHandle::pluginVersion() { - QFunctionPointer pv = 0; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - pv = qApp->platformFunction(_pluginVersion); +#ifndef DTK_DISABLE_XCB + return DXCBPlatformWindowInterface::pluginVersion(); +#else + return {}; #endif - - if (Q_UNLIKELY(!pv)) - return QString(); - - return reinterpret_cast(pv)(); } /*! @@ -450,12 +375,11 @@ QString DPlatformHandle::pluginVersion() */ bool DPlatformHandle::isDXcbPlatform() { - if (!qApp) - return false; - - static bool _is_dxcb = qApp->platformName() == DXCB_PLUGIN_KEY || qApp->property(DXCB_PLUGIN_SYMBOLIC_PROPERTY).toBool(); - - return _is_dxcb; +#ifndef DTK_DISABLE_XCB + return DXCBPlatformWindowInterface::isDXcbPlatform(); +#else + return false; +#endif } /*! @@ -551,28 +475,12 @@ bool DPlatformHandle::isDXcbPlatform() */ void DPlatformHandle::enableDXcbForWindow(QWindow *window) { - // 优先使用窗口管理器中实现的no titlebar接口实现自定义窗口修饰器的效果 - if (setEnabledNoTitlebarForWindow(window, true)) { - return; + DPlatformHandle handle(window); +#ifndef DTK_DISABLE_XCB + if (auto impl = dynamic_cast(platformWindowImpl(&handle))) { + impl->setEnabled(true); } - - if (!isDXcbPlatform()) - return; - - QFunctionPointer enable_dxcb = nullptr; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - enable_dxcb = qApp->platformFunction(_enableDxcb); #endif - - if (enable_dxcb) { - (*reinterpret_cast(enable_dxcb))(window); - } else if (window->handle()) { - Q_ASSERT_X(window->property(_useDxcb).toBool(), "DPlatformHandler:", - "Must be called before window handle has been created. See also QWindow::handle()"); - } else { - window->setProperty(_useDxcb, true); - } } /*! @@ -593,9 +501,12 @@ void DPlatformHandle::enableDXcbForWindow(QWindow *window) */ void DPlatformHandle::enableDXcbForWindow(QWindow *window, bool redirectContent) { - window->setProperty(_redirectContent, redirectContent); - - enableDXcbForWindow(window); + DPlatformHandle handle(window); +#ifndef DTK_DISABLE_XCB + if (auto impl = dynamic_cast(platformWindowImpl(&handle))) { + impl->enableDXcb(redirectContent); + } +#endif } /*! @@ -606,61 +517,15 @@ void DPlatformHandle::enableDXcbForWindow(QWindow *window, bool redirectContent) */ bool DPlatformHandle::isEnabledDXcb(const QWindow *window) { - if (isEnabledNoTitlebar(window)) - return true; - - QFunctionPointer is_enable_dxcb = nullptr; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - is_enable_dxcb = qApp->platformFunction(_isEnableDxcb); -#endif - - if (is_enable_dxcb) { - return (*reinterpret_cast(is_enable_dxcb))(window); - } - - return window->property(_useDxcb).toBool(); -} - -static void initWindowRadius(QWindow *window) -{ - if (window->property(_windowRadius).isValid()) - return; - - auto theme = DGuiApplicationHelper::instance()->systemTheme(); - int radius = theme->windowRadius(18); //###(zccrs): 暂时在此处给窗口默认设置为18px的圆角 - - setWindowProperty(window, _windowRadius, radius); - // Qt::UniqueConnection will report a warning - // to `unique connections require a pointer to member function of a QObject subclass`. - const char *uniqueueConnectionFlag("_d_uniqueueConnectionFlag"); - bool connected = window->property(uniqueueConnectionFlag).toBool(); - if (!connected) { - window->setProperty(uniqueueConnectionFlag, true); - window->connect(theme, &DPlatformTheme::windowRadiusChanged, window, [window] (int radius) { - if (!resolved(window, PropRole::WindowRadius)) - setWindowProperty(window, _windowRadius, radius); - }); + DPlatformHandle handle(const_cast(window)); +#ifndef DTK_DISABLE_XCB + if (auto impl = dynamic_cast(platformWindowImpl(&handle))) { + return impl->isEnabled(); } +#endif + return false; } -class Q_DECL_HIDDEN CreatorWindowEventFilter : public QObject { -public: - CreatorWindowEventFilter(QObject *par= nullptr): QObject(par){} - -public: - bool eventFilter(QObject *watched, QEvent *event) override { - if (event->type() == QEvent::PlatformSurface) { - QPlatformSurfaceEvent *se = static_cast(event); - if (se->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) { // 若收到此信号, 则 WinID 已被创建 - auto window = qobject_cast(watched); - initWindowRadius(window); - } - } - return QObject::eventFilter(watched, event); - } -}; - /*! \brief DPlatformHandle::setEnabledNoTitlebarForWindow. @@ -675,46 +540,9 @@ class Q_DECL_HIDDEN CreatorWindowEventFilter : public QObject { */ bool DPlatformHandle::setEnabledNoTitlebarForWindow(QWindow *window, bool enable) { - auto isDWaylandPlatform = [] { - return qApp->platformName() == "dwayland" || qApp->property("_d_isDwayland").toBool(); - }; - if (!(isDXcbPlatform() || isDWaylandPlatform() || DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform))) - return false; - -#ifndef DTK_DISABLE_TREELAND - if (window && DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { - - auto handle = dPlatformWindowInterfaceByWindow(window); - if (handle) { - handle->setEnabledNoTitlebar(enable); - } - return true; - } -#endif - - if (isEnabledNoTitlebar(window) == enable) - return true; - - QFunctionPointer enable_no_titlear = nullptr; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - enable_no_titlear = qApp->platformFunction(_setEnableNoTitlebar); -#endif - - if (enable_no_titlear) { - bool ok = (*reinterpret_cast(enable_no_titlear))(window, enable); - if (ok && enable) { - if (window->handle()) { - initWindowRadius(window); - } else { - window->installEventFilter(new CreatorWindowEventFilter(window)); - } - } - - return ok; - } - - return false; + DPlatformHandle handle(window); + auto impl = platformWindowImpl(&handle); + return impl->setEnabledNoTitlebar(enable); } /*! @@ -725,34 +553,9 @@ bool DPlatformHandle::setEnabledNoTitlebarForWindow(QWindow *window, bool enable */ bool DPlatformHandle::isEnabledNoTitlebar(const QWindow *window) { - QFunctionPointer is_enable_no_titlebar = nullptr; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - is_enable_no_titlebar = qApp->platformFunction(_isEnableNoTitlebar); -#endif - - if (is_enable_no_titlebar) { - return (*reinterpret_cast(is_enable_no_titlebar))(window); - } - - return false; -} - -inline DPlatformHandle::WMBlurArea operator *(const DPlatformHandle::WMBlurArea &area, qreal scale) -{ - if (qFuzzyCompare(scale, 1.0)) - return area; - - DPlatformHandle::WMBlurArea new_area; - - new_area.x = qRound64(area.x * scale); - new_area.y = qRound64(area.y * scale); - new_area.width = qRound64(area.width * scale); - new_area.height = qRound64(area.height * scale); - new_area.xRadius = qRound64(area.xRadius * scale); - new_area.yRaduis = qRound64(area.yRaduis * scale); - - return new_area; + DPlatformHandle handle(const_cast(window)); + auto impl = platformWindowImpl(&handle); + return impl->isEnabledNoTitlebar(); } /*! @@ -799,66 +602,13 @@ inline DPlatformHandle::WMBlurArea operator *(const DPlatformHandle::WMBlurArea */ bool DPlatformHandle::setWindowBlurAreaByWM(QWindow *window, const QVector &area) { - if (!window) { - return false; - } - - if (isEnabledDXcb(window)) { - QVector areas; - for (auto item : area) - areas << item.x << item.y << item.width << item.height << item.xRadius << item.yRaduis; - setWindowProperty(window, _windowBlurAreas, QVariant::fromValue(areas)); - return true; + DPlatformHandle handle(const_cast(window)); +#ifndef DTK_DISABLE_XCB + if (auto impl = dynamic_cast(platformWindowImpl(&handle))) { + return impl->setWindowBlurArea(area); } - - QFunctionPointer setWmBlurWindowBackgroundArea = Q_NULLPTR; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - setWmBlurWindowBackgroundArea = qApp->platformFunction(_setWmBlurWindowBackgroundArea); #endif - - if (!setWmBlurWindowBackgroundArea) { - qWarning("setWindowBlurAreaByWM is not support"); - - return false; - } - - QSurfaceFormat format = window->format(); - - format.setAlphaBufferSize(8); - window->setFormat(format); - - const qreal device_ratio = window->devicePixelRatio(); - - if (qFuzzyCompare(device_ratio, 1.0)) { - return reinterpret_cast&)>(setWmBlurWindowBackgroundArea)(window->winId(), area); - } - - QVector new_areas; - - new_areas.reserve(area.size()); - - for (const WMBlurArea &a : area) { - new_areas.append(a * device_ratio); - } - - return reinterpret_cast&)>(setWmBlurWindowBackgroundArea)(window->winId(), new_areas); -} - -inline QPainterPath operator *(const QPainterPath &path, qreal scale) -{ - if (qFuzzyCompare(1.0, scale)) - return path; - - QPainterPath new_path = path; - - for (int i = 0; i < path.elementCount(); ++i) { - const QPainterPath::Element &e = path.elementAt(i); - - new_path.setElementPositionAt(i, qRound(e.x * scale), qRound(e.y * scale)); - } - - return new_path; + return false; } /*! @@ -907,48 +657,13 @@ inline QPainterPath operator *(const QPainterPath &path, qreal scale) */ bool DPlatformHandle::setWindowBlurAreaByWM(QWindow *window, const QList &paths) { - if (!window) { - return false; - } - - if (isEnabledDXcb(window)) { - setWindowProperty(window, _windowBlurPaths, QVariant::fromValue(paths)); - - return true; + DPlatformHandle handle(const_cast(window)); +#ifndef DTK_DISABLE_XCB + if (auto impl = dynamic_cast(platformWindowImpl(&handle))) { + return impl->setWindowBlurArea(paths); } - - QFunctionPointer setWmBlurWindowBackgroundPathList = Q_NULLPTR; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - setWmBlurWindowBackgroundPathList = qApp->platformFunction(_setWmBlurWindowBackgroundPathList); #endif - - if (!setWmBlurWindowBackgroundPathList) { - qWarning("setWindowBlurAreaByWM is not support"); - - return false; - } - - QSurfaceFormat format = window->format(); - - format.setAlphaBufferSize(8); - window->setFormat(format); - - const qreal device_ratio = window->devicePixelRatio(); - - if (qFuzzyCompare(device_ratio, 1.0)) { - return reinterpret_cast&)>(setWmBlurWindowBackgroundPathList)(window->winId(), paths); - } - - QList new_paths; - - new_paths.reserve(paths.size()); - - for (const QPainterPath &p : paths) { - new_paths.append(p * device_ratio); - } - - return reinterpret_cast&)>(setWmBlurWindowBackgroundPathList)(window->winId(), new_paths); + return false; } /*! @@ -990,49 +705,13 @@ bool DPlatformHandle::setWindowBlurAreaByWM(QWindow *window, const QList(platformWindowImpl(&handler))) { + return impl->setWindowWallpaperPara(area, sMode, fMode); } - - QFunctionPointer setWmWallpaperParameter = Q_NULLPTR; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - setWmWallpaperParameter = qApp->platformFunction(_setWmWallpaperParameter); #endif - - if (!setWmWallpaperParameter) { - qWarning("setWindowWallpaperParaByWM is not support"); - - return false; - } - - QSurfaceFormat format = window->format(); - - format.setAlphaBufferSize(8); - window->setFormat(format); - - quint32 bMode = sMode | fMode; - - // 激活 backing store - window->setProperty("_d_dxcb_wallpaper", QVariant::fromValue(QPair(area, bMode))); - - if (!window->handle()) { - return true; - } else { - qWarning() << "because the window handle has been created, so 2D mode will have no effect"; - } - - const qreal device_ratio = window->devicePixelRatio(); - if (qFuzzyCompare(device_ratio, 1.0) || !area.isValid()) { - return reinterpret_cast(setWmWallpaperParameter)(window->winId(), area, bMode); - } - - QRect new_area(area.x() * device_ratio, - area.y() * device_ratio, - area.width() * device_ratio, - area.height() * device_ratio); - - return reinterpret_cast(setWmWallpaperParameter)(window->winId(), new_area, bMode); + return false; } /*! @@ -1045,11 +724,10 @@ bool DPlatformHandle::setWindowWallpaperParaByWM(QWindow *window, const QRect &a */ bool DPlatformHandle::connectWindowManagerChangedSignal(QObject *object, std::function slot) { - if (object) { - return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::windowManagerChanged, object, slot); - } - - return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::windowManagerChanged, slot); +#ifndef DTK_DISABLE_XCB + return DXCBPlatformWindowInterface::connectWindowManagerChangedSignal(object, slot); +#endif + return false; } /*! @@ -1063,11 +741,10 @@ bool DPlatformHandle::connectWindowManagerChangedSignal(QObject *object, std::fu */ bool DPlatformHandle::connectHasBlurWindowChanged(QObject *object, std::function slot) { - if (object) { - return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasBlurWindowChanged, object, slot); - } - - return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasBlurWindowChanged, slot); +#ifndef DTK_DISABLE_XCB + return DXCBPlatformWindowInterface::connectHasBlurWindowChanged(object, slot); +#endif + return false; } /*! @@ -1105,230 +782,228 @@ bool DPlatformHandle::setWindowBlurAreaByWM(const QList &paths) */ void DPlatformHandle::setDisableWindowOverrideCursor(QWindow *window, bool disable) { - window->setProperty(_disableOverrideCursor, disable); + DPlatformHandle handler(window); +#ifndef DTK_DISABLE_XCB + if (auto impl = dynamic_cast(platformWindowImpl(&handler))) { + impl->setDisableWindowOverrideCursor(disable); + } +#endif } int DPlatformHandle::windowRadius() const { - return m_window->property(_windowRadius).toInt(); + auto impl = platformWindowImpl(this); + return impl->windowRadius(); } int DPlatformHandle::borderWidth() const { - return m_window->property(_borderWidth).toInt(); + auto impl = platformWindowImpl(this); + return impl->borderWidth(); } QColor DPlatformHandle::borderColor() const { - return qvariant_cast(m_window->property(_borderColor)); + auto impl = platformWindowImpl(this); + return impl->borderColor(); } int DPlatformHandle::shadowRadius() const { - return m_window->property(_shadowRadius).toInt(); + auto impl = platformWindowImpl(this); + return impl->shadowRadius(); } QPoint DPlatformHandle::shadowOffset() const { - return m_window->property(_shadowOffset).toPoint(); + auto impl = platformWindowImpl(this); + return impl->shadowOffset(); } QColor DPlatformHandle::shadowColor() const { - return qvariant_cast(m_window->property(_shadowColor)); + auto impl = platformWindowImpl(this); + return impl->shadowColor(); } DPlatformHandle::EffectScene DPlatformHandle::windowEffect() { - return qvariant_cast(m_window->property(_windowEffect)); + auto impl = platformWindowImpl(this); + return impl->windowEffect(); } DPlatformHandle::EffectType DPlatformHandle::windowStartUpEffect() { - return qvariant_cast(m_window->property(_windowStartUpEffect)); + auto impl = platformWindowImpl(this); + return impl->windowStartUpEffect(); } QPainterPath DPlatformHandle::clipPath() const { - return qvariant_cast(m_window->property(_clipPath)); + auto impl = platformWindowImpl(this); + return impl->clipPath(); } QRegion DPlatformHandle::frameMask() const { - return qvariant_cast(m_window->property(_frameMask)); + auto impl = platformWindowImpl(this); + return impl->frameMask(); } QMargins DPlatformHandle::frameMargins() const { - return qvariant_cast(m_window->property(_frameMargins)); + auto impl = platformWindowImpl(this); + return impl->frameMargins(); } bool DPlatformHandle::translucentBackground() const { - return m_window->property(_translucentBackground).toBool(); + auto impl = platformWindowImpl(this); + return impl->translucentBackground(); } bool DPlatformHandle::enableSystemResize() const { - return m_window->property(_enableSystemResize).toBool(); + auto impl = platformWindowImpl(this); + return impl->enableSystemResize(); } bool DPlatformHandle::enableSystemMove() const { - return m_window->property(_enableSystemMove).toBool(); + auto impl = platformWindowImpl(this); + return impl->enableSystemMove(); } bool DPlatformHandle::enableBlurWindow() const { - return m_window->property(_enableBlurWindow).toBool(); + auto impl = platformWindowImpl(this); + return impl->enableBlurWindow(); } bool DPlatformHandle::autoInputMaskByClipPath() const { - return m_window->property(_autoInputMaskByClipPath).toBool(); +#ifndef DTK_DISABLE_XCB + if (auto impl = dynamic_cast(platformWindowImpl(this))) { + return impl->autoInputMaskByClipPath(); + } +#endif + return false; } WId DPlatformHandle::realWindowId() const { - return qvariant_cast(m_window->property("_d_real_content_window")); +#ifndef DTK_DISABLE_XCB + if (auto impl = dynamic_cast(platformWindowImpl(this))) { + return impl->realWindowId(); + } +#endif + return 0; } WId DPlatformHandle::windowLeader() { - QFunctionPointer clientLeader = Q_NULLPTR; - -#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) - clientLeader = qApp->platformFunction(_clientLeader); +#ifndef DTK_DISABLE_XCB + return DXCBPlatformWindowInterface::windowLeader(); #endif - - if (!clientLeader) { - return 0; - } - - return reinterpret_cast(clientLeader)(); + return 0; } void DPlatformHandle::setWindowRadius(int windowRadius) { - setWindowProperty(m_window, _windowRadius, windowRadius); - resolve(m_window, PropRole::WindowRadius); + auto impl = platformWindowImpl(this); + impl->setWindowRadius(windowRadius); } void DPlatformHandle::setBorderWidth(int borderWidth) { - setWindowProperty(m_window, _borderWidth, borderWidth); + auto impl = platformWindowImpl(this); + impl->setBorderWidth(borderWidth); } void DPlatformHandle::setBorderColor(const QColor &borderColor) { - setWindowProperty(m_window, _borderColor, QVariant::fromValue(borderColor)); + auto impl = platformWindowImpl(this); + impl->setBorderColor(borderColor); } void DPlatformHandle::setWindowEffect(DPlatformHandle::EffectScenes effectScene) { - setWindowProperty(m_window, _windowEffect, static_cast(effectScene)); + auto impl = platformWindowImpl(this); + impl->setWindowEffect(effectScene); } void DPlatformHandle::setWindowStartUpEffect(DPlatformHandle::EffectTypes effectType) { - setWindowProperty(m_window, _windowStartUpEffect, static_cast(effectType)); + auto impl = platformWindowImpl(this); + impl->setWindowStartUpEffect(effectType); } void DPlatformHandle::setShadowRadius(int shadowRadius) { - setWindowProperty(m_window, _shadowRadius, shadowRadius); + auto impl = platformWindowImpl(this); + impl->setShadowRadius(shadowRadius); } void DPlatformHandle::setShadowOffset(const QPoint &shadowOffset) { - setWindowProperty(m_window, _shadowOffset, shadowOffset); + auto impl = platformWindowImpl(this); + impl->setShadowOffset(shadowOffset); } void DPlatformHandle::setShadowColor(const QColor &shadowColor) { - setWindowProperty(m_window, _shadowColor, QVariant::fromValue(shadowColor)); + auto impl = platformWindowImpl(this); + impl->setShadowColor(shadowColor); } void DPlatformHandle::setClipPath(const QPainterPath &clipPath) { - setWindowProperty(m_window, _clipPath, QVariant::fromValue(clipPath)); + auto impl = platformWindowImpl(this); + impl->setClipPath(clipPath); } void DPlatformHandle::setFrameMask(const QRegion &frameMask) { - setWindowProperty(m_window, _frameMask, QVariant::fromValue(frameMask)); + auto impl = platformWindowImpl(this); + impl->setFrameMask(frameMask); } void DPlatformHandle::setTranslucentBackground(bool translucentBackground) { - setWindowProperty(m_window, _translucentBackground, translucentBackground); + auto impl = platformWindowImpl(this); + impl->setTranslucentBackground(translucentBackground); } void DPlatformHandle::setEnableSystemResize(bool enableSystemResize) { - setWindowProperty(m_window, _enableSystemResize, enableSystemResize); + auto impl = platformWindowImpl(this); + impl->setEnableSystemResize(enableSystemResize); } void DPlatformHandle::setEnableSystemMove(bool enableSystemMove) { - setWindowProperty(m_window, _enableSystemMove, enableSystemMove); + auto impl = platformWindowImpl(this); + impl->setEnableSystemMove(enableSystemMove); } void DPlatformHandle::setEnableBlurWindow(bool enableBlurWindow) { -#ifndef DTK_DISABLE_TREELAND - if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) { - g_platformThemeMap.value(this)->setEnableBlurWindow(enableBlurWindow); - return; - } -#endif - setWindowProperty(m_window, _enableBlurWindow, enableBlurWindow); + auto impl = platformWindowImpl(this); + impl->setEnableBlurWindow(enableBlurWindow); } void DPlatformHandle::setAutoInputMaskByClipPath(bool autoInputMaskByClipPath) { - setWindowProperty(m_window, _autoInputMaskByClipPath, autoInputMaskByClipPath); +#ifndef DTK_DISABLE_XCB + if (auto impl = dynamic_cast(platformWindowImpl(this))) { + impl->setAutoInputMaskByClipPath(autoInputMaskByClipPath); + } +#endif } bool DPlatformHandle::eventFilter(QObject *obj, QEvent *event) { - if (obj == m_window) { - if (event->type() == QEvent::DynamicPropertyChange) { - QDynamicPropertyChangeEvent *e = static_cast(event); - - if (e->propertyName() == _windowRadius) { - Q_EMIT windowRadiusChanged(); - } else if (e->propertyName() == _borderWidth) { - Q_EMIT borderWidthChanged(); - } else if (e->propertyName() == _borderColor) { - Q_EMIT borderColorChanged(); - } else if (e->propertyName() == _shadowRadius) { - Q_EMIT shadowRadiusChanged(); - } else if (e->propertyName() == _shadowOffset) { - Q_EMIT shadowOffsetChanged(); - } else if (e->propertyName() == _shadowColor) { - Q_EMIT shadowColorChanged(); - } else if (e->propertyName() == _clipPath) { - Q_EMIT clipPathChanged(); - } else if (e->propertyName() == _frameMask) { - Q_EMIT frameMaskChanged(); - } else if (e->propertyName() == _frameMargins) { - Q_EMIT frameMarginsChanged(); - } else if (e->propertyName() == _translucentBackground) { - Q_EMIT translucentBackgroundChanged(); - } else if (e->propertyName() == _enableSystemResize) { - Q_EMIT enableSystemResizeChanged(); - } else if (e->propertyName() == _enableSystemMove) { - Q_EMIT enableSystemMoveChanged(); - } else if (e->propertyName() == _enableBlurWindow) { - Q_EMIT enableBlurWindowChanged(); - } else if (e->propertyName() == _autoInputMaskByClipPath) { - Q_EMIT autoInputMaskByClipPathChanged(); - } - } - } - - return false; + return QObject::eventFilter(obj, event); } DGUI_END_NAMESPACE diff --git a/src/plugins/dplatformwindowinterface.cpp b/src/plugins/dplatformwindowinterface.cpp new file mode 100644 index 0000000..da24341 --- /dev/null +++ b/src/plugins/dplatformwindowinterface.cpp @@ -0,0 +1,196 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "private/dplatformwindowinterface_p.h" + +DGUI_BEGIN_NAMESPACE + +DPlatformWindowInterface::DPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle) + : m_window(window) + , m_platformHandle(platformHandle) +{ +} + +DPlatformWindowInterface::~DPlatformWindowInterface() +{ +} + +QWindow *DPlatformWindowInterface::window() const +{ + return m_window; +} + +void DPlatformWindowInterface::setEnabled(bool enabled) +{ + Q_UNUSED(enabled) +} + +bool DPlatformWindowInterface::isEnabled() const +{ + return false; +} + +bool DPlatformWindowInterface::isEnabledNoTitlebar() const +{ + return {}; +} + +bool DPlatformWindowInterface::setEnabledNoTitlebar(bool enable) +{ + Q_UNUSED(enable) + return {}; +} + +void DPlatformWindowInterface::setDisableWindowOverrideCursor(bool disable) +{ + Q_UNUSED(disable) +} + +int DPlatformWindowInterface::windowRadius() const +{ + return -1; +} + +void DPlatformWindowInterface::setWindowRadius(int windowRadius) +{ + Q_UNUSED(windowRadius) +} + +int DPlatformWindowInterface::borderWidth() const +{ + return -1; +} + +void DPlatformWindowInterface::setBorderWidth(int borderWidth) +{ + Q_UNUSED(borderWidth) +} + +QColor DPlatformWindowInterface::borderColor() const +{ + return {}; +} + +void DPlatformWindowInterface::setBorderColor(const QColor &borderColor) +{ + Q_UNUSED(borderColor) +} + +int DPlatformWindowInterface::shadowRadius() const +{ + return -1; +} + +void DPlatformWindowInterface::setShadowRadius(int shadowRadius) +{ + Q_UNUSED(shadowRadius) +} + +QPoint DPlatformWindowInterface::shadowOffset() const +{ + return {}; +} + +void DPlatformWindowInterface::setShadowOffset(const QPoint &shadowOffset) +{ + Q_UNUSED(shadowOffset) +} + +QColor DPlatformWindowInterface::shadowColor() const +{ + return {}; +} + +void DPlatformWindowInterface::setShadowColor(const QColor &shadowColor) +{ + Q_UNUSED(shadowColor) +} + +DPlatformHandle::EffectScene DPlatformWindowInterface::windowEffect() +{ + return {}; +} + +void DPlatformWindowInterface::setWindowEffect(DPlatformHandle::EffectScenes effectScene) +{ + Q_UNUSED(effectScene) +} + +DPlatformHandle::EffectType DPlatformWindowInterface::windowStartUpEffect() +{ + return {}; +} + +void DPlatformWindowInterface::setWindowStartUpEffect(DPlatformHandle::EffectTypes effectType) +{ + Q_UNUSED(effectType) +} + +QPainterPath DPlatformWindowInterface::clipPath() const +{ + return {}; +} + +void DPlatformWindowInterface::setClipPath(const QPainterPath &clipPath) +{ + Q_UNUSED(clipPath) +} + +QRegion DPlatformWindowInterface::frameMask() const +{ + return {}; +} + +void DPlatformWindowInterface::setFrameMask(const QRegion &frameMask) +{ + Q_UNUSED(frameMask) +} + +QMargins DPlatformWindowInterface::frameMargins() const +{ + return {}; +} + +bool DPlatformWindowInterface::translucentBackground() const +{ + return {}; +} + +void DPlatformWindowInterface::setTranslucentBackground(bool translucentBackground) +{ + Q_UNUSED(translucentBackground) +} + +bool DPlatformWindowInterface::enableSystemResize() const +{ + return {}; +} + +void DPlatformWindowInterface::setEnableSystemResize(bool enableSystemResize) +{ + Q_UNUSED(enableSystemResize) +} + +bool DPlatformWindowInterface::enableSystemMove() const +{ + return {}; +} + +void DPlatformWindowInterface::setEnableSystemMove(bool enableSystemMove) +{ + Q_UNUSED(enableSystemMove) +} + +bool DPlatformWindowInterface::enableBlurWindow() const +{ + return {}; +} + +void DPlatformWindowInterface::setEnableBlurWindow(bool enableBlurWindow) +{ + Q_UNUSED(enableBlurWindow) +} + +DGUI_END_NAMESPACE + diff --git a/src/plugins/platform/treeland/dtreelandplatformwindowinterface.cpp b/src/plugins/platform/treeland/dtreelandplatformwindowinterface.cpp index 22769cb..f14fa89 100644 --- a/src/plugins/platform/treeland/dtreelandplatformwindowinterface.cpp +++ b/src/plugins/platform/treeland/dtreelandplatformwindowinterface.cpp @@ -7,24 +7,23 @@ #undef protected #include "dtreelandplatformwindowinterface.h" -#include "dtreelandplatformwindowinterface.h" -#include "dtreelandplatforminterface.h" + +#include +#include #include #include #include +#include -#include "personalizationwaylandclientextension.h" -#include #include "dvtablehook.h" -#include -#include -#include -#include +#include "personalizationwaylandclientextension.h" DCORE_USE_NAMESPACE -class MoveWindowHelper : public QObject +DGUI_BEGIN_NAMESPACE + +class Q_DECL_HIDDEN MoveWindowHelper : public QObject { public: explicit MoveWindowHelper(QWindow *w); @@ -146,33 +145,36 @@ bool MoveWindowHelper::windowEvent(QWindow *w, QEvent *event) class Q_DECL_HIDDEN WindowEventFilter : public QObject { public: - WindowEventFilter(QObject *parent = nullptr, DTreeLandPlatformWindowInterface *interface = nullptr) - : QObject(parent) - , m_interface(interface) + WindowEventFilter(DTreeLandPlatformWindowInterface *interface = nullptr) + : QObject(interface) { } -public: - bool eventFilter(QObject *watched, QEvent *event) override { + DTreeLandPlatformWindowInterface *interface() const + { + return qobject_cast(parent()); + } + + bool eventFilter(QObject *watched, QEvent *event) { if (event->type() == QEvent::PlatformSurface) { QPlatformSurfaceEvent *se = static_cast(event); if (se->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) { - m_interface->initWaylandWindow(); - m_interface->onSurfaceCreated(); + if (auto item = interface()) { + item->initWaylandWindow(); + item->onSurfaceCreated(); + } } } return QObject::eventFilter(watched, event); } -private: - DTreeLandPlatformWindowInterface *m_interface; }; -DTreeLandPlatformWindowInterface::DTreeLandPlatformWindowInterface(QObject *parent, QWindow *window) +DTreeLandPlatformWindowInterface::DTreeLandPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle, QObject *parent) : QObject(parent) - , m_window(window) + , DPlatformWindowInterface(window, platformHandle) { m_manager = PersonalizationManager::instance(); - m_window->installEventFilter(new WindowEventFilter(this, this)); + m_window->installEventFilter(new WindowEventFilter(this)); connect(m_manager, &PersonalizationManager::activeChanged, this, [this](){ if (m_manager->isActive()) { handlePendingTasks(); @@ -225,6 +227,18 @@ void DTreeLandPlatformWindowInterface::initWaylandWindow() connect(waylandWindow, &QtWaylandClient::QWaylandWindow::wlSurfaceDestroyed, this, &DTreeLandPlatformWindowInterface::onSurfaceDestroyed, Qt::UniqueConnection); } +void DTreeLandPlatformWindowInterface::setEnabled(bool enabled) +{ + if (setEnabledNoTitlebar(enabled)) { + return; + } +} + +bool DTreeLandPlatformWindowInterface::isEnabled() const +{ + return isEnabledNoTitlebar(); +} + PersonalizationWindowContext *DTreeLandPlatformWindowInterface::getWindowContext() { if (!m_manager->isSupported()) { @@ -270,6 +284,11 @@ void DTreeLandPlatformWindowInterface::handlePendingTasks() } } +bool DTreeLandPlatformWindowInterface::isEnabledNoTitlebar() const +{ + return m_isNoTitlebar; +} + bool DTreeLandPlatformWindowInterface::setEnabledNoTitlebar(bool enable) { if (m_isNoTitlebar == enable) { @@ -280,6 +299,25 @@ bool DTreeLandPlatformWindowInterface::setEnabledNoTitlebar(bool enable) return true; } +int DTreeLandPlatformWindowInterface::windowRadius() const +{ + return m_radius; +} + +void DTreeLandPlatformWindowInterface::setWindowRadius(int windowRadius) +{ + if (m_radius == windowRadius) { + return; + } + m_radius = windowRadius; + doSetWindowRadius(); +} + +bool DTreeLandPlatformWindowInterface::enableBlurWindow() const +{ + return m_isWindowBlur; +} + void DTreeLandPlatformWindowInterface::setEnableBlurWindow(bool enable) { if (m_isWindowBlur == enable) { @@ -307,6 +345,27 @@ void DTreeLandPlatformWindowInterface::doSetEnabledNoTitlebar() } } +void DTreeLandPlatformWindowInterface::doSetWindowRadius() +{ + auto handleFunc = [this](){ + auto windowContext = getWindowContext(); + if (!windowContext) { + qWarning() << "windowContext is nullptr!"; + return; + } + windowContext->set_round_corner_radius(m_radius); + if (m_platformHandle) { + Q_EMIT m_platformHandle->windowRadiusChanged(); + } + return; + }; + if (m_manager->isActive()) { + handleFunc(); + } else { + m_pendingTasks.enqueue(handleFunc); + } +} + void DTreeLandPlatformWindowInterface::doSetEnabledBlurWindow() { auto handleFunc = [this](){ @@ -323,3 +382,4 @@ void DTreeLandPlatformWindowInterface::doSetEnabledBlurWindow() m_pendingTasks.enqueue(handleFunc); } } +DGUI_END_NAMESPACE diff --git a/src/plugins/platform/treeland/dtreelandplatformwindowinterface.h b/src/plugins/platform/treeland/dtreelandplatformwindowinterface.h index 1a35320..48c127e 100644 --- a/src/plugins/platform/treeland/dtreelandplatformwindowinterface.h +++ b/src/plugins/platform/treeland/dtreelandplatformwindowinterface.h @@ -9,21 +9,32 @@ #include "dtreelandplatforminterface.h" #include #include +#include "private/dplatformwindowinterface_p.h" -DGUI_USE_NAMESPACE -class DTreeLandPlatformWindowInterface : public QObject +DGUI_BEGIN_NAMESPACE + +class PersonalizationWindowContext; +class DTreeLandPlatformWindowInterface : public QObject, public DPlatformWindowInterface { Q_OBJECT public: - explicit DTreeLandPlatformWindowInterface(QObject *parent = nullptr, QWindow *window = nullptr); - ~DTreeLandPlatformWindowInterface(); - bool setEnabledNoTitlebar(bool enable); - void setEnableBlurWindow(bool enable); - void doSetEnabledNoTitlebar(); - void doSetEnabledBlurWindow(); - [[nodiscard]]QWindow *getWindow() const { return m_window; } + explicit DTreeLandPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle, QObject *parent = nullptr); + ~DTreeLandPlatformWindowInterface() override; + void initWaylandWindow(); + void setEnabled(bool enabled) override; + bool isEnabled() const override; + + bool isEnabledNoTitlebar() const override; + bool setEnabledNoTitlebar(bool enable) override; + + int windowRadius() const override; + void setWindowRadius(int windowRadius) override; + + bool enableBlurWindow() const override; + void setEnableBlurWindow(bool enableBlurWindow) override; + public slots: void onSurfaceCreated(); void onSurfaceDestroyed(); @@ -31,14 +42,17 @@ public slots: private: PersonalizationWindowContext *getWindowContext(); void handlePendingTasks(); + void doSetEnabledNoTitlebar(); + void doSetWindowRadius(); + void doSetEnabledBlurWindow(); -private: - QWindow *m_window = nullptr; QQueue> m_pendingTasks; PersonalizationManager *m_manager = nullptr; PersonalizationWindowContext *m_windowContext = nullptr; - bool m_isNoTitlebar = true; + bool m_isNoTitlebar = false; bool m_isWindowBlur = false; + int m_radius = 0; }; +DGUI_END_NAMESPACE #endif // DTREELANDPLATFORMWINDOWINTERFACE_H diff --git a/src/plugins/platform/xcb/dxcbplatformwindowinterface.cpp b/src/plugins/platform/xcb/dxcbplatformwindowinterface.cpp new file mode 100644 index 0000000..e764a47 --- /dev/null +++ b/src/plugins/platform/xcb/dxcbplatformwindowinterface.cpp @@ -0,0 +1,724 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#include "dxcbplatformwindowinterface.h" +#include "dguiapplicationhelper.h" +#include "dplatformtheme.h" +#include "dwindowmanagerhelper.h" + +#include + +#include +#include +#include + +DGUI_BEGIN_NAMESPACE + +#define DXCB_PLUGIN_KEY "dxcb" +#define DXCB_PLUGIN_SYMBOLIC_PROPERTY "_d_isDxcb" + +#define DEFINE_CONST_CHAR(Name) const char _##Name[] = "_d_" #Name + +DEFINE_CONST_CHAR(useDxcb); +DEFINE_CONST_CHAR(redirectContent); +DEFINE_CONST_CHAR(netWmStates); +DEFINE_CONST_CHAR(windowRadius); +DEFINE_CONST_CHAR(borderWidth); +DEFINE_CONST_CHAR(borderColor); +DEFINE_CONST_CHAR(windowEffect); +DEFINE_CONST_CHAR(windowStartUpEffect); +DEFINE_CONST_CHAR(shadowRadius); +DEFINE_CONST_CHAR(shadowOffset); +DEFINE_CONST_CHAR(shadowColor); +DEFINE_CONST_CHAR(clipPath); +DEFINE_CONST_CHAR(frameMask); +DEFINE_CONST_CHAR(frameMargins); +DEFINE_CONST_CHAR(translucentBackground); +DEFINE_CONST_CHAR(enableSystemResize); +DEFINE_CONST_CHAR(enableSystemMove); +DEFINE_CONST_CHAR(enableBlurWindow); +DEFINE_CONST_CHAR(windowBlurAreas); +DEFINE_CONST_CHAR(windowBlurPaths); +DEFINE_CONST_CHAR(windowWallpaperParas); +DEFINE_CONST_CHAR(autoInputMaskByClipPath); + +DEFINE_CONST_CHAR(resolve_mask); +enum PropRole { + WindowRadius, + + // TO BE CONTINUE +}; + +// functions +DEFINE_CONST_CHAR(setWmBlurWindowBackgroundArea); +DEFINE_CONST_CHAR(setWmBlurWindowBackgroundPathList); +DEFINE_CONST_CHAR(setWmBlurWindowBackgroundMaskImage); +DEFINE_CONST_CHAR(setWmWallpaperParameter); +DEFINE_CONST_CHAR(setWindowProperty); +DEFINE_CONST_CHAR(pluginVersion); +DEFINE_CONST_CHAR(disableOverrideCursor); +DEFINE_CONST_CHAR(enableDxcb); +DEFINE_CONST_CHAR(isEnableDxcb); +DEFINE_CONST_CHAR(setEnableNoTitlebar); +DEFINE_CONST_CHAR(isEnableNoTitlebar); +DEFINE_CONST_CHAR(clientLeader); + +static void resolve(QObject *obj, PropRole role) +{ + int mask = obj->property(_resolve_mask).toInt(); + obj->setProperty(_resolve_mask, (mask |= 1 << role)); +} + +static bool resolved(QObject *obj, PropRole role) +{ + int mask = obj->property(_resolve_mask).toInt(); + return mask & (1 << role); +} + +static void setWindowProperty(QWindow *window, const char *name, const QVariant &value) +{ + if (!window) + return; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + static QFunctionPointer setWindowProperty = qApp->platformFunction(_setWindowProperty); +#else + constexpr QFunctionPointer setWindowProperty = nullptr; +#endif + + if (!setWindowProperty) { + window->setProperty(name, value); + + return; + } + + reinterpret_cast(setWindowProperty)(window, name, value); +} + +DXCBPlatformWindowInterface::DXCBPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle, QObject *parent) + : QObject(parent) + , DPlatformWindowInterface(window, platformHandle) +{ + if (window) { + window->installEventFilter(this); + } +} + +DXCBPlatformWindowInterface::~DXCBPlatformWindowInterface() +{ +} + +QString DXCBPlatformWindowInterface::pluginVersion() +{ + QFunctionPointer pv = 0; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + pv = qApp->platformFunction(_pluginVersion); +#endif + + if (Q_UNLIKELY(!pv)) + return QString(); + + return reinterpret_cast(pv)(); +} + +bool DXCBPlatformWindowInterface::isDXcbPlatform() +{ + if (!qApp) + return false; + + static bool _is_dxcb = qApp->platformName() == DXCB_PLUGIN_KEY || qApp->property(DXCB_PLUGIN_SYMBOLIC_PROPERTY).toBool(); + + return _is_dxcb; +} + +bool DXCBPlatformWindowInterface::connectWindowManagerChangedSignal(QObject *object, std::function slot) +{ + if (object) { + return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::windowManagerChanged, object, slot); + } + + return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::windowManagerChanged, slot); +} + +bool DXCBPlatformWindowInterface::connectHasBlurWindowChanged(QObject *object, std::function slot) +{ + if (object) { + return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasBlurWindowChanged, object, slot); + } + + return QObject::connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasBlurWindowChanged, slot); +} + +WId DXCBPlatformWindowInterface::windowLeader() +{ + QFunctionPointer clientLeader = Q_NULLPTR; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + clientLeader = qApp->platformFunction(_clientLeader); +#endif + + if (!clientLeader) { + return 0; + } + + return reinterpret_cast(clientLeader)(); +} + +void DXCBPlatformWindowInterface::setEnabled(bool enabled) +{ + // 优先使用窗口管理器中实现的no titlebar接口实现自定义窗口修饰器的效果 + if (setEnabledNoTitlebar(enabled)) { + return; + } + + if (!isDXcbPlatform()) + return; + + QFunctionPointer enable_dxcb = nullptr; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + enable_dxcb = qApp->platformFunction(_enableDxcb); +#endif + + if (enable_dxcb) { + (*reinterpret_cast(enable_dxcb))(m_window); + } else if (m_window->handle()) { + Q_ASSERT_X(m_window->property(_useDxcb).toBool(), "DXCBPlatformWindowInterfacer:", + "Must be called before window handle has been created. See also QWindow::handle()"); + } else { + m_window->setProperty(_useDxcb, enabled); + } +} + +void DXCBPlatformWindowInterface::enableDXcb(bool redirectContent) +{ + m_window->setProperty(_redirectContent, redirectContent); + + setEnabled(true); +} + +bool DXCBPlatformWindowInterface::isEnabled() const +{ + if (isEnabledNoTitlebar()) + return true; + + QFunctionPointer is_enable_dxcb = nullptr; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + is_enable_dxcb = qApp->platformFunction(_isEnableDxcb); +#endif + + if (is_enable_dxcb) { + return (*reinterpret_cast(is_enable_dxcb))(m_window); + } + + return m_window->property(_useDxcb).toBool(); +} + +bool DXCBPlatformWindowInterface::eventFilter(QObject *obj, QEvent *event) +{ + if (obj == m_window && m_platformHandle) { + if (event->type() == QEvent::DynamicPropertyChange) { + QDynamicPropertyChangeEvent *e = static_cast(event); + + if (e->propertyName() == _windowRadius) { + Q_EMIT m_platformHandle->windowRadiusChanged(); + } else if (e->propertyName() == _borderWidth) { + Q_EMIT m_platformHandle->borderWidthChanged(); + } else if (e->propertyName() == _borderColor) { + Q_EMIT m_platformHandle->borderColorChanged(); + } else if (e->propertyName() == _shadowRadius) { + Q_EMIT m_platformHandle->shadowRadiusChanged(); + } else if (e->propertyName() == _shadowOffset) { + Q_EMIT m_platformHandle->shadowOffsetChanged(); + } else if (e->propertyName() == _shadowColor) { + Q_EMIT m_platformHandle->shadowColorChanged(); + } else if (e->propertyName() == _clipPath) { + Q_EMIT m_platformHandle->clipPathChanged(); + } else if (e->propertyName() == _frameMask) { + Q_EMIT m_platformHandle->frameMaskChanged(); + } else if (e->propertyName() == _frameMargins) { + Q_EMIT m_platformHandle->frameMarginsChanged(); + } else if (e->propertyName() == _translucentBackground) { + Q_EMIT m_platformHandle->translucentBackgroundChanged(); + } else if (e->propertyName() == _enableSystemResize) { + Q_EMIT m_platformHandle->enableSystemResizeChanged(); + } else if (e->propertyName() == _enableSystemMove) { + Q_EMIT m_platformHandle->enableSystemMoveChanged(); + } else if (e->propertyName() == _enableBlurWindow) { + Q_EMIT m_platformHandle->enableBlurWindowChanged(); + } else if (e->propertyName() == _autoInputMaskByClipPath) { + Q_EMIT m_platformHandle->autoInputMaskByClipPathChanged(); + } + } + } + + return QObject::eventFilter(obj, event); +} + +static void initWindowRadius(QWindow *window) +{ + if (window->property(_windowRadius).isValid()) + return; + + auto theme = DGuiApplicationHelper::instance()->systemTheme(); + int radius = theme->windowRadius(18); //###(zccrs): 暂时在此处给窗口默认设置为18px的圆角 + + setWindowProperty(window, _windowRadius, radius); + // Qt::UniqueConnection will report a warning + // to `unique connections require a pointer to member function of a QObject subclass`. + const char *uniqueueConnectionFlag("_d_uniqueueConnectionFlag"); + bool connected = window->property(uniqueueConnectionFlag).toBool(); + if (!connected) { + window->setProperty(uniqueueConnectionFlag, true); + window->connect(theme, &DPlatformTheme::windowRadiusChanged, window, [window] (int radius) { + if (!resolved(window, PropRole::WindowRadius)) + setWindowProperty(window, _windowRadius, radius); + }); + } +} + +class Q_DECL_HIDDEN CreatorWindowEventFilter : public QObject { +public: + CreatorWindowEventFilter(QObject *par= nullptr): QObject(par){} + +public: + bool eventFilter(QObject *watched, QEvent *event) override { + if (event->type() == QEvent::PlatformSurface) { + QPlatformSurfaceEvent *se = static_cast(event); + if (se->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) { // 若收到此信号, 则 WinID 已被创建 + auto window = qobject_cast(watched); + initWindowRadius(window); + } + } + return QObject::eventFilter(watched, event); + } +}; + +bool DXCBPlatformWindowInterface::isEnabledNoTitlebar() const +{ + QFunctionPointer is_enable_no_titlebar = nullptr; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + is_enable_no_titlebar = qApp->platformFunction(_isEnableNoTitlebar); +#endif + + if (is_enable_no_titlebar) { + return (*reinterpret_cast(is_enable_no_titlebar))(m_window); + } + + return false; +} + +bool DXCBPlatformWindowInterface::setEnabledNoTitlebar(bool enable) +{ + if (isEnabledNoTitlebar() == enable) + return true; + + QFunctionPointer enable_no_titlear = nullptr; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + enable_no_titlear = qApp->platformFunction(_setEnableNoTitlebar); +#endif + + if (enable_no_titlear) { + bool ok = (*reinterpret_cast(enable_no_titlear))(m_window, enable); + if (ok && enable) { + if (m_window->handle()) { + initWindowRadius(m_window); + } else { + m_window->installEventFilter(new CreatorWindowEventFilter(m_window)); + } + } + + return ok; + } + + return false; +} + +inline DPlatformHandle::WMBlurArea operator *(const DPlatformHandle::WMBlurArea &area, qreal scale) +{ + if (qFuzzyCompare(scale, 1.0)) + return area; + + DPlatformHandle::WMBlurArea new_area; + + new_area.x = qRound64(area.x * scale); + new_area.y = qRound64(area.y * scale); + new_area.width = qRound64(area.width * scale); + new_area.height = qRound64(area.height * scale); + new_area.xRadius = qRound64(area.xRadius * scale); + new_area.yRaduis = qRound64(area.yRaduis * scale); + + return new_area; +} + +/*! + \brief DXCBPlatformWindowInterface::setWindowBlurAreaByWM + 设置窗口背景的模糊区域,示例: + \code + QWindow w; + QVector area_list; + DXCBPlatformWindowInterface::WMBlurArea area; + + area.x = 50; + area.y = 50; + area.width = 200; + area.height = 200; + area.xRadius = 10; + area.yRaduis = 10; + area_list.append(area); + + DXCBPlatformWindowInterface::setWindowBlurAreaByWM(&w, area_list); + + QSurfaceFormat format = w.format(); + format.setAlphaBufferSize(8); + + w.setFormat(format); + w.resize(300, 300); + w.show(); + + \endcode + \image blur_window_demo1.png + \a window 目标窗口对象 + \a area 模糊区域,此区域范围内的窗口背景将填充为窗口后面内容模糊之后的图像 + \return 如果设置成功则返回 true,否则返回 false + \note 对于需要显示模糊背景的窗口,需要将其 QSurfaceFormat 的 alpha 通道设置为8 + \note 调用此接口设置窗口背景模糊区域后将覆盖之前所设置的区域,包括调用 + setWindowBlurAreaByWM(QWindow *, const QList &) + 所设置的区域 + \note 建议使用 DBlurEffectWidget 实现窗口背景模糊效果 + \note 此功能依赖于窗口管理器的实现,目前仅支持 deepin-wm 和 kwin 这两个窗口管理器 + \sa Dtk::Widget::DBlurEffectWidget + \sa QSurfaceFormat::setAlphaBufferSize + \sa QWindow::setFormat + \sa DWindowManagerHelper::hasBlurWindow + \sa DXCBPlatformWindowInterface::setWindowBlurAreaByWM(QWindow *, const QList &) + */ +bool DXCBPlatformWindowInterface::setWindowBlurArea(const QVector &area) +{ + if (!m_window) { + return false; + } + + if (isEnabled()) { + QVector areas; + for (auto item : area) + areas << item.x << item.y << item.width << item.height << item.xRadius << item.yRaduis; + setWindowProperty(m_window, _windowBlurAreas, QVariant::fromValue(areas)); + return true; + } + + QFunctionPointer setWmBlurWindowBackgroundArea = Q_NULLPTR; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + setWmBlurWindowBackgroundArea = qApp->platformFunction(_setWmBlurWindowBackgroundArea); +#endif + + if (!setWmBlurWindowBackgroundArea) { + qWarning("setWindowBlurAreaByWM is not support"); + + return false; + } + + QSurfaceFormat format = m_window->format(); + + format.setAlphaBufferSize(8); + m_window->setFormat(format); + + const qreal device_ratio = m_window->devicePixelRatio(); + + if (qFuzzyCompare(device_ratio, 1.0)) { + return reinterpret_cast&)>(setWmBlurWindowBackgroundArea)(m_window->winId(), area); + } + + QVector new_areas; + + new_areas.reserve(area.size()); + + for (const DPlatformHandle::WMBlurArea &a : area) { + new_areas.append(a * device_ratio); + } + + return reinterpret_cast&)>(setWmBlurWindowBackgroundArea)(m_window->winId(), new_areas); +} + +inline QPainterPath operator *(const QPainterPath &path, qreal scale) +{ + if (qFuzzyCompare(1.0, scale)) + return path; + + QPainterPath new_path = path; + + for (int i = 0; i < path.elementCount(); ++i) { + const QPainterPath::Element &e = path.elementAt(i); + + new_path.setElementPositionAt(i, qRound(e.x * scale), qRound(e.y * scale)); + } + + return new_path; +} + +bool DXCBPlatformWindowInterface::setWindowBlurArea(const QList &paths) +{ + if (!m_window) { + return false; + } + + if (isEnabled()) { + setWindowProperty(m_window, _windowBlurPaths, QVariant::fromValue(paths)); + + return true; + } + + QFunctionPointer setWmBlurWindowBackgroundPathList = Q_NULLPTR; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + setWmBlurWindowBackgroundPathList = qApp->platformFunction(_setWmBlurWindowBackgroundPathList); +#endif + + if (!setWmBlurWindowBackgroundPathList) { + qWarning("setWindowBlurAreaByWM is not support"); + + return false; + } + + QSurfaceFormat format = m_window->format(); + + format.setAlphaBufferSize(8); + m_window->setFormat(format); + + const qreal device_ratio = m_window->devicePixelRatio(); + + if (qFuzzyCompare(device_ratio, 1.0)) { + return reinterpret_cast&)>(setWmBlurWindowBackgroundPathList)(m_window->winId(), paths); + } + + QList new_paths; + + new_paths.reserve(paths.size()); + + for (const QPainterPath &p : paths) { + new_paths.append(p * device_ratio); + } + + return reinterpret_cast&)>(setWmBlurWindowBackgroundPathList)(m_window->winId(), new_paths); +} + +bool DXCBPlatformWindowInterface::setWindowWallpaperPara(const QRect &area, DPlatformHandle::WallpaperScaleMode sMode, DPlatformHandle::WallpaperFillMode fMode) +{ + if (!m_window) { + return false; + } + + QFunctionPointer setWmWallpaperParameter = Q_NULLPTR; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0) + setWmWallpaperParameter = qApp->platformFunction(_setWmWallpaperParameter); +#endif + + if (!setWmWallpaperParameter) { + qWarning("setWindowWallpaperParaByWM is not support"); + + return false; + } + + QSurfaceFormat format = m_window->format(); + + format.setAlphaBufferSize(8); + m_window->setFormat(format); + + quint32 bMode = sMode | fMode; + + // 激活 backing store + m_window->setProperty("_d_dxcb_wallpaper", QVariant::fromValue(QPair(area, bMode))); + + if (!m_window->handle()) { + return true; + } else { + qWarning() << "because the window handle has been created, so 2D mode will have no effect"; + } + + const qreal device_ratio = m_window->devicePixelRatio(); + if (qFuzzyCompare(device_ratio, 1.0) || !area.isValid()) { + return reinterpret_cast(setWmWallpaperParameter)(m_window->winId(), area, bMode); + } + + QRect new_area(area.x() * device_ratio, + area.y() * device_ratio, + area.width() * device_ratio, + area.height() * device_ratio); + + return reinterpret_cast(setWmWallpaperParameter)(m_window->winId(), new_area, bMode); +} + +void DXCBPlatformWindowInterface::setDisableWindowOverrideCursor(bool disable) +{ + m_window->setProperty(_disableOverrideCursor, disable); +} + +int DXCBPlatformWindowInterface::windowRadius() const +{ + return m_window->property(_windowRadius).toInt(); +} + +void DXCBPlatformWindowInterface::setWindowRadius(int windowRadius) +{ + setWindowProperty(m_window, _windowRadius, windowRadius); + resolve(m_window, PropRole::WindowRadius); +} + +int DXCBPlatformWindowInterface::borderWidth() const +{ + return m_window->property(_borderWidth).toInt(); +} + +void DXCBPlatformWindowInterface::setBorderWidth(int borderWidth) +{ + setWindowProperty(m_window, _borderWidth, borderWidth); +} + +QColor DXCBPlatformWindowInterface::borderColor() const +{ + return qvariant_cast(m_window->property(_borderColor)); +} + +void DXCBPlatformWindowInterface::setBorderColor(const QColor &borderColor) +{ + setWindowProperty(m_window, _borderColor, QVariant::fromValue(borderColor)); +} + +int DXCBPlatformWindowInterface::shadowRadius() const +{ + return m_window->property(_shadowRadius).toInt(); +} + +void DXCBPlatformWindowInterface::setShadowRadius(int shadowRadius) +{ + setWindowProperty(m_window, _shadowRadius, shadowRadius); +} + +QPoint DXCBPlatformWindowInterface::shadowOffset() const +{ + return m_window->property(_shadowOffset).toPoint(); +} + +void DXCBPlatformWindowInterface::setShadowOffset(const QPoint &shadowOffset) +{ + setWindowProperty(m_window, _shadowOffset, shadowOffset); +} + +QColor DXCBPlatformWindowInterface::shadowColor() const +{ + return qvariant_cast(m_window->property(_shadowColor)); +} + +void DXCBPlatformWindowInterface::setShadowColor(const QColor &shadowColor) +{ + setWindowProperty(m_window, _shadowColor, QVariant::fromValue(shadowColor)); +} + +DPlatformHandle::EffectScene DXCBPlatformWindowInterface::windowEffect() +{ + return qvariant_cast(m_window->property(_windowEffect)); +} + +void DXCBPlatformWindowInterface::setWindowEffect(DPlatformHandle::EffectScenes effectScene) +{ + setWindowProperty(m_window, _windowEffect, static_cast(effectScene)); +} + +DPlatformHandle::EffectType DXCBPlatformWindowInterface::windowStartUpEffect() +{ + return qvariant_cast(m_window->property(_windowStartUpEffect)); +} + +void DXCBPlatformWindowInterface::setWindowStartUpEffect(DPlatformHandle::EffectTypes effectType) +{ + setWindowProperty(m_window, _windowStartUpEffect, static_cast(effectType)); +} + +QPainterPath DXCBPlatformWindowInterface::clipPath() const +{ + return qvariant_cast(m_window->property(_clipPath)); +} + +void DXCBPlatformWindowInterface::setClipPath(const QPainterPath &clipPath) +{ + setWindowProperty(m_window, _clipPath, QVariant::fromValue(clipPath)); +} + +QRegion DXCBPlatformWindowInterface::frameMask() const +{ + return qvariant_cast(m_window->property(_frameMask)); +} + +void DXCBPlatformWindowInterface::setFrameMask(const QRegion &frameMask) +{ + setWindowProperty(m_window, _frameMask, QVariant::fromValue(frameMask)); +} + +QMargins DXCBPlatformWindowInterface::frameMargins() const +{ + return qvariant_cast(m_window->property(_frameMargins)); +} + +bool DXCBPlatformWindowInterface::translucentBackground() const +{ + return m_window->property(_translucentBackground).toBool(); +} + +void DXCBPlatformWindowInterface::setTranslucentBackground(bool translucentBackground) +{ + setWindowProperty(m_window, _translucentBackground, translucentBackground); +} + +bool DXCBPlatformWindowInterface::enableSystemResize() const +{ + return m_window->property(_enableSystemResize).toBool(); +} + +void DXCBPlatformWindowInterface::setEnableSystemResize(bool enableSystemResize) +{ + setWindowProperty(m_window, _enableSystemResize, enableSystemResize); +} + +bool DXCBPlatformWindowInterface::enableSystemMove() const +{ + return m_window->property(_enableSystemMove).toBool(); +} + +void DXCBPlatformWindowInterface::setEnableSystemMove(bool enableSystemMove) +{ + setWindowProperty(m_window, _enableSystemMove, enableSystemMove); +} + +bool DXCBPlatformWindowInterface::enableBlurWindow() const +{ + return m_window->property(_enableBlurWindow).toBool(); +} + +void DXCBPlatformWindowInterface::setEnableBlurWindow(bool enableBlurWindow) +{ + setWindowProperty(m_window, _enableBlurWindow, enableBlurWindow); +} + +bool DXCBPlatformWindowInterface::autoInputMaskByClipPath() const +{ + return m_window->property(_autoInputMaskByClipPath).toBool(); +} + +void DXCBPlatformWindowInterface::setAutoInputMaskByClipPath(bool autoInputMaskByClipPath) +{ + setWindowProperty(m_window, _autoInputMaskByClipPath, autoInputMaskByClipPath); +} + +WId DXCBPlatformWindowInterface::realWindowId() const +{ + return qvariant_cast(m_window->property("_d_real_content_window")); +} + +DGUI_END_NAMESPACE diff --git a/src/plugins/platform/xcb/dxcbplatformwindowinterface.h b/src/plugins/platform/xcb/dxcbplatformwindowinterface.h new file mode 100644 index 0000000..480a74a --- /dev/null +++ b/src/plugins/platform/xcb/dxcbplatformwindowinterface.h @@ -0,0 +1,95 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DXCBPLATFORMWINDOWINTERFACE_H +#define DXCBPLATFORMWINDOWINTERFACE_H + +#include "private/dplatformwindowinterface_p.h" + +#include + +DGUI_BEGIN_NAMESPACE + +class DXCBPlatformWindowInterface : public QObject, public DPlatformWindowInterface +{ + Q_OBJECT +public: + explicit DXCBPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle, QObject *parent = nullptr); + ~DXCBPlatformWindowInterface() override; + + static QString pluginVersion(); + static bool isDXcbPlatform(); + static bool connectWindowManagerChangedSignal(QObject *object, std::function slot); + static bool connectHasBlurWindowChanged(QObject *object, std::function slot); + static WId windowLeader(); + + void enableDXcb(bool redirectContent); + + bool setWindowBlurArea(const QVector &area); + bool setWindowBlurArea(const QList &paths); + bool setWindowWallpaperPara(const QRect &area, DPlatformHandle::WallpaperScaleMode sMode, DPlatformHandle::WallpaperFillMode fMode); + + bool autoInputMaskByClipPath() const; + void setAutoInputMaskByClipPath(bool autoInputMaskByClipPath); + + WId realWindowId() const; + + void setEnabled(bool enabled) override; + bool isEnabled() const override; + + void setDisableWindowOverrideCursor(bool disable) override; + + bool isEnabledNoTitlebar() const override; + bool setEnabledNoTitlebar(bool enable) override; + + int windowRadius() const override; + void setWindowRadius(int windowRadius) override; + + int borderWidth() const override; + void setBorderWidth(int borderWidth) override; + + QColor borderColor() const override; + void setBorderColor(const QColor &borderColor) override; + + int shadowRadius() const override; + void setShadowRadius(int shadowRadius) override; + + QPoint shadowOffset() const override; + void setShadowOffset(const QPoint &shadowOffset) override; + + QColor shadowColor() const override; + void setShadowColor(const QColor &shadowColor) override; + + DPlatformHandle::EffectScene windowEffect() override; + void setWindowEffect(DPlatformHandle::EffectScenes effectScene) override; + + DPlatformHandle::EffectType windowStartUpEffect() override; + void setWindowStartUpEffect(DPlatformHandle::EffectTypes effectType) override; + + QPainterPath clipPath() const override; + void setClipPath(const QPainterPath &clipPath) override; + + QRegion frameMask() const override; + void setFrameMask(const QRegion &frameMask) override; + + QMargins frameMargins() const override; + + bool translucentBackground() const override; + void setTranslucentBackground(bool translucentBackground) override; + + bool enableSystemResize() const override; + void setEnableSystemResize(bool enableSystemResize) override; + + bool enableSystemMove() const override; + void setEnableSystemMove(bool enableSystemMove) override; + + bool enableBlurWindow() const override; + void setEnableBlurWindow(bool enableBlurWindow) override; + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; +}; + +DGUI_END_NAMESPACE +#endif // DXCBPLATFORMWINDOWINTERFACE_H diff --git a/src/private/dplatformwindowinterface_p.h b/src/private/dplatformwindowinterface_p.h new file mode 100644 index 0000000..b9e4f62 --- /dev/null +++ b/src/private/dplatformwindowinterface_p.h @@ -0,0 +1,86 @@ +// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd. +// +// SPDX-License-Identifier: LGPL-3.0-or-later + +#ifndef DPLATFORMWINDOWINTERFACE_P_H +#define DPLATFORMWINDOWINTERFACE_P_H + +#include +#include + +#include "dplatformhandle.h" + +DGUI_BEGIN_NAMESPACE + +class LIBDTKCORESHARED_EXPORT DPlatformWindowInterface +{ +public: + explicit DPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle); + virtual ~DPlatformWindowInterface(); + + QWindow* window() const; + + virtual void setEnabled(bool enabled); + virtual bool isEnabled() const; + + virtual bool isEnabledNoTitlebar() const; + virtual bool setEnabledNoTitlebar(bool enable); + + virtual void setDisableWindowOverrideCursor(bool disable); + + virtual int windowRadius() const; + virtual void setWindowRadius(int windowRadius); + + virtual int borderWidth() const; + virtual void setBorderWidth(int borderWidth); + + virtual QColor borderColor() const; + virtual void setBorderColor(const QColor &borderColor); + + virtual int shadowRadius() const; + virtual void setShadowRadius(int shadowRadius); + + virtual QPoint shadowOffset() const; + virtual void setShadowOffset(const QPoint &shadowOffset); + + virtual QColor shadowColor() const; + virtual void setShadowColor(const QColor &shadowColor); + + virtual DPlatformHandle::EffectScene windowEffect(); + virtual void setWindowEffect(DPlatformHandle::EffectScenes effectScene); + + virtual DPlatformHandle::EffectType windowStartUpEffect(); + virtual void setWindowStartUpEffect(DPlatformHandle::EffectTypes effectType); + + virtual QPainterPath clipPath() const; + virtual void setClipPath(const QPainterPath &clipPath); + + virtual QRegion frameMask() const; + virtual void setFrameMask(const QRegion &frameMask); + + virtual QMargins frameMargins() const; + + virtual bool translucentBackground() const; + virtual void setTranslucentBackground(bool translucentBackground); + + virtual bool enableSystemResize() const; + virtual void setEnableSystemResize(bool enableSystemResize); + + virtual bool enableSystemMove() const; + virtual void setEnableSystemMove(bool enableSystemMove); + + virtual bool enableBlurWindow() const; + virtual void setEnableBlurWindow(bool enableBlurWindow); +protected: + QPointer m_window; + QPointer m_platformHandle; +}; + +class LIBDTKCORESHARED_EXPORT DPlatformWindowInterfaceFactory { +public: + using Creator = DPlatformWindowInterface * (*)(QWindow *, DPlatformHandle*); + static void registerInterface(Creator creator); +}; + +DGUI_END_NAMESPACE +#endif // DPLATFORMWINDOWINTERFACE_P_H diff --git a/src/private/private.cmake b/src/private/private.cmake index 6ca2ce9..856e00d 100644 --- a/src/private/private.cmake +++ b/src/private/private.cmake @@ -8,4 +8,5 @@ set(private_SRC ${CMAKE_CURRENT_LIST_DIR}/dtaskbarcontrol_p.h ${CMAKE_CURRENT_LIST_DIR}/dfontmanager_p.h ${CMAKE_CURRENT_LIST_DIR}/dplatforminterface_p.h + ${CMAKE_CURRENT_LIST_DIR}/dplatformwindowinterface_p.h )