Skip to content

Commit

Permalink
refactor: treeland platform theme interface
Browse files Browse the repository at this point in the history
扩展Treeland的个性化接口

Log:
pms: Task-365811
  • Loading branch information
mhduiy committed Nov 25, 2024
1 parent acbe739 commit cb99e5c
Show file tree
Hide file tree
Showing 14 changed files with 889 additions and 179 deletions.
173 changes: 35 additions & 138 deletions src/kernel/dplatformhandle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,24 @@
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#define protected public
#include <QWindow>
#undef protected

#include "dguiapplicationhelper.h"
#include "dplatformhandle.h"
#include "dplatformtheme.h"
#include "dwindowmanagerhelper.h"
#include "dvtablehook.h"

#ifndef DTK_DISABLE_TREELAND
#include "wayland/personalizationwaylandclientextension.h"
#include "plugins/platform/treeland/dtreelandplatformwindowinterface.h"
#endif

#include <private/qwaylandwindow_p.h>
#include <QtWaylandClient/private/qwaylandwindow_p.h>
#include <dtkcore_global.h>

#include <QGuiApplication>
#include <QDebug>
#include <QPlatformSurfaceEvent>
#include <QStyleHints>

DCORE_USE_NAMESPACE
#include <QHash>

DGUI_BEGIN_NAMESPACE

Expand Down Expand Up @@ -108,6 +104,20 @@ static void setWindowProperty(QWindow *window, const char *name, const QVariant
reinterpret_cast<void(*)(QWindow *, const char *, const QVariant &)>(setWindowProperty)(window, name, value);
}

#ifndef DTK_DISABLE_TREELAND
static QHash<DPlatformHandle *, DTreeLandPlatformWindowInterface *> g_platformThemeMap;

static DTreeLandPlatformWindowInterface *dPlatformWindowInterfaceByWindow(QWindow * window)

Check warning on line 110 in src/kernel/dplatformhandle.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Parameter 'window' can be declared with const

Check warning on line 110 in src/kernel/dplatformhandle.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Parameter 'window' can be declared with const
{
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
Expand Down Expand Up @@ -395,6 +405,17 @@ 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));

connect(this, &DPlatformHandle::destroyed, this, [this](){
g_platformThemeMap.value(this)->deleteLater();
g_platformThemeMap.remove(this);
});
}
#endif

enableDXcbForWindow(window);

window->installEventFilter(this);
Expand Down Expand Up @@ -630,137 +651,12 @@ class Q_DECL_HIDDEN CreatorWindowEventFilter : public QObject {
if (se->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) { // 若收到此信号, 则 WinID 已被创建
auto window = qobject_cast<QWindow *>(watched);
initWindowRadius(window);

#ifndef DTK_DISABLE_TREELAND
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform) && PersonalizationManager::instance()->isSupported()) {
PersonalizationManager::instance()->setEnableTitleBar(window, false);
}
#endif
deleteLater();
}
}
return QObject::eventFilter(watched, event);
}
};

class MoveWindowHelper : public QObject
{
public:
explicit MoveWindowHelper(QWindow *w);
~MoveWindowHelper();

static QHash<const QWindow*, MoveWindowHelper*> mapped;

private:
static bool windowEvent(QWindow *w, QEvent *event);
void updateEnableSystemMoveFromProperty();

QWindow *m_window;
bool m_windowMoving;
bool m_enableSystemMove;
};

QHash<const QWindow*, MoveWindowHelper*> MoveWindowHelper::mapped;

MoveWindowHelper::MoveWindowHelper(QWindow *window)
: QObject(window)
, m_window(window)
{
mapped[window] = this;
updateEnableSystemMoveFromProperty();
}

MoveWindowHelper::~MoveWindowHelper()
{
if (DVtableHook::hasVtable(m_window)) {
DVtableHook::resetVtable(m_window);
}

mapped.remove(qobject_cast<QWindow*>(parent()));
}

void MoveWindowHelper::updateEnableSystemMoveFromProperty()
{
if (!m_window) {
return;
}
const QVariant &v = m_window->property("_d_enableSystemMove");

m_enableSystemMove = !v.isValid() || v.toBool();

if (m_enableSystemMove) {
DVtableHook::overrideVfptrFun(m_window, &QWindow::event, &MoveWindowHelper::windowEvent);
} else if (DVtableHook::hasVtable(m_window)) {
DVtableHook::resetVfptrFun(m_window, &QWindow::event);
}
}

bool MoveWindowHelper::windowEvent(QWindow *w, QEvent *event)
{
MoveWindowHelper *self = mapped.value(w);

if (!self)
return DVtableHook::callOriginalFun(w, &QWindow::event, event);
// m_window 的 event 被 override 以后,在 windowEvent 里面获取到的 this 就成 m_window 了,
// 而不是 DNoTitlebarWlWindowHelper,所以此处 windowEvent 改为 static 并传 self 进来
{
static bool isTouchDown = false;
static QPointF touchBeginPosition;
if (event->type() == QEvent::TouchBegin) {
isTouchDown = true;
}
if (event->type() == QEvent::TouchEnd || event->type() == QEvent::MouseButtonRelease) {
isTouchDown = false;
}
if (isTouchDown && event->type() == QEvent::MouseButtonPress) {
touchBeginPosition = static_cast<QMouseEvent*>(event)->globalPos();
}
// add some redundancy to distinguish trigger between system menu and system move
if (event->type() == QEvent::MouseMove) {
QPointF currentPos = static_cast<QMouseEvent*>(event)->globalPos();
QPointF delta = touchBeginPosition - currentPos;
if (delta.manhattanLength() < QGuiApplication::styleHints()->startDragDistance()) {
return DVtableHook::callOriginalFun(w, &QWindow::event, event);
}
}
}

bool is_mouse_move = event->type() == QEvent::MouseMove && static_cast<QMouseEvent*>(event)->buttons() == Qt::LeftButton;

if (event->type() == QEvent::MouseButtonRelease) {
self->m_windowMoving = false;
}

if (!DVtableHook::callOriginalFun(w, &QWindow::event, event))
return false;

// workaround for kwin: Qt receives no release event when kwin finishes MOVE operation,
// which makes app hang in windowMoving state. when a press happens, there's no sense of
// keeping the moving state, we can just reset ti back to normal.
if (event->type() == QEvent::MouseButtonPress) {
self->m_windowMoving = false;
}

if (is_mouse_move && !event->isAccepted()
&& w->geometry().contains(static_cast<QMouseEvent*>(event)->globalPos())) {
if (!self->m_windowMoving && self->m_enableSystemMove) {
self->m_windowMoving = true;

event->accept();
if (w && w->handle()) {
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
static_cast<QPlatformWindow *>(w->handle())->startSystemMove(QCursor::pos());
#else
static_cast<QPlatformWindow *>(w->handle())->startSystemMove();
#endif
}
}
}

return true;
}


/*!
\brief DPlatformHandle::setEnabledNoTitlebarForWindow.
Expand All @@ -783,10 +679,11 @@ bool DPlatformHandle::setEnabledNoTitlebarForWindow(QWindow *window, bool enable

#ifndef DTK_DISABLE_TREELAND
if (window && DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) {
window->installEventFilter(new CreatorWindowEventFilter(window));
if (MoveWindowHelper::mapped.value(window))
return true;
Q_UNUSED(new MoveWindowHelper(window))

auto handle = dPlatformWindowInterfaceByWindow(window);
if (handle) {
handle->setEnabledNoTitlebar(true);
}
return true;
}
#endif
Expand Down Expand Up @@ -1377,7 +1274,7 @@ void DPlatformHandle::setEnableBlurWindow(bool enableBlurWindow)
{
#ifndef DTK_DISABLE_TREELAND
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) {
PersonalizationManager::instance()->setEnableBlurWindow(m_window, enableBlurWindow);
g_platformThemeMap.value(this)->setEnableBlurWindow(enableBlurWindow);
return;
}
#endif
Expand Down
63 changes: 58 additions & 5 deletions src/kernel/dplatformtheme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// SPDX-License-Identifier: LGPL-3.0-or-later

#include "dplatformtheme.h"
#include "dguiapplicationhelper.h"
#include "private/dplatformtheme_p.h"

#ifndef DTK_DISABLE_XCB
Expand All @@ -18,10 +19,12 @@
#include <QMetaProperty>
#include <QDebug>
#include <DGuiApplicationHelper>

#include <functional>
#include <DConfig>

DGUI_BEGIN_NAMESPACE
#define DTK_PREFERENCE_NAME "org.deepin.dtk.preference"
#define DTK_SIZE_MODE_KEY "sizeMode"
#define DTK_SCROLLBAR_POLICY_KEY "scrollBarPolicy"

static DPlatformInterfaceFactory::HelperCreator OutsideInterfaceCreator = nullptr;

Expand Down Expand Up @@ -75,6 +78,18 @@ void DPlatformThemePrivate::notifyPaletteChanged()
notifyPaletteChangeTimer->start(300);
}

void DPlatformThemePrivate::onDtkPreferenceDConfigChanged(const QString &key)
{
D_Q(DPlatformTheme);
if (key == DTK_SIZE_MODE_KEY) {
sizeMode = static_cast<DGuiApplicationHelper::SizeMode>(dtkPreferenceConfig->value(key).toInt());
Q_EMIT q->sizeModeChanged(sizeMode);
} else if (key == DTK_SCROLLBAR_POLICY_KEY) {
scrollBarPolicy = static_cast<Qt::ScrollBarPolicy>(dtkPreferenceConfig->value(key).toInt());
Q_EMIT q->scrollBarPolicyChanged(scrollBarPolicy);
}
}

/*!
\class Dtk::Gui::DPlatformTheme
\inmodule dtkgui
Expand All @@ -98,7 +113,7 @@ DPlatformTheme::DPlatformTheme(quint32 window, QObject *parent)
#endif

#ifndef DTK_DISABLE_TREELAND
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsTreelandPlatform)) {
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) {
d->platformInterface = new DTreelandPlatformInterface(this);
}
#endif
Expand All @@ -109,6 +124,44 @@ DPlatformTheme::DPlatformTheme(quint32 window, QObject *parent)
}

d->theme = new DNativeSettings(window, QByteArray(), this);

d->dtkPreferenceConfig = Dtk::Core::DConfig::createGeneric(DTK_PREFERENCE_NAME, "", this);
d->sizeMode = static_cast<DGuiApplicationHelper::SizeMode>(d->dtkPreferenceConfig->value(DTK_SIZE_MODE_KEY).toInt());
d->scrollBarPolicy = static_cast<Qt::ScrollBarPolicy>(d->dtkPreferenceConfig->value(DTK_SCROLLBAR_POLICY_KEY).toInt());
connect(d->dtkPreferenceConfig, &Dtk::Core::DConfig::valueChanged, this, [this](const QString &key) -> void{
D_D(DPlatformTheme);
d->onDtkPreferenceDConfigChanged(key);
});

#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
connect(this, &DPlatformTheme::windowChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Window, std::placeholders::_1));
connect(this, &DPlatformTheme::windowTextChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::WindowText, std::placeholders::_1));
connect(this, &DPlatformTheme::baseChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Base, std::placeholders::_1));
connect(this, &DPlatformTheme::alternateBaseChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::AlternateBase, std::placeholders::_1));
connect(this, &DPlatformTheme::toolTipBaseChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::ToolTipBase, std::placeholders::_1));
connect(this, &DPlatformTheme::toolTipTextChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::ToolTipText, std::placeholders::_1));
connect(this, &DPlatformTheme::textChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Text, std::placeholders::_1));
connect(this, &DPlatformTheme::buttonChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Button, std::placeholders::_1));
connect(this, &DPlatformTheme::buttonTextChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::ButtonText, std::placeholders::_1));
connect(this, &DPlatformTheme::brightTextChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::BrightText, std::placeholders::_1));
connect(this, &DPlatformTheme::lightChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Light, std::placeholders::_1));
connect(this, &DPlatformTheme::midlightChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Midlight, std::placeholders::_1));
connect(this, &DPlatformTheme::darkChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Dark, std::placeholders::_1));
connect(this, &DPlatformTheme::midChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Mid, std::placeholders::_1));
connect(this, &DPlatformTheme::shadowChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Shadow, std::placeholders::_1));
connect(this, &DPlatformTheme::highlightChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Highlight, std::placeholders::_1));
connect(this, &DPlatformTheme::highlightedTextChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::HighlightedText, std::placeholders::_1));
connect(this, &DPlatformTheme::linkChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::Link, std::placeholders::_1));
connect(this, &DPlatformTheme::linkVisitedChanged, std::bind(&DPlatformThemePrivate::onQtColorChanged, d, QPalette::LinkVisited, std::placeholders::_1));
connect(this, &DPlatformTheme::itemBackgroundChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::ItemBackground, std::placeholders::_1));
connect(this, &DPlatformTheme::textTitleChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::TextTitle, std::placeholders::_1));
connect(this, &DPlatformTheme::textTipsChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::TextTips, std::placeholders::_1));
connect(this, &DPlatformTheme::textWarningChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::TextWarning, std::placeholders::_1));
connect(this, &DPlatformTheme::textLivelyChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::TextLively, std::placeholders::_1));
connect(this, &DPlatformTheme::lightLivelyChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::LightLively, std::placeholders::_1));
connect(this, &DPlatformTheme::darkLivelyChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::DarkLively, std::placeholders::_1));
connect(this, &DPlatformTheme::frameBorderChanged, std::bind(&DPlatformThemePrivate::onDtkColorChanged, d, DPalette::FrameBorder, std::placeholders::_1));
#endif
}

DPlatformTheme::DPlatformTheme(quint32 window, DPlatformTheme *parent)
Expand Down Expand Up @@ -554,7 +607,7 @@ int DPlatformTheme::dotsPerInch(const QString &screenName) const
int DPlatformTheme::sizeMode() const
{
D_DC(DPlatformTheme);
return d->platformInterface->sizeMode();
return d->sizeMode;
}

/*!
Expand All @@ -567,7 +620,7 @@ int DPlatformTheme::sizeMode() const
int DPlatformTheme::scrollBarPolicy() const
{
D_DC(DPlatformTheme);
return d->platformInterface->scrollBarPolicy();
return d->scrollBarPolicy;
}

void DPlatformTheme::setCursorBlinkTime(int cursorBlinkTime)
Expand Down
Loading

0 comments on commit cb99e5c

Please sign in to comment.