Skip to content

fix(dconfig): cache configuration objects for the compositor lifetime - #1252

Draft
zzxyb wants to merge 1 commit into
linuxdeepin:masterfrom
zzxyb:dconfig
Draft

fix(dconfig): cache configuration objects for the compositor lifetime#1252
zzxyb wants to merge 1 commit into
linuxdeepin:masterfrom
zzxyb:dconfig

Conversation

@zzxyb

@zzxyb zzxyb commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Add SystemDConfigManager to centrally own and cache global, user, seat, output, and application DConfig objects.

Delay Treeland startup until the global and initial user configurations are initialized, abort on global initialization failure, and fall back to generated defaults when user configuration initialization fails.

Log: centralize DConfig initialization and lifetime management
PMS: TASK-393777
Influence: DConfig startup, user switching, and hot-plugged output/input configuration

Summary by Sourcery

Introduce a central SystemDConfigManager to own and cache global, user, seat, output, and application configuration objects, and integrate it into Treeland startup and runtime.

New Features:

  • Add a SystemDConfigManager singleton that provides cached access to global, user, seat, output, and application DConfig instances.

Enhancements:

  • Delay Treeland compositor initialization until global and initial user DConfig initialization completes, aborting on global failure and falling back to defaults on user/seat failures.
  • Refactor Helper, InputManager, Output, and WindowConfigStore to obtain their configuration objects from the shared SystemDConfigManager instead of constructing them individually.
  • Improve user-switching and seat configuration handling by reusing cached per-user configs and guarding against stale pointers during async initialization.

Add SystemDConfigManager to centrally own and cache global, user, seat,
output, and application DConfig objects.

Delay Treeland startup until the global and initial user configurations
are initialized, abort on global initialization failure, and fall back
to generated defaults when user configuration initialization fails.

Log: centralize DConfig initialization and lifetime management
PMS: TASK-393777
Influence: DConfig startup, user switching, and hot-plugged output/input configuration
@deepin-ci-robot

Copy link
Copy Markdown

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: zzxyb

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@zzxyb
zzxyb marked this pull request as ready for review August 6, 2026 07:33

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @zzxyb, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@zzxyb
zzxyb requested a review from zccrs August 6, 2026 07:33
@sourcery-ai

sourcery-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Reviewer's Guide

Introduce a central SystemDConfigManager to own and cache Treeland DConfig objects, and defer Treeland startup until global and initial user configurations are initialized, replacing scattered per-component DConfig creation and tightening initialization/error-handling paths.

Sequence diagram for Treeland startup with SystemDConfigManager-managed DConfig initialization

sequenceDiagram
    participant main
    participant app as QGuiApplication
    participant configMgr as SystemDConfigManager
    participant treeland as Treeland
    participant tlPriv as TreelandPrivate

    main->>app: construct
    main->>configMgr: SystemDConfigManager(&app)
    configMgr->>configMgr: globalConfig = TreelandConfig::create
    alt globalConfig.initializeFailed
        configMgr-->>app: InitializeFailed
        app-->>main: exit(1)
    else globalConfig.initializeSucceed
        configMgr-->>app: InitializeSucceed
        app->>main: startTreeland()
        main->>treeland: std::make_unique<Treeland>()
        treeland->>tlPriv: init(onInitialized)
        tlPriv->>configMgr: initializeUserConfigs(initialUserName)
        alt userConfigsAlreadySucceeded
            tlPriv->>tlPriv: initializeTreeland()
            tlPriv-->>treeland: onInitialized()
            treeland->>treeland: initialize()
        else userConfigsPending
            tlPriv->>configMgr: initialUserConfig()
            tlPriv->>configMgr: seatUserConfig(initialUserName)
            configMgr-->>tlPriv: TreelandUserConfig
            configMgr-->>tlPriv: SeatUserDConfig
            tlPriv->>TreelandUserConfig: connect(configInitializeSucceed/Failed)
            tlPriv->>SeatUserDConfig: connect(configInitializeSucceed/Failed)
            TreelandUserConfig-->>tlPriv: configInitializeSucceed or Failed
            SeatUserDConfig-->>tlPriv: configInitializeSucceed or Failed
            tlPriv->>tlPriv: initializeWhenReady()
            tlPriv->>tlPriv: initializeTreeland()
            tlPriv-->>treeland: onInitialized()
            treeland->>treeland: initialize()
        end
    end
Loading

File-Level Changes

Change Details Files
Centralized DConfig lifecycle management via SystemDConfigManager singleton.
  • Add SystemDConfigManager QObject that owns global, user, seat, output, and app DConfig instances and caches them by key.
  • Wire global TreelandConfig initialization signals to SystemDConfigManager InitializeSucceed/InitializeFailed signals and expose status helpers.
  • Provide helpers to pre-initialize initial user and seat configs and expose cached initial user config pointer.
src/core/systemdconfigmanager.h
src/core/systemdconfigmanager.cpp
src/CMakeLists.txt
Gate Treeland startup on global and initial user DConfig initialization.
  • Change TreelandPrivate::init to accept a completion callback and factor remaining initialization into Treeland::initialize.
  • In main.cpp, construct SystemDConfigManager before Treeland, start Treeland only on global config success, and abort startup on global config failure with critical logging.
  • In TreelandPrivate::init, request initial user configs from SystemDConfigManager, delaying Helper initialization and user model wiring until user and seat configs have either succeeded or failed, and logging when falling back to defaults.
src/core/treeland.cpp
src/core/treeland.h
src/main.cpp
Refactor Helper, InputManager, WindowConfigStore, and Output to consume cached configs instead of creating their own.
  • Update Helper to obtain initial user and global configs from SystemDConfigManager, change m_config/m_globalConfig ownership to raw pointers, and adjust uses and runWhenTreelandConfigInitialized callers accordingly.
  • Change Helper::init user-switch path to fetch per-user TreelandUserConfig from SystemDConfigManager, manage signal reconnections safely, and guard callbacks against config pointer changes.
  • Modify InputManager::setupSeatUserConfig to retrieve SeatUserDConfig from SystemDConfigManager, drop manual deletion, and guard initialization callbacks against stale configs.
  • Update WindowConfigStore::configForApp to delegate to SystemDConfigManager::appConfig and remove the local app config cache.
  • Update Output to obtain OutputConfig instances through SystemDConfigManager and assert manager presence.
src/seat/helper.cpp
src/seat/helper.h
src/input/inputmanager.cpp
src/core/windowconfigstore.cpp
src/core/windowconfigstore.h
src/output/output.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

中文:本 PR 引入 SystemDConfigManager 作为全局 DConfig 中央管理与缓存点,并将 Helper/Input/Output/WindowConfigStore 等处的分散配置对象创建迁移到该中心,以便在合成器生命周期内复用配置对象并统一初始化流程;同时在启动阶段等待全局与初始用户配置初始化结果后再进入 Treeland 初始化逻辑。

English: This PR introduces SystemDConfigManager as a centralized owner/cache for global, user, seat, output, and app DConfig wrapper objects, refactors multiple call sites to fetch configs from the manager, and gates Treeland startup on global + initial user config initialization outcomes.

Changes:

  • Add SystemDConfigManager singleton to own and cache DConfig wrapper instances across compositor lifetime.
  • Delay Treeland startup until global + initial user/seat configs reach a terminal initialization state (abort on global failure; warn/fallback on user/seat failure).
  • Refactor Helper, InputManager, Output, and WindowConfigStore to use cached config instances instead of constructing their own.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/seat/helper.h Switch config ownership from unique_ptr to cached raw pointers.
src/seat/helper.cpp Fetch global/user configs from SystemDConfigManager; adjust user-switch wiring.
src/output/output.cpp Fetch per-output config from the shared config manager.
src/main.cpp Create SystemDConfigManager early and gate Treeland startup on its init signals.
src/input/inputmanager.cpp Reuse cached seat-user config; improve stale-pointer safety during async init.
src/core/windowconfigstore.h Remove per-instance app-config cache storage.
src/core/windowconfigstore.cpp Retrieve per-app configs from SystemDConfigManager.
src/core/treeland.h Add initialize() to support delayed initialization.
src/core/treeland.cpp Delay compositor initialization until user/seat config init completes (with fallback).
src/core/systemdconfigmanager.h New centralized DConfig manager interface + caches.
src/core/systemdconfigmanager.cpp New centralized DConfig manager implementation + global init forwarding.
src/CMakeLists.txt Build integration for the new manager source files.
Suppressed comments (1)

src/seat/helper.cpp:1915

  • 中文:现在 TreelandUserConfig 对象会被 SystemDConfigManager 缓存复用,同一个用户可能多次触发 updateCurrentUser()UserModel::setCurrentUserName 不会去重)。这里对 configInitializeSucceed 的连接不是 single-shot/unique,可能累积多次连接,导致 onConfigInitialized() 被重复执行(重复 reload、重复同步等)。建议用 Qt::SingleShotConnection

English: With SystemDConfigManager caching, the same TreelandUserConfig instance can be reused, and updateCurrentUser() may be invoked repeatedly for the same user (since UserModel::setCurrentUserName doesn’t de-dup). This configInitializeSucceed connection is neither single-shot nor unique, so it can accumulate and call onConfigInitialized() multiple times. Use Qt::SingleShotConnection.

            connect(m_config,
                    &TreelandUserConfig::configInitializeSucceed,
                    this,
                    onConfigInitialized);
        }

Comment thread src/seat/helper.cpp
Comment on lines +304 to +310
if (auto *configManager = SystemDConfigManager::instance()) {
m_config = configManager->initialUserConfig();
m_globalConfig = configManager->globalConfig();
}

Q_ASSERT(m_config);
Q_ASSERT(m_globalConfig);
Comment thread src/output/output.cpp
Comment on lines 155 to +158
QString outputName = WallpaperManager::getOutputId(output->output()->nativeHandle());
m_config = OutputConfig::createByName("org.deepin.dde.treeland.output",
"org.deepin.dde.treeland",
"/" + outputName, this);
auto *configManager = SystemDConfigManager::instance();
Q_ASSERT(configManager);
m_config = configManager ? configManager->outputConfig(outputName) : nullptr;
Comment on lines +114 to +116
if (outputName.isEmpty()) {
return nullptr;
}
Comment on lines +41 to +43
Q_SIGNALS:
void InitializeSucceed();
void InitializeFailed();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

直接叫 dconfigmanager 就行

TreelandUserConfig *initialUserConfig() const;

Q_SIGNALS:
void InitializeSucceed();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

信号首字母不要用大写

connect(m_globalConfig,
&TreelandConfig::configInitializeSucceed,
this,
[this](DTK_CORE_NAMESPACE::DConfig *) { Q_EMIT InitializeSucceed(); },

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

可以直接连接,为啥要用lambda

Comment thread src/main.cpp
SystemDConfigManager systemDConfigManager(&app);
std::unique_ptr<Treeland::Treeland> treeland;

auto startTreeland = [&treeland] {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

加个日志

Comment thread src/main.cpp
}

quitCode = app.exec();
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

else里加个日志说明在等待dconfig初始化完成

QHash<QString, SeatUserDConfig *> m_seatUserConfigs;
QHash<QString, OutputConfig *> m_outputConfigs;
QHash<QString, AppConfig *> m_appConfigs;
TreelandUserConfig *m_initialUserConfig = nullptr;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

成员变量改名为 currentUserConfig

// Creates and caches the initial user's configs. Returns true only when both
// configs have already finished successfully; callers should listen for
// their initialization signals when this returns false.
bool initializeUserConfigs(const QString &userName);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

应该叫 setCurrentUser?

不过为啥要在这里做这样的封装,treeland.cpp 里直接使用 userConfig 获取,自己做当前config对象存储。

Comment thread src/core/treeland.cpp

#ifndef DISABLE_DDM
auto userModel = qmlEngine->singletonInstance<UserModel *>("Treeland", "UserModel");
const QString initialUserName = userModel ? userModel->currentUserName()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

userModel 里要加一个 pendingUserXXXX 的方法,当这个用户对应的dconfig未reday时,它还不是currentUser,对于想要切换到的user,应该先为pending状态,对应的dconfig reday后才变成currentUser,避免依赖 UserModel::currentUserNameChanged 的地方认为用户切换完成误用了dconfig。

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

user对应的dconfig未完成初始化时,所有的也有代码逻辑能获取到的信息都应该是旧的,相当于没有进行user的切换。

@zzxyb
zzxyb marked this pull request as draft August 10, 2026 07:59
@deepin-bot

deepin-bot Bot commented Aug 14, 2026

Copy link
Copy Markdown

TAG Bot

New tag: 0.8.18
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1286

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants