Compare commits

..

107 Commits

Author SHA1 Message Date
github-actions[bot] b03849d6de chore: New release 5.7.25
Log:
2025-10-30 13:59:43 +00:00
zhangkun 187be9a947 feat: improve icon theme generation with scalable support
1. Add SCALABLE_SIZE constant for scalable icon directories
2. Change foundSize return type from uint to int to support scalable
detection
3. Modify writeScaledImage to accept baseSize parameter instead of
parsing from directory
4. Move directory parsing logic to writeImage function for better
organization
5. Add scalable directory detection in size parsing logic
6. Use QImageReader's scaledSize for better image scaling quality
7. Fix error handling to continue processing instead of exiting on first
error

Log: Improved icon theme generation with better scalable icon support

Influence:
1. Test with icon directories containing scalable icons
2. Verify different scale factors work correctly
3. Test error handling when encountering invalid image files
4. Verify image quality at various scales
5. Test with both fixed-size and scalable icon directories

feat: 改进图标主题生成,支持可缩放图标

1. 添加 SCALABLE_SIZE 常量用于可缩放图标目录
2. 将 foundSize 返回类型从 uint 改为 int 以支持可缩放检测
3. 修改 writeScaledImage 函数,接受 baseSize 参数而非从目录解析
4. 将目录解析逻辑移至 writeImage 函数以获得更好的代码组织
5. 在尺寸解析逻辑中添加可缩放目录检测
6. 使用 QImageReader 的 scaledSize 获得更好的图像缩放质量
7. 修复错误处理,在遇到错误时继续处理而非立即退出

Log: 改进图标主题生成,提供更好的可缩放图标支持

Influence:
1. 测试包含可缩放图标的目录
2. 验证不同缩放因子是否正确工作
3. 测试遇到无效图像文件时的错误处理
4. 验证各种缩放比例下的图像质量
5. 测试固定尺寸和可缩放图标目录
2025-10-23 08:41:20 +00:00
github-actions[bot] 16145642e1 chore: New release 5.7.24
Log:
2025-10-16 20:13:34 +08:00
zhangkun 39a50cca37 feat: improve icon size detection and duplicate handling
1. Added foundSize function to parse icon size from directory names
using multiple strategies
2. Implemented duplicate entry detection to skip existing icons in DCI
files
3. Added QFileInfo and QLogging includes for new functionality
4. Removed debug-specific code that was adding unnecessary prefixes
5. Improved size detection logic to handle both numeric and "NxN" format
directory names
6. Added fallback to parent directory when current directory name
doesn't contain size information

Log: Improved icon theme generation with better size detection and
duplicate prevention

Influence:
1. Test icon theme generation with various directory naming conventions
2. Verify that duplicate icons are properly skipped during generation
3. Test with directories containing numeric names vs "widthxheight"
format
4. Verify fallback to parent directory size detection works correctly
5. Check that existing icons in DCI files are not overwritten
6. Test with different directory structures and naming patterns

feat: 改进图标尺寸检测和重复项处理

1. 添加 foundSize 函数,使用多种策略从目录名解析图标尺寸
2. 实现重复条目检测,跳过 DCI 文件中已存在的图标
3. 添加 QFileInfo 和 QLogging 包含以支持新功能
4. 移除添加不必要前缀的调试专用代码
5. 改进尺寸检测逻辑,支持数字和"NxN"格式的目录名
6. 在当前目录名不包含尺寸信息时,添加回退到父目录的检测

Log: 改进图标主题生成,提供更好的尺寸检测和重复项预防

Influence:
1. 测试使用不同目录命名约定的图标主题生成
2. 验证在生成过程中重复图标是否被正确跳过
3. 测试包含数字名称与"宽x高"格式的目录
4. 验证回退到父目录尺寸检测是否正常工作
5. 检查 DCI 文件中现有图标是否不会被覆盖
6. 测试不同的目录结构和命名模式
2025-10-16 11:05:03 +00:00
yeshanshan 2767618f84 fix: fix Qt6 compilation error with libxdg
1. Restructured the conditional logic for libxdg usage to avoid Qt6
compilation errors
2. Moved the DTK_DISABLE_LIBXDG check to outer scope to properly handle
both Qt5 and Qt6
3. Added explicit Qt6 handling by disabling libxdg when not using Qt5
4. This resolves build failures in Qt6 environments where
Qt5XdgIconLoader is not available

The previous implementation only checked for Qt5XdgIconLoader when
using Qt5, but didn't properly handle Qt6 scenarios, causing compilation
errors when building with Qt6.

fix: 修复 Qt6 下 libxdg 编译错误

1. 重构了 libxdg 使用的条件逻辑以避免 Qt6 编译错误
2. 将 DTK_DISABLE_LIBXDG 检查移到外层作用域以正确处理 Qt5 和 Qt6
3. 添加了明确的 Qt6 处理逻辑,在非 Qt5 环境下禁用 libxdg
4. 解决了在 Qt6 环境中因 Qt5XdgIconLoader 不可用而导致的构建失败问题

之前的实现只在 Qt5 环境下检查 Qt5XdgIconLoader,但没有正确处理 Qt6 场
景,导致在使用 Qt6 构建时出现编译错误。
2025-10-16 17:39:56 +08:00
ComixHe 36c06be095 fix: correct lockfile path construction
Move process ID namespace handling from lockfile to socket_key variable to ensure consistent lock file paths.
Reorganize code structure for proper execution order.

Signed-off-by: ComixHe <heyuming@deepin.org>
2025-10-16 13:14:00 +08:00
ComixHe 80db4dd238 feat: support Qt 6.10
Also adjusting the logic for finding QtXDGIconLoader.
This library only be used in Qt 5.

Signed-off-by: ComixHe <heyuming@deepin.org>
2025-10-13 13:03:30 +08:00
github-actions[bot] 3d0713f7a2 chore: New release 5.7.23
Log:
2025-09-25 17:44:27 +08:00
Mingcong Bai af1259edbb fix(tests): fix build for Qt 6.9
Qt 6.9 renamed <private/qdesktopunixservices_p.h> to
<private/qgenericunixservices_p.h>, as well as some of the classes along
the same format (QGenericUnixServices => QDesktopUnixServices).

Add a condition test with QT_VERSION to fix build with Qt >= 6.9.

Signed-off-by: Mingcong Bai <jeffbai@aosc.io>
2025-09-24 16:17:19 +08:00
Robertkill 3b5ba9bbda fix: 解决控制中心闪烁问题
初始化时立即读取并设置主题色,避免异步出现主题色闪烁问题

Log: 修复配置管理以使用标准 DConfig 接口

Influence:
1. 测试主题切换功能以确保正确的主题类型检测
2. 验证动画设置使用新的配置方法正常工作
3. 检查主题偏好是否正确保存和恢复
4. 测试配置值缺失或无效时的应用程序行为

PMS: BUG-334439
2025-09-18 13:26:13 +08:00
github-actions[bot] c8f2955bd0 chore: New release 5.7.22
Log:
2025-09-04 20:06:26 +08:00
zhangkun 96d0b45dd0 feat: add T11 font size and adjust T5 default
Added T11 font size with 8px default value to extend the font size
options
Modified T5 default size from 17px to 16px for better size progression
Updated font pixel size array to include the new T11 size
Added t11() accessor method and corresponding test case
cherry-pick from: 2c3b351b43

feat: 添加 T11 字体大小并调整 T5 默认值

添加了默认值为 8px 的 T11 字体大小以扩展字体大小选项
将 T5 默认大小从 17px 修改为 16px 以获得更好的大小递进
更新了字体像素大小数组以包含新的 T11 大小
添加了 t11() 访问器方法和相应的测试用例
cherry-pick from: 2c3b351b43

pms: BUG-310879
2025-09-01 11:27:52 +08:00
ComixHe 00109d07e3 fix: improve PID namespace detection in setSingleInstance
Replace stat-based PID namespace detection with QFileInfo approach
for better compatibility across different kernel versions and
containerized environments. Add robust parsing and fallback handling
for namespace format variations.

PMS: BUG-329663
Signed-off-by: ComixHe <heyuming@deepin.org>
2025-08-19 10:14:09 +08:00
github-actions[bot] d2c2efc49a chore: New release 5.7.21
Log:
2025-08-14 20:28:21 +08:00
yeshanshan 9842a0644e fix: resolve compilation warnings and deprecation issues
1. Fixed deprecated enum usage by adding explicit deprecation comment
for IconAttibute
2. Added QT version checks for QMouseEvent::globalPos() vs
globalPosition() API changes
3. Marked unused parameters with Q_UNUSED to suppress warnings
4. Added version checks for DTK 6.0 API changes
5. Fixed test class visibility warnings by adding GTEST_API_ prefix
6. Improved warning messages to use modern qWarning() stream syntax
7. Added [[maybe_unused]] attribute for DEFINE_CONST_CHAR macro
8. Added version checks for QVariant type handling differences between
Qt5/Qt6
9. Fixed potential memory leak in DIconTheme::isXdgIcon() logic
10. Added proper type checks for QVariant conversions

Log: Fixed various compilation warnings and deprecated API usage

Influence:
1. Verify icon rendering still works correctly after enum changes
2. Test window movement functionality with both Qt5 and Qt6
3. Check palette handling in DGuiApplicationHelper
4. Verify test cases still pass with updated class visibility
5. Test QVariant conversions in DPlatformHandle properties

fix: 解决编译警告和废弃API问题

1. 为废弃的IconAttibute枚举添加明确的弃用注释
2. 为QMouseEvent::globalPos()和globalPosition()API变更添加QT版本检查
3. 使用Q_UNUSED标记未使用参数以消除警告
4. 添加DTK 6.0 API变更的版本检查
5. 通过添加GTEST_API_前缀修复测试类可见性警告
6. 改进警告消息使用现代qWarning()流式语法
7. 为DEFINE_CONST_CHAR宏添加[[maybe_unused]]属性
8. 添加Qt5/Qt6之间QVariant类型处理的版本检查
9. 修复DIconTheme::isXdgIcon()中潜在的内存泄漏问题
10. 为QVariant转换添加适当的类型检查

Log: 修复各种编译警告和废弃API使用问题

Influence:
1. 验证图标渲染在枚举变更后仍能正常工作
2. 测试Qt5和Qt6下的窗口移动功能
3. 检查DGuiApplicationHelper中的调色板处理
4. 验证更新类可见性后测试用例是否仍能通过
5. 测试DPlatformHandle属性中的QVariant转换
2025-08-14 11:39:10 +00:00
yeshanshan 9d3d659afe feat: add flags parameter to DDciIconPlayer play method
1. Added new overloaded play method that accepts
DDciIconImagePlayer::Flags parameter
2. Modified existing play method to call new method with default
IgnoreLastImageLoop flag
3. Updated documentation to reflect new method signature and behavior
4. Allows more control over icon playback behavior through flags
parameter

feat: 为 DDciIconPlayer 的 play 方法添加 flags 参数

1. 添加了新的重载 play 方法,接受 DDciIconImagePlayer::Flags 参数
2. 修改现有 play 方法以使用默认的 IgnoreLastImageLoop 标志调用新方法
3. 更新文档以反映新的方法签名和行为
4. 通过 flags 参数提供对图标播放行为的更多控制
2025-08-07 14:38:07 +08:00
github-actions[bot] eaf96e824d chore: New release 5.7.20
Log:
2025-07-31 20:29:47 +08:00
zhangkun 7c05bace4a feat: switch to QGuiApplication for SVG rendering
1. Changed from QCoreApplication to QGuiApplication to support SVG
rendering
2. Updated CMakeLists to link against QtGui instead of QtCore
3. This change is necessary because SVG rendering requires GUI
components
4. Note: CLI environment users must set QT_QPA_PLATFORM=offscreen

feat: 切换到 QGuiApplication 以支持 SVG 渲染

1. 从 QCoreApplication 切换到 QGuiApplication 以支持 SVG 渲染
2. 更新 CMakeLists 链接 QtGui 替代 QtCore
3. 此变更是必要的因为 SVG 渲染需要 GUI 组件
4. 注意:命令行环境用户需要设置 QT_QPA_PLATFORM=offscreen
2025-07-31 13:42:53 +08:00
yeshanshan a892ddc4e2 feat: add concurrent processing for DCI icon conversion
1. Added QtConcurrent support for parallel processing of icon files
2. Implemented error handling with custom DciProcessingError exception
3. Grouped icon files by name to avoid concurrent access to same DCI
file
4. Improved performance by processing icon groups in parallel
5. Added proper error propagation and atomic flag for early termination
6. Maintained existing functionality while adding concurrency
7. Each icon group is processed as a unit to ensure thread safety with
DCI files

feat: 为DCI图标转换添加并发处理

1. 添加QtConcurrent支持以实现图标文件的并行处理
2. 使用自定义DciProcessingError异常实现错误处理
3. 按名称分组图标文件以避免对同一DCI文件的并发访问
4. 通过并行处理图标组提高性能
5. 添加适当的错误传播和原子标志用于提前终止
6. 在添加并发性的同时保持现有功能
7. 每个图标组作为一个单元处理以确保DCI文件的线程安全
2025-07-24 20:49:35 +08:00
yeshanshan 65cf7b4161 refactor: move icon finder functionality to separate tool
1. Removed icon finding functionality from dci-icon-theme to make it a
pure TUI tool
2. Created new dci-iconfinder tool specifically for icon lookup
operations
3. Changed dci-icon-theme to use QCoreApplication instead of
QGuiApplication
4. Updated version handling to use DTK version macros
5. Removed GUI dependencies from dci-icon-theme
6. Added proper documentation for both tools

This change was necessary to separate concerns and allow dci-icon-theme
to be used in environments without GUI dependencies while maintaining
icon lookup capabilities in a dedicated tool.

refactor: 将图标查找功能移至独立工具

1. 从dci-icon-theme中移除图标查找功能,使其成为纯命令行工具
2. 创建新的dci-iconfinder工具专门处理图标查找操作
3. 将dci-icon-theme改为使用QCoreApplication而非QGuiApplication
4. 更新版本处理以使用DTK版本宏
5. 移除dci-icon-theme对GUI的依赖
6. 为两个工具添加了适当的文档

此变更是为了分离关注点,使dci-icon-theme可以在没有GUI依赖的环境中使用,
同时将图标查找功能保留在专用工具中。
2025-07-23 04:16:59 +00:00
ComixHe 6b7e941839 feat: add pid namespace isolation to setSingleInstance
Enhance setSingleInstance to support multiple PID namespaces for
containerized environments. This prevents applications in different
containers from interfering with each other's single instance detection.

The lockfile format becomes: {original_name}_{namespace_inode}.lock,
ensuring unique identification across different PID namespaces.

Signed-off-by: ComixHe <heyuming@deepin.org>
2025-07-22 14:19:01 +08:00
yeshanshan dc2eaeb61c docs: update REUSE license file for CHANGELOG
Added CHANGELOG.md to the list of files under CC-BY-4.0 license
in .reuse/dep5
This change ensures proper licensing attribution for the changelog file
The modification follows the project's REUSE compliance standards

docs: 更新 REUSE 许可文件以包含 CHANGELOG

在 .reuse/dep5 文件中将 CHANGELOG.md 添加到 CC-BY-4.0 许可证下的文件列表
此变更确保了对变更日志文件的正确许可归属
修改遵循项目的 REUSE 合规标准
2025-07-21 09:55:22 +08:00
github-actions[bot] 4dd22b538d chore: New release 5.7.19
Log:
2025-07-03 13:23:09 +00:00
yeshanshan 2ea4e762fe fix: enhance build security hardening
1. Added security hardening compiler flags in debian/rules including
stack protection and RELRO
2. Removed redundant linker flag from dtkgui.cmake that was already set
in debian/rules
3. Consolidated security-related build flags in debian/rules for better
maintainability
4. The changes improve binary security against common exploits while
maintaining compatibility

fix: 增强构建安全加固

1. 在debian/rules中添加了安全加固编译标志,包括栈保护和RELRO
2. 从dtkgui.cmake中移除了已在debian/rules中设置的冗余链接器标志
3. 将安全相关的构建标志整合到debian/rules中以提高可维护性
4. 这些改动提高了二进制文件对常见漏洞攻击的防护能力,同时保持兼容性
2025-07-03 13:03:14 +00:00
github-actions[bot] 18388f26f8 chore: New release 5.7.18
Log:
2025-06-27 09:19:06 +00:00
yeshanshan 9e54cbfad4 fix: make version parameter optional in release workflow
1. Changed version parameter from required to optional in GitHub
workflow
2. Fixed spec file formatting by aligning Version and Release fields
3. Added %{?dist} macro to Release field for proper RPM building

The changes make the release workflow more flexible by allowing version-
less releases while maintaining proper RPM spec file formatting and
distribution tagging. This helps with automated release processes and
ensures consistent package building across different distributions.

fix: 在发布工作流中使版本参数可选

1. 将 GitHub 工作流中的版本参数从必填改为可选
2. 修复 spec 文件格式,对齐 Version 和 Release 字段
3. 在 Release 字段添加 %{?dist} 宏以支持正确的 RPM 构建

这些变更使发布工作流更加灵活,允许无版本号的发布,同时保持 RPM spec 文件
的正确格式和分发标签。这有助于自动化发布流程并确保在不同发行版上一致的软
件包构建。
2025-06-27 16:43:59 +08:00
github-actions[bot] 6ff5c37579 chore(rpm): New release 5.7.17
Log:
2025-06-19 10:22:12 +08:00
asterwyx dd35e33644 chore: update .syncexclude
Exclude CHANGELOG.md.
2025-06-18 17:03:05 +08:00
Yixue Wang f834cb588d feat(ci): Add auto release workflow
Log: as title
2025-06-11 11:46:44 +08:00
Yixue Wang 9f500cbe94 feat: Support VERSION file
Use VERSION file to manage DTK version. VERSION file defines package
version. It also decides the initial value of cached variable
DTK_VERSION which controls the project version in cmake build system.
VERSION file is not synchronized to DTK6, as DTK6 has its own VERSION
file. One can still pass version to DTK_VERSION when running cmake
configure. This is helpful for developers.

Signed-off-by: Yixue Wang <wangyixue@deepin.org>
2025-06-11 11:46:44 +08:00
Wang Zichong 44bed9e070 fix: add missing prefix for QTranslator::load()
Log:
2025-06-06 18:12:53 +08:00
ComixHe 3f1cfd6800 fix: add missing header
Signed-off-by: ComixHe <heyuming@deepin.org>
2025-06-06 10:10:42 +08:00
Wang Zichong 1f44c47e55 chore: use another QTranslator::load overload to tidy code
使用另一个 QTranslator::load 重载来使代码更简洁,并潜在的支持
QLocale::uiLanguages().

并且添加了一个额外的接口来方便其他项目更方便的调用.

Log:
2025-06-04 09:54:37 +00:00
Ye ShanShan 28c53f37e7 chore: bump version to 5.7.16
update changelog to 5.7.16
2025-05-19 09:26:17 +00:00
Ye ShanShan 75d176f234 chore: bump version to 5.7.15
update changelog to 5.7.15
2025-05-08 10:48:29 +00:00
Ye ShanShan 6d6a4a4380 fix: correct bitwise operation in preference handling
1. Fixed incorrect bitwise AND operation in OrgDeepinDTKPreference class
2. Changed `fetchAndAndOrdered(1 << (index - 0))` to
`fetchAndAndOrdered(~(1 << (index - 0)))`
3. This ensures proper bit clearing operation when updating property
status flags
4. The original code would incorrectly set bits instead of clearing them

fix: 修复偏好设置处理中的位操作错误

1. 修正了 OrgDeepinDTKPreference 类中错误的位与操作
2. 将 `fetchAndAndOrdered(1 << (index - 0))` 改为
`fetchAndAndOrdered(~(1 << (index - 0)))`
3. 确保在更新属性状态标志时正确的位清除操作
4. 原代码会错误地设置位而不是清除它们
2025-05-08 09:52:03 +00:00
Ye ShanShan ed252239b2 fix: prevent theme saving when DontSaveApplicationTheme is set
Added a condition to check DontSaveApplicationTheme attribute before
saving theme type to config
This prevents unwanted theme persistence when the application explicitly
requests not to save theme preferences
The change maintains backward compatibility while respecting the
application's preference flag

fix: 当设置DontSaveApplicationTheme时阻止主题保存

在将主题类型保存到配置前添加了检查DontSaveApplicationTheme属性的条件
这可以防止当应用程序明确要求不保存主题偏好时进行不必要的主题持久化
该改动在尊重应用程序偏好标志的同时保持了向后兼容性
2025-05-08 09:52:03 +00:00
Ye ShanShan aa13f2a82f refactor: improve thread safety in OrgDeepinDTKPreference
1. Changed parent initialization from direct assignment to nullptr in
constructor
2. Added QPointer to track parent object for thread safety
3. Implemented parent object verification before setting parent
relationship
4. Added safety checks for parent object changes during thread
operations
5. Updated build path in file header comment

refactor: 改进 OrgDeepinDTKPreference 的线程安全性

1. 将构造函数中的父对象初始化改为直接赋值为 nullptr
2. 添加 QPointer 用于线程安全的父对象跟踪
3. 在设置父子关系前实现父对象验证
4. 添加线程操作期间父对象变化的安全检查
5. 更新文件头注释中的构建路径
2025-05-07 03:45:13 +00:00
Ye ShanShan decbf724b3 fix: build failed in qt5
Changed Q_GLOBAL_STATIC to Q_GLOBAL_STATIC_WITH_ARGS for
OrgDeepinDTKPreference initialization
This modification provides better type safety and clearer syntax for the
complex initialization parameters
The change maintains the same functionality while following Qt's
recommended practices for static initialization

refactor: 更新 DConfig 初始化语法

将 Q_GLOBAL_STATIC 改为 Q_GLOBAL_STATIC_WITH_ARGS 用于
OrgDeepinDTKPreference 初始化
此修改为复杂的初始化参数提供了更好的类型安全性和更清晰的语法
该变更保持了相同的功能,同时遵循 Qt 推荐的静态初始化实践
2025-04-29 06:03:39 +00:00
JiDe Zhang 7c2b35ae42 feat: use dconfig2cpp for read/write the DConfig
The org.deepin.dtk.preference.json file is not in this project, so
we can't generated codes by cmake.
2025-04-25 10:03:22 +08:00
JiDe Zhang ec6fbaf651 fix: fix build on Qt 6.8
Maybe start from 6.8.1
2025-04-25 10:03:22 +08:00
Ye ShanShan d3b68df561 chore: bump version to 5.7.14
update changelog to 5.7.14
2025-04-17 13:56:22 +00:00
ComixHe 5eb6b4c403 build: compiling failed with Qt 6.9
Signed-off-by: ComixHe <heyuming@deepin.org>
2025-04-17 06:25:31 +00:00
Ye ShanShan 75208f151f chore: bump version to 5.7.13
update changelog to 5.7.13
2025-03-20 18:07:30 +08:00
Ye ShanShan 5ce8bf3755 chore: bump version to 5.7.12
update changelog to 5.7.12
2025-03-06 17:40:25 +08:00
Ye ShanShan 0a0182faac fix: palette refresh delayed in qt6
QGuiApplication::paletteChanged is deprecated in qt6,
Delay to emit themeTypeChanged signal, palette doesn't refresh
after sending ThemeChangeEvent.

pms: BUG-303929
2025-03-06 15:49:13 +08:00
jingshenghao c52610f23c feat: Add files generated by qdbusXML2cpp and DCONG2cpp
Add files generated by qdbusXML2cpp and DCONG2cpp

Log: Add files generated by qdbusXML2cpp and DCONG2cpp
2025-03-04 20:04:38 +08:00
Ye ShanShan 6cc9f8ac48 chore: bump version to 5.7.11
update changelog to 5.7.11
2025-02-27 21:05:15 +08:00
Ye ShanShan 8110fd861e chore: bump version to 5.7.10
update changelog to 5.7.10
2025-02-13 11:01:28 +00:00
Ye ShanShan 3c16e777fe fix: icon is blurry
iconSize doesn't multiplied by devicePixelRatio in pixmap,
but it's doesn't need to be in qt5.

pms:BUG-302919
2025-02-13 02:33:28 +00:00
deepin-ci-robot c0812b7af6 chore: update changelog
Release 5.7.9.
2025-01-23 09:47:46 +00:00
deepin-ci-robot b0c91b8714 chore: update changelog
Release 5.7.8.
2025-01-14 20:02:14 +08:00
zhangkun dc5aa91b44 chore: update default window corner size
The default value is 12

pms: BUG-286881
2025-01-14 07:53:30 +00:00
YeShanShan 976aa9113c fix: missing window decoration for treeland
It's exist when using DPlatformHandle by stack variable.
We save window decoration state in DTreeLandPlatformWindowHelper, and refresh them when surface created.

pms: BUG-278281
2025-01-14 13:06:43 +08:00
deepin-ci-robot b566c12e40 chore: update changelog
Release 5.7.7.
2025-01-09 18:33:34 +08:00
Felix Yan 329bf5a247 chore: correct typos about Dtk::Gui::DDciIcon::IconAttribute
Renaming enum would break ABI, but using doesn't modify ABI.

pms: BUG-368399
2025-01-09 16:17:49 +08:00
YeShanShan 7362e047b7 fix: accessing wild pointer in qt6
qobject_cast<QWindow*>(window) is returned nullptr if window is destroyed in qt6, and we can see it  on tst_QWindow::qobject_castOnDestruction() in tst_qwindow.cpp.
Object's address may be the same as before  in qt6,  memory may be optimized.

pms: BUG-299239
2025-01-09 14:29:21 +08:00
deepin-ci-robot 1ede364ac6 chore: update changelog
Release 5.7.6.
2025-01-02 06:40:54 +00:00
zhangkun e0873d04b3 fix: set font family invalid
FamilyResolved flag not set

pms: BUG-295665
2025-01-01 14:23:50 +08:00
Ye ShanShan acd947fa3e fix: iterator out of bounds for dciicon
Add check.

pms: TASK-368399
2024-12-27 10:54:13 +08:00
Ye ShanShan b152721ae8 refact: refacting DPlatformHandle to adapt treeland
Refact DPlatformHandle to update window settings.
Remove task dequeue in treeland interface when Personalization is inactive.
Add DTreeLandPlatformWindowHelper to manage windowContext.

pms: TASK-368399
2024-12-25 15:09:20 +08:00
Ye ShanShan 4bdfc69e31 Revert "refact: refacting DPlatformHandle to adap treeland"
This reverts commit e33a3945b2.
2024-12-25 15:09:20 +08:00
Ye ShanShan e33a3945b2 refact: refacting DPlatformHandle to adap treeland
Refacting DPlatformHandle to update window settings.
2024-12-24 16:39:11 +08:00
deepin-ci-robot 7871d7c448 chore: update changelog
Release 5.7.5.
2024-12-17 01:54:23 +00:00
YeShanShan df159744c6 fix: missing default windowRadius
as title.

pms: BUG-291123
2024-12-13 15:41:18 +08:00
ck 4ff3a644af fix: availableSizes not work on Qt6
Qt6 QIconEngine::availableSizes will not call
virtual_hook(QIconEngine::AvailableSizesHook
2024-12-12 09:57:50 +08:00
deepin-ci-robot 3a2792c869 chore: update changelog
Release 5.7.4.
2024-12-04 18:17:01 +08:00
ck 06dedd11df fix: nullptr check missing
add nullptr check

pms: Bug-289175
2024-12-04 09:12:38 +00:00
zhangkun 00584efe94 fix: window blur invalid
Set blur again when creating the surface

pms: BUG-278281
2024-12-03 13:22:50 +08:00
ck f5a7cc22cd fix: linglong app load qt translations failed
qt translations fallback to GenericDataLocation paths
2024-12-03 09:59:16 +08:00
Ye ShanShan 79440d4b47 fix: app crashed when window destroyed in quick
ghostVtable will be released whenever Window is destroyed by
delete or deleteLater function, we don't need to resetVtable,
and we shouldn't resetVtable when destructing m_window.

pms: BUG-368399
2024-12-02 17:44:20 +08:00
Ye ShanShan 726790ee06 fix: app crashed when window destroyed in quick
as title.

pms: BUG-368399
2024-11-30 10:23:24 +08:00
zhangkun cf97c88b76 feat: Limit maximum and minimum fonts
防止字体出现过大和过小的情况

pms: 368711
2024-11-29 15:46:18 +08:00
Ye ShanShan 76d00b0301 fix: blur is invalid for treeland
waylandWindow is empty when sometimes.
App crashed when window visibleChanged repeated.

pms: BUG-278281
2024-11-29 12:07:45 +08:00
Ye ShanShan fed4aae652 feat: support treeland platform for wmHelper
WindowManager's some interface may be deprecated, like MotifFunctions
and allWindowIdList.
and there is currently no abstraction of platform common
interfaces.

pms: BUG-287901
2024-11-27 10:42:32 +08:00
zhangkun e10215f3c1 fix: Possible null pointer dereference and Notitlebar input parameter error
as title

pms: Task-368711
2024-11-26 13:10:01 +08:00
zhangkun 16d4999f1b refactor: treeland platform theme interface
扩展Treeland的个性化接口

Log:
pms: Task-365811
2024-11-25 21:41:56 +08:00
zhangkun 1f0b9ed118 refactor: xcb platform theme interface
将DPlatformTheme中的接口抽象出来,不再写死dxcb,方便之后扩展其他平台的个性化接口

Log:
pms: Task-365811
2024-11-25 21:41:56 +08:00
kuchune b75b68a604 chore(CI): add debian check workflow
add debian check workflow

log: 增加debian检查工作流
2024-11-25 14:07:20 +08:00
deepin-ci-robot d07aca6786 chore: update changelog
Release 5.7.3.
2024-11-22 10:29:31 +08:00
wangfei 5ad7ed1ce8 fix: can't drag scrollbar in window under treeland
add the logic about moving window from platform plugin

Log: as title.
pms: BUG-284215
2024-11-22 09:33:48 +08:00
Yutao Meng de728b0bee fix: Supporting window blury effect under Treeland
pms:
BUG-278197
BUG-278281
BUG-284681
Log: Supporting window blury effect under Treeland
2024-11-21 12:17:38 +00:00
zhangkun d435f92784 fix: No judgment on the validity of the protocol
Determine whether the protocol is registered

Bug: https://pms.uniontech.com/bug-view-286859.html
2024-11-18 19:03:17 +08:00
deepin-ci-robot 43624a42e9 chore: update changelog
Release 5.7.2.
2024-11-15 13:47:25 +08:00
wangfei b975592ce1 chore: add the ActiveColorDark setting
get the active color according to system theme(light or dark).
There are two different active colors between light and dark theme.

Log:
2024-11-13 13:09:30 +08:00
wangfei f0a7d5d44d chore: highlight color is inconsistency
remove the operation that reduces lightness of active color in dark theme

Log:
2024-11-11 15:12:57 +08:00
ck a0398d03d5 chore: add IsWaylandPlatform attribute
only test platformName == wayland
2024-11-08 13:56:17 +08:00
Yutao Meng a407dc4032 fix: Print "load translate" debug log to channels
Avoid printing such logs to terminal

Bug: https://pms.uniontech.com/bug-view-284539.html
Log: Print "load translate" debug log to channels
2024-11-07 08:47:36 +00:00
zhangkun 255f171e9f fix: Under treeland, the dialog has not disabled titlebar
The same application only called the protocol once before

https://pms.uniontech.com/task-view-365811.html
2024-11-07 11:15:14 +08:00
zhangkun 525beab369 chore: Correct the name of TreelandProtocols package in cmake
As title

Log: https://pms.uniontech.com/task-view-365811.html
2024-11-04 09:44:26 +08:00
deepin-ci-robot 231c29ac65 chore: update changelog
Release 5.7.1.
2024-10-31 10:25:12 +08:00
ck 6038e6fcf8 chore: config dtk animations
set/unset `D_DTK_DISABLE_ANIMATIONS` according to the dconfig
2024-10-25 15:30:29 +08:00
zhangkun 316a3e741c feat: Add compile test
- Add compile test for treeland
- fix reuse

Log:
2024-10-24 15:15:35 +08:00
zhangkun 806457e8bc feat: Adapt to TreeLand's Titlebar protocol
Resolve the issues of DTK application crashing and dual title bar in treeland.

Log: Adapt to TreeLand's Titlebar protocol
Task: https://pms.uniontech.com/task-view-365811.html
2024-10-21 15:59:26 +08:00
Hillwood Yang b25353026b feat: Support Qt 6.8
Log: Fix build on Qt 6.8
2024-10-21 10:31:12 +08:00
Ye ShanShan 8cf037d44b fix: app crashed in x11
Missing check for Treeland.

TODO: CreatorWindowEventFile should distinguish between X11 and
Treeland.
2024-08-30 19:32:02 +08:00
Zhang Dingyuan af9a6fc359 chore: add dtkgui namespace
as title

Log:
2024-08-29 13:25:29 +08:00
Zhang Dingyuan 2dae5b2e82 chore: add extra cmake modules
as title

Log:
2024-08-29 13:25:29 +08:00
Zhang Dingyuan 7a49e9c164 chore: update license
update reuse

Log:
2024-08-29 13:25:29 +08:00
Zhang Dingyuan b2c91d0c2e chore: add build dep
as title

Log:
2024-08-29 13:25:29 +08:00
Zhang Dingyuan 4fb86c1204 chore: update license info
as title

Log:
2024-08-29 13:25:29 +08:00
Zhang Dingyuan afe212871f feat: add fixme note
I have no idea

Log:
2024-08-29 13:25:29 +08:00
Zhang Dingyuan 3a6a15b9f2 fix: remove treeland personalization protocols useless function
remove set_resizable and set_movable

Log:
2024-08-29 13:25:29 +08:00
Zhang Dingyuan c227e1adce fix: cannot move window on wayland
code from deepin platform plugin

Log:
2024-08-29 13:25:29 +08:00
Zhang Dingyuan 9c99626771 feat: support qt5 and qt6
as title

Log:
2024-08-29 13:25:29 +08:00
wangfei 6f375cfc0c feat: Add notitlebar function on wayland platform
add notitlebar function on wayland platform

Log: add notitlebar function on wayland platform
2024-08-29 13:25:29 +08:00
zhangkun 7ec030f0b9 Revert "feat: add close.dci"
This reverts commit 12b60a3c8a.

Issue: https://github.com/linuxdeepin/developer-center/issues/10482
2024-08-23 15:13:18 +08:00
94 changed files with 6332 additions and 1009 deletions

13
.github/workflows/call-api-check.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: apiCheck
on:
pull_request_target:
types: [opened, synchronize, reopened]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
api-check:
uses: linuxdeepin/.github/.github/workflows/api-check.yml@master
secrets: inherit

50
.github/workflows/call-auto-release.yml vendored Normal file
View File

@ -0,0 +1,50 @@
name: Auto Release
on:
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g., 1.0.0)'
type: string
required: false
name:
description: 'The name of the person to release the version'
type: string
required: false
email:
description: 'The email of the person to release the version'
type: string
required: false
timezone:
description: 'The timezone in the debian changelog file'
required: false
type: string
default: 'Asia/Shanghai'
workflow_call:
inputs:
version:
description: 'Release version (e.g., 1.0.0)'
type: string
required: true
name:
description: 'The name of the person to release the version'
type: string
required: false
email:
description: 'The email of the person to release the version'
type: string
required: false
timezone:
description: 'The timezone in the debian changelog file'
required: false
type: string
default: 'Asia/Shanghai'
jobs:
auto_release:
uses: linuxdeepin/.github/.github/workflows/auto-release.yml@master
secrets: inherit
with:
version: ${{ inputs.version }}
name: ${{ inputs.name }}
email: ${{ inputs.email }}
timezone: ${{ inputs.timezone }}

13
.github/workflows/call-debian-check.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: debianCheck
on:
pull_request_target:
types: [opened, synchronize, reopened]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
debian-check:
uses: linuxdeepin/.github/.github/workflows/debian-check.yml@master
secrets: inherit

13
.github/workflows/call-static-check.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: staticCheck
on:
pull_request_target:
types: [opened, synchronize, reopened]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
static-check:
uses: linuxdeepin/.github/.github/workflows/static-check.yml@master
secrets: inherit

View File

@ -34,7 +34,7 @@ Copyright: None
License: LGPL-3.0-or-later
# README
Files: *README.md *README.zh_CN.md
Files: *README.md *README.zh_CN.md CHANGELOG.md
Copyright: None
License: CC-BY-4.0
@ -49,7 +49,7 @@ Copyright: None
License: CC0-1.0
# Project file
Files: *.pro *.prf *.pri *.qrc *CMakeLists.txt *.cmake *.in
Files: *.pro *.prf *.pri *.qrc *CMakeLists.txt *.cmake *.in VERSION
Copyright: None
License: CC0-1.0
@ -58,3 +58,11 @@ Files: src/util/icons/actions/* src/util/icons/icons/* src/util/icons/texts/*
src/util/icons/dci/* tests/images/* tests/actions/* tests/dcis/* examples/animation-dci/*
Copyright: UnionTech Software Technology Co., Ltd.
License: LGPL-3.0-or-later
Files: toolGenerate/**/*
Copyright: None
License: CC0-1.0
Files: src/kernel/orgdeepindtkpreference.hpp
Copyright: None
License: CC0-1.0

View File

@ -9,3 +9,5 @@
# are always ignored
linglong.yaml
conanfile.py
VERSION
CHANGELOG.md

97
CHANGELOG.md Normal file
View File

@ -0,0 +1,97 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [5.7.25] - 2025-10-30
### Changed
- Improve icon theme generation with scalable support
## [5.7.24] - 2025-10-16
### Added
- Support Qt 6.10
### Changed
- Improve icon size detection and duplicate handling
### Fixed
- Correct lockfile path construction
- Fix Qt6 compilation error with libxdg
## [5.7.23] - 2025-09-25
### Fixed
- 解决控制中心闪烁问题
- Fix build for Qt 6.9
## [5.7.22] - 2025-09-04
### Added
- Add T11 font size and adjust T5 default
### Fixed
- Improve PID namespace detection in setSingleInstance
## [5.7.21] - 2025-08-14
### Added
- Add flags parameter to DDciIconPlayer play method
### Fixed
- Resolve compilation warnings and deprecation issues
## [5.7.20] - 2025-07-31
### Added
- Add pid namespace isolation to setSingleInstance
- Add concurrent processing for DCI icon conversion
### Changed
- Update REUSE license file for CHANGELOG
- Move icon finder functionality to separate tool
- Switch to QGuiApplication for SVG rendering
## [5.7.19] - 2025-07-03
### Fixed
- Enhance build security hardening
## [5.7.18] - 2025-06-27
### Fixed
- Make version parameter optional in release workflow
## [5.7.17] - 2025-06-19
### Added
- Add missing header
- Fix: add missing prefix for QTranslator::load()
### Changed
- Chore: use another QTranslator::load overload to tidy code
- Support VERSION file
- Add auto release workflow
- Update .syncexclude
[5.7.17]: https://github.com/linuxdeepin/dtkgui/compare/5.7.16..5.7.17
<!-- generated by git-cliff -->

View File

@ -1,6 +1,8 @@
cmake_minimum_required(VERSION 3.25)
set(DTK_VERSION "5.6.11" CACHE STRING "define project version")
file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" DTK_FILE_VERSION)
string(STRIP "${DTK_FILE_VERSION}" DTK_FILE_VERSION)
set(DTK_VERSION "${DTK_FILE_VERSION}" CACHE STRING "define project version")
project(DtkGui
VERSION ${DTK_VERSION}
DESCRIPTION "DTK Gui module"

1
VERSION Normal file
View File

@ -0,0 +1 @@
5.7.25

1
VERSION.in Normal file
View File

@ -0,0 +1 @@
@version@

View File

@ -1,6 +1,6 @@
# Maintainer: justforlxz <justforlxz@gmail.com>
pkgname=dtkgui-git
pkgver=5.5.22.r8.g6ef1509
pkgver=5.7.25
pkgrel=1
sourcename=dtkgui
sourcetars=("$sourcename"_"$pkgver".tar.xz)
@ -9,10 +9,10 @@ pkgdesc='Deepin Toolkit, gui module for DDE look and feel'
arch=('x86_64' 'aarch64')
url="https://github.com/linuxdeepin/dtkgui"
license=('LGPL3')
depends=('dtkcore-git' 'dtkcommon-git' 'qt5-svg' 'libqtxdg' 'freeimage' 'librsvg')
depends=('dtkcore-git' 'dtkcommon-git' 'qt5-svg' 'libqtxdg' 'freeimage' 'librsvg' 'qt5-wayland')
# INFO: you can disable freeimage not to support RAW images
# Then set DTK_DISABLE_EX_IMAGE_FORMAT=OFF
makedepends=('git' 'qt5-tools' 'gtest' 'gmock' 'ninja' 'cmake' 'doxygen')
makedepends=('git' 'qt5-tools' 'gtest' 'gmock' 'ninja' 'cmake' 'doxygen' 'extra-cmake-modules')
conflicts=('dtkgui')
provides=('dtkgui')
groups=('deepin-git')

189
debian/changelog vendored
View File

@ -1,3 +1,192 @@
dtkgui (5.7.25) unstable; urgency=medium
* Release 5.7.25
-- yeshanshan <yeshanshan@uniontech.com> Thu, 30 Oct 2025 21:47:33 +0800
dtkgui (5.7.24) unstable; urgency=medium
* Release 5.7.24
-- yeshanshan <yeshanshan@uniontech.com> Thu, 16 Oct 2025 19:45:30 +0800
dtkgui (5.7.23) unstable; urgency=medium
* Release 5.7.23
-- yeshanshan <packages@deepin.org> Thu, 25 Sep 2025 16:49:18 +0800
dtkgui (5.7.22) unstable; urgency=medium
* Release 5.7.22
-- yeshanshan <yeshanshan@uniontech.com> Thu, 04 Sep 2025 19:27:38 +0800
dtkgui (5.7.21) unstable; urgency=medium
* Release 5.7.21
-- yeshanshan <packages@deepin.org> Thu, 14 Aug 2025 19:47:40 +0800
dtkgui (5.7.20) unstable; urgency=medium
* Release 5.7.20
-- yeshanshan <yeshanshan@uniontech.com> Thu, 31 Jul 2025 19:59:35 +0800
dtkgui (5.7.19) unstable; urgency=medium
* Release 5.7.19
-- yeshanshan <yeshanshan@uniontech.com> Thu, 03 Jul 2025 21:12:27 +0800
dtkgui (5.7.18) unstable; urgency=medium
* Release 5.7.18
-- yeshanshan <yeshanshan@uniontech.com> Fri, 27 Jun 2025 17:09:35 +0800
dtkgui (5.7.17) unstable; urgency=medium
* Release 5.7.17
-- yeshanshan <yeshanshan@uniontech.com> Thu, 19 Jun 2025 10:03:48 +0800
dtkgui (5.7.16) unstable; urgency=medium
* Release 5.7.16
-- YeShanShan <yeshanshan@uniontech.com> Mon, 19 May 2025 17:21:59 +0800
dtkgui (5.7.15) unstable; urgency=medium
* fix: correct bitwise operation in preference handling
* fix: prevent theme saving when DontSaveApplicationTheme is set
* refactor: improve thread safety in OrgDeepinDTKPreference
* fix: build failed in qt5
* feat: use dconfig2cpp for read/write the DConfig
* fix: fix build on Qt 6.8
-- YeShanShan <yeshanshan@uniontech.com> Thu, 08 May 2025 17:53:09 +0800
dtkgui (5.7.14) unstable; urgency=medium
* build: compiling failed with Qt 6.9
-- YeShanShan <yeshanshan@uniontech.com> Thu, 17 Apr 2025 21:51:32 +0800
dtkgui (5.7.13) unstable; urgency=medium
* Release 5.7.13
-- YeShanShan <yeshanshan@uniontech.com> Thu, 20 Mar 2025 17:05:55 +0800
dtkgui (5.7.12) unstable; urgency=medium
* fix: palette refresh delayed in qt6
* feat: Add files generated by qdbusXML2cpp and DCONG2cpp
-- YeShanShan <yeshanshan@uniontech.com> Thu, 06 Mar 2025 17:29:35 +0800
dtkgui (5.7.11) unstable; urgency=medium
* Release 5.7.11
-- YeShanShan <yeshanshan@uniontech.com> Thu, 27 Feb 2025 20:47:39 +0800
dtkgui (5.7.10) unstable; urgency=medium
* fix: icon is blurry
-- YeShanShan <yeshanshan@uniontech.com> Thu, 13 Feb 2025 17:18:19 +0800
dtkgui (5.7.9) unstable; urgency=medium
[ root ]
* UNRELEASED
-- Deepin Packages Builder <packages@deepin.org> Thu, 23 Jan 2025 09:07:08 +0000
dtkgui (5.7.8) unstable; urgency=medium
* fix: missing window decoration for treeland
* chore: update default window corner size
-- Deepin Packages Builder <packages@deepin.org> Tue, 14 Jan 2025 11:17:31 +0000
dtkgui (5.7.7) unstable; urgency=medium
* fix: accessing wild pointer in qt6
* chore: correct typos about Dtk::Gui::DDciIcon::IconAttribute
Thanks to Felix Yan
-- Deepin Packages Builder <packages@deepin.org> Thu, 09 Jan 2025 09:28:38 +0000
dtkgui (5.7.6) unstable; urgency=medium
* refact: refacting DPlatformHandle to adap treeland
* Revert "refact: refacting DPlatformHandle to adap treeland"
* refact: refacting DPlatformHandle to adapt treeland
* fix: iterator out of bounds for dciicon
* fix: set font family invalid
-- Deepin Packages Builder <packages@deepin.org> Thu, 02 Jan 2025 05:43:53 +0000
dtkgui (5.7.5) unstable; urgency=medium
* fix: availableSizes not work on Qt6
-- Deepin Packages Builder <packages@deepin.org> Thu, 12 Dec 2024 03:03:53 +0000
dtkgui (5.7.4) unstable; urgency=medium
* chore(CI): add debian check workflow
Thanks to kuchune
* refactor: xcb platform theme interface
* refactor: treeland platform theme interface 扩展Treeland的个性化接口
* fix: Possible null pointer dereference and Notitlebar input parameter error
* feat: support treeland platform for wmHelper
* fix: blur is invalid for treeland
* feat: Limit maximum and minimum fonts
* fix: app crashed when window destroyed in quick
* fix: app crashed when window destroyed in quick
* fix: linglong app load qt translations failed
-- Deepin Packages Builder <packages@deepin.org> Tue, 03 Dec 2024 02:00:46 +0000
dtkgui (5.7.3) unstable; urgency=medium
* fix: No judgment on the validity of the protocol(Bug: 286859)
-- Deepin Packages Builder <packages@deepin.org> Wed, 20 Nov 2024 02:19:06 +0000
dtkgui (5.7.2) unstable; urgency=medium
* chore: Correct the name of TreelandProtocols package in cmake
* fix: Under treeland, the dialog has not disabled titlebar
* fix: Print "load translate" debug log to channels(Bug: 284539)
* chore: add IsWaylandPlatform attribute
* chore: highlight color is inconsistency
-- Deepin Packages Builder <packages@deepin.org> Wed, 13 Nov 2024 01:53:26 +0000
dtkgui (5.7.1) unstable; urgency=medium
* Revert "feat: add close.dci"(Issue: https://github.com/linuxdeepin/developer-center/issues/10482)
* feat: Add notitlebar function on wayland platform
* feat: support qt5 and qt6
* fix: cannot move window on wayland
* fix: remove treeland personalization protocols useless function
* feat: add fixme note
* chore: update license info
* chore: add build dep
* chore: update license
* chore: add extra cmake modules
* chore: add dtkgui namespace
* fix: app crashed in x11
-- Deepin Packages Builder <packages@deepin.org> Wed, 16 Oct 2024 03:30:46 +0000
dtkgui (5.6.34) unstable; urgency=medium
* feat: add close.dci

5
debian/control vendored
View File

@ -2,10 +2,11 @@ Source: dtkgui
Section: libdevel
Priority: optional
Maintainer: Deepin Packages Builder <packages@deepin.com>
Build-Depends: debhelper-compat (= 12), pkg-config,
Build-Depends: debhelper-compat (= 12), pkg-config,
qtbase5-private-dev, qtbase5-dev-tools, doxygen, graphviz, qttools5-dev,
libdtkcore-dev, librsvg2-dev, libfreeimage-dev, libraw-dev, libgtest-dev, libgmock-dev,
libqt5xdg-dev, libqt5xdgiconloader-dev, cmake, qt5-image-formats-plugins
libqt5xdg-dev, libqt5xdgiconloader-dev, cmake, qt5-image-formats-plugins, libqt5waylandclient5-dev,
extra-cmake-modules, qtwayland5-dev-tools, qtwayland5-private-dev, libkf5wayland-dev, treeland-protocols
Standards-Version: 3.9.8
Package: libdtkgui5

6
debian/rules vendored
View File

@ -3,6 +3,12 @@ DPKG_EXPORT_BUILDFLAGS = 1
include /usr/share/dpkg/default.mk
export QT_SELECT = qt5
# 安全编译参数
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
export DEB_CFLAGS_MAINT_APPEND = -Wall
export DEB_CXXFLAGS_MAINT_APPEND = -Wall
export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -Wl,-E
DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
VERSION = $(DEB_VERSION_UPSTREAM)

View File

@ -223,7 +223,7 @@ cmake --build build
| Light | 0 |
| Dark | 1 |
@enum Dtk::Gui::DDciIcon::IconAttibute
@enum Dtk::Gui::DDciIcon::IconAttribute
@brief DCI图标属性
@details
| 键 | 值 |
@ -282,7 +282,7 @@ cmake --build build
@param[in] theme 图标主题
@param[in] mode 图标模式默认为Normal
@fn bool Dtk::Gui::DDciIcon::isSupportedAttribute(DDciIconMatchResult result, IconAttibute attr)
@fn bool Dtk::Gui::DDciIcon::isSupportedAttribute(DDciIconMatchResult result, IconAttribute attr)
@brief 判断DCI图标是否支持指定属性
@param[in] result DCI图标匹配结果
@param[in] attr 图标属性

View File

@ -171,6 +171,11 @@
@details 为指定的图标模式计算要显示的内容,这可能会导致 currentImage 发生变化。这是个一次性行为,不会影响下一次调用 setMode 后的结果。
@param[in] mode 指定要播放的图标模式,如果此模式支持动画,会触发此模式自身的动画播放(与 setMode 导致的动画不同的是,此动画不涉及两种模式变化时的过渡规则),否则将修改 currentImage 为此模式对应的静态图片资源。
@fn Dtk::Gui::DDciIconPlayer::play(DDciIcon::Mode mode, DDciIconImagePlayer::Flags flags)
@details 为指定的图标模式和播放参数计算要显示的内容。
@param[in] mode 指定要播放的图标模式。
@param[in] flags 播放参数
@fn Dtk::Gui::DDciIconPlayer::stop()
@details 如果当前正在播放动画,则停止当前动画的播放,但不会影响队列中下一个动画的播放。可能会导致 DDciIconPlayer::state 发生变化。
@sa DDciIconPlayer::abort

View File

@ -18,11 +18,6 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Set build option
option(DTK_DISABLE_LIBXDG "Disable libxdg" OFF)
find_package(Qt${QT_VERSION_MAJOR}XdgIconLoader)
if (NOT Qt${QT_VERSION_MAJOR}XdgIconLoader_FOUND)
message(WARNING " XdgIconLoader Not Found, DISABLE LIBXDG !")
set (DTK_DISABLE_LIBXDG ON)
endif()
option(DTK_DISABLE_LIBRSVG "Disable librsvg" OFF)
option(DTK_DISABLE_EX_IMAGE_FORMAT "Disable libraw and freeimage" OFF)
@ -43,7 +38,6 @@ set(CONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/Dtk${DTK_VERSION_MAJOR}Gui
set(PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall -Wextra -fopenmp")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--as-needed")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie")
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
set(BUILD_TESTING ON)
@ -121,6 +115,19 @@ find_package(Dtk${DTK_VERSION_MAJOR} REQUIRED Core)
find_package(DtkBuildHelper REQUIRED)
pkg_check_modules(librsvg REQUIRED IMPORTED_TARGET librsvg-2.0)
if(NOT DTK_DISABLE_LIBXDG)
# Only use libxdg under Qt5
if (${QT_VERSION_MAJOR} STREQUAL "5")
find_package(Qt5XdgIconLoader REQUIRED)
if (NOT Qt5XdgIconLoader_FOUND)
message(WARNING " XdgIconLoader Not Found, DISABLE LIBXDG !")
set (DTK_DISABLE_LIBXDG ON)
endif()
else()
set (DTK_DISABLE_LIBXDG ON)
endif()
endif()
# Check optional image handler dependencies.
find_package(FreeImage)
pkg_check_modules(libraw IMPORTED_TARGET libraw)

View File

@ -59,7 +59,10 @@ public:
IsXWindowPlatform = ReadOnlyLimit << 2,
IsTableEnvironment = ReadOnlyLimit << 3,
IsDeepinEnvironment = ReadOnlyLimit << 4,
IsSpecialEffectsEnvironment = ReadOnlyLimit << 5
IsSpecialEffectsEnvironment = ReadOnlyLimit << 5,
IsWaylandPlatform = ReadOnlyLimit << 6,
IsTreelandPlatform Q_DECL_ENUMERATOR_DEPRECATED_X("Use DGuiApplicationHelper::IsWaylandPlatform instead") = IsWaylandPlatform,
HasAnimations = ReadOnlyLimit << 7,
};
Q_ENUM(Attribute)
Q_DECLARE_FLAGS(Attributes, Attribute)
@ -121,6 +124,7 @@ public:
static QStringList userManualPaths(const QString &appName);
bool hasUserManual() const;
static bool loadTranslator(const QString &fileName, const QString &appName, const QList<QLocale> &localeFallback = QList<QLocale>() << QLocale::system());
static bool loadTranslator(const QString &fileName, const QList<QString> &translateDirs, const QList<QLocale> &localeFallback);
static bool loadTranslator(const QList<QLocale> &localeFallback = QList<QLocale>() << QLocale::system());

View File

@ -19,7 +19,7 @@ class QWindow;
QT_END_NAMESPACE
DGUI_BEGIN_NAMESPACE
// TODO: class DPlatformHandle will be removed in the future
class DPlatformHandle : public QObject
{
Q_OBJECT
@ -44,6 +44,7 @@ class DPlatformHandle : public QObject
public:
explicit DPlatformHandle(QWindow *window, QObject *parent = 0);
~DPlatformHandle();
static QString pluginVersion();
static bool isDXcbPlatform();

View File

@ -13,6 +13,7 @@
DGUI_BEGIN_NAMESPACE
class DPlatformThemePrivate;
// TODO: class DPlatformTheme will be removed in the future
class DPlatformTheme : public DNativeSettings
{
Q_OBJECT
@ -35,6 +36,7 @@ class DPlatformTheme : public DNativeSettings
Q_PROPERTY(QByteArray gtkFontName READ gtkFontName WRITE setGtkFontName NOTIFY gtkFontNameChanged)
Q_PROPERTY(QColor activeColor READ activeColor WRITE setActiveColor NOTIFY activeColorChanged)
Q_PROPERTY(QColor darkActiveColor READ darkActiveColor WRITE setDarkActiveColor NOTIFY darkActiveColorChanged)
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
// QPalette
Q_PROPERTY(QColor window READ window WRITE setWindow NOTIFY windowChanged)
@ -101,6 +103,7 @@ public:
QByteArray gtkFontName() const;
QColor activeColor() const;
QColor darkActiveColor() const;
bool isValidPalette() const;
@ -152,6 +155,7 @@ public Q_SLOTS:
void setFontPointSize(qreal fontPointSize);
void setGtkFontName(const QByteArray &fontName);
void setActiveColor(const QColor activeColor);
void setDarkActiveColor(const QColor &activeColor);
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
void setWindow(const QColor &window);
void setWindowText(const QColor &windowText);
@ -201,6 +205,7 @@ Q_SIGNALS:
void fontPointSizeChanged(qreal fontPointSize);
void gtkFontNameChanged(QByteArray fontName);
void activeColorChanged(QColor activeColor);
void darkActiveColorChanged(QColor activeColor);
void paletteChanged(DPalette palette);
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
void windowChanged(QColor window);
@ -238,9 +243,6 @@ Q_SIGNALS:
private:
friend class DPlatformThemePrivate;
private:
D_PRIVATE_SLOT(void _q_onThemePropertyChanged(const QByteArray &name, const QVariant &value))
};
DGUI_END_NAMESPACE

View File

@ -77,9 +77,11 @@ public:
Light = 0,
Dark = 1
};
// IconAttibute is deprecated, please use IconAttribute instead.
enum IconAttibute {
HasPalette = 0x001
};
using IconAttribute = DDciIcon::IconAttibute;
enum IconMatchedFlag {
None = 0,
DontFallbackMode = 0x01,
@ -106,8 +108,8 @@ public:
int actualSize(int size, Theme theme, Mode mode = Normal) const;
QList<int> availableSizes(Theme theme, Mode mode = Normal) const;
bool isSupportedAttribute(DDciIconMatchResult result, IconAttibute attr) const;
static bool isSupportedAttribute(const DDciIconImage &image, IconAttibute attr);
bool isSupportedAttribute(DDciIconMatchResult result, IconAttribute attr) const;
static bool isSupportedAttribute(const DDciIconImage &image, IconAttribute attr);
QPixmap pixmap(qreal devicePixelRatio, int iconSize, Theme theme, Mode mode = Normal,
const DDciIconPalette &palette = DDciIconPalette()) const;

View File

@ -106,6 +106,7 @@ public:
QImage currentImage() const;
void play(DDciIcon::Mode mode);
void play(DDciIcon::Mode mode, DDciIconImagePlayer::Flags flags);
void stop();
void abort();

View File

@ -44,6 +44,7 @@ public:
T8,
T9,
T10,
T11,
NSizeTypes
};
Q_ENUM(SizeType)
@ -110,6 +111,10 @@ public:
{
return get(T10);
}
inline const QFont t11() const
{
return get(T11);
}
Q_SIGNALS:
void fontChanged();

View File

@ -1,5 +1,5 @@
Name: dtkgui
Version: 5.5.17
Version: 5.7.25
Release: 1%{?dist}
Summary: Deepin dtkgui
License: LGPLv3+

View File

@ -1,3 +1,14 @@
if("${QT_VERSION_MAJOR}" STREQUAL "6")
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets WaylandClient)
if (${Qt6Core_VERSION} VERSION_GREATER_EQUAL "6.10.0")
set(QT_NO_PRIVATE_MODULE_WARNING ON)
find_package(Qt6 REQUIRED COMPONENTS CorePrivate GuiPrivate WaylandClientPrivate)
endif()
else()
find_package(Qt5 REQUIRED COMPONENTS WaylandClient XkbCommonSupport)
endif()
add_library(${LIB_NAME} SHARED)
include(dbus/dbus.cmake)
@ -5,6 +16,7 @@ include(filedrag/dfiledrag.cmake)
include(kernel/kernel.cmake)
include(private/private.cmake)
include(util/util.cmake)
include(plugins/plugins.cmake)
target_sources(${LIB_NAME} PRIVATE
${dbus_SRC}
@ -34,8 +46,16 @@ PRIVATE
Qt${QT_VERSION_MAJOR}::GuiPrivate
Qt${QT_VERSION_MAJOR}::CorePrivate
Qt${QT_VERSION_MAJOR}::DBus
Qt${QT_VERSION_MAJOR}::WaylandClientPrivate
)
if("${QT_VERSION_MAJOR}" STREQUAL "5")
target_link_libraries(${LIB_NAME}
PRIVATE
Qt${QT_VERSION_MAJOR}::XkbCommonSupportPrivate
)
endif()
if(DTK_DISABLE_LIBRSVG)
find_package(Qt${QT_VERSION_MAJOR}Svg REQUIRED)
target_link_libraries(${LIB_NAME} PRIVATE Qt${QT_VERSION_MAJOR}::Svg)

View File

@ -5,8 +5,10 @@
#include "dguiapplicationhelper.h"
#include "private/dguiapplicationhelper_p.h"
#include "dplatformhandle.h"
#include <DFontManager>
#include <DStandardPaths>
#include <DSGApplication>
#include <QHash>
#include <QColor>
@ -24,6 +26,7 @@
#include <QDirIterator>
#include <QDesktopServices>
#include <QLibraryInfo>
#include <QTimer>
#ifdef Q_OS_UNIX
#include <QDBusError>
@ -33,7 +36,6 @@
#include <QDBusConnection>
#include <QDBusConnectionInterface>
#include <QProcess>
#include <DConfig>
#endif
#include <QDir>
#include <QLockFile>
@ -57,9 +59,13 @@
#include <qpa/qplatformtheme.h>
#ifdef Q_OS_LINUX
#include <pwd.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#include "orgdeepindtkpreference.hpp"
#ifdef Q_OS_UNIX
class EnvReplaceGuard
{
@ -114,8 +120,9 @@ Q_GLOBAL_STATIC(DFontManager, _globalFM)
#define WINDOW_THEME_KEY "_d_platform_theme"
#define APP_THEME_TYPE "themeType"
Q_GLOBAL_STATIC_WITH_ARGS(DTK_CORE_NAMESPACE::DConfig, _d_dconfig, ("org.deepin.dtk.preference"));
#define DTK_ANIMATIONS_ENV "D_DTK_DISABLE_ANIMATIONS"
Q_GLOBAL_STATIC_WITH_ARGS(OrgDeepinDTKPreference, _d_dconfig, (DTK_CORE_NAMESPACE::DConfig::globalThread(), nullptr,
"org.deepin.dtk.preference", DTK_CORE_NAMESPACE::DSGApplication::id(), {}, false, nullptr))
/*!
@private
@ -205,11 +212,18 @@ public:
}
virtual bool eventFilter(QObject *watched, QEvent *event) override
{
if (watched != qApp)
return QObject::eventFilter(watched, event);
switch(event->type()) {
case QEvent::ApplicationFontChange: {
const QFont font(qGuiApp->font());
m_transmitter->q_func()->fontChanged(font);
} break;
case QEvent::ApplicationPaletteChange: {
m_transmitter->onApplicationPaletteChanged();
break;
}
default:
break;
}
@ -266,11 +280,10 @@ void DGuiApplicationHelperPrivate::initApplication(QGuiApplication *app)
app->installEventFilter(new GuiApplicationEventFilter(this, app));
#else
q->connect(app, &QGuiApplication::fontChanged, q, &DGuiApplicationHelper::fontChanged);
#endif
// TODO handle event in qt6.
q->connect(app, &QGuiApplication::paletteChanged, q, [this] {
onApplicationPaletteChanged();
});
#endif
if (Q_UNLIKELY(!appTheme)) { // 此时说明appTheme可能已经被初始化为了systemtheme
if (QGuiApplicationPrivate::is_app_running) {
@ -309,7 +322,7 @@ DPlatformTheme *DGuiApplicationHelperPrivate::initWindow(QWindow *window) const
window->setProperty(WINDOW_THEME_KEY, QVariant::fromValue(theme));
theme->setParent(window); // 跟随窗口销毁
auto onWindowThemeChanged = [window, theme, this] {
auto onWindowThemeChanged = [window, this] {
// 如果程序自定义了调色板, 则没有必要再关心窗口自身平台主题的变化
// 需要注意的是, 这里的信号和事件可能会与 notifyAppThemeChanged 中的重复
// 但是不能因此而移除这里的通知, 当窗口自身所对应的平台主题发生变化时, 这里
@ -343,10 +356,19 @@ void DGuiApplicationHelperPrivate::_q_initApplicationTheme(bool notifyChange)
// 监听与程序主题相关的改变
QObject::connect(appTheme, &DPlatformTheme::themeNameChanged, app, onAppThemeChanged);
QObject::connect(appTheme, &DPlatformTheme::paletteChanged, app, onAppThemeChanged);
QObject::connect(appTheme, &DPlatformTheme::activeColorChanged, app, [this] {
QTimer *timer = new QTimer(app);
timer->setInterval(100);
timer->setSingleShot(true);
QObject::connect(timer, &QTimer::timeout, timer, [this] {
if (!appPalette)
notifyAppThemeChanged();
});
QObject::connect(appTheme, &DPlatformTheme::activeColorChanged, app, [timer]{
timer->start();
});
QObject::connect(appTheme, &DPlatformTheme::darkActiveColorChanged, app, [timer] {
timer->start();
});
// appTheme在此之前可能由systemTheme所代替被使用此时在创建appTheme
// 并初始化之后,应当发送信号通知程序主题的改变
@ -359,16 +381,23 @@ void DGuiApplicationHelperPrivate::notifyAppThemeChanged()
{
D_Q(DGuiApplicationHelper);
notifyAppThemeChangedByEvent();
// 通知主题类型发生变化, 此处可能存在误报的行为, 不过不应该对此做额外的约束
// 此信号的行为应当等价于 applicationPaletteChanged
Q_EMIT q->themeTypeChanged(q->themeType());
// 通知调色板对象的改变
Q_EMIT q->applicationPaletteChanged();
QMetaObject::invokeMethod(q, [q] () {
// 通知主题类型发生变化, 此处可能存在误报的行为, 不过不应该对此做额外的约束
// 此信号的行为应当等价于 applicationPaletteChanged
Q_EMIT q->themeTypeChanged(q->themeType());
// 通知调色板对象的改变
Q_EMIT q->applicationPaletteChanged();
}, Qt::QueuedConnection);
}
void DGuiApplicationHelperPrivate::notifyAppThemeChangedByEvent()
{
// https://github.com/qt/qtbase/commit/68a9c5fe513e147e4cffd29b50a4714813df411e
#if QT_VERSION >= QT_VERSION_CHECK(6, 10, 0)
QWindowSystemInterfacePrivate::ThemeChangeEvent event;
#else
QWindowSystemInterfacePrivate::ThemeChangeEvent event(nullptr);
#endif
// 此事件会促使QGuiApplication重新从QPlatformTheme中获取系统级别的QPalette.
// 而在deepin平台下, 系统级别的QPalette来源自 \a applicationPalette()
QGuiApplicationPrivate::processThemeChanged(&event);
@ -425,19 +454,19 @@ void DGuiApplicationHelperPrivate::initPaletteType() const
return;
auto applyThemeType = [this](bool emitSignal){
int ct = _d_dconfig->value(APP_THEME_TYPE, DGuiApplicationHelper::UnknownType).toInt();
int ct = _d_dconfig->themeType();
if (ct > DGuiApplicationHelper::DarkType || ct < DGuiApplicationHelper::UnknownType)
ct = DGuiApplicationHelper::UnknownType;
const_cast<DGuiApplicationHelperPrivate *>(this)->setPaletteType(DGuiApplicationHelper::ColorType(ct), emitSignal);
};
applyThemeType(false);
QObject::connect(_d_dconfig, &DConfig::valueChanged, _d_dconfig, [applyThemeType](const QString &key){
if (key != APP_THEME_TYPE)
return;
// 读取配置文件中的主题类型并立即应用
DTK_CORE_NAMESPACE::DConfig dconfig("org.deepin.dtk.preference");
int ct = dconfig.value("themeType", DGuiApplicationHelper::UnknownType).toInt();
const_cast<DGuiApplicationHelperPrivate *>(this)->setPaletteType(DGuiApplicationHelper::ColorType(ct), false);
QObject::connect(_d_dconfig.operator ()(), &OrgDeepinDTKPreference::themeTypeChanged, _d_dconfig, [applyThemeType] {
applyThemeType(true);
});
}
@ -485,13 +514,13 @@ DGuiApplicationHelper::SizeMode DGuiApplicationHelperPrivate::fetchSizeMode(bool
/*!
\enum DGuiApplicationHelper::ColorType
DGuiApplicationHelper::ColorType .
\var DGuiApplicationHelper::ColorType DGuiApplicationHelper::UnknownType
()
\var DGuiApplicationHelper::ColorType DGuiApplicationHelper::LightType
\var DGuiApplicationHelper::ColorType DGuiApplicationHelper::DarkType
*/
@ -499,28 +528,28 @@ DGuiApplicationHelper::SizeMode DGuiApplicationHelperPrivate::fetchSizeMode(bool
/*!
\enum DGuiApplicationHelper::Attribute
DGuiApplicationHelper::Attribute
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::UseInactiveColorGroup
Inactive状态时就会使用QPalette::Inactive的颜色
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::ColorCompositing
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::ReadOnlyLimit
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsDeepinPlatformTheme
使deepin的platformtheme插件platformtheme插件可以为Qt程序提供特定的控件样式使chameleon主题
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsDXcbPlatform
使dtk的xcb窗口插件dxcb插件提供了窗口圆角和阴影功能
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsXWindowPlatform
X11环境中
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsTableEnvironment
deepin平板环境中XDG_CURRENT_DESKTOP环境变量是不是tablet结尾
\var DGuiApplicationHelper::Attribute DGuiApplicationHelper::IsDeepinEnvironment
deepin桌面环境中XDG_CURRENT_DESKTOP环境变量是不是deepin
*/
@ -748,7 +777,7 @@ static QColor dark_qpalette[QPalette::NColorRoles] {
QColor("#282828"), //Base
QColor("#252525"), //Window
QColor(0, 0, 0, 0.05 * 255), //Shadow
QColor("#0081ff"), //Highlight
QColor("#024CCA"), //Highlight
QColor("#F1F6FF"), //HighlightedText
QColor("#0082fa"), //Link
QColor("#ad4579"), //LinkVisited
@ -969,15 +998,7 @@ void DGuiApplicationHelper::generatePaletteColor(DPalette &base, QPalette::Color
base.setBrush(QPalette::Disabled, role, window);
base.setBrush(QPalette::Inactive, role, window);
return;
} else if (role == QPalette::Highlight && toColorType(base) == DarkType) {
// 暗色模式下的高亮色亮度要降低10%,避免太突兀
QColor highlight = base.highlight().color();
if (highlight.isValid()) {
base.setColor(QPalette::Highlight, adjustColor(highlight, 0, 0, -20, 0, 0, 0, 0));
}
}
generatePaletteColor_helper(base, role, type);
}
@ -1030,6 +1051,20 @@ void DGuiApplicationHelper::generatePalette(DPalette &base, ColorType type)
}
}
static inline QColor getActiveColor(const DPlatformTheme *theme, DGuiApplicationHelper::ColorType type)
{
QColor activeColor;
if (type == DGuiApplicationHelper::DarkType) {
activeColor = theme->darkActiveColor();
if (!activeColor.isValid()) {
activeColor = theme->activeColor();
}
} else {
activeColor = theme->activeColor();
}
return activeColor;
}
/*!
\brief .
@ -1055,7 +1090,7 @@ DPalette DGuiApplicationHelper::fetchPalette(const DPlatformTheme *theme)
bool ok = false;
base_palette = theme->fetchPalette(standardPalette(type), &ok);
const QColor &active_color = theme->activeColor();
const QColor &active_color = getActiveColor(theme, type);
if (active_color.isValid()) {
base_palette.setColor(QPalette::Normal, QPalette::Highlight, active_color);
@ -1226,7 +1261,7 @@ DPalette DGuiApplicationHelper::applicationPalette(ColorType paletteType) const
// 覆盖DPalette中的的QPalette数据
pa.QPalette::operator =(qGuiApp->palette());
} else {
const QColor &active_color = theme->activeColor();
const QColor &active_color = getActiveColor(theme, type);
if (active_color.isValid()) {
// 应用Active Color
@ -1308,6 +1343,11 @@ void DGuiApplicationHelper::setApplicationPalette(const DPalette &palette)
*/
DPalette DGuiApplicationHelper::windowPalette(QWindow *window) const
{
#if DTK_VERSION >= DTK_VERSION_CHECK(5, 0, 0, 0)
Q_UNUSED(window);
qCWarning(dgAppHelper) << "DGuiApplicationHelper::windowPalette is deprecated, please use applicationPalette instead.";
return applicationPalette();
#else
D_DC(DGuiApplicationHelper);
// 如果程序自定义了调色版, 则不再关心窗口对应的平台主题上的设置
@ -1322,6 +1362,7 @@ DPalette DGuiApplicationHelper::windowPalette(QWindow *window) const
}
return fetchPalette(theme);
#endif
}
#endif
@ -1461,11 +1502,37 @@ bool DGuiApplicationHelper::setSingleInstance(const QString &key, DGuiApplicatio
}
socket_key += key;
#ifdef Q_OS_LINUX
auto info = QFileInfo{"/proc/self/ns/pid"};
// maybe kernel doesn't support namespace
while (info.exists()) {
auto pidns = QFileInfo{info.symLinkTarget()}.fileName();
if (pidns.isEmpty()) {
break;
}
// maybe format has been changed
auto start = pidns.indexOf('[');
auto end = pidns.indexOf(']');
if (start == -1 || end == -1) {
break;
}
auto num = pidns.mid(start + 1, end - start - 1);
// append pid namespace
socket_key += QStringLiteral("_%1").arg(num);
break;
}
#endif
QString lockfile = socket_key;
if (!lockfile.startsWith(QLatin1Char('/'))) {
lockfile = QDir::cleanPath(QDir::tempPath());
lockfile += QLatin1Char('/') + socket_key;
}
lockfile += QStringLiteral(".lock");
static QScopedPointer <QLockFile> lock(new QLockFile(lockfile));
// 同一个进程多次调用本接口使用最后一次设置的 key
@ -1607,6 +1674,28 @@ bool DGuiApplicationHelper::hasUserManual() const
return userManualPaths(qApp->applicationName()).size() > 0;
}
static inline QStringList translateDirs(const QString &appName)
{
Q_ASSERT(!appName.isEmpty());
QStringList dirs;
DCORE_USE_NAMESPACE
//("/home/user/.local/share", "/usr/local/share", "/usr/share")
auto dataDirs = DStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
for (const auto &path : dataDirs) {
DPathBuf pathBuf(path);
dirs << (pathBuf / appName / "translations").toString();
}
return dirs;
}
bool DGuiApplicationHelper::loadTranslator(const QString &fileName, const QString &appName, const QList<QLocale> &localeFallback)
{
return loadTranslator(fileName, translateDirs(appName), localeFallback);
}
bool DGuiApplicationHelper::loadTranslator(const QString &fileName, const QList<QString> &translateDirs, const QList<QLocale> &localeFallback)
{
DCORE_USE_NAMESPACE;
@ -1619,40 +1708,30 @@ bool DGuiApplicationHelper::loadTranslator(const QString &fileName, const QList<
for (auto item : defaultDirPrefix)
dirs << item.join("translations").toString();
QStringList missingQmfiles;
for (const auto &locale : localeFallback) {
QStringList translateFilenames {QString("%1_%2").arg(fileName).arg(locale.name())};
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
auto behavior = Qt::SkipEmptyParts;
#else
auto behavior = QString::SkipEmptyParts;
#endif
const QStringList parseLocalNameList = locale.name().split("_", behavior);
if (parseLocalNameList.length() > 0)
translateFilenames << QString("%1_%2").arg(fileName).arg(parseLocalNameList.at(0));
for (const auto &translateFilename : translateFilenames) {
for (const auto &dir : dirs) {
DPathBuf path(dir);
QString translatePath = (path / translateFilename).toString();
if (QFile::exists(translatePath + ".qm")) {
qDebug() << "load translate" << translatePath;
auto translator = new QTranslator(qApp);
translator->load(translatePath);
qApp->installTranslator(translator);
qApp->setProperty("dapp_locale", locale.name());
return true;
}
for (const auto &dir : dirs) {
auto translator = new QTranslator(qApp);
// QTranslator::load(locale, filename, prefix, directory, suffix) automatically handles
// locale fallback (e.g., zh_CN -> zh -> C) and file existence checking
if (translator->load(locale, fileName, QString('_'), dir)) {
qCDebug(dgAppHelper) << "load translate" << fileName << "for locale" << locale.name() << "from" << dir;
qApp->installTranslator(translator);
qApp->setProperty("dapp_locale", locale.name());
return true;
}
// fix english does not need to translation.
if (locale.language() != QLocale::English)
missingQmfiles << translateFilename + ".qm";
delete translator; // Clean up if loading failed
}
}
if (missingQmfiles.size() > 0) {
qWarning() << fileName << "can not find qm files" << missingQmfiles;
// Collect locale names for warning message
QStringList localeNames;
for (const auto &locale : localeFallback) {
if (locale.language() != QLocale::English) // English does not need translation
localeNames << locale.name();
}
if (!localeNames.isEmpty()) {
qWarning() << fileName << "can not find qm files for locales" << localeNames;
}
return false;
}
@ -1664,21 +1743,18 @@ bool DGuiApplicationHelper::loadTranslator(const QList<QLocale> &localeFallback)
#else
auto qTranslationsPath = QLibraryInfo::path(QLibraryInfo::TranslationsPath);
#endif
loadTranslator("qt", {qTranslationsPath}, localeFallback);
loadTranslator("qtbase", {qTranslationsPath}, localeFallback);
DCORE_USE_NAMESPACE
QList<QString> translateDirs;
auto appName = qApp->applicationName();
//("/home/user/.local/share", "/usr/local/share", "/usr/share")
auto dataDirs = DStandardPaths::standardLocations(QStandardPaths::GenericDataLocation);
for (const auto &path : dataDirs) {
DPathBuf DPathBuf(path);
translateDirs << (DPathBuf / appName / "translations").toString();
}
auto qtranslateDirs = translateDirs("qt" QT_STRINGIFY(QT_VERSION_MAJOR));
qtranslateDirs.prepend(qTranslationsPath);
// ${translateDir}/${appName}_${localeName}.qm
return loadTranslator(appName, translateDirs, localeFallback);
loadTranslator("qt", qtranslateDirs, localeFallback);
loadTranslator("qtbase", qtranslateDirs, localeFallback);
auto appName = qApp->applicationName();
return loadTranslator(appName, appName, localeFallback);
}
DGuiApplicationHelper::SizeMode DGuiApplicationHelper::sizeMode() const
@ -1739,6 +1815,17 @@ bool DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::Attribute attri
case IsSpecialEffectsEnvironment: {
return qgetenv("DTK_DISABLED_SPECIAL_EFFECTS").toInt() != 1;
}
case IsWaylandPlatform: {
static bool isTreeland = qApp->platformName() == QByteArrayLiteral("wayland");
return isTreeland;
}
case HasAnimations: {
static bool isDisable = qEnvironmentVariableIsSet(DTK_ANIMATIONS_ENV);
if (isDisable)
return false;
return _d_dconfig->enableDtkAnimations();
}
default:
return DGuiApplicationHelperPrivate::attributes.testFlag(attribute);
}
@ -1778,7 +1865,8 @@ void DGuiApplicationHelper::setPaletteType(DGuiApplicationHelper::ColorType pale
d->initPaletteType();
d->setPaletteType(paletteType, true);
_d_dconfig->setValue(APP_THEME_TYPE, paletteType);
if (!DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::DontSaveApplicationTheme))
_d_dconfig->setThemeType(static_cast<int>(paletteType));
}
/*!

File diff suppressed because it is too large Load Diff

View File

@ -3,17 +3,33 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "dplatformtheme.h"
#include "dguiapplicationhelper.h"
#include "private/dplatformtheme_p.h"
#ifndef DTK_DISABLE_XCB
#include "plugins/platform/xcb/dxcbplatforminterface.h"
#endif
#ifndef DTK_DISABLE_TREELAND
#include "plugins/platform/treeland/dtreelandplatforminterface.h"
#endif
#include "private/dplatforminterface_p.h"
#include "orgdeepindtkpreference.hpp"
#include <QVariant>
#include <QTimer>
#include <QMetaProperty>
#include <QDebug>
#include <functional>
#include <DGuiApplicationHelper>
DGUI_BEGIN_NAMESPACE
static DPlatformInterfaceFactory::HelperCreator OutsideInterfaceCreator = nullptr;
void DPlatformInterfaceFactory::registerInterface(HelperCreator creator)
{
OutsideInterfaceCreator = creator;
}
// "/deepin/palette" 为调色板属性的存储位置
// 在x11平台下将使用_DEEPIN_PALETTE作为存储调色板数据的窗口属性
DPlatformThemePrivate::DPlatformThemePrivate(Dtk::Gui::DPlatformTheme *qq)
@ -22,76 +38,6 @@ DPlatformThemePrivate::DPlatformThemePrivate(Dtk::Gui::DPlatformTheme *qq)
}
void DPlatformThemePrivate::_q_onThemePropertyChanged(const QByteArray &name, const QVariant &value)
{
D_Q(DPlatformTheme);
// 转发属性变化的信号此信号来源可能为parent theme或“非调色板”的属性变化。
// 使用队列的形式转发,避免多次发出同样的信号
q->staticMetaObject.invokeMethod(q, "propertyChanged", Qt::QueuedConnection,
Q_ARG(const QByteArray&, name), Q_ARG(const QVariant&, value));
if (QByteArrayLiteral("Gtk/FontName") == name) {
Q_EMIT q->gtkFontNameChanged(value.toByteArray());
return;
}
if (name.startsWith("Qt/DPI/")) {
const QString &screen_name = QString::fromLocal8Bit(name.mid(7));
if (!screen_name.isEmpty()) {
bool ok = false;
int dpi = value.toInt(&ok);
Q_EMIT q->dotsPerInchChanged(screen_name, ok ? dpi : -1);
}
return;
}
if (QByteArrayLiteral("Xft/DPI") == name) {
bool ok = false;
int dpi = value.toInt(&ok);
Q_EMIT q->dotsPerInchChanged(QString(), ok ? dpi : -1);
}
const QByteArrayList &list = name.split('/');
if (list.count() != 2)
return;
QByteArray pn = list.last();
if (pn.isEmpty())
return;
// 转换首字母为小写
pn[0] = QChar(pn.at(0)).toLower().toLatin1();
// 直接使用静态的meta object防止通过metaObject函数调用到dynamic metaobject
const QMetaObject *mo = &DPlatformTheme::staticMetaObject;
int index = mo->indexOfProperty(pn.constData());
if (index < 0)
return;
const QMetaProperty &p = mo->property(index);
bool is_parent_signal = q->sender() != theme;
// 当自己的属性有效时应该忽略父主题的属性变化信号,优先以自身的属性值为准。
if (is_parent_signal && p.read(q).isValid()) {
return;
}
if (p.hasNotifySignal()) {
// invoke会做Q_ASSERT(mobj->cast(object))判断, DPlatformTheme的dynamic metaObject为
// qt5platform-plugin插件的DNativeSettings. 导致崩溃.
// invokeOnGadget与invoke代码逻辑一致, 只是少了异步支持.
if (!p.notifySignal().invokeOnGadget(q, QGenericArgument(value.typeName(), value.constData())))
qWarning() << "_q_onThemePropertyChanged() error when notify signal" << p.notifySignal().name();
}
}
void DPlatformThemePrivate::onQtColorChanged(QPalette::ColorRole role, const QColor &color)
{
if (!palette) {
@ -142,7 +88,42 @@ DPlatformTheme::DPlatformTheme(quint32 window, QObject *parent)
{
D_D(DPlatformTheme);
if (OutsideInterfaceCreator) {
d->platformInterface = OutsideInterfaceCreator(this);
} else {
#ifndef DTK_DISABLE_XCB
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsXWindowPlatform)) {
d->platformInterface = new DXCBPlatformInterface(0, this);
}
#endif
#ifndef DTK_DISABLE_TREELAND
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) {
d->platformInterface = new DTreelandPlatformInterface(this);
}
#endif
}
if (!d->platformInterface) {
d->platformInterface = new DPlatformInterface(this);
}
d->theme = new DNativeSettings(window, QByteArray(), this);
d->dtkPreferenceConfig = OrgDeepinDTKPreference::createGeneric("", this);
d->sizeMode = static_cast<DGuiApplicationHelper::SizeMode>(d->dtkPreferenceConfig->sizeMode());
d->scrollBarPolicy = static_cast<Qt::ScrollBarPolicy>(d->dtkPreferenceConfig->scrollBarPolicy());
connect(d->dtkPreferenceConfig, &OrgDeepinDTKPreference::sizeModeChanged, this, [this] {
D_D(DPlatformTheme);
d->sizeMode = static_cast<DGuiApplicationHelper::SizeMode>(d->dtkPreferenceConfig->sizeMode());
Q_EMIT sizeModeChanged(d->sizeMode);
});
connect(d->dtkPreferenceConfig, &OrgDeepinDTKPreference::scrollBarPolicyChanged, this, [this] {
D_D(DPlatformTheme);
d->scrollBarPolicy = static_cast<Qt::ScrollBarPolicy>(d->dtkPreferenceConfig->scrollBarPolicy());
Q_EMIT scrollBarPolicyChanged(d->scrollBarPolicy);
});
#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));
@ -172,8 +153,6 @@ DPlatformTheme::DPlatformTheme(quint32 window, QObject *parent)
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
connect(d->theme, SIGNAL(propertyChanged(const QByteArray &, const QVariant &)),
this, SLOT(_q_onThemePropertyChanged(const QByteArray &, const QVariant &)));
}
DPlatformTheme::DPlatformTheme(quint32 window, DPlatformTheme *parent)
@ -194,6 +173,9 @@ DPlatformTheme::~DPlatformTheme()
if (d->palette) {
delete d->palette;
}
if (d->platformInterface) {
delete d->platformInterface;
}
}
bool DPlatformTheme::isValid() const
@ -298,6 +280,7 @@ DPalette DPlatformTheme::fetchPalette(const DPalette &base, bool *ok) const
void DPlatformTheme::setPalette(const DPalette &palette)
{
Q_UNUSED(palette);
#define SET_PALETTE(Role) \
set##Role(palette.color(QPalette::Normal, DPalette::Role))
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
@ -331,134 +314,106 @@ void DPlatformTheme::setPalette(const DPalette &palette)
#endif
}
#define FETCH_PROPERTY(Name, Function) \
D_DC(DPlatformTheme); \
QVariant value = d->theme->getSetting(QByteArrayLiteral(Name)); \
if (d->fallbackProperty && !value.isValid() && d->parent) \
return d->parent->Function(); \
#define FETCH_PROPERTY_WITH_ARGS(Name, Function, Args) \
D_DC(DPlatformTheme); \
QVariant value = d->theme->getSetting(Name); \
if (d->fallbackProperty && !value.isValid() && d->parent) \
return d->parent->Function(Args); \
int DPlatformTheme::cursorBlinkTime() const
{
FETCH_PROPERTY("Net/CursorBlinkTime", cursorBlinkTime)
return value.toInt();
D_DC(DPlatformTheme);
return d->platformInterface->cursorBlinkTime();
}
int DPlatformTheme::cursorBlinkTimeout() const
{
FETCH_PROPERTY("Net/CursorBlinkTimeout", cursorBlinkTimeout)
return value.toInt();
D_DC(DPlatformTheme);
return d->platformInterface->cursorBlinkTimeout();
}
bool DPlatformTheme::cursorBlink() const
{
FETCH_PROPERTY("Net/CursorBlink", cursorBlink)
return value.toInt();
D_DC(DPlatformTheme);
return d->platformInterface->cursorBlink();
}
int DPlatformTheme::doubleClickDistance() const
{
FETCH_PROPERTY("Net/DoubleClickDistance", doubleClickDistance)
return value.toInt();
D_DC(DPlatformTheme);
return d->platformInterface->doubleClickDistance();
}
int DPlatformTheme::doubleClickTime() const
{
FETCH_PROPERTY("Net/DoubleClickTime", doubleClickTime)
return value.toInt();
D_DC(DPlatformTheme);
return d->platformInterface->doubleClickTime();
}
int DPlatformTheme::dndDragThreshold() const
{
FETCH_PROPERTY("Net/DndDragThreshold", dndDragThreshold)
return value.toInt();
D_DC(DPlatformTheme);
return d->platformInterface->dndDragThreshold();
}
int DPlatformTheme::windowRadius() const
{
return windowRadius(-1);
D_DC(DPlatformTheme);
return d->platformInterface->windowRadius();
}
int DPlatformTheme::windowRadius(int defaultValue) const
{
Q_D(const DPlatformTheme);
QVariant value = d->theme->getSetting(QByteArrayLiteral("DTK/WindowRadius"));
bool ok = false;
if (d->fallbackProperty && !value.isValid() && d->parent)
return d->parent->windowRadius(defaultValue);
int radius = value.toInt(&ok);
return ok ? radius : defaultValue;
D_DC(DPlatformTheme);
return d->platformInterface->windowRadius(defaultValue);
}
QByteArray DPlatformTheme::themeName() const
{
FETCH_PROPERTY("Net/ThemeName", themeName)
return value.toByteArray();
D_DC(DPlatformTheme);
return d->platformInterface->themeName();
}
QByteArray DPlatformTheme::iconThemeName() const
{
FETCH_PROPERTY("Net/IconThemeName", iconThemeName)
return value.toByteArray();
D_DC(DPlatformTheme);
return d->platformInterface->iconThemeName();
}
QByteArray DPlatformTheme::soundThemeName() const
{
FETCH_PROPERTY("Net/SoundThemeName", soundThemeName)
return value.toByteArray();
D_DC(DPlatformTheme);
return d->platformInterface->soundThemeName();
}
QByteArray DPlatformTheme::fontName() const
{
FETCH_PROPERTY("Qt/FontName", fontName)
return value.toByteArray();
D_DC(DPlatformTheme);
return d->platformInterface->fontName();
}
QByteArray DPlatformTheme::monoFontName() const
{
FETCH_PROPERTY("Qt/MonoFontName", monoFontName)
return value.toByteArray();
D_DC(DPlatformTheme);
return d->platformInterface->monoFontName();
}
qreal DPlatformTheme::fontPointSize() const
{
FETCH_PROPERTY("Qt/FontPointSize", fontPointSize)
return value.toDouble();
D_DC(DPlatformTheme);
return d->platformInterface->fontPointSize();
}
QByteArray DPlatformTheme::gtkFontName() const
{
FETCH_PROPERTY("Gtk/FontName", gtkFontName)
return value.toByteArray();
D_DC(DPlatformTheme);
return d->platformInterface->gtkFontName();
}
QColor DPlatformTheme::activeColor() const
{
FETCH_PROPERTY("Qt/ActiveColor", activeColor)
D_DC(DPlatformTheme);
return d->platformInterface->activeColor();
}
return qvariant_cast<QColor>(value);
QColor DPlatformTheme::darkActiveColor() const
{
D_DC(DPlatformTheme);
return d->platformInterface->darkActiveColor();
}
bool DPlatformTheme::isValidPalette() const
@ -470,155 +425,171 @@ bool DPlatformTheme::isValidPalette() const
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
QColor DPlatformTheme::window() const
{
return GET_COLOR(window);
D_DC(DPlatformTheme);
return d->platformInterface->window();
}
QColor DPlatformTheme::windowText() const
{
return GET_COLOR(windowText);
D_DC(DPlatformTheme);
return d->platformInterface->windowText();
}
QColor DPlatformTheme::base() const
{
return GET_COLOR(base);
D_DC(DPlatformTheme);
return d->platformInterface->base();
}
QColor DPlatformTheme::alternateBase() const
{
return GET_COLOR(alternateBase);
D_DC(DPlatformTheme);
return d->platformInterface->alternateBase();
}
QColor DPlatformTheme::toolTipBase() const
{
return GET_COLOR(toolTipBase);
D_DC(DPlatformTheme);
return d->platformInterface->toolTipBase();
}
QColor DPlatformTheme::toolTipText() const
{
return GET_COLOR(toolTipText);
D_DC(DPlatformTheme);
return d->platformInterface->toolTipText();
}
QColor DPlatformTheme::text() const
{
return GET_COLOR(text);
D_DC(DPlatformTheme);
return d->platformInterface->text();
}
QColor DPlatformTheme::button() const
{
return GET_COLOR(button);
D_DC(DPlatformTheme);
return d->platformInterface->button();
}
QColor DPlatformTheme::buttonText() const
{
return GET_COLOR(buttonText);
D_DC(DPlatformTheme);
return d->platformInterface->buttonText();
}
QColor DPlatformTheme::brightText() const
{
return GET_COLOR(brightText);
D_DC(DPlatformTheme);
return d->platformInterface->brightText();
}
QColor DPlatformTheme::light() const
{
return GET_COLOR(light);
D_DC(DPlatformTheme);
return d->platformInterface->light();
}
QColor DPlatformTheme::midlight() const
{
return GET_COLOR(midlight);
D_DC(DPlatformTheme);
return d->platformInterface->midlight();
}
QColor DPlatformTheme::dark() const
{
return GET_COLOR(dark);
D_DC(DPlatformTheme);
return d->platformInterface->dark();
}
QColor DPlatformTheme::mid() const
{
return GET_COLOR(mid);
D_DC(DPlatformTheme);
return d->platformInterface->mid();
}
QColor DPlatformTheme::shadow() const
{
return GET_COLOR(shadow);
D_DC(DPlatformTheme);
return d->platformInterface->shadow();
}
QColor DPlatformTheme::highlight() const
{
return GET_COLOR(highlight);
D_DC(DPlatformTheme);
return d->platformInterface->highlight();
}
QColor DPlatformTheme::highlightedText() const
{
return GET_COLOR(highlightedText);
D_DC(DPlatformTheme);
return d->platformInterface->highlightedText();
}
QColor DPlatformTheme::link() const
{
return GET_COLOR(link);
D_DC(DPlatformTheme);
return d->platformInterface->link();
}
QColor DPlatformTheme::linkVisited() const
{
return GET_COLOR(linkVisited);
D_DC(DPlatformTheme);
return d->platformInterface->linkVisited();
}
QColor DPlatformTheme::itemBackground() const
{
return GET_COLOR(itemBackground);
D_DC(DPlatformTheme);
return d->platformInterface->itemBackground();
}
QColor DPlatformTheme::textTitle() const
{
return GET_COLOR(textTitle);
D_DC(DPlatformTheme);
return d->platformInterface->textTitle();
}
QColor DPlatformTheme::textTips() const
{
return GET_COLOR(textTips);
D_DC(DPlatformTheme);
return d->platformInterface->textTips();
}
QColor DPlatformTheme::textWarning() const
{
return GET_COLOR(textWarning);
D_DC(DPlatformTheme);
return d->platformInterface->textWarning();
}
QColor DPlatformTheme::textLively() const
{
return GET_COLOR(textLively);
D_DC(DPlatformTheme);
return d->platformInterface->textLively();
}
QColor DPlatformTheme::lightLively() const
{
return GET_COLOR(lightLively);
D_DC(DPlatformTheme);
return d->platformInterface->lightLively();
}
QColor DPlatformTheme::darkLively() const
{
return GET_COLOR(darkLively);
D_DC(DPlatformTheme);
return d->platformInterface->darkLively();
}
QColor DPlatformTheme::frameBorder() const
{
return GET_COLOR(frameBorder);
D_DC(DPlatformTheme);
return d->platformInterface->frameBorder();
}
#endif
int DPlatformTheme::dotsPerInch(const QString &screenName) const
{
bool ok = false;
if (!screenName.isEmpty()) {
FETCH_PROPERTY_WITH_ARGS("Qt/DPI/" + screenName.toLocal8Bit(), dotsPerInch, screenName);
int dpi = value.toInt(&ok);
if (ok)
return dpi;
}
FETCH_PROPERTY_WITH_ARGS("Xft/DPI", dotsPerInch, screenName);
int dpi = value.toInt(&ok);
return ok ? dpi : -1;
D_DC(DPlatformTheme);
return d->platformInterface->dotsPerInch(screenName);
}
/*!
@ -628,8 +599,7 @@ int DPlatformTheme::dotsPerInch(const QString &screenName) const
int DPlatformTheme::sizeMode() const
{
D_DC(DPlatformTheme);
QVariant value = d->theme->getSetting(QByteArrayLiteral("DTK/SizeMode"));
return value.toInt();
return d->sizeMode;
}
/*!
@ -641,263 +611,275 @@ int DPlatformTheme::sizeMode() const
*/
int DPlatformTheme::scrollBarPolicy() const
{
FETCH_PROPERTY("Qt/ScrollBarPolicy", scrollBarPolicy)
return qvariant_cast<int>(value);
D_DC(DPlatformTheme);
return d->scrollBarPolicy;
}
void DPlatformTheme::setCursorBlinkTime(int cursorBlinkTime)
{
D_D(DPlatformTheme);
d->theme->setSetting("Net/CursorBlinkTime", cursorBlinkTime);
D_DC(DPlatformTheme);
return d->platformInterface->setCursorBlinkTime(cursorBlinkTime);
}
void DPlatformTheme::setCursorBlinkTimeout(int cursorBlinkTimeout)
{
D_D(DPlatformTheme);
d->theme->setSetting("Net/CursorBlinkTimeout", cursorBlinkTimeout);
D_DC(DPlatformTheme);
return d->platformInterface->setCursorBlinkTimeout(cursorBlinkTimeout);
}
void DPlatformTheme::setCursorBlink(bool cursorBlink)
{
D_D(DPlatformTheme);
d->theme->setSetting("Net/CursorBlink", cursorBlink);
D_DC(DPlatformTheme);
return d->platformInterface->setCursorBlink(cursorBlink);
}
void DPlatformTheme::setDoubleClickDistance(int doubleClickDistance)
{
D_D(DPlatformTheme);
d->theme->setSetting("Net/DoubleClickDistance", doubleClickDistance);
D_DC(DPlatformTheme);
return d->platformInterface->setDoubleClickDistance(doubleClickDistance);
}
void DPlatformTheme::setDoubleClickTime(int doubleClickTime)
{
D_D(DPlatformTheme);
d->theme->setSetting("Net/DoubleClickTime", doubleClickTime);
D_DC(DPlatformTheme);
return d->platformInterface->setDoubleClickTime(doubleClickTime);
}
void DPlatformTheme::setDndDragThreshold(int dndDragThreshold)
{
D_D(DPlatformTheme);
d->theme->setSetting("Net/DndDragThreshold", dndDragThreshold);
D_DC(DPlatformTheme);
return d->platformInterface->setDndDragThreshold(dndDragThreshold);
}
void DPlatformTheme::setThemeName(const QByteArray &themeName)
{
D_D(DPlatformTheme);
d->theme->setSetting("Net/ThemeName", themeName);
D_DC(DPlatformTheme);
return d->platformInterface->setThemeName(themeName);
}
void DPlatformTheme::setIconThemeName(const QByteArray &iconThemeName)
{
D_D(DPlatformTheme);
d->theme->setSetting("Net/IconThemeName", iconThemeName);
D_DC(DPlatformTheme);
return d->platformInterface->setIconThemeName(iconThemeName);
}
void DPlatformTheme::setSoundThemeName(const QByteArray &soundThemeName)
{
D_D(DPlatformTheme);
d->theme->setSetting("Net/SoundThemeName", soundThemeName);
D_DC(DPlatformTheme);
return d->platformInterface->setSoundThemeName(soundThemeName);
}
void DPlatformTheme::setFontName(const QByteArray &fontName)
{
D_D(DPlatformTheme);
d->theme->setSetting("Qt/FontName", fontName);
D_DC(DPlatformTheme);
return d->platformInterface->setFontName(fontName);
}
void DPlatformTheme::setMonoFontName(const QByteArray &monoFontName)
{
D_D(DPlatformTheme);
d->theme->setSetting("Qt/MonoFontName", monoFontName);
D_DC(DPlatformTheme);
return d->platformInterface->setMonoFontName(monoFontName);
}
void DPlatformTheme::setFontPointSize(qreal fontPointSize)
{
D_D(DPlatformTheme);
d->theme->setSetting("Qt/FontPointSize", fontPointSize);
D_DC(DPlatformTheme);
return d->platformInterface->setFontPointSize(fontPointSize);
}
void DPlatformTheme::setGtkFontName(const QByteArray &fontName)
{
D_D(DPlatformTheme);
d->theme->setSetting("Gtk/FontName", fontName);
D_DC(DPlatformTheme);
return d->platformInterface->setGtkFontName(fontName);
}
void DPlatformTheme::setActiveColor(const QColor activeColor)
{
D_D(DPlatformTheme);
D_DC(DPlatformTheme);
return d->platformInterface->setActiveColor(activeColor);
}
d->theme->setSetting("Qt/ActiveColor", activeColor);
void DPlatformTheme::setDarkActiveColor(const QColor &activeColor)
{
D_DC(DPlatformTheme);
return d->platformInterface->setDarkActiveColor(activeColor);
}
#define SET_COLOR(Role) setSetting(QByteArrayLiteral(#Role), Role)
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
void DPlatformTheme::setWindow(const QColor &window)
{
SET_COLOR(window);
D_DC(DPlatformTheme);
return d->platformInterface->setWindow(window);
}
void DPlatformTheme::setWindowText(const QColor &windowText)
{
SET_COLOR(windowText);
D_DC(DPlatformTheme);
return d->platformInterface->setWindowText(windowText);
}
void DPlatformTheme::setBase(const QColor &base)
{
SET_COLOR(base);
D_DC(DPlatformTheme);
return d->platformInterface->setBase(base);
}
void DPlatformTheme::setAlternateBase(const QColor &alternateBase)
{
SET_COLOR(alternateBase);
D_DC(DPlatformTheme);
return d->platformInterface->setAlternateBase(alternateBase);
}
void DPlatformTheme::setToolTipBase(const QColor &toolTipBase)
{
SET_COLOR(toolTipBase);
D_DC(DPlatformTheme);
return d->platformInterface->setToolTipBase(toolTipBase);
}
void DPlatformTheme::setToolTipText(const QColor &toolTipText)
{
SET_COLOR(toolTipText);
D_DC(DPlatformTheme);
return d->platformInterface->setToolTipText(toolTipText);
}
void DPlatformTheme::setText(const QColor &text)
{
SET_COLOR(text);
D_DC(DPlatformTheme);
return d->platformInterface->setText(text);
}
void DPlatformTheme::setButton(const QColor &button)
{
SET_COLOR(button);
D_DC(DPlatformTheme);
return d->platformInterface->setButton(button);
}
void DPlatformTheme::setButtonText(const QColor &buttonText)
{
SET_COLOR(buttonText);
D_DC(DPlatformTheme);
return d->platformInterface->setButtonText(buttonText);
}
void DPlatformTheme::setBrightText(const QColor &brightText)
{
SET_COLOR(brightText);
D_DC(DPlatformTheme);
return d->platformInterface->setBrightText(brightText);
}
void DPlatformTheme::setLight(const QColor &light)
{
SET_COLOR(light);
D_DC(DPlatformTheme);
return d->platformInterface->setLight(light);
}
void DPlatformTheme::setMidlight(const QColor &midlight)
{
SET_COLOR(midlight);
D_DC(DPlatformTheme);
return d->platformInterface->setMidlight(midlight);
}
void DPlatformTheme::setDark(const QColor &dark)
{
SET_COLOR(dark);
D_DC(DPlatformTheme);
return d->platformInterface->setDark(dark);
}
void DPlatformTheme::setMid(const QColor &mid)
{
SET_COLOR(mid);
D_DC(DPlatformTheme);
return d->platformInterface->setMid(mid);
}
void DPlatformTheme::setShadow(const QColor &shadow)
{
SET_COLOR(shadow);
D_DC(DPlatformTheme);
return d->platformInterface->setShadow(shadow);
}
void DPlatformTheme::setHighlight(const QColor &highlight)
{
SET_COLOR(highlight);
D_DC(DPlatformTheme);
return d->platformInterface->setHighlight(highlight);
}
void DPlatformTheme::setHighlightedText(const QColor &highlightText)
{
SET_COLOR(highlightText);
D_DC(DPlatformTheme);
return d->platformInterface->setHighlightedText(highlightText);
}
void DPlatformTheme::setLink(const QColor &link)
{
SET_COLOR(link);
D_DC(DPlatformTheme);
return d->platformInterface->setLink(link);
}
void DPlatformTheme::setLinkVisited(const QColor &linkVisited)
{
SET_COLOR(linkVisited);
D_DC(DPlatformTheme);
return d->platformInterface->setLinkVisited(linkVisited);
}
void DPlatformTheme::setItemBackground(const QColor &itemBackground)
{
SET_COLOR(itemBackground);
D_DC(DPlatformTheme);
return d->platformInterface->setItemBackground(itemBackground);
}
void DPlatformTheme::setTextTitle(const QColor &textTitle)
{
SET_COLOR(textTitle);
D_DC(DPlatformTheme);
return d->platformInterface->setTextTitle(textTitle);
}
void DPlatformTheme::setTextTips(const QColor &textTips)
{
SET_COLOR(textTips);
D_DC(DPlatformTheme);
return d->platformInterface->setTextTips(textTips);
}
void DPlatformTheme::setTextWarning(const QColor &textWarning)
{
SET_COLOR(textWarning);
D_DC(DPlatformTheme);
return d->platformInterface->setTextWarning(textWarning);
}
void DPlatformTheme::setTextLively(const QColor &textLively)
{
SET_COLOR(textLively);
D_DC(DPlatformTheme);
return d->platformInterface->setTextLively(textLively);
}
void DPlatformTheme::setLightLively(const QColor &lightLively)
{
SET_COLOR(lightLively);
D_DC(DPlatformTheme);
return d->platformInterface->setLightLively(lightLively);
}
void DPlatformTheme::setDarkLively(const QColor &darkLively)
{
SET_COLOR(darkLively);
D_DC(DPlatformTheme);
return d->platformInterface->setDarkLively(darkLively);
}
void DPlatformTheme::setFrameBorder(const QColor &frameBorder)
{
SET_COLOR(frameBorder);
D_DC(DPlatformTheme);
return d->platformInterface->setFrameBorder(frameBorder);
}
#endif
void DPlatformTheme::setDotsPerInch(const QString &screenName, int dpi)
{
D_D(DPlatformTheme);
if (screenName.isEmpty()) {
d->theme->setSetting("Xft/DPI", dpi);
} else {
d->theme->setSetting("Qt/DPI/" + screenName.toLocal8Bit(), dpi);
}
D_DC(DPlatformTheme);
return d->platformInterface->setDotsPerInch(screenName, dpi);
}
void DPlatformTheme::setWindowRadius(int windowRadius)
{
D_D(DPlatformTheme);
d->theme->setSetting("DTK/WindowRadius", windowRadius);
D_DC(DPlatformTheme);
return d->platformInterface->setWindowRadius(windowRadius);
}
DGUI_END_NAMESPACE

View File

@ -24,6 +24,10 @@
#include <functional>
#ifndef DTK_DISABLE_TREELAND
#include "plugins/platform/treeland/dtreelandwindowmanagerhelper.h"
#endif
DGUI_BEGIN_NAMESPACE
#define DEFINE_CONST_CHAR(Name) const char _##Name[] = "_d_" #Name
@ -111,6 +115,11 @@ public:
mutable QList<DForeignWindow *> windowList;
};
// TODO abstract an interface to adapt to various WM.
#ifndef DTK_DISABLE_TREELAND
Q_GLOBAL_STATIC(TreelandWindowManagerHelper, treelandWMHGlobal)
#endif
class DWindowManagerHelper_ : public DWindowManagerHelper {};
Q_GLOBAL_STATIC(DWindowManagerHelper_, wmhGlobal)
@ -323,6 +332,11 @@ DWindowManagerHelper::~DWindowManagerHelper()
*/
DWindowManagerHelper *DWindowManagerHelper::instance()
{
#ifndef DTK_DISABLE_TREELAND
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) {
return treelandWMHGlobal;
}
#endif
return wmhGlobal;
}
@ -519,6 +533,11 @@ void DWindowManagerHelper::popupSystemWindowMenu(const QWindow *window)
*/
bool DWindowManagerHelper::hasBlurWindow() const
{
#ifndef DTK_DISABLE_TREELAND
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) {
return treelandWMHGlobal->hasBlurWindow();
}
#endif
return callPlatformFunction<bool, bool(*)()>(_hasBlurWindow);
}
@ -528,6 +547,12 @@ bool DWindowManagerHelper::hasBlurWindow() const
*/
bool DWindowManagerHelper::hasComposite() const
{
#ifndef DTK_DISABLE_TREELAND
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) {
return treelandWMHGlobal->hasComposite();
}
#endif
QFunctionPointer hasComposite = Q_NULLPTR;
#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
@ -557,6 +582,11 @@ bool DWindowManagerHelper::hasComposite() const
*/
bool DWindowManagerHelper::hasNoTitlebar() const
{
#ifndef DTK_DISABLE_TREELAND
if (DGuiApplicationHelper::testAttribute(DGuiApplicationHelper::IsWaylandPlatform)) {
return treelandWMHGlobal->hasNoTitlebar();
}
#endif
return callPlatformFunction<bool, bool(*)()>(_hasNoTitlebar);
}

View File

@ -7,4 +7,5 @@ file(GLOB KERNEL_SOURCE
set(kernel_SRC
${KERNEL_HEADER}
${KERNEL_SOURCE}
${CMAKE_CURRENT_LIST_DIR}/orgdeepindtkpreference.hpp
)

View File

@ -0,0 +1,751 @@
/**
* This file is generated by dconfig2cpp.
* Command line arguments: ./build5/tools/dconfig2cpp/dconfig2cpp -c OrgDeepinDTKPreference /usr/share/dsg/configs/org.deepin.dtk.preference.json
* Generation time: 2025-05-08T17:31:56
* JSON file version: 1.0
*
* WARNING: DO NOT MODIFY THIS FILE MANUALLY.
* If you need to change the content, please modify the dconfig2cpp tool.
*/
#ifndef ORGDEEPINDTKPREFERENCE_H
#define ORGDEEPINDTKPREFERENCE_H
#include <QThread>
#include <QVariant>
#include <QPointer>
#include <QDebug>
#include <QAtomicPointer>
#include <QAtomicInteger>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QProperty>
#endif
#include <DSGApplication>
#include <DConfig>
class OrgDeepinDTKPreference : public QObject {
Q_OBJECT
Q_PROPERTY(bool autoDisplayFeature READ autoDisplayFeature WRITE setAutoDisplayFeature NOTIFY autoDisplayFeatureChanged RESET resetAutoDisplayFeature)
Q_PROPERTY(bool enableDtkAnimations READ enableDtkAnimations WRITE setEnableDtkAnimations NOTIFY enableDtkAnimationsChanged RESET resetEnableDtkAnimations)
Q_PROPERTY(bool featureUpdated READ featureUpdated WRITE setFeatureUpdated NOTIFY featureUpdatedChanged RESET resetFeatureUpdated)
Q_PROPERTY(bool keyboardsearchDisabled READ keyboardsearchDisabled WRITE setKeyboardsearchDisabled NOTIFY keyboardsearchDisabledChanged RESET resetKeyboardsearchDisabled)
Q_PROPERTY(QString rules READ rules WRITE setRules NOTIFY rulesChanged RESET resetRules)
Q_PROPERTY(qlonglong scrollBarPolicy READ scrollBarPolicy WRITE setScrollBarPolicy NOTIFY scrollBarPolicyChanged RESET resetScrollBarPolicy)
Q_PROPERTY(qlonglong sizeMode READ sizeMode WRITE setSizeMode NOTIFY sizeModeChanged RESET resetSizeMode)
Q_PROPERTY(qlonglong themeType READ themeType WRITE setThemeType NOTIFY themeTypeChanged RESET resetThemeType)
Q_PROPERTY(qlonglong titlebarHeight READ titlebarHeight WRITE setTitlebarHeight NOTIFY titlebarHeightChanged RESET resetTitlebarHeight)
Q_PROPERTY(bool underlineShortcut READ underlineShortcut WRITE setUnderlineShortcut NOTIFY underlineShortcutChanged RESET resetUnderlineShortcut)
Q_CLASSINFO("DConfigKeyList", "autoDisplayFeature;enableDtkAnimations;featureUpdated;keyboardsearchDisabled;rules;scrollBarPolicy;sizeMode;themeType;titlebarHeight;underlineShortcut")
Q_CLASSINFO("DConfigFileName", "org.deepin.dtk.preference")
Q_CLASSINFO("DConfigFileVersion", "1.0")
public:
explicit OrgDeepinDTKPreference(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend,
const QString &name, const QString &appId, const QString &subpath,
bool isGeneric, QObject *parent)
: QObject(nullptr) {
if (!thread->isRunning()) {
qWarning() << QLatin1String("Warning: The provided thread is not running.");
}
Q_ASSERT(QThread::currentThread() != thread);
auto worker = new QObject();
worker->moveToThread(thread);
QPointer<QObject> watcher(parent);
QMetaObject::invokeMethod(worker, [=, this]() {
DTK_CORE_NAMESPACE::DConfig *config = nullptr;
if (isGeneric) {
if (backend) {
config = DTK_CORE_NAMESPACE::DConfig::createGeneric(backend, name, subpath, nullptr);
} else {
config = DTK_CORE_NAMESPACE::DConfig::createGeneric(name, subpath, nullptr);
}
} else {
if (backend) {
if (appId.isNull()) {
config = DTK_CORE_NAMESPACE::DConfig::create(backend, DTK_CORE_NAMESPACE::DSGApplication::id(),
name, subpath, nullptr);
} else {
config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr);
}
} else {
if (appId.isNull()) {
config = DTK_CORE_NAMESPACE::DConfig::create(DTK_CORE_NAMESPACE::DSGApplication::id(),
name, subpath, nullptr);
} else {
config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr);
}
}
}
if (!config) {
qWarning() << QLatin1String("Failed to create DConfig instance.");
worker->deleteLater();
return;
}
config->moveToThread(QThread::currentThread());
initializeInConfigThread(config);
if (watcher != parent) {
// delete this if watcher is changed to nullptr.
deleteLater();
} else if (!this->parent() && parent) {
// !parent() means that parent is not changed.
this->setParent(watcher);
}
worker->deleteLater();
});
}
static OrgDeepinDTKPreference* create(const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread())
{ return new OrgDeepinDTKPreference(thread, nullptr, QStringLiteral(u"\u006f\u0072\u0067\u002e\u0064\u0065\u0065\u0070\u0069\u006e\u002e\u0064\u0074\u006b\u002e\u0070\u0072\u0065\u0066\u0065\u0072\u0065\u006e\u0063\u0065"), appId, subpath, false, parent); }
static OrgDeepinDTKPreference* create(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread())
{ return new OrgDeepinDTKPreference(thread, backend, QStringLiteral(u"\u006f\u0072\u0067\u002e\u0064\u0065\u0065\u0070\u0069\u006e\u002e\u0064\u0074\u006b\u002e\u0070\u0072\u0065\u0066\u0065\u0072\u0065\u006e\u0063\u0065"), appId, subpath, false, parent); }
static OrgDeepinDTKPreference* createByName(const QString &name, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread())
{ return new OrgDeepinDTKPreference(thread, nullptr, name, appId, subpath, false, parent); }
static OrgDeepinDTKPreference* createByName(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &appId = {}, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread())
{ return new OrgDeepinDTKPreference(thread, backend, name, appId, subpath, false, parent); }
static OrgDeepinDTKPreference* createGeneric(const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread())
{ return new OrgDeepinDTKPreference(thread, nullptr, QStringLiteral(u"\u006f\u0072\u0067\u002e\u0064\u0065\u0065\u0070\u0069\u006e\u002e\u0064\u0074\u006b\u002e\u0070\u0072\u0065\u0066\u0065\u0072\u0065\u006e\u0063\u0065"), {}, subpath, true, parent); }
static OrgDeepinDTKPreference* create(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread())
{ return new OrgDeepinDTKPreference(thread, backend, QStringLiteral(u"\u006f\u0072\u0067\u002e\u0064\u0065\u0065\u0070\u0069\u006e\u002e\u0064\u0074\u006b\u002e\u0070\u0072\u0065\u0066\u0065\u0072\u0065\u006e\u0063\u0065"), {}, subpath, true, parent); }
static OrgDeepinDTKPreference* createGenericByName(const QString &name, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread())
{ return new OrgDeepinDTKPreference(thread, nullptr, name, {}, subpath, true, parent); }
static OrgDeepinDTKPreference* createGenericByName(DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath = {}, QObject *parent = nullptr, QThread *thread = DTK_CORE_NAMESPACE::DConfig::globalThread())
{ return new OrgDeepinDTKPreference(thread, backend, name, {}, subpath, true, parent); }
~OrgDeepinDTKPreference() {
if (m_config.loadRelaxed()) {
m_config.loadRelaxed()->deleteLater();
}
}
Q_INVOKABLE DTK_CORE_NAMESPACE::DConfig *config() const {
return m_config.loadRelaxed();
}
Q_INVOKABLE bool isInitializeSucceed() const {
return m_status.loadRelaxed() == static_cast<int>(Status::Succeed);
}
Q_INVOKABLE bool isInitializeFailed() const {
return m_status.loadRelaxed() == static_cast<int>(Status::Failed);
}
Q_INVOKABLE bool isInitializing() const {
return m_status.loadRelaxed() == static_cast<int>(Status::Invalid);
}
Q_INVOKABLE QStringList keyList() const {
return { QStringLiteral("autoDisplayFeature"),
QStringLiteral("enableDtkAnimations"),
QStringLiteral("featureUpdated"),
QStringLiteral("keyboardsearchDisabled"),
QStringLiteral("rules"),
QStringLiteral("scrollBarPolicy"),
QStringLiteral("sizeMode"),
QStringLiteral("themeType"),
QStringLiteral("titlebarHeight"),
QStringLiteral("underlineShortcut")};
}
Q_INVOKABLE bool isDefaultValue(const QString &key) const {
if (key == QStringLiteral("autoDisplayFeature"))
return autoDisplayFeatureIsDefaultValue();
if (key == QStringLiteral("enableDtkAnimations"))
return enableDtkAnimationsIsDefaultValue();
if (key == QStringLiteral("featureUpdated"))
return featureUpdatedIsDefaultValue();
if (key == QStringLiteral("keyboardsearchDisabled"))
return keyboardsearchDisabledIsDefaultValue();
if (key == QStringLiteral("rules"))
return rulesIsDefaultValue();
if (key == QStringLiteral("scrollBarPolicy"))
return scrollBarPolicyIsDefaultValue();
if (key == QStringLiteral("sizeMode"))
return sizeModeIsDefaultValue();
if (key == QStringLiteral("themeType"))
return themeTypeIsDefaultValue();
if (key == QStringLiteral("titlebarHeight"))
return titlebarHeightIsDefaultValue();
if (key == QStringLiteral("underlineShortcut"))
return underlineShortcutIsDefaultValue();
return false;
}
bool autoDisplayFeature() const {
return p_autoDisplayFeature;
}
void setAutoDisplayFeature(const bool &value) {
auto oldValue = p_autoDisplayFeature;
p_autoDisplayFeature = value;
markPropertySet(0);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("autoDisplayFeature"), value);
});
}
if (p_autoDisplayFeature != oldValue) {
Q_EMIT autoDisplayFeatureChanged();
Q_EMIT valueChanged(QStringLiteral("autoDisplayFeature"), value);
}
}
void resetAutoDisplayFeature() {
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this]() {
m_config.loadRelaxed()->reset(QStringLiteral("autoDisplayFeature"));
});
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QBindable<bool> bindableAutoDisplayFeature() {
return QBindable<bool>(this, "autoDisplayFeature");
}
#endif
Q_INVOKABLE bool autoDisplayFeatureIsDefaultValue() const {
return !testPropertySet(0);
}
bool enableDtkAnimations() const {
return p_enableDtkAnimations;
}
void setEnableDtkAnimations(const bool &value) {
auto oldValue = p_enableDtkAnimations;
p_enableDtkAnimations = value;
markPropertySet(1);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("enableDtkAnimations"), value);
});
}
if (p_enableDtkAnimations != oldValue) {
Q_EMIT enableDtkAnimationsChanged();
Q_EMIT valueChanged(QStringLiteral("enableDtkAnimations"), value);
}
}
void resetEnableDtkAnimations() {
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this]() {
m_config.loadRelaxed()->reset(QStringLiteral("enableDtkAnimations"));
});
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QBindable<bool> bindableEnableDtkAnimations() {
return QBindable<bool>(this, "enableDtkAnimations");
}
#endif
Q_INVOKABLE bool enableDtkAnimationsIsDefaultValue() const {
return !testPropertySet(1);
}
bool featureUpdated() const {
return p_featureUpdated;
}
void setFeatureUpdated(const bool &value) {
auto oldValue = p_featureUpdated;
p_featureUpdated = value;
markPropertySet(2);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("featureUpdated"), value);
});
}
if (p_featureUpdated != oldValue) {
Q_EMIT featureUpdatedChanged();
Q_EMIT valueChanged(QStringLiteral("featureUpdated"), value);
}
}
void resetFeatureUpdated() {
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this]() {
m_config.loadRelaxed()->reset(QStringLiteral("featureUpdated"));
});
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QBindable<bool> bindableFeatureUpdated() {
return QBindable<bool>(this, "featureUpdated");
}
#endif
Q_INVOKABLE bool featureUpdatedIsDefaultValue() const {
return !testPropertySet(2);
}
bool keyboardsearchDisabled() const {
return p_keyboardsearchDisabled;
}
void setKeyboardsearchDisabled(const bool &value) {
auto oldValue = p_keyboardsearchDisabled;
p_keyboardsearchDisabled = value;
markPropertySet(3);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("keyboardsearchDisabled"), value);
});
}
if (p_keyboardsearchDisabled != oldValue) {
Q_EMIT keyboardsearchDisabledChanged();
Q_EMIT valueChanged(QStringLiteral("keyboardsearchDisabled"), value);
}
}
void resetKeyboardsearchDisabled() {
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this]() {
m_config.loadRelaxed()->reset(QStringLiteral("keyboardsearchDisabled"));
});
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QBindable<bool> bindableKeyboardsearchDisabled() {
return QBindable<bool>(this, "keyboardsearchDisabled");
}
#endif
Q_INVOKABLE bool keyboardsearchDisabledIsDefaultValue() const {
return !testPropertySet(3);
}
QString rules() const {
return p_rules;
}
void setRules(const QString &value) {
auto oldValue = p_rules;
p_rules = value;
markPropertySet(4);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("rules"), value);
});
}
if (p_rules != oldValue) {
Q_EMIT rulesChanged();
Q_EMIT valueChanged(QStringLiteral("rules"), value);
}
}
void resetRules() {
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this]() {
m_config.loadRelaxed()->reset(QStringLiteral("rules"));
});
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QBindable<QString> bindableRules() {
return QBindable<QString>(this, "rules");
}
#endif
Q_INVOKABLE bool rulesIsDefaultValue() const {
return !testPropertySet(4);
}
qlonglong scrollBarPolicy() const {
return p_scrollBarPolicy;
}
void setScrollBarPolicy(const qlonglong &value) {
auto oldValue = p_scrollBarPolicy;
p_scrollBarPolicy = value;
markPropertySet(5);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("scrollBarPolicy"), value);
});
}
if (p_scrollBarPolicy != oldValue) {
Q_EMIT scrollBarPolicyChanged();
Q_EMIT valueChanged(QStringLiteral("scrollBarPolicy"), value);
}
}
void resetScrollBarPolicy() {
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this]() {
m_config.loadRelaxed()->reset(QStringLiteral("scrollBarPolicy"));
});
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QBindable<qlonglong> bindableScrollBarPolicy() {
return QBindable<qlonglong>(this, "scrollBarPolicy");
}
#endif
Q_INVOKABLE bool scrollBarPolicyIsDefaultValue() const {
return !testPropertySet(5);
}
qlonglong sizeMode() const {
return p_sizeMode;
}
void setSizeMode(const qlonglong &value) {
auto oldValue = p_sizeMode;
p_sizeMode = value;
markPropertySet(6);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("sizeMode"), value);
});
}
if (p_sizeMode != oldValue) {
Q_EMIT sizeModeChanged();
Q_EMIT valueChanged(QStringLiteral("sizeMode"), value);
}
}
void resetSizeMode() {
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this]() {
m_config.loadRelaxed()->reset(QStringLiteral("sizeMode"));
});
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QBindable<qlonglong> bindableSizeMode() {
return QBindable<qlonglong>(this, "sizeMode");
}
#endif
Q_INVOKABLE bool sizeModeIsDefaultValue() const {
return !testPropertySet(6);
}
qlonglong themeType() const {
return p_themeType;
}
void setThemeType(const qlonglong &value) {
auto oldValue = p_themeType;
p_themeType = value;
markPropertySet(7);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("themeType"), value);
});
}
if (p_themeType != oldValue) {
Q_EMIT themeTypeChanged();
Q_EMIT valueChanged(QStringLiteral("themeType"), value);
}
}
void resetThemeType() {
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this]() {
m_config.loadRelaxed()->reset(QStringLiteral("themeType"));
});
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QBindable<qlonglong> bindableThemeType() {
return QBindable<qlonglong>(this, "themeType");
}
#endif
Q_INVOKABLE bool themeTypeIsDefaultValue() const {
return !testPropertySet(7);
}
qlonglong titlebarHeight() const {
return p_titlebarHeight;
}
void setTitlebarHeight(const qlonglong &value) {
auto oldValue = p_titlebarHeight;
p_titlebarHeight = value;
markPropertySet(8);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("titlebarHeight"), value);
});
}
if (p_titlebarHeight != oldValue) {
Q_EMIT titlebarHeightChanged();
Q_EMIT valueChanged(QStringLiteral("titlebarHeight"), value);
}
}
void resetTitlebarHeight() {
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this]() {
m_config.loadRelaxed()->reset(QStringLiteral("titlebarHeight"));
});
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QBindable<qlonglong> bindableTitlebarHeight() {
return QBindable<qlonglong>(this, "titlebarHeight");
}
#endif
Q_INVOKABLE bool titlebarHeightIsDefaultValue() const {
return !testPropertySet(8);
}
bool underlineShortcut() const {
return p_underlineShortcut;
}
void setUnderlineShortcut(const bool &value) {
auto oldValue = p_underlineShortcut;
p_underlineShortcut = value;
markPropertySet(9);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("underlineShortcut"), value);
});
}
if (p_underlineShortcut != oldValue) {
Q_EMIT underlineShortcutChanged();
Q_EMIT valueChanged(QStringLiteral("underlineShortcut"), value);
}
}
void resetUnderlineShortcut() {
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this]() {
m_config.loadRelaxed()->reset(QStringLiteral("underlineShortcut"));
});
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QBindable<bool> bindableUnderlineShortcut() {
return QBindable<bool>(this, "underlineShortcut");
}
#endif
Q_INVOKABLE bool underlineShortcutIsDefaultValue() const {
return !testPropertySet(9);
}
Q_SIGNALS:
void configInitializeFailed(DTK_CORE_NAMESPACE::DConfig *config);
void configInitializeSucceed(DTK_CORE_NAMESPACE::DConfig *config);
void valueChanged(const QString &key, const QVariant &value);
void autoDisplayFeatureChanged();
void enableDtkAnimationsChanged();
void featureUpdatedChanged();
void keyboardsearchDisabledChanged();
void rulesChanged();
void scrollBarPolicyChanged();
void sizeModeChanged();
void themeTypeChanged();
void titlebarHeightChanged();
void underlineShortcutChanged();
private:
void initializeInConfigThread(DTK_CORE_NAMESPACE::DConfig *config) {
Q_ASSERT(!m_config.loadRelaxed());
m_config.storeRelaxed(config);
if (!config->isValid()) {
m_status.storeRelaxed(static_cast<int>(Status::Failed));
Q_EMIT configInitializeFailed(config);
return;
}
if (testPropertySet(0)) {
config->setValue(QStringLiteral("autoDisplayFeature"), QVariant::fromValue(p_autoDisplayFeature));
} else {
updateValue(QStringLiteral("autoDisplayFeature"), QVariant::fromValue(p_autoDisplayFeature));
}
if (testPropertySet(1)) {
config->setValue(QStringLiteral("enableDtkAnimations"), QVariant::fromValue(p_enableDtkAnimations));
} else {
updateValue(QStringLiteral("enableDtkAnimations"), QVariant::fromValue(p_enableDtkAnimations));
}
if (testPropertySet(2)) {
config->setValue(QStringLiteral("featureUpdated"), QVariant::fromValue(p_featureUpdated));
} else {
updateValue(QStringLiteral("featureUpdated"), QVariant::fromValue(p_featureUpdated));
}
if (testPropertySet(3)) {
config->setValue(QStringLiteral("keyboardsearchDisabled"), QVariant::fromValue(p_keyboardsearchDisabled));
} else {
updateValue(QStringLiteral("keyboardsearchDisabled"), QVariant::fromValue(p_keyboardsearchDisabled));
}
if (testPropertySet(4)) {
config->setValue(QStringLiteral("rules"), QVariant::fromValue(p_rules));
} else {
updateValue(QStringLiteral("rules"), QVariant::fromValue(p_rules));
}
if (testPropertySet(5)) {
config->setValue(QStringLiteral("scrollBarPolicy"), QVariant::fromValue(p_scrollBarPolicy));
} else {
updateValue(QStringLiteral("scrollBarPolicy"), QVariant::fromValue(p_scrollBarPolicy));
}
if (testPropertySet(6)) {
config->setValue(QStringLiteral("sizeMode"), QVariant::fromValue(p_sizeMode));
} else {
updateValue(QStringLiteral("sizeMode"), QVariant::fromValue(p_sizeMode));
}
if (testPropertySet(7)) {
config->setValue(QStringLiteral("themeType"), QVariant::fromValue(p_themeType));
} else {
updateValue(QStringLiteral("themeType"), QVariant::fromValue(p_themeType));
}
if (testPropertySet(8)) {
config->setValue(QStringLiteral("titlebarHeight"), QVariant::fromValue(p_titlebarHeight));
} else {
updateValue(QStringLiteral("titlebarHeight"), QVariant::fromValue(p_titlebarHeight));
}
if (testPropertySet(9)) {
config->setValue(QStringLiteral("underlineShortcut"), QVariant::fromValue(p_underlineShortcut));
} else {
updateValue(QStringLiteral("underlineShortcut"), QVariant::fromValue(p_underlineShortcut));
}
connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) {
updateValue(key);
}, Qt::DirectConnection);
m_status.storeRelaxed(static_cast<int>(Status::Succeed));
Q_EMIT configInitializeSucceed(config);
}
void updateValue(const QString &key, const QVariant &fallback = QVariant()) {
Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread());
const QVariant &value = m_config.loadRelaxed()->value(key, fallback);
if (key == QStringLiteral("autoDisplayFeature")) {
markPropertySet(0, !m_config.loadRelaxed()->isDefaultValue(key));
auto newValue = qvariant_cast<bool>(value);
QMetaObject::invokeMethod(this, [this, newValue, key, value]() {
Q_ASSERT(QThread::currentThread() == this->thread());
if (p_autoDisplayFeature != newValue) {
p_autoDisplayFeature = newValue;
Q_EMIT autoDisplayFeatureChanged();
Q_EMIT valueChanged(key, value);
}
});
return;
}
if (key == QStringLiteral("enableDtkAnimations")) {
markPropertySet(1, !m_config.loadRelaxed()->isDefaultValue(key));
auto newValue = qvariant_cast<bool>(value);
QMetaObject::invokeMethod(this, [this, newValue, key, value]() {
Q_ASSERT(QThread::currentThread() == this->thread());
if (p_enableDtkAnimations != newValue) {
p_enableDtkAnimations = newValue;
Q_EMIT enableDtkAnimationsChanged();
Q_EMIT valueChanged(key, value);
}
});
return;
}
if (key == QStringLiteral("featureUpdated")) {
markPropertySet(2, !m_config.loadRelaxed()->isDefaultValue(key));
auto newValue = qvariant_cast<bool>(value);
QMetaObject::invokeMethod(this, [this, newValue, key, value]() {
Q_ASSERT(QThread::currentThread() == this->thread());
if (p_featureUpdated != newValue) {
p_featureUpdated = newValue;
Q_EMIT featureUpdatedChanged();
Q_EMIT valueChanged(key, value);
}
});
return;
}
if (key == QStringLiteral("keyboardsearchDisabled")) {
markPropertySet(3, !m_config.loadRelaxed()->isDefaultValue(key));
auto newValue = qvariant_cast<bool>(value);
QMetaObject::invokeMethod(this, [this, newValue, key, value]() {
Q_ASSERT(QThread::currentThread() == this->thread());
if (p_keyboardsearchDisabled != newValue) {
p_keyboardsearchDisabled = newValue;
Q_EMIT keyboardsearchDisabledChanged();
Q_EMIT valueChanged(key, value);
}
});
return;
}
if (key == QStringLiteral("rules")) {
markPropertySet(4, !m_config.loadRelaxed()->isDefaultValue(key));
auto newValue = qvariant_cast<QString>(value);
QMetaObject::invokeMethod(this, [this, newValue, key, value]() {
Q_ASSERT(QThread::currentThread() == this->thread());
if (p_rules != newValue) {
p_rules = newValue;
Q_EMIT rulesChanged();
Q_EMIT valueChanged(key, value);
}
});
return;
}
if (key == QStringLiteral("scrollBarPolicy")) {
markPropertySet(5, !m_config.loadRelaxed()->isDefaultValue(key));
auto newValue = qvariant_cast<qlonglong>(value);
QMetaObject::invokeMethod(this, [this, newValue, key, value]() {
Q_ASSERT(QThread::currentThread() == this->thread());
if (p_scrollBarPolicy != newValue) {
p_scrollBarPolicy = newValue;
Q_EMIT scrollBarPolicyChanged();
Q_EMIT valueChanged(key, value);
}
});
return;
}
if (key == QStringLiteral("sizeMode")) {
markPropertySet(6, !m_config.loadRelaxed()->isDefaultValue(key));
auto newValue = qvariant_cast<qlonglong>(value);
QMetaObject::invokeMethod(this, [this, newValue, key, value]() {
Q_ASSERT(QThread::currentThread() == this->thread());
if (p_sizeMode != newValue) {
p_sizeMode = newValue;
Q_EMIT sizeModeChanged();
Q_EMIT valueChanged(key, value);
}
});
return;
}
if (key == QStringLiteral("themeType")) {
markPropertySet(7, !m_config.loadRelaxed()->isDefaultValue(key));
auto newValue = qvariant_cast<qlonglong>(value);
QMetaObject::invokeMethod(this, [this, newValue, key, value]() {
Q_ASSERT(QThread::currentThread() == this->thread());
if (p_themeType != newValue) {
p_themeType = newValue;
Q_EMIT themeTypeChanged();
Q_EMIT valueChanged(key, value);
}
});
return;
}
if (key == QStringLiteral("titlebarHeight")) {
markPropertySet(8, !m_config.loadRelaxed()->isDefaultValue(key));
auto newValue = qvariant_cast<qlonglong>(value);
QMetaObject::invokeMethod(this, [this, newValue, key, value]() {
Q_ASSERT(QThread::currentThread() == this->thread());
if (p_titlebarHeight != newValue) {
p_titlebarHeight = newValue;
Q_EMIT titlebarHeightChanged();
Q_EMIT valueChanged(key, value);
}
});
return;
}
if (key == QStringLiteral("underlineShortcut")) {
markPropertySet(9, !m_config.loadRelaxed()->isDefaultValue(key));
auto newValue = qvariant_cast<bool>(value);
QMetaObject::invokeMethod(this, [this, newValue, key, value]() {
Q_ASSERT(QThread::currentThread() == this->thread());
if (p_underlineShortcut != newValue) {
p_underlineShortcut = newValue;
Q_EMIT underlineShortcutChanged();
Q_EMIT valueChanged(key, value);
}
});
return;
}
}
inline void markPropertySet(const int index, bool on = true) {
if (index < 32) {
if (on)
m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0));
else
m_propertySetStatus0.fetchAndAndOrdered(~(1 << (index - 0)));
return;
}
Q_UNREACHABLE();
}
inline bool testPropertySet(const int index) const {
if (index < 32) {
return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0)));
}
Q_UNREACHABLE();
}
QAtomicPointer<DTK_CORE_NAMESPACE::DConfig> m_config = nullptr;
public:
enum class Status {
Invalid = 0,
Succeed = 1,
Failed = 2
};
private:
QAtomicInteger<int> m_status = static_cast<int>(Status::Invalid);
bool p_autoDisplayFeature { false };
bool p_enableDtkAnimations { false };
bool p_featureUpdated { false };
bool p_keyboardsearchDisabled { false };
// Default value: ""
QString p_rules { QLatin1String("") };
qlonglong p_scrollBarPolicy { 0 };
qlonglong p_sizeMode { 0 };
qlonglong p_themeType { 0 };
qlonglong p_titlebarHeight { -1 };
bool p_underlineShortcut { false };
QAtomicInteger<quint32> m_propertySetStatus0 = 0;
};
#endif // ORGDEEPINDTKPREFERENCE_H

View File

@ -0,0 +1,480 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "dplatformtheme.h"
#include "private/dplatforminterface_p.h"
DGUI_BEGIN_NAMESPACE
DPlatformInterface::DPlatformInterface(DPlatformTheme *platformTheme)
: m_platformTheme(platformTheme)
{
}
DPlatformInterface::~DPlatformInterface()
{
}
int DPlatformInterface::cursorBlinkTime() const
{
return {};
}
int DPlatformInterface::cursorBlinkTimeout() const
{
return {};
}
bool DPlatformInterface::cursorBlink() const
{
return {};
}
int DPlatformInterface::doubleClickDistance() const
{
return {};
}
int DPlatformInterface::doubleClickTime() const
{
return {};
}
int DPlatformInterface::dndDragThreshold() const
{
return {};
}
int DPlatformInterface::windowRadius() const
{
return -1;
}
int DPlatformInterface::windowRadius(int defaultValue) const
{
return defaultValue;
}
QByteArray DPlatformInterface::themeName() const
{
return {};
}
QByteArray DPlatformInterface::iconThemeName() const
{
return {};
}
QByteArray DPlatformInterface::soundThemeName() const
{
return {};
}
QByteArray DPlatformInterface::fontName() const
{
return {};
}
QByteArray DPlatformInterface::monoFontName() const
{
return {};
}
qreal DPlatformInterface::fontPointSize() const
{
return {};
}
QByteArray DPlatformInterface::gtkFontName() const
{
return {};
}
QColor DPlatformInterface::activeColor() const
{
return {};
}
QColor DPlatformInterface::darkActiveColor() const
{
return {};
}
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
QColor DPlatformInterface::window() const
{
return {};
}
QColor DPlatformInterface::windowText() const
{
return {};
}
QColor DPlatformInterface::base() const
{
return {};
}
QColor DPlatformInterface::alternateBase() const
{
return {};
}
QColor DPlatformInterface::toolTipBase() const
{
return {};
}
QColor DPlatformInterface::toolTipText() const
{
return {};
}
QColor DPlatformInterface::text() const
{
return {};
}
QColor DPlatformInterface::button() const
{
return {};
}
QColor DPlatformInterface::buttonText() const
{
return {};
}
QColor DPlatformInterface::brightText() const
{
return {};
}
QColor DPlatformInterface::light() const
{
return {};
}
QColor DPlatformInterface::midlight() const
{
return {};
}
QColor DPlatformInterface::dark() const
{
return {};
}
QColor DPlatformInterface::mid() const
{
return {};
}
QColor DPlatformInterface::shadow() const
{
return {};
}
QColor DPlatformInterface::highlight() const
{
return {};
}
QColor DPlatformInterface::highlightedText() const
{
return {};
}
QColor DPlatformInterface::link() const
{
return {};
}
QColor DPlatformInterface::linkVisited() const
{
return {};
}
QColor DPlatformInterface::itemBackground() const
{
return {};
}
QColor DPlatformInterface::textTitle() const
{
return {};
}
QColor DPlatformInterface::textTips() const
{
return {};
}
QColor DPlatformInterface::textWarning() const
{
return {};
}
QColor DPlatformInterface::textLively() const
{
return {};
}
QColor DPlatformInterface::lightLively() const
{
return {};
}
QColor DPlatformInterface::darkLively() const
{
return {};
}
QColor DPlatformInterface::frameBorder() const
{
return {};
}
#endif
int DPlatformInterface::dotsPerInch(const QString &) const
{
return {};
}
int DPlatformInterface::sizeMode() const
{
return {};
}
int DPlatformInterface::scrollBarPolicy() const
{
return {};
}
void DPlatformInterface::setCursorBlinkTime(int)
{
}
void DPlatformInterface::setCursorBlinkTimeout(int)
{
}
void DPlatformInterface::setCursorBlink(bool)
{
}
void DPlatformInterface::setDoubleClickDistance(int)
{
}
void DPlatformInterface::setDoubleClickTime(int)
{
}
void DPlatformInterface::setDndDragThreshold(int)
{
}
void DPlatformInterface::setThemeName(const QByteArray &)
{
}
void DPlatformInterface::setIconThemeName(const QByteArray &)
{
}
void DPlatformInterface::setSoundThemeName(const QByteArray &)
{
}
void DPlatformInterface::setFontName(const QByteArray &)
{
}
void DPlatformInterface::setMonoFontName(const QByteArray &)
{
}
void DPlatformInterface::setFontPointSize(qreal)
{
}
void DPlatformInterface::setGtkFontName(const QByteArray &)
{
}
void DPlatformInterface::setActiveColor(const QColor)
{
}
void DPlatformInterface::setDarkActiveColor(const QColor &)
{
}
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
void DPlatformInterface::setWindow(const QColor &)
{
}
void DPlatformInterface::setWindowText(const QColor &)
{
}
void DPlatformInterface::setBase(const QColor &)
{
}
void DPlatformInterface::setAlternateBase(const QColor &)
{
}
void DPlatformInterface::setToolTipBase(const QColor &)
{
}
void DPlatformInterface::setToolTipText(const QColor &)
{
}
void DPlatformInterface::setText(const QColor &)
{
}
void DPlatformInterface::setButton(const QColor &)
{
}
void DPlatformInterface::setButtonText(const QColor &)
{
}
void DPlatformInterface::setBrightText(const QColor &)
{
}
void DPlatformInterface::setLight(const QColor &)
{
}
void DPlatformInterface::setMidlight(const QColor &)
{
}
void DPlatformInterface::setDark(const QColor &)
{
}
void DPlatformInterface::setMid(const QColor &)
{
}
void DPlatformInterface::setShadow(const QColor &)
{
}
void DPlatformInterface::setHighlight(const QColor &)
{
}
void DPlatformInterface::setHighlightedText(const QColor &)
{
}
void DPlatformInterface::setLink(const QColor &)
{
}
void DPlatformInterface::setLinkVisited(const QColor &)
{
}
void DPlatformInterface::setItemBackground(const QColor &)
{
}
void DPlatformInterface::setTextTitle(const QColor &)
{
}
void DPlatformInterface::setTextTips(const QColor &)
{
}
void DPlatformInterface::setTextWarning(const QColor &)
{
}
void DPlatformInterface::setTextLively(const QColor &)
{
}
void DPlatformInterface::setLightLively(const QColor &)
{
}
void DPlatformInterface::setDarkLively(const QColor &)
{
}
void DPlatformInterface::setFrameBorder(const QColor &)
{
}
#endif
void DPlatformInterface::setDotsPerInch(const QString &, int)
{
}
void DPlatformInterface::setWindowRadius(int)
{
}
DGUI_END_NAMESPACE

View File

@ -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 {};
}
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

View File

@ -0,0 +1,59 @@
# SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
#
# SPDX-License-Identifier: LGPL-3.0-or-later
cmake_minimum_required(VERSION 3.16)
project(wayland_test)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(AUTOMOC_COMPILER_PREDEFINES ON)
find_package(Qt${QT_VERSION_MAJOR} ${REQUIRED_QT_VERSION} REQUIRED COMPONENTS Core Gui WaylandClient)
if(${QT_VERSION_MAJOR} STREQUAL "5")
find_package(Qt5 REQUIRED COMPONENTS XkbCommonSupport)
endif()
find_package(PkgConfig REQUIRED)
pkg_check_modules(WAYLAND_CLIENT REQUIRED wayland-client)
find_package(TreelandProtocols)
set(TreelandProtocols_FOUND ${TreelandProtocols_FOUND})
add_executable(${PROJECT_NAME} main.cpp)
if("${QT_VERSION_MAJOR}" STREQUAL "6")
qt6_generate_wayland_protocol_client_sources(${PROJECT_NAME} FILES
${TREELAND_PROTOCOLS_DATA_DIR}/treeland-personalization-manager-v1.xml
)
if (${Qt6Core_VERSION} VERSION_GREATER_EQUAL "6.10.0")
set(QT_NO_PRIVATE_MODULE_WARNING ON)
find_package(Qt6 REQUIRED COMPONENTS GuiPrivate CorePrivate WaylandClientPrivate)
endif()
else()
# ECM setup
include(FeatureSummary)
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${ECM_MODULE_PATH}")
find_package(QtWaylandScanner)
ecm_add_qtwayland_client_protocol(TABLET_SRCS
PROTOCOL ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-personalization-manager-v1.xml
BASENAME treeland-personalization-manager-v1
)
target_sources(${PROJECT_NAME} PRIVATE ${TABLET_SRCS})
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::XkbCommonSupportPrivate
)
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::GuiPrivate
Qt${QT_VERSION_MAJOR}::CorePrivate
Qt${QT_VERSION_MAJOR}::WaylandClientPrivate
${WAYLAND_CLIENT_LIBRARIES}
)

View File

@ -0,0 +1,36 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include <QGuiApplication>
#include <QtWaylandClient/QWaylandClientExtension>
#include <QtWaylandClient/private/qwaylandsurface_p.h>
#include <QtWaylandClient/private/qwaylandwindow_p.h>
#include <wayland-client-core.h>
#include "qwayland-treeland-personalization-manager-v1.h"
#include <qwaylandclientextension.h>
#include <private/qguiapplication_p.h>
#include <private/qwaylandintegration_p.h>
#include <private/qwaylandwindow_p.h>
#include <private/qwaylanddisplay_p.h>
class PersonalizationWindowContext : public QWaylandClientExtensionTemplate<PersonalizationWindowContext>,
public QtWayland::treeland_personalization_window_context_v1
{
public:
PersonalizationWindowContext(struct ::treeland_personalization_window_context_v1 *context)
: QWaylandClientExtensionTemplate<PersonalizationWindowContext>(1)
, QtWayland::treeland_personalization_window_context_v1(context)
{
set_titlebar(enable_mode::enable_mode_disable);
}
};
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
return 0;
}

View File

@ -0,0 +1,103 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "dtreelandplatforminterface.h"
#include "dplatformtheme.h"
#include "private/dplatforminterface_p.h"
#include "personalizationwaylandclientextension.h"
#include <QtWaylandClient/private/qwaylandwindow_p.h>
#include <QtWaylandClient/private/qwaylandsurface_p.h>
#include <QWindow>
DGUI_BEGIN_NAMESPACE
DTreelandPlatformInterface::DTreelandPlatformInterface(DPlatformTheme *platformTheme)
: DPlatformInterface(platformTheme)
{
m_manager = PersonalizationManager::instance();
connect(m_manager, &PersonalizationManager::activeChanged, this, [this](){
if (m_manager->isActive()) {
initContext();
}
});
}
void DTreelandPlatformInterface::initContext()
{
if (m_appearanceContext.isNull()) {
m_appearanceContext.reset(new PersonalizationAppearanceContext(m_manager->get_appearance_context(), this));
}
if (m_fontContext.isNull()) {
m_fontContext.reset(new PersonalizationFontContext(m_manager->get_font_context(), this));
}
}
QByteArray DTreelandPlatformInterface::iconThemeName() const
{
return m_iconThemeName;
}
QByteArray DTreelandPlatformInterface::fontName() const
{
return m_fontName;
}
QByteArray DTreelandPlatformInterface::monoFontName() const
{
return m_monoFontName;
}
qreal DTreelandPlatformInterface::fontPointSize() const
{
return m_fontPointSize;
}
QColor DTreelandPlatformInterface::activeColor() const
{
return m_activeColor;
}
QByteArray DTreelandPlatformInterface::themeName() const
{
return m_themeName;
}
void DTreelandPlatformInterface::setIconThemeName(const QByteArray &iconThemeName)
{
if (m_appearanceContext) {
m_appearanceContext->set_icon_theme(iconThemeName);
}
}
void DTreelandPlatformInterface::setFontName(const QByteArray &fontName)
{
if (m_fontContext) {
m_fontContext->set_font(fontName);
}
}
void DTreelandPlatformInterface::setMonoFontName(const QByteArray &monoFontName)
{
if (m_fontContext) {
m_fontContext->set_monospace_font(monoFontName);
}
}
void DTreelandPlatformInterface::setFontPointSize(qreal fontPointSize)
{
if (m_fontContext) {
m_fontContext->set_font_size(fontPointSize);
}
}
void DTreelandPlatformInterface::setActiveColor(const QColor activeColor)
{
if (m_appearanceContext) {
m_appearanceContext->set_active_color(activeColor.name());
}
}
DGUI_END_NAMESPACE

View File

@ -0,0 +1,66 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef DTREELANDPLATFORMINTERFACE_H
#define DTREELANDPLATFORMINTERFACE_H
#include "private/dplatforminterface_p.h"
#include <QHash>
#include <QQueue>
#include <DObject>
DGUI_BEGIN_NAMESPACE
class DTreelandPlatformInterfacePrivate;
class PersonalizationManager;
class PersonalizationFontContext;
class PersonalizationAppearanceContext;
class PersonalizationWindowContext;
class DTreelandPlatformInterface : public QObject, public DPlatformInterface, public DCORE_NAMESPACE::DObject
{
Q_OBJECT
friend PersonalizationFontContext;
friend PersonalizationAppearanceContext;
friend PersonalizationWindowContext;
public:
explicit DTreelandPlatformInterface(DPlatformTheme *platformTheme);
QByteArray iconThemeName() const override;
QByteArray fontName() const override;
QByteArray monoFontName() const override;
qreal fontPointSize() const override;
QColor activeColor() const override;
QByteArray themeName() const override;
void setIconThemeName(const QByteArray &iconThemeName) override;
void setFontName(const QByteArray &fontName) override;
void setMonoFontName(const QByteArray &monoFontName) override;
void setFontPointSize(qreal fontPointSize) override;
void setActiveColor(const QColor activeColor) override;
private:
void initContext();
private:
PersonalizationManager *m_manager;
QScopedPointer<PersonalizationAppearanceContext> m_appearanceContext;
QScopedPointer<PersonalizationFontContext> m_fontContext;
QColor m_activeColor;
int m_titleHeight;
QByteArray m_fontName;
QByteArray m_monoFontName;
QByteArray m_iconThemeName;
QByteArray m_cursorThemeName;
qreal m_fontPointSize;
int m_windowRadius;
int m_scrollBarPolicy;
QByteArray m_themeName;
uint32_t m_blurOpacity;
};
DGUI_END_NAMESPACE
#endif

View File

@ -0,0 +1,398 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#define protected public
#include <QWindow>
#undef protected
#include "dtreelandplatformwindowinterface.h"
#include <QWaylandClientExtension>
#include <QStyleHints>
#include <private/qwaylandintegration_p.h>
#include <private/qguiapplication_p.h>
#include <private/qwaylandwindow_p.h>
#include <private/qwaylandsurface_p.h>
#include "dvtablehook.h"
#include "personalizationwaylandclientextension.h"
DCORE_USE_NAMESPACE
DGUI_BEGIN_NAMESPACE
class Q_DECL_HIDDEN 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()
{
mapped.remove(static_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);
// TODO Crashed when delete by Vtable.
if (event->type() == QEvent::DeferredDelete) {
DVtableHook::resetVtable(w);
return w->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) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
touchBeginPosition = static_cast<QMouseEvent*>(event)->globalPosition();
#else
touchBeginPosition = static_cast<QMouseEvent*>(event)->globalPos();
#endif
}
// add some redundancy to distinguish trigger between system menu and system move
if (event->type() == QEvent::MouseMove) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QPointF currentPos = static_cast<QMouseEvent*>(event)->globalPosition();
#else
QPointF currentPos = static_cast<QMouseEvent*>(event)->globalPos();
#endif
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 QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (is_mouse_move && !event->isAccepted()
&& w->geometry().contains(static_cast<QMouseEvent*>(event)->globalPosition().toPoint())) {
#else
if (is_mouse_move && !event->isAccepted()
&& w->geometry().contains(static_cast<QMouseEvent*>(event)->globalPos())) {
#endif
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;
}
QMap<QWindow *, DTreeLandPlatformWindowHelper*> DTreeLandPlatformWindowHelper::windowMap;
DTreeLandPlatformWindowHelper *DTreeLandPlatformWindowHelper::get(QWindow *window)
{
if (!PersonalizationManager::instance()->isSupported()) {
return nullptr;
}
if (!window) {
return nullptr;
}
if (auto helper = windowMap.value(window)) {
return helper;
}
auto helper = new DTreeLandPlatformWindowHelper(window);
windowMap[window] = helper;
return helper;
}
DTreeLandPlatformWindowHelper::DTreeLandPlatformWindowHelper(QWindow *window)
: QObject(window)
{
window->installEventFilter(this);
if (!PersonalizationManager::instance()->isActive()) {
qWarning() << "Personalization is not active" << window;
connect(PersonalizationManager::instance(), &PersonalizationManager::activeChanged, this, &DTreeLandPlatformWindowHelper::onActiveChanged, Qt::QueuedConnection);
}
if (window->handle()) {
initWaylandWindow();
}
}
DTreeLandPlatformWindowHelper::~DTreeLandPlatformWindowHelper()
{
// see tst_qwindow.cpp tst_QWindow::qobject_castOnDestruction()
windowMap.remove(static_cast<QWindow*>(parent()));
}
bool DTreeLandPlatformWindowHelper::eventFilter(QObject *watched, QEvent *event) {
if (event->type() == QEvent::PlatformSurface) {
QPlatformSurfaceEvent *se = static_cast<QPlatformSurfaceEvent*>(event);
if (se->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) {
if (PersonalizationManager::instance()->isActive()) {
initWaylandWindow();
onSurfaceCreated();
}
}
}
return QObject::eventFilter(watched, event);
}
void DTreeLandPlatformWindowHelper::initWaylandWindow()
{
auto waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow *>(window()->handle());
if (!waylandWindow) {
qWarning() << "waylandWindow is nullptr!!!";
return;
}
connect(waylandWindow, &QtWaylandClient::QWaylandWindow::wlSurfaceCreated, this, &DTreeLandPlatformWindowHelper::onSurfaceCreated, Qt::UniqueConnection);
connect(waylandWindow, &QtWaylandClient::QWaylandWindow::wlSurfaceDestroyed, this, &DTreeLandPlatformWindowHelper::onSurfaceDestroyed, Qt::UniqueConnection);
}
void DTreeLandPlatformWindowHelper::onActiveChanged()
{
if (PersonalizationManager::instance()->isActive()) {
qDebug() << "Personalization is actived, window" << window();
if (window()->handle()) {
onSurfaceCreated();
}
}
}
void DTreeLandPlatformWindowHelper::onSurfaceCreated()
{
if (m_isNoTitlebar) {
doSetEnabledNoTitlebar();
}
if (m_radius > 0) {
doSetWindowRadius();
}
if (m_isWindowBlur) {
doSetEnabledBlurWindow();
}
}
void DTreeLandPlatformWindowHelper::onSurfaceDestroyed()
{
if (m_windowContext) {
m_windowContext->deleteLater();
m_windowContext = nullptr;
}
}
PersonalizationWindowContext *DTreeLandPlatformWindowHelper::windowContext() const
{
if (m_windowContext) {
return m_windowContext;
}
auto waylandWindow = dynamic_cast<QtWaylandClient::QWaylandWindow *>(window()->handle());
if (!waylandWindow)
return nullptr;
if (!waylandWindow->waylandSurface()) {
qWarning() << "waylandSurface is nullptr!!!";
return nullptr;
}
auto surface = waylandWindow->waylandSurface()->object();
if (!surface) {
qWarning() << "wl_surface is nullptr!!!";
return nullptr;
}
if (!m_windowContext) {
const_cast<DTreeLandPlatformWindowHelper *>(this)->m_windowContext = new PersonalizationWindowContext(PersonalizationManager::instance()->get_window_context(surface));
}
return m_windowContext;
}
void DTreeLandPlatformWindowHelper::setEnabledNoTitlebar(bool enable)
{
m_isNoTitlebar = enable;
doSetEnabledNoTitlebar();
}
void DTreeLandPlatformWindowHelper::setWindowRadius(int windowRadius)
{
m_radius = windowRadius;
doSetWindowRadius();
}
void DTreeLandPlatformWindowHelper::setEnableBlurWindow(bool enableBlurWindow)
{
m_isWindowBlur = enableBlurWindow;
doSetEnabledBlurWindow();
}
void DTreeLandPlatformWindowHelper::doSetEnabledNoTitlebar()
{
if (auto context = windowContext()) {
context->set_titlebar(m_isNoTitlebar ? PersonalizationWindowContext::enable_mode_disable : PersonalizationWindowContext::enable_mode_enable);
}
}
void DTreeLandPlatformWindowHelper::doSetWindowRadius()
{
if (auto context = windowContext()) {
context->set_round_corner_radius(m_radius);
}
}
void DTreeLandPlatformWindowHelper::doSetEnabledBlurWindow()
{
if (auto context = windowContext()) {
context->set_blend_mode(m_isWindowBlur ? PersonalizationWindowContext::blend_mode_blur : PersonalizationWindowContext::blend_mode_transparent);
}
}
DTreeLandPlatformWindowInterface::DTreeLandPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle, QObject *parent)
: QObject(parent)
, DPlatformWindowInterface(window, platformHandle)
{
if (!MoveWindowHelper::mapped.value(window)) {
Q_UNUSED(new MoveWindowHelper(window))
}
}
DTreeLandPlatformWindowInterface::~DTreeLandPlatformWindowInterface()
{
}
void DTreeLandPlatformWindowInterface::setEnabled(bool enabled)
{
if (setEnabledNoTitlebar(enabled)) {
return;
}
}
bool DTreeLandPlatformWindowInterface::isEnabled() const
{
return isEnabledNoTitlebar();
}
bool DTreeLandPlatformWindowInterface::isEnabledNoTitlebar() const
{
return m_isNoTitlebar;
}
bool DTreeLandPlatformWindowInterface::setEnabledNoTitlebar(bool enable)
{
if (m_isNoTitlebar == enable) {
return true;
}
m_isNoTitlebar = enable;
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) {
helper->setEnabledNoTitlebar(enable);
}
return true;
}
int DTreeLandPlatformWindowInterface::windowRadius() const
{
return m_radius;
}
void DTreeLandPlatformWindowInterface::setWindowRadius(int windowRadius)
{
if (m_radius == windowRadius) {
return;
}
m_radius = windowRadius;
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) {
helper->setWindowRadius(m_radius);
}
if (m_platformHandle) {
Q_EMIT m_platformHandle->windowRadiusChanged();
}
}
bool DTreeLandPlatformWindowInterface::enableBlurWindow() const
{
return m_isWindowBlur;
}
void DTreeLandPlatformWindowInterface::setEnableBlurWindow(bool enable)
{
if (m_isWindowBlur == enable) {
return;
}
m_isWindowBlur = enable;
if (auto helper = DTreeLandPlatformWindowHelper::get(m_window)) {
helper->setEnableBlurWindow(enable);
}
if (m_platformHandle) {
Q_EMIT m_platformHandle->enableBlurWindowChanged();
}
}
DGUI_END_NAMESPACE

View File

@ -0,0 +1,76 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef DTREELANDPLATFORMWINDOWINTERFACE_H
#define DTREELANDPLATFORMWINDOWINTERFACE_H
#include "dtkgui_global.h"
#include "dtreelandplatforminterface.h"
#include <QObject>
#include <QtWaylandClient/private/qwaylandwindow_p.h>
#include "private/dplatformwindowinterface_p.h"
DGUI_BEGIN_NAMESPACE
class PersonalizationWindowContext;
class DTreeLandPlatformWindowHelper : public QObject {
Q_OBJECT
public:
static DTreeLandPlatformWindowHelper *get(QWindow *window);
~DTreeLandPlatformWindowHelper() override;
QWindow *window() const { return qobject_cast<QWindow *>(parent()); }
PersonalizationWindowContext *windowContext() const;
void setEnabledNoTitlebar(bool enable);
void setWindowRadius(int windowRadius);
void setEnableBlurWindow(bool enableBlurWindow);
private slots:
void onActiveChanged();
void onSurfaceCreated();
void onSurfaceDestroyed();
private:
explicit DTreeLandPlatformWindowHelper(QWindow *window);
bool eventFilter(QObject *watched, QEvent *event) override;
void initWaylandWindow();
void doSetEnabledNoTitlebar();
void doSetWindowRadius();
void doSetEnabledBlurWindow();
private:
PersonalizationWindowContext *m_windowContext = nullptr;
static QMap<QWindow *, DTreeLandPlatformWindowHelper*> windowMap;
bool m_isNoTitlebar = false;
bool m_isWindowBlur = false;
int m_radius = 0;
};
class DTreeLandPlatformWindowInterface : public QObject, public DPlatformWindowInterface
{
Q_OBJECT
public:
DTreeLandPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle, QObject *parent = nullptr);
~DTreeLandPlatformWindowInterface() override;
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;
private:
bool m_isNoTitlebar = false;
bool m_isWindowBlur = false;
int m_radius = 0;
};
DGUI_END_NAMESPACE
#endif // DTREELANDPLATFORMWINDOWINTERFACE_H

View File

@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "dtreelandwindowmanagerhelper.h"
#include "personalizationwaylandclientextension.h"
DGUI_BEGIN_NAMESPACE
TreelandWindowManagerHelper::TreelandWindowManagerHelper(QObject *parent)
: DWindowManagerHelper(parent)
{
connect(PersonalizationManager::instance(), &PersonalizationManager::activeChanged, this, [this](){
Q_EMIT hasBlurWindowChanged();
Q_EMIT hasNoTitlebarChanged();
});
}
bool TreelandWindowManagerHelper::hasBlurWindow() const
{
return PersonalizationManager::instance()->isSupported();
}
bool TreelandWindowManagerHelper::hasComposite() const
{
return true;
}
bool TreelandWindowManagerHelper::hasNoTitlebar() const
{
return PersonalizationManager::instance()->isSupported();
}
DGUI_END_NAMESPACE

View File

@ -0,0 +1,25 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef DTREELANDWINDOWMANAGERHELPER_H
#define DTREELANDWINDOWMANAGERHELPER_H
#include "dtkgui_global.h"
#include "dwindowmanagerhelper.h"
#include <QObject>
DGUI_BEGIN_NAMESPACE
class TreelandWindowManagerHelper : public DWindowManagerHelper
{
public:
explicit TreelandWindowManagerHelper(QObject *parent = 0);
bool hasBlurWindow() const;
bool hasComposite() const;
bool hasNoTitlebar() const;
};
DGUI_END_NAMESPACE
#endif // DTREELANDWINDOWMANAGERHELPER_H

View File

@ -0,0 +1,152 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "personalizationwaylandclientextension.h"
#include <private/qguiapplication_p.h>
#include <private/qwaylandintegration_p.h>
#include <private/qwaylandwindow_p.h>
#include <qwaylandclientextension.h>
#include "dplatformtheme.h"
#include <QtWaylandClient/private/qwaylandsurface_p.h>
#include <QtWaylandClient/private/qwaylandwindow_p.h>
#include <QGuiApplication>
DGUI_BEGIN_NAMESPACE
PersonalizationManager::PersonalizationManager()
: QWaylandClientExtensionTemplate<PersonalizationManager>(treeland_personalization_manager_v1_interface.version)
, m_isSupported(false)
{
QtWaylandClient::QWaylandIntegration *waylandIntegration = static_cast<QtWaylandClient::QWaylandIntegration *>(QGuiApplicationPrivate::platformIntegration());
if (!waylandIntegration) {
qWarning() << "waylandIntegration is nullptr!!!";
return;
}
m_waylandDisplay = waylandIntegration->display();
if (m_waylandDisplay == nullptr) {
qWarning() << "waylandDisplay is nullptr!!!";
return;
}
addListener();
m_isSupported = m_waylandDisplay->hasRegistryGlobal(QString::fromUtf8(treeland_personalization_manager_v1_interface.name));
if (!m_isSupported) {
qWarning() << "PersonalizationManager is not support";
}
}
void PersonalizationManager::addListener()
{
m_waylandDisplay->addRegistryListener(&handleListenerGlobal, this);
}
void PersonalizationManager::removeListener()
{
m_waylandDisplay->removeListener(&handleListenerGlobal, this);
}
void PersonalizationManager::handleListenerGlobal(void *data, wl_registry *registry, uint32_t id, const QString &interface, uint32_t version)
{
if (interface == treeland_personalization_manager_v1_interface.name) {
PersonalizationManager *integration = static_cast<PersonalizationManager *>(data);
if (!integration) {
qWarning() << "integration is nullptr!!!";
return;
}
integration->init(registry, id, version);
}
}
PersonalizationManager *PersonalizationManager::instance()
{
static PersonalizationManager instance;
return &instance;
}
PersonalizationWindowContext::PersonalizationWindowContext(struct ::treeland_personalization_window_context_v1 *context)
: QWaylandClientExtensionTemplate<PersonalizationWindowContext>(treeland_personalization_window_context_v1_interface.version)
, QtWayland::treeland_personalization_window_context_v1(context)
{
}
PersonalizationAppearanceContext::PersonalizationAppearanceContext(struct ::treeland_personalization_appearance_context_v1 *context, DTreelandPlatformInterface *interface)
: QWaylandClientExtensionTemplate<PersonalizationAppearanceContext>(treeland_personalization_appearance_context_v1_interface.version)
, QtWayland::treeland_personalization_appearance_context_v1(context)
, m_interface(interface)
{
get_round_corner_radius();
get_icon_theme();
get_active_color();
get_window_theme_type();
get_window_opacity();
}
void PersonalizationAppearanceContext::treeland_personalization_appearance_context_v1_round_corner_radius(int32_t radius)
{
m_interface->m_windowRadius = radius;
emit m_interface->m_platformTheme->windowRadiusChanged(radius);
}
void PersonalizationAppearanceContext::treeland_personalization_appearance_context_v1_icon_theme(const QString &theme_name)
{
m_interface->m_iconThemeName = theme_name.toUtf8();
emit m_interface->m_platformTheme->iconThemeNameChanged(theme_name.toUtf8());
}
void PersonalizationAppearanceContext::treeland_personalization_appearance_context_v1_active_color(const QString &active_color)
{
m_interface->m_activeColor = active_color;
emit m_interface->m_platformTheme->activeColorChanged(active_color);
}
void PersonalizationAppearanceContext::treeland_personalization_appearance_context_v1_window_theme_type(uint32_t type)
{
QString theme = QStringLiteral("deepin");
if (type == PersonalizationAppearanceContext::theme_type::theme_type_dark) {
theme = theme + QStringLiteral("-dark");
}
m_interface->m_themeName = theme.toUtf8();
emit m_interface->m_platformTheme->themeNameChanged(theme.toUtf8());
}
void PersonalizationAppearanceContext::treeland_personalization_appearance_context_v1_window_opacity(uint32_t opacity)
{
m_interface->m_blurOpacity = opacity;
}
PersonalizationFontContext::PersonalizationFontContext(struct ::treeland_personalization_font_context_v1 *context, DTreelandPlatformInterface *interface)
: QWaylandClientExtensionTemplate<PersonalizationFontContext>(treeland_personalization_font_context_v1_interface.version)
, QtWayland::treeland_personalization_font_context_v1(context)
, m_interface(interface)
{
get_font();
get_monospace_font();
get_font_size();
}
void PersonalizationFontContext::treeland_personalization_font_context_v1_font(const QString &font_name)
{
m_interface->m_fontName = font_name.toUtf8();
emit m_interface->m_platformTheme->fontNameChanged(font_name.toUtf8());
}
void PersonalizationFontContext::treeland_personalization_font_context_v1_monospace_font(const QString &font_name)
{
m_interface->m_monoFontName = font_name.toUtf8();
emit m_interface->m_platformTheme->monoFontNameChanged(font_name.toUtf8());
}
void PersonalizationFontContext::treeland_personalization_font_context_v1_font_size(uint32_t font_size)
{
// treeland侧无法存储浮点数约定 font_size 为 10 倍的 pointSize
qreal pointSize = font_size / 10.0;
pointSize = qBound(8.25, pointSize, 15.00);
m_interface->m_fontPointSize = pointSize;
emit m_interface->m_platformTheme->fontPointSizeChanged(pointSize);
}
DGUI_END_NAMESPACE

View File

@ -0,0 +1,87 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef PERSONALIZATIONWAYLANDCLIENTEXTENSION_H
#define PERSONALIZATIONWAYLANDCLIENTEXTENSION_H
#include "dtreelandplatforminterface.h"
#include "qwayland-treeland-personalization-manager-v1.h"
#include <dtkgui_global.h>
#include <private/qwaylanddisplay_p.h>
#include <QtWaylandClient/QWaylandClientExtension>
#include <QWaylandClientExtensionTemplate>
DGUI_BEGIN_NAMESPACE
class PersonalizationAppearanceContext;
class PersonalizationCursorContext;
class PersonalizationFontContext;
class DTreelandPlatformInterfacePrivate;
class PersonalizationManager: public QWaylandClientExtensionTemplate<PersonalizationManager>,
public QtWayland::treeland_personalization_manager_v1
{
Q_OBJECT
public:
static PersonalizationManager *instance();
[[nodiscard]]inline bool isSupported() const { return m_isSupported; }
private:
void addListener();
void removeListener();
explicit PersonalizationManager();
static void handleListenerGlobal(void *data, wl_registry *registry, uint32_t id, const QString &interface, uint32_t version);
private:
QtWaylandClient::QWaylandDisplay *m_waylandDisplay;
bool m_isSupported;
};
class PersonalizationWindowContext : public QWaylandClientExtensionTemplate<PersonalizationWindowContext>,
public QtWayland::treeland_personalization_window_context_v1
{
Q_OBJECT
public:
explicit PersonalizationWindowContext(struct ::treeland_personalization_window_context_v1 *context);
};
class PersonalizationAppearanceContext : public QWaylandClientExtensionTemplate<PersonalizationAppearanceContext>,
public QtWayland::treeland_personalization_appearance_context_v1
{
Q_OBJECT
public:
explicit PersonalizationAppearanceContext(struct ::treeland_personalization_appearance_context_v1 *context, DTreelandPlatformInterface *interface);
protected:
void treeland_personalization_appearance_context_v1_round_corner_radius(int32_t radius) override;
void treeland_personalization_appearance_context_v1_icon_theme(const QString &theme_name) override;
void treeland_personalization_appearance_context_v1_active_color(const QString &active_color) override;
void treeland_personalization_appearance_context_v1_window_theme_type(uint32_t type) override;
void treeland_personalization_appearance_context_v1_window_opacity(uint32_t opacity) override;
private:
DTreelandPlatformInterface *m_interface;
};
class PersonalizationFontContext : public QWaylandClientExtensionTemplate<PersonalizationFontContext>,
public QtWayland::treeland_personalization_font_context_v1
{
Q_OBJECT
public:
explicit PersonalizationFontContext(struct ::treeland_personalization_font_context_v1 *context, DTreelandPlatformInterface *interface);
protected:
void treeland_personalization_font_context_v1_font(const QString &font_name) override;
void treeland_personalization_font_context_v1_monospace_font(const QString &font_name) override;
void treeland_personalization_font_context_v1_font_size(uint32_t font_size) override;
private:
DTreelandPlatformInterface *m_interface;
};
DGUI_END_NAMESPACE
#endif // PERSONALIZATIONWAYLANDCLIENTEXTENSION_H

View File

@ -0,0 +1,10 @@
file(GLOB TREELAND_HEADER
${CMAKE_CURRENT_LIST_DIR}/*.h
)
file(GLOB TREELAND_SOURCE
${CMAKE_CURRENT_LIST_DIR}/*.cpp
)
set(treeland_SRC
${TREELAND_HEADER}
${TREELAND_SOURCE}
)

View File

@ -0,0 +1,708 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "dxcbplatforminterface.h"
#include "dxcbplatforminterface_p.h"
#include <DNativeSettings>
#include <QPlatformSurfaceEvent>
#include <QGuiApplication>
#include <QMetaObject>
#include <QMetaProperty>
#include "dplatformtheme.h"
#include "dguiapplicationhelper.h"
#include <qpa/qplatformwindow.h>
DGUI_BEGIN_NAMESPACE
#define DEFINE_CONST_CHAR(Name) const char _##Name[] = "_d_" #Name
#define FETCH_PROPERTY(Name, Function) \
D_DC(DXCBPlatformInterface); \
QVariant value = d->theme->getSetting(QByteArrayLiteral(Name)); \
if (d->fallbackProperty && !value.isValid() && d->parent) \
return d->parent->Function(); \
#define FETCH_PROPERTY_WITH_ARGS(Name, Function, Args) \
D_DC(DXCBPlatformInterface); \
QVariant value = d->theme->getSetting(Name); \
if (d->fallbackProperty && !value.isValid() && d->parent) \
return d->parent->Function(Args); \
DXCBPlatformInterfacePrivate::DXCBPlatformInterfacePrivate(DXCBPlatformInterface *qq)
:DCORE_NAMESPACE::DObjectPrivate(qq)
{
}
void DXCBPlatformInterfacePrivate::_q_onThemePropertyChanged(const QByteArray &name, const QVariant &value)
{
D_Q(DXCBPlatformInterface);
// 转发属性变化的信号此信号来源可能为parent theme或“非调色板”的属性变化。
// 使用队列的形式转发,避免多次发出同样的信号
// q->staticMetaObject.invokeMethod(q, "propertyChanged", Qt::QueuedConnection,
// Q_ARG(const QByteArray&, name), Q_ARG(const QVariant&, value));
if (QByteArrayLiteral("Gtk/FontName") == name) {
Q_EMIT q->m_platformTheme->gtkFontNameChanged(value.toByteArray());
return;
}
if (name.startsWith("Qt/DPI/")) {
const QString &screen_name = QString::fromLocal8Bit(name.mid(7));
if (!screen_name.isEmpty()) {
bool ok = false;
int dpi = value.toInt(&ok);
Q_EMIT q->m_platformTheme->dotsPerInchChanged(screen_name, ok ? dpi : -1);
}
return;
}
if (QByteArrayLiteral("Xft/DPI") == name) {
bool ok = false;
int dpi = value.toInt(&ok);
Q_EMIT q->m_platformTheme->dotsPerInchChanged(QString(), ok ? dpi : -1);
}
const QByteArrayList &list = name.split('/');
if (list.count() != 2)
return;
QByteArray pn = list.last();
if (pn.isEmpty())
return;
// 转换首字母为小写
pn[0] = QChar(pn.at(0)).toLower().toLatin1();
// 直接使用静态的meta object防止通过metaObject函数调用到dynamic metaobject
const QMetaObject *mo = &DPlatformTheme::staticMetaObject;
int index = mo->indexOfProperty(pn.constData());
if (index < 0)
return;
const QMetaProperty &p = mo->property(index);
bool is_parent_signal = q->sender() != theme;
// 当自己的属性有效时应该忽略父主题的属性变化信号,优先以自身的属性值为准。
if (is_parent_signal && p.read(q).isValid()) {
return;
}
if (p.hasNotifySignal()) {
// invoke会做Q_ASSERT(mobj->cast(object))判断, DPlatformTheme的dynamic metaObject为
// qt5platform-plugin插件的DNativeSettings. 导致崩溃.
// invokeOnGadget与invoke代码逻辑一致, 只是少了异步支持.
// return;
if (!p.notifySignal().invokeOnGadget(q->m_platformTheme, QGenericArgument(value.typeName(), value.constData())))
qWarning() << "_q_onThemePropertyChanged() error when notify signal" << p.notifySignal().name();
}
}
DXCBPlatformInterface::DXCBPlatformInterface(quint32 window, DPlatformTheme *platformTheme)
: DPlatformInterface(platformTheme)
, Core::DObject(*new DXCBPlatformInterfacePrivate(this))
{
D_D(DXCBPlatformInterface);
d->theme = new DNativeSettings(window, QByteArray(), platformTheme);
connect(d->theme, SIGNAL(propertyChanged(const QByteArray &, const QVariant &)),
this, SLOT(_q_onThemePropertyChanged(const QByteArray &, const QVariant &)));
}
int DXCBPlatformInterface::cursorBlinkTime() const
{
FETCH_PROPERTY("Net/CursorBlinkTime", cursorBlinkTime)
return value.toInt();
}
int DXCBPlatformInterface::cursorBlinkTimeout() const
{
FETCH_PROPERTY("Net/CursorBlinkTimeout", cursorBlinkTimeout)
return value.toInt();
}
bool DXCBPlatformInterface::cursorBlink() const
{
FETCH_PROPERTY("Net/CursorBlink", cursorBlink)
return value.toInt();
}
int DXCBPlatformInterface::doubleClickDistance() const
{
FETCH_PROPERTY("Net/DoubleClickDistance", doubleClickDistance)
return value.toInt();
}
int DXCBPlatformInterface::doubleClickTime() const
{
FETCH_PROPERTY("Net/DoubleClickTime", doubleClickTime)
return value.toInt();
}
int DXCBPlatformInterface::dndDragThreshold() const
{
FETCH_PROPERTY("Net/DndDragThreshold", dndDragThreshold)
return value.toInt();
}
int DXCBPlatformInterface::windowRadius() const
{
return windowRadius(-1);
}
int DXCBPlatformInterface::windowRadius(int defaultValue) const
{
Q_D(const DXCBPlatformInterface);
QVariant value = d->theme->getSetting(QByteArrayLiteral("DTK/WindowRadius"));
bool ok = false;
if (d->fallbackProperty && !value.isValid() && d->parent)
return d->parent->windowRadius(defaultValue);
int radius = value.toInt(&ok);
return ok ? radius : defaultValue;
}
QByteArray DXCBPlatformInterface::themeName() const
{
FETCH_PROPERTY("Net/ThemeName", themeName)
return value.toByteArray();
}
QByteArray DXCBPlatformInterface::iconThemeName() const
{
FETCH_PROPERTY("Net/IconThemeName", iconThemeName)
return value.toByteArray();
}
QByteArray DXCBPlatformInterface::soundThemeName() const
{
FETCH_PROPERTY("Net/SoundThemeName", soundThemeName)
return value.toByteArray();
}
QByteArray DXCBPlatformInterface::fontName() const
{
FETCH_PROPERTY("Qt/FontName", fontName)
return value.toByteArray();
}
QByteArray DXCBPlatformInterface::monoFontName() const
{
FETCH_PROPERTY("Qt/MonoFontName", monoFontName)
return value.toByteArray();
}
qreal DXCBPlatformInterface::fontPointSize() const
{
FETCH_PROPERTY("Qt/FontPointSize", fontPointSize)
return value.toDouble();
}
QByteArray DXCBPlatformInterface::gtkFontName() const
{
FETCH_PROPERTY("Gtk/FontName", gtkFontName)
return value.toByteArray();
}
QColor DXCBPlatformInterface::activeColor() const
{
FETCH_PROPERTY("Qt/ActiveColor", activeColor)
return qvariant_cast<QColor>(value);
}
QColor DXCBPlatformInterface::darkActiveColor() const
{
FETCH_PROPERTY("Qt/DarkActiveColor", darkActiveColor)
return qvariant_cast<QColor>(value);
}
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
#define GET_COLOR(Role) qvariant_cast<QColor>(getSetting(QByteArrayLiteral(#Role)))
static QColor getSetting(const QByteArray &key)
{
Q_UNUSED(key);
qWarning() << "Not implemented, key:" << key;
return {};
}
QColor DXCBPlatformInterface::window() const
{
return GET_COLOR(window);
}
QColor DXCBPlatformInterface::windowText() const
{
return GET_COLOR(windowText);
}
QColor DXCBPlatformInterface::base() const
{
return GET_COLOR(base);
}
QColor DXCBPlatformInterface::alternateBase() const
{
return GET_COLOR(alternateBase);
}
QColor DXCBPlatformInterface::toolTipBase() const
{
return GET_COLOR(toolTipBase);
}
QColor DXCBPlatformInterface::toolTipText() const
{
return GET_COLOR(toolTipText);
}
QColor DXCBPlatformInterface::text() const
{
return GET_COLOR(text);
}
QColor DXCBPlatformInterface::button() const
{
return GET_COLOR(button);
}
QColor DXCBPlatformInterface::buttonText() const
{
return GET_COLOR(buttonText);
}
QColor DXCBPlatformInterface::brightText() const
{
return GET_COLOR(brightText);
}
QColor DXCBPlatformInterface::light() const
{
return GET_COLOR(light);
}
QColor DXCBPlatformInterface::midlight() const
{
return GET_COLOR(midlight);
}
QColor DXCBPlatformInterface::dark() const
{
return GET_COLOR(dark);
}
QColor DXCBPlatformInterface::mid() const
{
return GET_COLOR(mid);
}
QColor DXCBPlatformInterface::shadow() const
{
return GET_COLOR(shadow);
}
QColor DXCBPlatformInterface::highlight() const
{
return GET_COLOR(highlight);
}
QColor DXCBPlatformInterface::highlightedText() const
{
return GET_COLOR(highlightedText);
}
QColor DXCBPlatformInterface::link() const
{
return GET_COLOR(link);
}
QColor DXCBPlatformInterface::linkVisited() const
{
return GET_COLOR(linkVisited);
}
QColor DXCBPlatformInterface::itemBackground() const
{
return GET_COLOR(itemBackground);
}
QColor DXCBPlatformInterface::textTitle() const
{
return GET_COLOR(textTitle);
}
QColor DXCBPlatformInterface::textTips() const
{
return GET_COLOR(textTips);
}
QColor DXCBPlatformInterface::textWarning() const
{
return GET_COLOR(textWarning);
}
QColor DXCBPlatformInterface::textLively() const
{
return GET_COLOR(textLively);
}
QColor DXCBPlatformInterface::lightLively() const
{
return GET_COLOR(lightLively);
}
QColor DXCBPlatformInterface::darkLively() const
{
return GET_COLOR(darkLively);
}
QColor DXCBPlatformInterface::frameBorder() const
{
return GET_COLOR(frameBorder);
}
#endif
int DXCBPlatformInterface::dotsPerInch(const QString &screenName) const
{
bool ok = false;
if (!screenName.isEmpty()) {
FETCH_PROPERTY_WITH_ARGS("Qt/DPI/" + screenName.toLocal8Bit(), dotsPerInch, screenName);
int dpi = value.toInt(&ok);
if (ok)
return dpi;
}
FETCH_PROPERTY_WITH_ARGS("Xft/DPI", dotsPerInch, screenName);
int dpi = value.toInt(&ok);
return ok ? dpi : -1;
}
/*!
\property DXCBPlatformInterface::sizeMode
\brief This property holds the sizeMode of the system's SizeMode.
*/
int DXCBPlatformInterface::sizeMode() const
{
D_DC(DXCBPlatformInterface);
QVariant value = d->theme->getSetting(QByteArrayLiteral("DTK/SizeMode"));
return value.toInt();
}
/*!
\property DXCBPlatformInterface::scrollBarPolicy
\brief This property holds the scrollBarPolicy of the system. same as Qt::ScrollBarPolicy
\retval 0 show as needed auto hide, default
\retval 1 always off
\retval 2 always on
*/
int DXCBPlatformInterface::scrollBarPolicy() const
{
FETCH_PROPERTY("Qt/ScrollBarPolicy", scrollBarPolicy)
return qvariant_cast<int>(value);
}
void DXCBPlatformInterface::setCursorBlinkTime(int cursorBlinkTime)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Net/CursorBlinkTime", cursorBlinkTime);
}
void DXCBPlatformInterface::setCursorBlinkTimeout(int cursorBlinkTimeout)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Net/CursorBlinkTimeout", cursorBlinkTimeout);
}
void DXCBPlatformInterface::setCursorBlink(bool cursorBlink)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Net/CursorBlink", cursorBlink);
}
void DXCBPlatformInterface::setDoubleClickDistance(int doubleClickDistance)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Net/DoubleClickDistance", doubleClickDistance);
}
void DXCBPlatformInterface::setDoubleClickTime(int doubleClickTime)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Net/DoubleClickTime", doubleClickTime);
}
void DXCBPlatformInterface::setDndDragThreshold(int dndDragThreshold)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Net/DndDragThreshold", dndDragThreshold);
}
void DXCBPlatformInterface::setThemeName(const QByteArray &themeName)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Net/ThemeName", themeName);
}
void DXCBPlatformInterface::setIconThemeName(const QByteArray &iconThemeName)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Net/IconThemeName", iconThemeName);
}
void DXCBPlatformInterface::setSoundThemeName(const QByteArray &soundThemeName)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Net/SoundThemeName", soundThemeName);
}
void DXCBPlatformInterface::setFontName(const QByteArray &fontName)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Qt/FontName", fontName);
}
void DXCBPlatformInterface::setMonoFontName(const QByteArray &monoFontName)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Qt/MonoFontName", monoFontName);
}
void DXCBPlatformInterface::setFontPointSize(qreal fontPointSize)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Qt/FontPointSize", fontPointSize);
}
void DXCBPlatformInterface::setGtkFontName(const QByteArray &fontName)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Gtk/FontName", fontName);
}
void DXCBPlatformInterface::setActiveColor(const QColor activeColor)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Qt/ActiveColor", activeColor);
}
void DXCBPlatformInterface::setDarkActiveColor(const QColor &activeColor)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("Qt/DarkActiveColor", activeColor);
}
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
#define SET_COLOR(Role) setSetting(QByteArrayLiteral(#Role), Role)
static void setSetting(const QByteArray &key, const QColor &color)
{
Q_UNUSED(key);
Q_UNUSED(color);
qWarning() << "Not implemented, key: " << key << "value: " << color;
}
void DXCBPlatformInterface::setWindow(const QColor &window)
{
SET_COLOR(window);
}
void DXCBPlatformInterface::setWindowText(const QColor &windowText)
{
SET_COLOR(windowText);
}
void DXCBPlatformInterface::setBase(const QColor &base)
{
SET_COLOR(base);
}
void DXCBPlatformInterface::setAlternateBase(const QColor &alternateBase)
{
SET_COLOR(alternateBase);
}
void DXCBPlatformInterface::setToolTipBase(const QColor &toolTipBase)
{
SET_COLOR(toolTipBase);
}
void DXCBPlatformInterface::setToolTipText(const QColor &toolTipText)
{
SET_COLOR(toolTipText);
}
void DXCBPlatformInterface::setText(const QColor &text)
{
SET_COLOR(text);
}
void DXCBPlatformInterface::setButton(const QColor &button)
{
SET_COLOR(button);
}
void DXCBPlatformInterface::setButtonText(const QColor &buttonText)
{
SET_COLOR(buttonText);
}
void DXCBPlatformInterface::setBrightText(const QColor &brightText)
{
SET_COLOR(brightText);
}
void DXCBPlatformInterface::setLight(const QColor &light)
{
SET_COLOR(light);
}
void DXCBPlatformInterface::setMidlight(const QColor &midlight)
{
SET_COLOR(midlight);
}
void DXCBPlatformInterface::setDark(const QColor &dark)
{
SET_COLOR(dark);
}
void DXCBPlatformInterface::setMid(const QColor &mid)
{
SET_COLOR(mid);
}
void DXCBPlatformInterface::setShadow(const QColor &shadow)
{
SET_COLOR(shadow);
}
void DXCBPlatformInterface::setHighlight(const QColor &highlight)
{
SET_COLOR(highlight);
}
void DXCBPlatformInterface::setHighlightedText(const QColor &highlightText)
{
SET_COLOR(highlightText);
}
void DXCBPlatformInterface::setLink(const QColor &link)
{
SET_COLOR(link);
}
void DXCBPlatformInterface::setLinkVisited(const QColor &linkVisited)
{
SET_COLOR(linkVisited);
}
void DXCBPlatformInterface::setItemBackground(const QColor &itemBackground)
{
SET_COLOR(itemBackground);
}
void DXCBPlatformInterface::setTextTitle(const QColor &textTitle)
{
SET_COLOR(textTitle);
}
void DXCBPlatformInterface::setTextTips(const QColor &textTips)
{
SET_COLOR(textTips);
}
void DXCBPlatformInterface::setTextWarning(const QColor &textWarning)
{
SET_COLOR(textWarning);
}
void DXCBPlatformInterface::setTextLively(const QColor &textLively)
{
SET_COLOR(textLively);
}
void DXCBPlatformInterface::setLightLively(const QColor &lightLively)
{
SET_COLOR(lightLively);
}
void DXCBPlatformInterface::setDarkLively(const QColor &darkLively)
{
SET_COLOR(darkLively);
}
void DXCBPlatformInterface::setFrameBorder(const QColor &frameBorder)
{
SET_COLOR(frameBorder);
}
#endif
void DXCBPlatformInterface::setDotsPerInch(const QString &screenName, int dpi)
{
D_D(DXCBPlatformInterface);
if (screenName.isEmpty()) {
d->theme->setSetting("Xft/DPI", dpi);
} else {
d->theme->setSetting("Qt/DPI/" + screenName.toLocal8Bit(), dpi);
}
}
void DXCBPlatformInterface::setWindowRadius(int windowRadius)
{
D_D(DXCBPlatformInterface);
d->theme->setSetting("DTK/WindowRadius", windowRadius);
}
DGUI_END_NAMESPACE
#include "moc_dxcbplatforminterface.cpp"

View File

@ -0,0 +1,131 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef DXCBPLATFORMINTERFACE_H
#define DXCBPLATFORMINTERFACE_H
#include "private/dplatforminterface_p.h"
#include <DObject>
DGUI_BEGIN_NAMESPACE
class DXCBPlatformInterfacePrivate;
class DXCBPlatformInterface : public QObject, public DPlatformInterface, public DCORE_NAMESPACE::DObject
{
Q_OBJECT
D_DECLARE_PRIVATE(DXCBPlatformInterface)
public:
explicit DXCBPlatformInterface(quint32 window, DPlatformTheme *platformTheme);
int cursorBlinkTime() const override;
int cursorBlinkTimeout() const override;
bool cursorBlink() const override;
int doubleClickDistance() const override;
int doubleClickTime() const override;
int dndDragThreshold() const override;
int windowRadius() const override;
int windowRadius(int defaultValue) const override;
QByteArray themeName() const override;
QByteArray iconThemeName() const override;
QByteArray soundThemeName() const override;
QByteArray fontName() const override;
QByteArray monoFontName() const override;
qreal fontPointSize() const override;
QByteArray gtkFontName() const override;
QColor activeColor() const override;
QColor darkActiveColor() const override;
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
QColor window() const override;
QColor windowText() const override;
QColor base() const override;
QColor alternateBase() const override;
QColor toolTipText() const override;
QColor toolTipBase() const override;
QColor text() const override;
QColor button() const override;
QColor buttonText() const override;
QColor brightText() const override;
QColor light() const override;
QColor midlight() const override;
QColor dark() const override;
QColor mid() const override;
QColor shadow() const override;
QColor highlight() const override;
QColor highlightedText() const override;
QColor link() const override;
QColor linkVisited() const override;
QColor itemBackground() const override;
QColor textTitle() const override;
QColor textTips() const override;
QColor textWarning() const override;
QColor textLively() const override;
QColor lightLively() const override;
QColor darkLively() const override;
QColor frameBorder() const override;
#endif
int sizeMode() const override;
int scrollBarPolicy() const override;
public Q_SLOTS:
void setCursorBlinkTime(int cursorBlinkTime) override;
void setCursorBlinkTimeout(int cursorBlinkTimeout) override;
void setCursorBlink(bool cursorBlink) override;
void setDoubleClickDistance(int doubleClickDistance) override;
void setDoubleClickTime(int doubleClickTime) override;
void setDndDragThreshold(int dndDragThreshold) override;
void setThemeName(const QByteArray &themeName) override;
void setIconThemeName(const QByteArray &iconThemeName) override;
void setSoundThemeName(const QByteArray &soundThemeName) override;
void setFontName(const QByteArray &fontName) override;
void setMonoFontName(const QByteArray &monoFontName) override;
void setFontPointSize(qreal fontPointSize) override;
void setGtkFontName(const QByteArray &fontName) override;
void setActiveColor(const QColor activeColor) override;
void setDarkActiveColor(const QColor &activeColor) override;
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
void setWindow(const QColor &window) override;
void setWindowText(const QColor &windowText) override;
void setBase(const QColor &base) override;
void setAlternateBase(const QColor &alternateBase) override;
void setToolTipBase(const QColor &toolTipBase) override;
void setToolTipText(const QColor &toolTipText) override;
void setText(const QColor &text) override;
void setButton(const QColor &button) override;
void setButtonText(const QColor &buttonText) override;
void setBrightText(const QColor &brightText) override;
void setLight(const QColor &light) override;
void setMidlight(const QColor &midlight) override;
void setDark(const QColor &dark) override;
void setMid(const QColor &mid) override;
void setShadow(const QColor &shadow) override;
void setHighlight(const QColor &highlight) override;
void setHighlightedText(const QColor &highlightedText) override;
void setLink(const QColor &link) override;
void setLinkVisited(const QColor &linkVisited) override;
void setItemBackground(const QColor &itemBackground) override;
void setTextTitle(const QColor &textTitle) override;
void setTextTips(const QColor &textTips) override;
void setTextWarning(const QColor &textWarning) override;
void setTextLively(const QColor &textLively) override;
void setLightLively(const QColor &lightLively) override;
void setDarkLively(const QColor &darkLively) override;
void setFrameBorder(const QColor &frameBorder) override;
#endif
int dotsPerInch(const QString &screenName = QString()) const override;
void setDotsPerInch(const QString &screenName, int dpi) override;
void setWindowRadius(int windowRadius) override;
private:
friend class DPlatformThemePrivate;
D_PRIVATE_SLOT(void _q_onThemePropertyChanged(const QByteArray &name, const QVariant &value))
};
DGUI_END_NAMESPACE
#endif // DXCBPLATFORMINTERFACE_H

View File

@ -0,0 +1,36 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef DXCBPLATFORMINTERFACE_P_H
#define DXCBPLATFORMINTERFACE_P_H
#include "dxcbplatforminterface.h"
#include "private/dplatforminterface_p.h"
#include <QHash>
#include <DObjectPrivate>
DGUI_BEGIN_NAMESPACE
class DNativeSettings;
class DPlatformTheme;
class DXCBPlatformInterfacePrivate : public DCORE_NAMESPACE::DObjectPrivate
{
public:
D_DECLARE_PUBLIC(DXCBPlatformInterface)
DXCBPlatformInterfacePrivate(DXCBPlatformInterface *qq);
void _q_onThemePropertyChanged(const QByteArray &name, const QVariant &value);
public:
DPlatformTheme *parent = nullptr;
bool fallbackProperty = true;
DNativeSettings *theme;
QHash<QString, QString> m_properties;
};
DGUI_END_NAMESPACE
#endif // DNATIVESETTINGS_P_H

View File

@ -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 <private/qwaylandwindow_p.h>
#include <QGuiApplication>
#include <QPlatformSurfaceEvent>
#include <QStyleHints>
DGUI_BEGIN_NAMESPACE
#define DXCB_PLUGIN_KEY "dxcb"
#define DXCB_PLUGIN_SYMBOLIC_PROPERTY "_d_isDxcb"
#define DEFINE_CONST_CHAR(Name) [[maybe_unused]] 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<void(*)(QWindow *, const char *, const QVariant &)>(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<QString(*)()>(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<void ()> 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<void ()> 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<quint32(*)()>(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<bool(*)(QWindow*)>(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<bool(*)(const QWindow*)>(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<QDynamicPropertyChangeEvent *>(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(12); //###(zccrs): 暂时在此处给窗口默认设置为12px的圆角
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<QPlatformSurfaceEvent*>(event);
if (se->surfaceEventType() == QPlatformSurfaceEvent::SurfaceCreated) { // 若收到此信号, 则 WinID 已被创建
auto window = qobject_cast<QWindow *>(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<bool(*)(const QWindow*)>(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<bool(*)(QWindow*, bool)>(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<DXCBPlatformWindowInterface::WMBlurArea> 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<QPainterPath> &)
\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<QPainterPath> &)
*/
bool DXCBPlatformWindowInterface::setWindowBlurArea(const QVector<DPlatformHandle::WMBlurArea> &area)
{
if (!m_window) {
return false;
}
if (isEnabled()) {
QVector<quint32> 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<bool(*)(const quint32, const QVector<DPlatformHandle::WMBlurArea>&)>(setWmBlurWindowBackgroundArea)(m_window->winId(), area);
}
QVector<DPlatformHandle::WMBlurArea> new_areas;
new_areas.reserve(area.size());
for (const DPlatformHandle::WMBlurArea &a : area) {
new_areas.append(a * device_ratio);
}
return reinterpret_cast<bool(*)(const quint32, const QVector<DPlatformHandle::WMBlurArea>&)>(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<QPainterPath> &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<bool(*)(const quint32, const QList<QPainterPath>&)>(setWmBlurWindowBackgroundPathList)(m_window->winId(), paths);
}
QList<QPainterPath> new_paths;
new_paths.reserve(paths.size());
for (const QPainterPath &p : paths) {
new_paths.append(p * device_ratio);
}
return reinterpret_cast<bool(*)(const quint32, const QList<QPainterPath>&)>(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<QRect, int>(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<bool(*)(const quint32, const QRect&, const quint32)>(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<bool(*)(const quint32, const QRect&, const quint32)>(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<QColor>(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<QColor>(m_window->property(_shadowColor));
}
void DXCBPlatformWindowInterface::setShadowColor(const QColor &shadowColor)
{
setWindowProperty(m_window, _shadowColor, QVariant::fromValue(shadowColor));
}
DPlatformHandle::EffectScene DXCBPlatformWindowInterface::windowEffect()
{
return qvariant_cast<DPlatformHandle::EffectScene>(m_window->property(_windowEffect));
}
void DXCBPlatformWindowInterface::setWindowEffect(DPlatformHandle::EffectScenes effectScene)
{
setWindowProperty(m_window, _windowEffect, static_cast<quint32>(effectScene));
}
DPlatformHandle::EffectType DXCBPlatformWindowInterface::windowStartUpEffect()
{
return qvariant_cast<DPlatformHandle::EffectType>(m_window->property(_windowStartUpEffect));
}
void DXCBPlatformWindowInterface::setWindowStartUpEffect(DPlatformHandle::EffectTypes effectType)
{
setWindowProperty(m_window, _windowStartUpEffect, static_cast<quint32>(effectType));
}
QPainterPath DXCBPlatformWindowInterface::clipPath() const
{
return qvariant_cast<QPainterPath>(m_window->property(_clipPath));
}
void DXCBPlatformWindowInterface::setClipPath(const QPainterPath &clipPath)
{
setWindowProperty(m_window, _clipPath, QVariant::fromValue(clipPath));
}
QRegion DXCBPlatformWindowInterface::frameMask() const
{
return qvariant_cast<QRegion>(m_window->property(_frameMask));
}
void DXCBPlatformWindowInterface::setFrameMask(const QRegion &frameMask)
{
setWindowProperty(m_window, _frameMask, QVariant::fromValue(frameMask));
}
QMargins DXCBPlatformWindowInterface::frameMargins() const
{
return qvariant_cast<QMargins>(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<WId>(m_window->property("_d_real_content_window"));
}
DGUI_END_NAMESPACE

View File

@ -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 <QWindow>
DGUI_BEGIN_NAMESPACE
class DXCBPlatformWindowInterface : public QObject, public DPlatformWindowInterface
{
Q_OBJECT
public:
DXCBPlatformWindowInterface(QWindow *window, DPlatformHandle *platformHandle, QObject *parent = nullptr);
~DXCBPlatformWindowInterface() override;
static QString pluginVersion();
static bool isDXcbPlatform();
static bool connectWindowManagerChangedSignal(QObject *object, std::function<void ()> slot);
static bool connectHasBlurWindowChanged(QObject *object, std::function<void ()> slot);
static WId windowLeader();
void enableDXcb(bool redirectContent);
bool setWindowBlurArea(const QVector<DPlatformHandle::WMBlurArea> &area);
bool setWindowBlurArea(const QList<QPainterPath> &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

View File

@ -0,0 +1,10 @@
file(GLOB XCB_HEADER
${CMAKE_CURRENT_LIST_DIR}/*.h
)
file(GLOB XCB_SOURCE
${CMAKE_CURRENT_LIST_DIR}/*.cpp
)
set(xcb_SRC
${XCB_HEADER}
${XCB_SOURCE}
)

79
src/plugins/plugins.cmake Normal file
View File

@ -0,0 +1,79 @@
option(DTK_DISABLE_XCB "Disable XCB Protocols" OFF)
option(DTK_DISABLE_TREELAND "Disable Treeland Protocols" OFF)
file(GLOB PLATFORM_INTERFACE_HEADER
${CMAKE_CURRENT_LIST_DIR}/*.h
)
file(GLOB PLATFORM_INTERFACE_SOURCE
${CMAKE_CURRENT_LIST_DIR}/*.cpp
)
set(platform_interface_SRC
${PLATFORM_INTERFACE_HEADER}
${PLATFORM_INTERFACE_SOURCE}
)
target_sources(${LIB_NAME} PRIVATE
${platform_interface_SRC}
)
set(PRIVATE_HEADER_FILES ${CMAKE_CURRENT_SOURCE_DIR}/private/dplatforminterface_p.h)
set(PRIVATE_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/dtk${PROJECT_VERSION_MAJOR}/DGui/Private")
# XCB
if(NOT DTK_DISABLE_XCB)
message("Support XCB!")
include(plugins/platform/xcb/xcb.cmake)
target_sources(${LIB_NAME} PRIVATE
${xcb_SRC}
)
else()
target_compile_definitions(${LIB_NAME} PRIVATE DTK_DISABLE_XCB)
endif()
# Treeland
try_compile(DEEPIN_WAYLAND_TEST_COMPILE_RESULT ${CMAKE_CURRENT_BINARY_DIR}/treeland_test
${CMAKE_CURRENT_LIST_DIR}/platform/config.tests/treeland_test treeland_test CMAKE_FLAGS -DQT_VERSION_MAJOR=${QT_VERSION_MAJOR})
if(NOT DEEPIN_WAYLAND_TEST_COMPILE_RESULT)
message("wayland_test failed, disable treeland support")
set(DTK_DISABLE_TREELAND ON)
endif()
if(NOT DTK_DISABLE_TREELAND)
find_package(TreelandProtocols)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS WaylandClient)
set(TreelandProtocols_FOUND ${TreelandProtocols_FOUND})
endif()
if(NOT DTK_DISABLE_TREELAND AND TreelandProtocols_FOUND)
message("Support Treeland!")
if("${QT_VERSION_MAJOR}" STREQUAL "6")
qt6_generate_wayland_protocol_client_sources(${LIB_NAME} FILES
${TREELAND_PROTOCOLS_DATA_DIR}/treeland-personalization-manager-v1.xml
)
else()
# ECM setup
include(FeatureSummary)
find_package(ECM REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${ECM_MODULE_PATH}")
find_package(QtWaylandScanner)
ecm_add_qtwayland_client_protocol(CLIENT_LIB_SRCS
PROTOCOL ${TREELAND_PROTOCOLS_DATA_DIR}/treeland-personalization-manager-v1.xml
BASENAME treeland-personalization-manager-v1
)
target_sources(${LIB_NAME} PRIVATE
${CLIENT_LIB_SRCS}
)
endif()
include(plugins/platform/treeland/treeland.cmake)
target_sources(${LIB_NAME} PRIVATE
${treeland_SRC}
)
else()
target_compile_definitions(${LIB_NAME} PRIVATE DTK_DISABLE_TREELAND)
endif()
install(FILES ${PRIVATE_HEADER_FILES} DESTINATION "${PRIVATE_INCLUDE_INSTALL_DIR}")

View File

@ -17,7 +17,7 @@ class DFontManagerPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate
public:
DFontManagerPrivate(DFontManager *qq);
int fontPixelSize[DFontManager::NSizeTypes] = {40, 30, 24, 20, 17, 14, 13, 12, 11, 10};
int fontPixelSize[DFontManager::NSizeTypes] = {40, 30, 24, 20, 16, 14, 13, 12, 11, 10, 8};
int baseFontSizeType = DFontManager::T6;
// 字号的差值
int fontPixelSizeDiff = 0;

View File

@ -0,0 +1,136 @@
// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#ifndef DPLATFORMINTERFACE_H
#define DPLATFORMINTERFACE_H
#include <QObject>
#include <QWindow>
#include "dtkgui_global.h"
DGUI_BEGIN_NAMESPACE
class DPlatformTheme;
class LIBDTKCORESHARED_EXPORT DPlatformInterface
{
public:
explicit DPlatformInterface(DPlatformTheme *platformTheme);
virtual ~DPlatformInterface();
virtual int cursorBlinkTime() const;
virtual int cursorBlinkTimeout() const;
virtual bool cursorBlink() const;
virtual int doubleClickDistance() const;
virtual int doubleClickTime() const;
virtual int dndDragThreshold() const;
virtual int windowRadius() const;
virtual int windowRadius(int defaultValue) const;
virtual QByteArray themeName() const;
virtual QByteArray iconThemeName() const;
virtual QByteArray soundThemeName() const;
virtual QByteArray fontName() const;
virtual QByteArray monoFontName() const;
virtual qreal fontPointSize() const;
virtual QByteArray gtkFontName() const;
virtual QColor activeColor() const;
virtual QColor darkActiveColor() const;
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
virtual QColor window() const;
virtual QColor windowText() const;
virtual QColor base() const;
virtual QColor alternateBase() const;
virtual QColor toolTipBase() const;
virtual QColor toolTipText() const;
virtual QColor text() const;
virtual QColor button() const;
virtual QColor buttonText() const;
virtual QColor brightText() const;
virtual QColor light() const;
virtual QColor midlight() const;
virtual QColor dark() const;
virtual QColor mid() const;
virtual QColor shadow() const;
virtual QColor highlight() const;
virtual QColor highlightedText() const;
virtual QColor link() const;
virtual QColor linkVisited() const;
virtual QColor itemBackground() const;
virtual QColor textTitle() const;
virtual QColor textTips() const;
virtual QColor textWarning() const;
virtual QColor textLively() const;
virtual QColor lightLively() const;
virtual QColor darkLively() const;
virtual QColor frameBorder() const;
#endif
virtual int sizeMode() const;
virtual int scrollBarPolicy() const;
public:
virtual void setCursorBlinkTime(int cursorBlinkTime);
virtual void setCursorBlinkTimeout(int cursorBlinkTimeout);
virtual void setCursorBlink(bool cursorBlink);
virtual void setDoubleClickDistance(int doubleClickDistance);
virtual void setDoubleClickTime(int doubleClickTime);
virtual void setDndDragThreshold(int dndDragThreshold);
virtual void setThemeName(const QByteArray &themeName);
virtual void setIconThemeName(const QByteArray &iconThemeName);
virtual void setSoundThemeName(const QByteArray &soundThemeName);
virtual void setFontName(const QByteArray &fontName);
virtual void setMonoFontName(const QByteArray &monoFontName);
virtual void setFontPointSize(qreal fontPointSize);
virtual void setGtkFontName(const QByteArray &fontName);
virtual void setActiveColor(const QColor activeColor);
virtual void setDarkActiveColor(const QColor &activeColor);
#if DTK_VERSION < DTK_VERSION_CHECK(6, 0, 0, 0)
virtual void setWindow(const QColor &window);
virtual void setWindowText(const QColor &windowText);
virtual void setBase(const QColor &base);
virtual void setAlternateBase(const QColor &alternateBase);
virtual void setToolTipBase(const QColor &toolTipBase);
virtual void setToolTipText(const QColor &toolTipText);
virtual void setText(const QColor &text);
virtual void setButton(const QColor &button);
virtual void setButtonText(const QColor &buttonText);
virtual void setBrightText(const QColor &brightText);
virtual void setLight(const QColor &light);
virtual void setMidlight(const QColor &midlight);
virtual void setDark(const QColor &dark);
virtual void setMid(const QColor &mid);
virtual void setShadow(const QColor &shadow);
virtual void setHighlight(const QColor &highlight);
virtual void setHighlightedText(const QColor &highlightedText);
virtual void setLink(const QColor &link);
virtual void setLinkVisited(const QColor &linkVisited);
virtual void setItemBackground(const QColor &itemBackground);
virtual void setTextTitle(const QColor &textTitle);
virtual void setTextTips(const QColor &textTips);
virtual void setTextWarning(const QColor &textWarning);
virtual void setTextLively(const QColor &textLively);
virtual void setLightLively(const QColor &lightLively);
virtual void setDarkLively(const QColor &darkLively);
virtual void setFrameBorder(const QColor &frameBorder);
#endif
virtual int dotsPerInch(const QString &screenName = QString()) const;
virtual void setDotsPerInch(const QString &screenName, int dpi);
virtual void setWindowRadius(int windowRadius);
protected:
DPlatformTheme *m_platformTheme;
};
class LIBDTKCORESHARED_EXPORT DPlatformInterfaceFactory {
public:
using HelperCreator = DPlatformInterface * (*)(DPlatformTheme*);
static void registerInterface(HelperCreator creator);
};
DGUI_END_NAMESPACE
#endif // DNATIVESETTINGS_P_H

View File

@ -5,9 +5,15 @@
#ifndef DPLATFORMTHEME_P_H
#define DPLATFORMTHEME_P_H
#include "private/dplatforminterface_p.h"
#include "dplatformtheme.h"
#include "dnativesettings_p.h"
#include <dguiapplicationhelper.h>
class OrgDeepinDTKPreference;
DCORE_USE_NAMESPACE
DGUI_BEGIN_NAMESPACE
class DPlatformThemePrivate : public DNativeSettingsPrivate
@ -18,7 +24,6 @@ public:
// 接收parent主题或非调色板DNativeSettings对象theme对象的属性变化通知
// 调色板相关的属性变化与此无关
void _q_onThemePropertyChanged(const QByteArray &name, const QVariant &value);
void onQtColorChanged(QPalette::ColorRole role, const QColor &color);
void onDtkColorChanged(DPalette::ColorType type, const QColor &color);
void notifyPaletteChanged();
@ -34,6 +39,12 @@ public:
DPalette *palette = nullptr;
// 减少调色板changed信号的通知频率
QTimer *notifyPaletteChangeTimer = nullptr;
OrgDeepinDTKPreference *dtkPreferenceConfig = nullptr;
DPlatformInterface *platformInterface = nullptr;
DGuiApplicationHelper::SizeMode sizeMode = DGuiApplicationHelper::NormalMode;
Qt::ScrollBarPolicy scrollBarPolicy = Qt::ScrollBarAsNeeded;
};
DGUI_END_NAMESPACE

View File

@ -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 <QPointer>
#include <QWindow>
#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<QWindow> m_window;
QPointer<DPlatformHandle> m_platformHandle;
};
class LIBDTKCORESHARED_EXPORT DPlatformWindowInterfaceFactory {
public:
using Creator = DPlatformWindowInterface * (*)(QWindow *, DPlatformHandle*);
static void registerInterface(Creator creator);
};
DGUI_END_NAMESPACE
#endif // DPLATFORMWINDOWINTERFACE_P_H

View File

@ -7,4 +7,6 @@ set(private_SRC
${CMAKE_CURRENT_LIST_DIR}/dregionmonitor_p.h
${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
)

View File

@ -598,6 +598,8 @@ void DDciIconPrivate::loadIconList()
node.entries << icon;
node.maxPaddings = qMax(node.maxPaddings, icon->maxPaddings);
}
if (node.entries.isEmpty())
continue;
icons << std::move(node);
}
}
@ -646,7 +648,7 @@ DDciIconEntry *DDciIconPrivate::tryMatchIcon(int iconSize, DDciIcon::Theme theme
}
const auto targetIcon = std::max_element(iconWeight.constBegin(), iconWeight.constEnd());
if (*targetIcon > 0)
if (targetIcon != iconWeight.constEnd() && *targetIcon > 0)
return listOfSize.entries.at(targetIcon - iconWeight.constBegin());
return nullptr;
}
@ -656,7 +658,11 @@ static const DDciIconEntry::ScalableLayer &findScalableLayer(const DDciIconEntry
const DDciIconEntry::ScalableLayer *maxLayer = nullptr;
const int imagePixelRatio = qCeil(devicePixelRatio);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
for (const auto &i : std::as_const(entry->scalableLayers)) {
#else
for (const auto &i : qAsConst(entry->scalableLayers)) {
#endif
if (!maxLayer || i.imagePixelRatio > maxLayer->imagePixelRatio)
maxLayer = &i;
if (i.imagePixelRatio > imagePixelRatio)
@ -850,7 +856,7 @@ QList<int> DDciIcon::availableSizes(DDciIcon::Theme theme, DDciIcon::Mode mode)
return sizes;
}
bool DDciIcon::isSupportedAttribute(DDciIconMatchResult result, IconAttibute attr) const
bool DDciIcon::isSupportedAttribute(DDciIconMatchResult result, IconAttribute attr) const
{
switch (attr) {
case HasPalette:
@ -862,7 +868,7 @@ bool DDciIcon::isSupportedAttribute(DDciIconMatchResult result, IconAttibute att
return false;
}
bool DDciIcon::isSupportedAttribute(const DDciIconImage &image, IconAttibute attr)
bool DDciIcon::isSupportedAttribute(const DDciIconImage &image, IconAttribute attr)
{
if (image.isNull())
return false;
@ -1135,7 +1141,11 @@ int DDciIconImage::currentImageNumber() const
void DDciIconImagePrivate::init()
{
readers.reserve(layers.size());
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
for (const auto &layer : std::as_const(layers)) {
#else
for (const auto &layer : qAsConst(layers)) {
#endif
ReaderData *data = new ReaderData;
Q_ASSERT(data);
auto buffer = new QBuffer();

View File

@ -207,7 +207,11 @@ bool DDciIconImagePlayer::setPalette(const DDciIconPalette &palette)
d->palette = palette;
bool hasPalette = false;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
for (const auto &i : std::as_const(d->images))
#else
for (const auto &i : qAsConst(d->images))
#endif
if (i.hasPalette())
hasPalette = true;
@ -649,7 +653,7 @@ void DDciIconPlayerPrivate::initPlayer()
// Remove the finished animation
animationJobs.removeFirst();
qCDebug(diPlayer, "Number of animations remaining is %i", animationJobs.size());
qCDebug(diPlayer) << "Number of animations remaining is" << animationJobs.size();
if (!animationJobs.isEmpty()) {
_q_playFromQueue();
return;
@ -1075,10 +1079,15 @@ QImage DDciIconPlayer::currentImage() const
return d->image;
}
void DDciIconPlayer::play(DDciIcon::Mode mode)
void DDciIconPlayer::play(DDciIcon::Mode mode, DDciIconImagePlayer::Flags flags)
{
D_D(DDciIconPlayer);
d->play(mode, DDciIconImagePlayer::IgnoreLastImageLoop);
d->play(mode, flags);
}
void DDciIconPlayer::play(DDciIcon::Mode mode)
{
play(mode, DDciIconImagePlayer::IgnoreLastImageLoop);
}
void DDciIconPlayer::stop()

View File

@ -49,7 +49,7 @@ DFontManager::~DFontManager()
\value T4
T4 , 20 px
\value T5
T5 , 17 px
T5 , 16 px
\value T6
T6 , 14 px
\value T7
@ -60,6 +60,8 @@ DFontManager::~DFontManager()
T9 , 11 px
\value T10
T10 , 10 px
\value T11
T11 , 8 px
\omitvalue NSizeTypes
*/
@ -147,6 +149,8 @@ QFont DFontManager::get(int pixelSize, const QFont &base)
{
QFont font = base;
font.setPixelSize(pixelSize);
// Ensure that the FamilyResolved flag is set in order for Qt to correctly set fonts
font.setFamilies(base.families());
return font;
}

View File

@ -6,6 +6,7 @@
#include "private/dbuiltiniconengine_p.h"
#include "private/dciiconengine_p.h"
#include "private/diconproxyengine_p.h"
#include <private/qicon_p.h>
#ifndef DTK_DISABLE_LIBXDG
#include "private/xdgiconproxyengine_p.h"
#else
@ -125,12 +126,12 @@ bool DIconTheme::isBuiltinIcon(const QIcon &icon)
bool DIconTheme::isXdgIcon(const QIcon &icon)
{
#ifdef DTK_DISABLE_LIBXDG
return false;
#else
if (icon.isNull())
return false;
#ifdef DTK_DISABLE_LIBXDG
return false;
#else
QIconEngine *engine = const_cast<QIcon &>(icon).data_ptr()->engine;
if (auto proxyEngine = dynamic_cast<DIconProxyEngine *>(engine))
return !proxyEngine->proxyKey().compare("XdgIconProxyEngine");

Binary file not shown.

View File

@ -77,6 +77,5 @@
<file alias="sp_alert.dci">dci/sp_alert.dci</file>
<file alias="sp_waiting.dci">dci/sp_waiting.dci</file>
<file alias="sp_warning.dci">dci/sp_warning.dci</file>
<file alias="close.dci">dci/close.dci</file>
</qresource>
</RCC>

View File

@ -19,6 +19,17 @@
DGUI_BEGIN_NAMESPACE
static qreal devicePixelRatio(QPainter *painter)
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (qApp->testAttribute(Qt::AA_UseHighDpiPixmaps))
return (painter && painter->device()) ? painter->device()->devicePixelRatioF() : qApp->devicePixelRatio();
return 1.0;
#else
return (painter && painter->device()) ? painter->device()->devicePixelRatioF() : qApp->devicePixelRatio();
#endif
}
class Q_DECL_HIDDEN ImageEntry : public QIconLoaderEngineEntry
{
public:
@ -50,11 +61,20 @@ public:
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override {
#else
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override {
#endif
Q_UNUSED(state)
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
const QSize pixmapSize = size * scale;
#else
const QSize pixmapSize(size);
#endif
QPixmap pm;
QString pmckey(pmcKey(size, mode, state));
QString pmckey(pmcKey(pixmapSize, mode, state));
if (QPixmapCache::find(pmckey, &pm)) {
genIconTypeIcon(pm, mode);
return pm;
@ -67,7 +87,7 @@ public:
}
if (dir.type == QIconDirInfo::Scalable)
reader.setScaledSize(size);
reader.setScaledSize(pixmapSize);
pm = QPixmap::fromImageReader(&reader);
if (!pm.isNull())
@ -111,7 +131,11 @@ public:
return dir.filePath("normal." + suffix);
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale) override {
#else
QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) override {
#endif
if (iconFileMap.isEmpty()) {
const QString &suffix = QFileInfo(filename).suffix();
QDir dir(filename);
@ -128,7 +152,11 @@ public:
reader.setFileName(iconFileMap.value(mode << 8 | state));
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
return ImageEntry::pixmap(size, mode, state, scale);
#else
return ImageEntry::pixmap(size, mode, state);
#endif
}
QMap<qint16, QString> iconFileMap;
@ -192,7 +220,11 @@ QPixmap DBuiltinIconEngine::pixmap(const QSize &size, QIcon::Mode mode,
QIconLoaderEngineEntry *entry = QIconLoaderEngine::entryForSize(m_info, size);
if (entry)
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
return entry->pixmap(size, mode, state, devicePixelRatio(nullptr));
#else
return entry->pixmap(size, mode, state);
#endif
return QPixmap();
}
@ -202,13 +234,7 @@ void DBuiltinIconEngine::paint(QPainter *painter, const QRect &rect,
{
ensureLoaded();
qreal scale = 1.0;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (qApp->testAttribute(Qt::AA_UseHighDpiPixmaps))
scale = painter->device() ? painter->device()->devicePixelRatioF() : qApp->devicePixelRatio();
#else
scale = painter->device() ? painter->device()->devicePixelRatioF() : qApp->devicePixelRatio();
#endif
const qreal scale = devicePixelRatio(painter);
QSize pixmapSize = rect.size() * scale;
QIconLoaderEngineEntry *entry = QIconLoaderEngine::entryForSize(m_info, pixmapSize);
@ -222,7 +248,11 @@ void DBuiltinIconEngine::paint(QPainter *painter, const QRect &rect,
QIcon(bgFileName).paint(painter, rect, Qt::AlignCenter, mode, state);
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
QPixmap pm = entry->pixmap(pixmapSize, mode, state, 1.0);
#else
QPixmap pm = entry->pixmap(pixmapSize, mode, state);
#endif
ImageEntry::Type type = static_cast<ImageEntry *>(entry)->type;
if (type == ImageEntry::TextType || (type == ImageEntry::ActionType && mode != QIcon::Normal)) {
QPainter pa(&pm);
@ -271,6 +301,28 @@ QString DBuiltinIconEngine::iconName()
return m_iconName;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QList<QSize> DBuiltinIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state)
{
Q_UNUSED(mode);
Q_UNUSED(state);
ensureLoaded();
QList<QSize> sizes;
const int N = m_info.entries.size();
sizes.reserve(N);
// Gets all sizes from the DirectoryInfo entries
for (int i = 0; i < N; ++i) {
const auto& entry = m_info.entries.at(i);
int size = entry->dir.size;
sizes.append(QSize(size, size));
}
return sizes;
}
#endif
QThemeIconInfo DBuiltinIconEngine::loadIcon(const QString &iconName, uint key)
{
QThemeIconInfo info;
@ -386,7 +438,11 @@ void DBuiltinIconEngine::virtual_hook(int id, void *data)
// QIcon::pixmap() multiplies size by the device pixel ratio.
const int integerScale = qCeil(arg.scale);
QIconLoaderEngineEntry *entry = QIconLoaderEngine::entryForSize(m_info, arg.size / integerScale, integerScale);
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
arg.pixmap = entry ? entry->pixmap(arg.size, arg.mode, arg.state, arg.scale) : QPixmap();
#else
arg.pixmap = entry ? entry->pixmap(arg.size, arg.mode, arg.state) : QPixmap();
#endif
}
break;
default:

View File

@ -33,6 +33,7 @@ public:
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QString iconName() override;
QList<QSize> availableSizes(QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) override;
#else
QString iconName() const override;
#endif

View File

@ -8,6 +8,7 @@
#include <QPainter>
#include <QPixmap>
#include <QPixmapCache>
#include <private/qhexstring_p.h>
#include <private/qiconloader_p.h>
@ -158,6 +159,23 @@ const
return m_iconName;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QList<QSize> DDciIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state)
{
Q_UNUSED(state);
ensureIconTheme();
const auto availableSizes = m_dciIcon.availableSizes(dciTheme(), dciMode(mode));
QList<QSize> sizes;
sizes.reserve(availableSizes.size());
for (int size : availableSizes)
sizes.append(QSize(size, size));
return sizes;
}
#endif
void DDciIconEngine::virtual_hook(int id, void *data)
{
ensureIconTheme();

View File

@ -30,6 +30,7 @@ public:
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QString iconName() override;
QList<QSize> availableSizes(QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) override;
#else
QString iconName() const override;
#endif

View File

@ -275,9 +275,8 @@ void DIconProxyEngine::ensureEngine()
}
#endif
if (!m_iconEngine && !nonCache[theme].contains(m_iconName)) {
qWarning("create icon [%s] engine failed.[theme:%s] nonCache[theme].size[%d]",
m_iconName.toUtf8().data(),
theme.toUtf8().data(), nonCache[theme].size());
qWarning() << "create icon [" << m_iconName << "] engine failed."
<< "theme:" << theme << "and nonCache's size:" << nonCache.size();
nonCache[theme].insert(m_iconName);
return;
}

View File

@ -189,7 +189,11 @@ QPixmap XdgIconProxyEngine::pixmapByEntry(QIconLoaderEngineEntry *entry, const Q
if (!XdgIconFollowColorScheme()) {
DEEPIN_XDG_THEME::colorScheme.setLocalData(DEEPIN_XDG_THEME::PALETTE_MAP());
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1)
return entry->pixmap(size, mode, state, 1.0);
#else
return entry->pixmap(size, mode, state);
#endif
}
QPixmap pixmap;
@ -206,7 +210,11 @@ QPixmap XdgIconProxyEngine::pixmapByEntry(QIconLoaderEngineEntry *entry, const Q
pixmap = followColorPixmap(static_cast<ScalableEntry *>(entry), size, mode, state);
} else {
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 1)
pixmap = entry->pixmap(size, mode, state, 1.0);
#else
pixmap = entry->pixmap(size, mode, state);
#endif
}
free(type_name);

View File

@ -1,6 +1,13 @@
set(BIN_NAME ut-DtkGui)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Widgets Test)
find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Gui Widgets DBus Network Test)
if ("${QT_VERSION_MAJOR}" STREQUAL "6")
if (${Qt6Core_VERSION} VERSION_GREATER_EQUAL "6.10.0")
set(QT_NO_PRIVATE_MODULE_WARNING ON)
find_package(Qt6 REQUIRED COMPONENTS CorePrivate GuiPrivate WaylandClientPrivate)
endif()
endif()
find_package(GTest REQUIRED)
file(GLOB test_SRC
@ -44,7 +51,7 @@ target_link_libraries(${BIN_NAME} PRIVATE
m
)
if(NOT DTK_DISABLE_EX_IMAGE_FORMAT AND EX_IMAGE_FORMAT_LIBS_FOUND)
if(NOT DTK_DISABLE_EX_IMAGE_FORMAT AND EX_IMAGE_FORMAT_LIBS_FOUND)
target_link_libraries(${BIN_NAME} PRIVATE
PkgConfig::libraw
FreeImage::FreeImage
@ -52,7 +59,7 @@ target_link_libraries(${BIN_NAME} PRIVATE
endif()
if(NOT DTK_DISABLE_LIBXDG)
target_link_libraries(${BIN_NAME} PRIVATE
target_link_libraries(${BIN_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}XdgIconLoader
)
endif()

View File

@ -127,6 +127,15 @@ void DDynamicMetaObject::init(const QMetaObject *metaObject)
QMetaPropertyBuilder op;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
switch (mp.metaType().id()) {
case QMetaType::QByteArray:
case QMetaType::QString:
case QMetaType::QColor:
case QMetaType::Int:
case QMetaType::Double:
case QMetaType::Bool:
#else
switch (mp.type()) {
case QVariant::Type::ByteArray:
case QVariant::Type::String:
@ -134,6 +143,7 @@ void DDynamicMetaObject::init(const QMetaObject *metaObject)
case QVariant::Type::Int:
case QVariant::Type::Double:
case QVariant::Type::Bool:
#endif
op = ob.addProperty(mp);
break;
default:

View File

@ -16,7 +16,7 @@
DGUI_BEGIN_NAMESPACE
class DPlatformSettings;
class DDynamicMetaObject : public QAbstractDynamicMetaObject
class Q_DECL_HIDDEN DDynamicMetaObject : public QAbstractDynamicMetaObject
{
public:
explicit DDynamicMetaObject(QObject *base, DPlatformSettings *settings, bool global_settings);

View File

@ -15,7 +15,7 @@ QT_END_NAMESPACE
DGUI_BEGIN_NAMESPACE
class DPlatformSettings
class Q_DECL_HIDDEN DPlatformSettings
{
public:
virtual ~DPlatformSettings() {}

View File

@ -5,7 +5,7 @@
#include "dummysettings.h"
#include <QDebug>
class DummySettingsPrivate : public QObject
class Q_DECL_HIDDEN DummySettingsPrivate : public QObject
{
public:
DummySettingsPrivate(DummySettings *q, const QString &domain, QObject *parent = nullptr);

View File

@ -10,7 +10,7 @@
DGUI_USE_NAMESPACE
class DummySettingsPrivate;
class DummySettings : public DPlatformSettings
class Q_DECL_HIDDEN DummySettings : public DPlatformSettings
{
public:
explicit DummySettings(const QString &domain = QString());

View File

@ -13,11 +13,18 @@
#include <qpa/qplatformwindow.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtGlobal>
#include <private/qgenericunixeventdispatcher_p.h>
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
#include <private/qdesktopunixservices_p.h>
#else
#include <private/qgenericunixservices_p.h>
#endif
MinimalIntegration::MinimalIntegration(const QStringList &parameters)
{
Q_UNUSED(parameters);
m_primaryScreen = new MinimalScreen();
m_primaryScreen->mGeometry = QRect(0, 0, 240, 320);
@ -53,7 +60,11 @@ QAbstractEventDispatcher *MinimalIntegration::createEventDispatcher() const
QPlatformServices *MinimalIntegration::services() const
{
if (!m_services)
#if QT_VERSION >= QT_VERSION_CHECK(6, 9, 0)
m_services.reset(new QDesktopUnixServices);
#else
m_services.reset(new QGenericUnixServices);
#endif
return m_services.get();
}

View File

@ -17,7 +17,7 @@ DGUI_USE_NAMESPACE
#define ICONNAME "icon_Layout"
#define ICONSIZE 16
class ut_DBuiltinIconEngine : public testing::Test
class GTEST_API_ ut_DBuiltinIconEngine : public testing::Test
{
protected:
void SetUp() override;
@ -60,7 +60,11 @@ TEST_F(ut_DBuiltinIconEngine, loadIcon)
ASSERT_EQ(entry->dir.path, builtinActionPath);
ASSERT_EQ(entry->dir.size, ICONSIZE);
ASSERT_EQ(entry->dir.type, QIconDirInfo::Scalable);
#if QT_VERSION >= QT_VERSION_CHECK(6, 8, 0)
ASSERT_FALSE(entry->pixmap(QSize(ICONSIZE, ICONSIZE), QIcon::Normal, QIcon::On, 1.0).isNull());
#else
ASSERT_FALSE(entry->pixmap(QSize(ICONSIZE, ICONSIZE), QIcon::Normal, QIcon::On).isNull());
#endif
#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
for (auto item : themeInfo.entries) {

View File

@ -14,7 +14,7 @@
DGUI_USE_NAMESPACE
class ut_DDciIconEngine : public testing::Test
class GTEST_API_ ut_DDciIconEngine : public testing::Test
{
protected:
void SetUp() override;

View File

@ -9,7 +9,7 @@
DGUI_USE_NAMESPACE
class ut_DDciIcon : public DTest
class GTEST_API_ ut_DDciIcon : public DTest
{
public:
ut_DDciIcon()

View File

@ -90,7 +90,7 @@ TEST(ut_DDciIconImage, render)
}
}
class ut_DDciIconPlayer : public DTest
class GTEST_API_ ut_DDciIconPlayer : public DTest
{
protected:
ut_DDciIconPlayer()

View File

@ -21,7 +21,7 @@ TEST(ut_DFontManager, StaticFunction)
ASSERT_TRUE(DFontManager::fontPixelSize(tF) > 0);
}
class TDFontManager : public DTestWithParam<int>
class GTEST_API_ TDFontManager : public DTestWithParam<int>
{
protected:
void SetUp();
@ -76,4 +76,5 @@ TEST_F(TDFontManager, testFontSize)
ASSERT_EQ(manager->t8().pixelSize(), manager->fontPixelSize(DFontManager::T8));
ASSERT_EQ(manager->t9().pixelSize(), manager->fontPixelSize(DFontManager::T9));
ASSERT_EQ(manager->t10().pixelSize(), manager->fontPixelSize(DFontManager::T10));
ASSERT_EQ(manager->t11().pixelSize(), manager->fontPixelSize(DFontManager::T11));
}

View File

@ -14,14 +14,14 @@ DGUI_BEGIN_NAMESPACE
#define WmClass "_d_WmClass"
#define ProcessId "_d_ProcessId"
class TDForeignWindow : public DTest
class GTEST_API_ TDForeignWindow : public DTest
{
protected:
virtual void SetUp()
{
const QVector<quint32> &currentIdList = DWindowManagerHelper::instance()->currentWorkspaceWindowIdList();
foreignWindows.clear();
for (quint32 currentId : qAsConst(currentIdList)) {
for (const auto &currentId : currentIdList) {
foreignWindows.append(DForeignWindow::fromWinId(currentId));
}
}
@ -36,13 +36,13 @@ protected:
TEST_F(TDForeignWindow, wmClass)
{
for (auto foreignWindow : qAsConst(foreignWindows))
for (auto foreignWindow : foreignWindows)
ASSERT_NE(foreignWindow->wmClass(), QString());
}
TEST_F(TDForeignWindow, pid)
{
for (auto foreignWindow : qAsConst(foreignWindows))
for (auto foreignWindow : foreignWindows)
ASSERT_NE(foreignWindow->pid(), 0);
}
@ -51,7 +51,7 @@ TEST_F(TDForeignWindow, event)
QDynamicPropertyChangeEvent wmevent(WmClass);
QDynamicPropertyChangeEvent pidevent(ProcessId);
for (auto foreignWindow : qAsConst(foreignWindows)) {
for (auto foreignWindow : foreignWindows) {
QSignalSpy wmspy(foreignWindow, SIGNAL(wmClassChanged()));
ASSERT_TRUE(foreignWindow->event(&wmevent));
ASSERT_EQ(wmspy.count(), 1);

View File

@ -23,7 +23,7 @@ private:
void virtual_hook(int id, void *data) override;
*/
class ut_DIconProxyEngine : public testing::Test
class GTEST_API_ ut_DIconProxyEngine : public testing::Test
{
protected:
void SetUp() override;

View File

@ -20,8 +20,9 @@ TEST(ut_DIconTheme, builtinIcon)
// icon2 只可能是从外部找到的图标,不会与 icon1 相同
ASSERT_TRUE(icon1.cacheKey() != icon2.cacheKey());
#ifndef DTK_DISABLE_LIBXDG
if (!icon2.isNull())
if (!icon2.isNull()) {
ASSERT_TRUE(DIconTheme::isXdgIcon(icon2));
}
#endif
}
@ -36,8 +37,9 @@ TEST(ut_DIconTheme, cachedTheme)
// icon2 只可能是从外部找到的图标,不会与 icon1 相同
ASSERT_TRUE(icon1.cacheKey() != icon2.cacheKey());
#ifndef DTK_DISABLE_LIBXDG
if (!icon2.isNull())
if (!icon2.isNull()) {
ASSERT_TRUE(DIconTheme::isXdgIcon(icon2));
}
#endif
const QIcon icon1_cached1 = DIconTheme::cached()->findQIcon("edit");

View File

@ -15,7 +15,7 @@
DGUI_USE_NAMESPACE
DCORE_USE_NAMESPACE
class ut_DNativeSettings : public testing::Test
class GTEST_API_ ut_DNativeSettings : public testing::Test
{
public:
static void SetUpTestSuite();

View File

@ -106,13 +106,21 @@ TEST_F(TDPlatformHandle, testFunction)
DPlatformHandle::setDisableWindowOverrideCursor(window, true);
QVariant windowRadius = window->property(WINDOWRADIUS);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (windowRadius.isValid() && windowRadius.canConvert<int>()) {
#else
if (windowRadius.isValid() && windowRadius.canConvert(QVariant::Int)) {
#endif
ASSERT_EQ(pHandle->windowRadius(), windowRadius.toInt());
}
QVariant borderWidth = window->property(BORDERWIDTH);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (borderWidth.isValid() && borderWidth.canConvert<int>()) {
#else
if (borderWidth.isValid() && borderWidth.canConvert(QVariant::Int)) {
#endif
ASSERT_EQ(pHandle->borderWidth(), borderWidth.toInt());
} else {
ASSERT_EQ(pHandle->borderWidth(), 0);
@ -120,7 +128,11 @@ TEST_F(TDPlatformHandle, testFunction)
QVariant borderColor = window->property(BORDRCOLOR);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (borderColor.isValid() && borderColor.canConvert<QColor>()) {
#else
if (borderColor.isValid() && borderColor.canConvert(QVariant::Color)) {
#endif
ASSERT_EQ(pHandle->borderColor(), borderColor.value<QColor>());
} else {
ASSERT_FALSE(pHandle->borderColor().isValid());
@ -128,7 +140,11 @@ TEST_F(TDPlatformHandle, testFunction)
QVariant shadowRadius = window->property(SHADOWRADIUS);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (shadowRadius.isValid() && shadowRadius.canConvert<int>()) {
#else
if (shadowRadius.isValid() && shadowRadius.canConvert(QVariant::Int)) {
#endif
ASSERT_EQ(pHandle->shadowRadius(), shadowRadius.toInt());
} else {
ASSERT_FALSE(pHandle->borderColor().isValid());
@ -136,7 +152,11 @@ TEST_F(TDPlatformHandle, testFunction)
QVariant shadowOffset = window->property(SHADOWOFFSET);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (shadowOffset.isValid() && shadowOffset.canConvert<QPoint>()) {
#else
if (shadowOffset.isValid() && shadowOffset.canConvert(QVariant::Point)) {
#endif
ASSERT_EQ(pHandle->shadowOffset(), shadowOffset.value<QPoint>());
} else {
ASSERT_TRUE(pHandle->shadowOffset().isNull());
@ -144,7 +164,11 @@ TEST_F(TDPlatformHandle, testFunction)
QVariant shadowColor = window->property(SHADOWCOLOR);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (shadowColor.isValid() && shadowColor.canConvert<QColor>()) {
#else
if (shadowColor.isValid() && shadowColor.canConvert(QVariant::Color)) {
#endif
ASSERT_EQ(pHandle->shadowColor(), shadowColor.value<QColor>());
} else {
ASSERT_FALSE(pHandle->shadowColor().isValid());
@ -160,7 +184,11 @@ TEST_F(TDPlatformHandle, testFunction)
QVariant frameMask = window->property(FRAMEMASK);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (frameMask.isValid() && frameMask.canConvert<QRegion>()) {
#else
if (frameMask.isValid() && frameMask.canConvert(QVariant::Region)) {
#endif
ASSERT_EQ(pHandle->frameMask(), frameMask.value<QRegion>());
} else {
ASSERT_TRUE(pHandle->frameMask().isEmpty());
@ -175,35 +203,55 @@ TEST_F(TDPlatformHandle, testFunction)
}
QVariant translucentBackground = window->property(TRANSLUCENTBACKGROUND);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (translucentBackground.isValid() && translucentBackground.canConvert<bool>()) {
#else
if (translucentBackground.isValid() && translucentBackground.canConvert(QVariant::Bool)) {
#endif
ASSERT_EQ(pHandle->translucentBackground(), translucentBackground.toBool());
} else {
ASSERT_FALSE(pHandle->translucentBackground());
}
QVariant enableSystemResize = window->property(ENABLESYSTEMRESIZE);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (enableSystemResize.isValid() && enableSystemResize.canConvert<bool>()) {
#else
if (enableSystemResize.isValid() && enableSystemResize.canConvert(QVariant::Bool)) {
#endif
ASSERT_EQ(pHandle->enableSystemResize(), enableSystemResize.toBool());
} else {
ASSERT_FALSE(pHandle->enableSystemResize());
}
QVariant enableSystemMove = window->property(ENABLESYSTEMMOVE);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (enableSystemMove.isValid() && enableSystemMove.canConvert<bool>()) {
#else
if (enableSystemMove.isValid() && enableSystemMove.canConvert(QVariant::Bool)) {
#endif
ASSERT_EQ(pHandle->enableSystemMove(), enableSystemMove.toBool());
} else {
ASSERT_FALSE(pHandle->enableSystemMove());
}
QVariant enableBlurWindow = window->property(ENABLEBLURWINDOW);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (enableBlurWindow.isValid() && enableBlurWindow.canConvert<bool>()) {
#else
if (enableBlurWindow.isValid() && enableBlurWindow.canConvert(QVariant::Bool)) {
#endif
ASSERT_EQ(pHandle->enableBlurWindow(), enableBlurWindow.toBool());
} else {
ASSERT_FALSE(pHandle->enableBlurWindow());
}
QVariant autoInputMaskByClipPath = window->property(AUTOINPUTMASKBYCLIPPATH);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (autoInputMaskByClipPath.isValid() && autoInputMaskByClipPath.canConvert<bool>()) {
#else
if (autoInputMaskByClipPath.isValid() && autoInputMaskByClipPath.canConvert(QVariant::Bool)) {
#endif
ASSERT_EQ(pHandle->autoInputMaskByClipPath(), autoInputMaskByClipPath.toBool());
} else {
ASSERT_FALSE(pHandle->autoInputMaskByClipPath());

View File

@ -50,12 +50,14 @@ TEST_F(TDWindowMangerHelper, testStaticFunction)
DWindowManagerHelper::setMotifDecorations(w->windowHandle(), DWindowManagerHelper::MotifDecorations(TestDecorations));
DWindowManagerHelper::MotifDecorations mDecos = DWindowManagerHelper::getMotifDecorations(w->windowHandle());
if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM)
if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM) {
ASSERT_EQ(mDecos, TestDecorations);
}
mDecos = DWindowManagerHelper::setMotifDecorations(w->windowHandle(), DWindowManagerHelper::MotifDecorations(TestAllDecorations), true);
if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM)
if (wm_helper->windowManagerName() == DWindowManagerHelper::KWinWM) {
ASSERT_EQ(mDecos, TestAllDecorations);
}
// 没有崩溃则测试成功
enum { TestWindowType = DWindowManagerHelper::DesktopType | DWindowManagerHelper::MenuType };

View File

@ -18,7 +18,7 @@
DGUI_USE_NAMESPACE
class ut_XdgIconProxyEngine : public testing::Test
class GTEST_API_ ut_XdgIconProxyEngine : public testing::Test
{
protected:
void SetUp() override;

View File

@ -0,0 +1,214 @@
/**
* This file is generated by dconfig2cpp.
* Command line arguments: ./dconfig2cpp -p ./dtkgui/toolGenerate/dconfig2cpp ./dtkgui/misc/org.deepin.dtk.ui.preference.json
* Generation time: 2025-01-14T10:54:59
* JSON file version: 1.0
*
* WARNING: DO NOT MODIFY THIS FILE MANUALLY.
* If you need to change the content, please modify the dconfig2cpp tool.
*/
#ifndef ORG_DEEPIN_DTK_UI_PREFERENCE_H
#define ORG_DEEPIN_DTK_UI_PREFERENCE_H
#include <QThread>
#include <QVariant>
#include <QDebug>
#include <QAtomicPointer>
#include <QAtomicInteger>
#include <DConfig>
class org_deepin_dtk_ui_preference : public QObject {
Q_OBJECT
Q_PROPERTY(double themeType READ themeType WRITE setThemeType NOTIFY themeTypeChanged)
Q_PROPERTY(double titlebarHeight READ titlebarHeight WRITE setTitlebarHeight NOTIFY titlebarHeightChanged)
public:
explicit org_deepin_dtk_ui_preference(QThread *thread, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr)
: QObject(parent) {
if (!thread->isRunning()) {
qWarning() << QStringLiteral("Warning: The provided thread is not running.");
}
Q_ASSERT(QThread::currentThread() != thread);
auto worker = new QObject();
worker->moveToThread(thread);
QMetaObject::invokeMethod(worker, [=]() {
auto config = DTK_CORE_NAMESPACE::DConfig::create(appId, name, subpath, nullptr);
if (!config) {
qWarning() << QStringLiteral("Failed to create DConfig instance.");
worker->deleteLater();
return;
}
config->moveToThread(QThread::currentThread());
initialize(config);
worker->deleteLater();
});
}
explicit org_deepin_dtk_ui_preference(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &appId, const QString &name, const QString &subpath, QObject *parent = nullptr)
: QObject(parent) {
if (!thread->isRunning()) {
qWarning() << QStringLiteral("Warning: The provided thread is not running.");
}
Q_ASSERT(QThread::currentThread() != thread);
auto worker = new QObject();
worker->moveToThread(thread);
QMetaObject::invokeMethod(worker, [=]() {
auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, appId, name, subpath, nullptr);
if (!config) {
qWarning() << QStringLiteral("Failed to create DConfig instance.");
worker->deleteLater();
return;
}
config->moveToThread(QThread::currentThread());
initialize(config);
worker->deleteLater();
});
}
explicit org_deepin_dtk_ui_preference(QThread *thread, const QString &name, const QString &subpath, QObject *parent = nullptr)
: QObject(parent) {
if (!thread->isRunning()) {
qWarning() << QStringLiteral("Warning: The provided thread is not running.");
}
Q_ASSERT(QThread::currentThread() != thread);
auto worker = new QObject();
worker->moveToThread(thread);
QMetaObject::invokeMethod(worker, [=]() {
auto config = DTK_CORE_NAMESPACE::DConfig::create(name, subpath, nullptr);
if (!config) {
qWarning() << QStringLiteral("Failed to create DConfig instance.");
worker->deleteLater();
return;
}
config->moveToThread(QThread::currentThread());
initialize(config);
worker->deleteLater();
});
}
explicit org_deepin_dtk_ui_preference(QThread *thread, DTK_CORE_NAMESPACE::DConfigBackend *backend, const QString &name, const QString &subpath, QObject *parent = nullptr)
: QObject(parent) {
if (!thread->isRunning()) {
qWarning() << QStringLiteral("Warning: The provided thread is not running.");
}
Q_ASSERT(QThread::currentThread() != thread);
auto worker = new QObject();
worker->moveToThread(thread);
QMetaObject::invokeMethod(worker, [=]() {
auto config = DTK_CORE_NAMESPACE::DConfig::create(backend, name, subpath, nullptr);
if (!config) {
qWarning() << QStringLiteral("Failed to create DConfig instance.");
worker->deleteLater();
return;
}
config->moveToThread(QThread::currentThread());
initialize(config);
worker->deleteLater();
});
}
~org_deepin_dtk_ui_preference() {
if (m_config.loadRelaxed()) {
m_config.loadRelaxed()->deleteLater();
}
}
double themeType() const {
return p_themeType;
}
void setThemeType(const double &value) {
auto oldValue = p_themeType;
p_themeType = value;
markPropertySet(0);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("themeType"), value);
});
}
if (p_themeType != oldValue) {
Q_EMIT themeTypeChanged();
}
}
double titlebarHeight() const {
return p_titlebarHeight;
}
void setTitlebarHeight(const double &value) {
auto oldValue = p_titlebarHeight;
p_titlebarHeight = value;
markPropertySet(1);
if (auto config = m_config.loadRelaxed()) {
QMetaObject::invokeMethod(config, [this, value]() {
m_config.loadRelaxed()->setValue(QStringLiteral("titlebarHeight"), value);
});
}
if (p_titlebarHeight != oldValue) {
Q_EMIT titlebarHeightChanged();
}
}
Q_SIGNALS:
void themeTypeChanged();
void titlebarHeightChanged();
private:
void initialize(DTK_CORE_NAMESPACE::DConfig *config) {
Q_ASSERT(!m_config.loadRelaxed());
m_config.storeRelaxed(config);
if (testPropertySet(0)) {
config->setValue(QStringLiteral("themeType"), QVariant::fromValue(p_themeType));
} else {
updateValue(QStringLiteral("themeType"), QVariant::fromValue(p_themeType));
}
if (testPropertySet(1)) {
config->setValue(QStringLiteral("titlebarHeight"), QVariant::fromValue(p_titlebarHeight));
} else {
updateValue(QStringLiteral("titlebarHeight"), QVariant::fromValue(p_titlebarHeight));
}
connect(config, &DTK_CORE_NAMESPACE::DConfig::valueChanged, this, [this](const QString &key) {
updateValue(key);
}, Qt::DirectConnection);
}
void updateValue(const QString &key, const QVariant &fallback = QVariant()) {
Q_ASSERT(QThread::currentThread() == m_config.loadRelaxed()->thread());
const QVariant &value = m_config.loadRelaxed()->value(key, fallback);
if (key == QStringLiteral("themeType")) {
auto newValue = qvariant_cast<double>(value);
QMetaObject::invokeMethod(this, [this, newValue]() {
if (p_themeType != newValue) {
p_themeType = newValue;
Q_EMIT themeTypeChanged();
}
});
return;
}
if (key == QStringLiteral("titlebarHeight")) {
auto newValue = qvariant_cast<double>(value);
QMetaObject::invokeMethod(this, [this, newValue]() {
if (p_titlebarHeight != newValue) {
p_titlebarHeight = newValue;
Q_EMIT titlebarHeightChanged();
}
});
return;
}
}
inline void markPropertySet(const int index) {
if (index < 32) {
m_propertySetStatus0.fetchAndOrOrdered(1 << (index - 0));
return;
}
Q_UNREACHABLE();
}
inline bool testPropertySet(const int index) const {
if (index < 32) {
return (m_propertySetStatus0.loadRelaxed() & (1 << (index - 0)));
}
Q_UNREACHABLE();
}
QAtomicPointer<DTK_CORE_NAMESPACE::DConfig> m_config = nullptr;
double p_themeType { 0 };
double p_titlebarHeight { -1 };
QAtomicInteger<quint32> m_propertySetStatus0 = 0;
};
#endif // ORG_DEEPIN_DTK_UI_PREFERENCE_H

View File

@ -3,3 +3,4 @@ add_subdirectory(dci-image-converter)
add_subdirectory(dci-icon-theme)
add_subdirectory(dde-kwin-debug)
add_subdirectory(image-handler)
add_subdirectory(dci-iconfinder)

View File

@ -1,12 +1,15 @@
set(BIN_NAME dci-icon-theme)
set(TARGET_NAME ${BIN_NAME}${DTK_VERSION_MAJOR})
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Concurrent REQUIRED)
add_executable(${TARGET_NAME}
main.cpp
)
target_link_libraries(${TARGET_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Concurrent
${LIB_NAME}
)
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${BIN_NAME})

View File

@ -6,8 +6,6 @@ For example, the tool is used in the following ways:
dci-icon-theme /usr/share/icons/hicolor/256x256/apps -o ~/Desktop/hicolor -O 3=95
dci-icon-theme -m *.png /usr/share/icons/hicolor/256x256/apps -o ~/Desktop/hicolor -O 3=95
dci-icon-theme --fix-dark-theme <input dci files directory> -o <output directory path>
dci-icon-theme --find <icon name>
dci-icon-theme --find <icon name> -t bloom
dci-icon-theme <input file directory> -o <output directory path> -s <csv file> -O <qualities>
@ -34,8 +32,6 @@ Options:
--fix-dark-theme Create symlinks from light theme for
dark theme files.
--find Find dci icon file path
-t, --theme <theme name> Give a theme name to find dci icon file
path
-O, --scale-quality <scale quality> Quility of dci scaled icon image
The value may like <scale size>=<quality
value> e.g. 2=98:3=95

View File

@ -9,16 +9,28 @@
#include <QBuffer>
#include <QDebug>
#include <QtConcurrent/QtConcurrent>
#include <DDciFile>
#include <DIconTheme>
#include <DGuiApplicationHelper>
#include <DPlatformTheme>
#include <stdexcept>
#include <atomic>
DCORE_USE_NAMESPACE
DGUI_USE_NAMESPACE
// Custom exception for DCI processing errors
class DciProcessingError : public std::runtime_error {
public:
explicit DciProcessingError(const QString &message, int code = -1)
: std::runtime_error(message.toStdString()), errorCode(code) {}
int getErrorCode() const { return errorCode; }
private:
int errorCode;
};
#define MAX_SCALE 10
#define INVALIDE_QUALITY -2
#define SCALABLE_SIZE 256
static int quality4Scaled[MAX_SCALE] = {};
static inline void initQuality() {
for (int i = 0; i < MAX_SCALE; ++i)
@ -28,10 +40,45 @@ static inline void initQuality() {
static inline void dciChecker(bool result, std::function<const QString()> cb) {
if (!result) {
qWarning() << "Failed on writing dci file" << cb();
exit(-6);
throw DciProcessingError("Failed on writing dci file", -6);
}
}
// TODO 应该使用xdg图标查找规范解析index.theme来查找尺寸
static int foundSize(const QFileInfo &fileInfo) {
QDir dir = fileInfo.absoluteDir();
// 解析尺寸
auto parseSize = [](const QString &dirName) -> int {
bool ok;
if (int size = dirName.toUInt(&ok); ok) {
return size;
}
if (dirName.contains('x') && dirName.split('x').size() == 2) {
if (int size = dirName.split('x').first().toUInt(&ok); ok) {
return size;
}
}
if (dirName == "scalable") {
return SCALABLE_SIZE;
}
return 0;
};
if (int size = parseSize(dir.dirName()); size > 0) {
return size;
}
// 尝试找上一级目录
if (!dir.cdUp())
return 0;
return parseSize(dir.dirName());
}
static inline QByteArray webpImageData(const QImage &image, int quality) {
QByteArray data;
QBuffer buffer(&data);
@ -41,28 +88,18 @@ static inline QByteArray webpImageData(const QImage &image, int quality) {
return data;
}
static bool writeScaledImage(DDciFile &dci, const QString &imageFile, const QString &targetDir, int scale/* = 2*/)
static bool writeScaledImage(DDciFile &dci, const QImage &image, const QString &targetDir, const int baseSize, int scale/* = 2*/)
{
QString sizeDir = targetDir.mid(1, targetDir.indexOf("/", 1) - 1);
bool ok = false;
int baseSize = sizeDir.toInt(&ok);
if (!ok)
baseSize = 256;
int size = scale * baseSize;
QImageReader image(imageFile);
if (!image.canRead()) {
qWarning() << "Ignore the null image file:" << imageFile;
return false;
}
if (image.supportsOption(QImageIOHandler::ScaledSize)) {
image.setScaledSize(QSize(size, size));
QImage img;
if (image.width() == size) {
img = image;
} else {
img = image.scaledToWidth(size, Qt::SmoothTransformation);
}
dciChecker(dci.mkdir(targetDir + QString("/%1").arg(scale)), [&]{return dci.lastErrorString();});
const QImage &img = image.read().scaledToWidth(size, Qt::SmoothTransformation);
int quality = quality4Scaled[scale - 1];
int quality = quality4Scaled[scale - 1];
const QByteArray &data = webpImageData(img, quality);
dciChecker(dci.writeFile(targetDir + QString("/%1/1.webp").arg(scale), data), [&]{return dci.lastErrorString();});
@ -71,13 +108,28 @@ static bool writeScaledImage(DDciFile &dci, const QString &imageFile, const QStr
static bool writeImage(DDciFile &dci, const QString &imageFile, const QString &targetDir)
{
QString sizeDir = targetDir.mid(1, targetDir.indexOf("/", 1) - 1);
bool ok = false;
int baseSize = sizeDir.toInt(&ok);
if (!ok)
baseSize = 256;
QImageReader reader(imageFile);
if (!reader.canRead()) {
qWarning() << "Ignore the null image file:" << imageFile;
return false;
}
for (int i = 0; i < MAX_SCALE; ++i) {
if (quality4Scaled[i] == INVALIDE_QUALITY)
continue;
int scale = i + 1;
if (!writeScaledImage(dci, imageFile, targetDir, i + 1))
reader.setScaledSize(QSize(baseSize * scale, baseSize * scale));
auto image = reader.read();
if (!writeScaledImage(dci, image, targetDir, baseSize, scale))
return false;
}
}
return true;
}
@ -131,7 +183,7 @@ QMultiHash<QString, QString> parseIconFileSymlinkMap(const QString &csvFile) {
QFile file(csvFile);
if (!file.open(QIODevice::ReadOnly)) {
qWarning() << "Failed on open symlink map file:" << csvFile;
exit(-7);
throw DciProcessingError("Failed on open symlink map file", -7);
}
QMultiHash<QString, QString> map;
@ -219,8 +271,6 @@ int main(int argc, char *argv[])
,
"csv file");
QCommandLineOption fixDarkTheme("fix-dark-theme", "Create symlinks from light theme for dark theme files.");
QCommandLineOption iconFinder("find", "Find dci icon file path");
QCommandLineOption themeOpt({"t","theme"}, "Give a theme name to find dci icon file path", "theme name");
QCommandLineOption scaleQuality({"O","scale-quality"}, "Quility of dci scaled icon image\n"
"The value may like <scale size>=<quality value> e.g. 2=98:3=95\n"
"The quality factor must be in the range 0 to 100 or -1.\n"
@ -229,8 +279,12 @@ int main(int argc, char *argv[])
"The higher the quality, the larger the dci icon file size", "scale quality");
QGuiApplication a(argc, argv);
a.setApplicationName("dci-icon-theme");
a.setApplicationVersion("0.0.6");
a.setApplicationVersion(QString("%1.%2.%3")
.arg(DTK_VERSION_MAJOR)
.arg(DTK_VERSION_MINOR)
.arg(DTK_VERSION_PATCH));
QCommandLineParser cp;
cp.setApplicationDescription("dci-icon-theme tool is a command tool that generate dci icons from common icons.\n"
@ -238,12 +292,10 @@ int main(int argc, char *argv[])
"\t dci-icon-theme /usr/share/icons/hicolor/256x256/apps -o ~/Desktop/hicolor -O 3=95\n"
"\t dci-icon-theme -m *.png /usr/share/icons/hicolor/256x256/apps -o ~/Desktop/hicolor -O 3=95\n"
"\t dci-icon-theme --fix-dark-theme <input dci files directory> -o <output directory path> \n"
"\t dci-icon-theme --find <icon name>\n"
"\t dci-icon-theme --find <icon name> -t bloom\n"
"\t dci-icon-theme <input file directory> -o <output directory path> -s <csv file> -O <qualities>\n"""
);
cp.addOptions({fileFilter, outputDirectory, symlinkMap, fixDarkTheme, iconFinder, themeOpt, scaleQuality});
cp.addOptions({fileFilter, outputDirectory, symlinkMap, fixDarkTheme, scaleQuality});
cp.addPositionalArgument("source", "Search the given directory and it's subdirectories, "
"get the files conform to rules of --match.",
"~/dci-png-icons");
@ -254,27 +306,11 @@ int main(int argc, char *argv[])
if (a.arguments().size() == 1)
cp.showHelp(-1);
bool isIconFinder = cp.isSet(iconFinder);
if (cp.positionalArguments().isEmpty()) {
qWarning() << "Not give a" << (isIconFinder ? "icon name." : "source directory.");
qWarning() << "Not give a source directory.";
cp.showHelp(-2);
}
QString iconThemeName;
if (cp.isSet(themeOpt)) {
iconThemeName = cp.value(themeOpt);
} else {
iconThemeName = DGuiApplicationHelper::instance()->applicationTheme()->iconThemeName();
}
if (isIconFinder) {
QString iconName = cp.positionalArguments().value(0);
QString iconPath = DIconTheme::findDciIconFile(iconName, iconThemeName);
qInfo() << iconName << "[" << iconThemeName << "]:" << iconPath;
return 0;
}
if (!cp.isSet(outputDirectory)) {
qWarning() << "Not give -o argument";
cp.showHelp(-4);
@ -295,10 +331,6 @@ int main(int argc, char *argv[])
#endif
QStringList qualityList = cp.value(scaleQuality).split(":", behavior);
#ifdef QT_DEBUG
surfix = cp.value(scaleQuality).prepend("-");
#endif
for (const QString &kv : qualityList) {
auto sq = kv.split("=");
if (sq.size() != 2) {
@ -331,12 +363,17 @@ int main(int argc, char *argv[])
QMultiHash<QString, QString> symlinksMap;
if (cp.isSet(symlinkMap)) {
symlinksMap = parseIconFileSymlinkMap(cp.value(symlinkMap));
try {
symlinksMap = parseIconFileSymlinkMap(cp.value(symlinkMap));
} catch (const DciProcessingError &e) {
qWarning() << "Error parsing symlink map:" << e.what();
return e.getErrorCode();
}
}
const QStringList nameFilter = cp.isSet(fileFilter) ? cp.values(fileFilter) : QStringList();
const auto sourceDirectory = cp.positionalArguments();
for (const auto &sd : qAsConst(sourceDirectory)) {
for (const auto &sd : sourceDirectory) {
QDir sourceDir(sd);
if (!sourceDir.exists()) {
qWarning() << "Ignore the non-exists directory:" << sourceDir;
@ -369,6 +406,8 @@ int main(int argc, char *argv[])
}
}
// Collect all files first, grouped by icon name to avoid concurrent access to same DCI file
QMap<QString, QList<QFileInfo>> iconGroups;
QDirIterator di(sourceDir.absolutePath(), nameFilter,
QDir::NoDotAndDotDot | QDir::Files,
QDirIterator::Subdirectories);
@ -380,7 +419,12 @@ int main(int argc, char *argv[])
continue;
if (cp.isSet(fixDarkTheme)) {
doFixDarkTheme(file, outputDir, symlinksMap);
try {
doFixDarkTheme(file, outputDir, symlinksMap);
} catch (const DciProcessingError &e) {
qWarning() << "Error fixing dark theme for file" << file.absoluteFilePath() << ":" << e.what();
return e.getErrorCode();
}
continue;
}
@ -389,46 +433,86 @@ int main(int argc, char *argv[])
continue;
}
QString dirName = file.absoluteDir().dirName();
bool isNum = false;
dirName.toInt(&isNum);
dirName.prepend("/");
iconGroups[file.completeBaseName()].append(file);
}
// Process with proper exception handling
std::atomic<bool> hasError{false};
int errorCode = 0;
// Process icon groups concurrently (each group shares same DCI file)
QList<QString> iconNames = iconGroups.keys();
QtConcurrent::blockingMap(iconNames, [&](const QString &iconName) {
if (hasError.load()) return; // Skip if already has error
try {
const QList<QFileInfo> &files = iconGroups[iconName];
const QString dciFilePath(outputDir.absoluteFilePath(iconName) + surfix + ".dci");
QScopedPointer<DDciFile> dciFile;
for (const QFileInfo &file : files) {
QString dirName = file.absoluteDir().dirName();
uint iconSize = foundSize(file);
dirName = iconSize > 0 ? QString("/%1").arg(iconSize) : dirName.prepend("/");
QScopedPointer<DDciFile> dciFile;
const QString dciFilePath(outputDir.absoluteFilePath(file.completeBaseName()) + surfix + ".dci");
if (QFileInfo::exists(dciFilePath)) {
dciFile.reset(new DDciFile(dciFilePath));
if (dciFile->isValid() && dciFile->exists(dirName)) {
qWarning() << "Skip exists dci file:" << dciFilePath << dirName << dciFile->list(dirName);
continue;
// Initialize DCI file once per icon group
if (dciFile.isNull()) {
if (QFileInfo::exists(dciFilePath)) {
dciFile.reset(new DDciFile(dciFilePath));
}
if (dciFile.isNull() || !dciFile->isValid()) {
dciFile.reset(new DDciFile);
}
}
if (dciFile->exists(dirName)) {
qWarning() << "Skip exists dci file:" << dciFilePath << dirName << dciFile->list(dirName);
continue;
}
qInfo() << "Writing to dci file:" << file.absoluteFilePath() << "==>" << dciFilePath;
QString sizeDir = iconSize > 0 ? dirName : "/256"; // "/256" as default
QString normalLight = sizeDir + "/normal.light"; // "/256/normal.light"
QString normalDark = sizeDir + "/normal.dark"; // "/256/normal.dark"
if (dciFile->exists(sizeDir)) {
qWarning() << "Skip exists dci file:" << dciFilePath << sizeDir << dciFile->list(sizeDir);
continue;
}
dciChecker(dciFile->mkdir(sizeDir), [&]{return dciFile->lastErrorString();});
dciChecker(dciFile->mkdir(normalLight), [&]{return dciFile->lastErrorString();});
if (!writeImage(*dciFile, file.filePath(), normalLight))
continue;
dciChecker(dciFile->mkdir(normalDark), [&]{return dciFile->lastErrorString();});
QFileInfo darkIcon(file.dir().absoluteFilePath("dark/" + file.fileName()));
if (darkIcon.exists()) {
writeImage(*dciFile, darkIcon.filePath(), normalDark);
} else {
dciChecker(recursionLink(*dciFile, normalLight, normalDark), [&]{return dciFile->lastErrorString();});
}
}
// Write DCI file once per icon group
if (!dciFile.isNull()) {
dciChecker(dciFile->writeToFile(dciFilePath), [&]{return dciFile->lastErrorString();});
// Create symlinks for all files in this group
for (const QFileInfo &file : files) {
makeLink(file, outputDir, dciFilePath, symlinksMap);
}
}
} catch (const DciProcessingError &e) {
qWarning() << "Error processing icon group" << iconName << ":" << e.what();
hasError.store(true);
errorCode = e.getErrorCode();
}
});
qInfo() << "Writing to dci file:" << file.absoluteFilePath() << "==>" << dciFilePath;
if (dciFile.isNull() || !dciFile->isValid())
dciFile.reset(new DDciFile);
QString sizeDir = isNum ? dirName : "/256"; // "/256"
QString normalLight = sizeDir + "/normal.light"; // "/256/normal.light"
QString normalDark = sizeDir + "/normal.dark"; // "/256/normal.dark"
dciChecker(dciFile->mkdir(sizeDir), [&]{return dciFile->lastErrorString();});
dciChecker(dciFile->mkdir(normalLight), [&]{return dciFile->lastErrorString();});
if (!writeImage(*dciFile, file.filePath(), normalLight))
continue;
dciChecker(dciFile->mkdir(normalDark), [&]{return dciFile->lastErrorString();});
QFileInfo darkIcon(file.dir().absoluteFilePath("dark/" + file.fileName()));
if (darkIcon.exists()) {
writeImage(*dciFile, darkIcon.filePath(), normalDark);
} else {
dciChecker(recursionLink(*dciFile, normalLight, normalDark), [&]{return dciFile->lastErrorString();});
}
dciChecker(dciFile->writeToFile(dciFilePath), [&]{return dciFile->lastErrorString();});
makeLink(file, outputDir, dciFilePath, symlinksMap);
if (hasError.load()) {
qWarning() << "Encountered errors during DCI file writing" << errorCode;
continue;
}
}

View File

@ -0,0 +1,14 @@
set(BIN_NAME dci-iconfinder)
set(TARGET_NAME ${BIN_NAME}${DTK_VERSION_MAJOR})
add_executable(${TARGET_NAME}
main.cpp
)
target_link_libraries(${TARGET_NAME} PRIVATE
Qt${QT_VERSION_MAJOR}::Gui
${LIB_NAME}
)
set_target_properties(${TARGET_NAME} PROPERTIES OUTPUT_NAME ${BIN_NAME})
install(TARGETS ${TARGET_NAME} DESTINATION "${TOOL_INSTALL_DIR}")

View File

@ -0,0 +1,61 @@
// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
#include <QGuiApplication>
#include <QCommandLineParser>
#include <QDebug>
#include <DIconTheme>
DGUI_USE_NAMESPACE
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
a.setApplicationName("dci-iconfinder");
a.setApplicationVersion(QString("%1.%2.%3")
.arg(DTK_VERSION_MAJOR)
.arg(DTK_VERSION_MINOR)
.arg(DTK_VERSION_PATCH));
QCommandLineParser cp;
cp.setApplicationDescription(
"dci-iconfinder tool is a command tool that find dci icons in the icon "
"theme.\n"
"For example, the tool is used in the following ways: \n"
"\t dci-iconfinder <icon name>\n"
"\t dci-iconfinder <icon name> -t bloom\n");
QCommandLineOption themeOpt({"t", "theme"},
"Give a theme name to find dci icon file path",
"theme name");
cp.addOptions({themeOpt});
cp.addPositionalArgument("iconnames", "The icon names to search for",
"iconnames");
cp.addHelpOption();
cp.addVersionOption();
cp.process(a);
if (cp.positionalArguments().isEmpty()) {
qWarning() << "Not give icon name.";
cp.showHelp(-1);
}
QString iconThemeName;
if (cp.isSet(themeOpt)) {
iconThemeName = cp.value(themeOpt);
} else {
iconThemeName = QIcon::themeName();
}
const auto icons = cp.positionalArguments();
for (const QString &iconName : icons) {
QString iconPath = DIconTheme::findDciIconFile(iconName, iconThemeName);
if (!iconPath.isEmpty())
qInfo().noquote() << iconName << "[" << iconThemeName << "]:" << iconPath;
}
return 0;
}