Skip to content

Linux

Warning

The current page still doesn't have a translation for this language.

You can read it through google translate.

Linux 是 swinx 最早适配的非 Windows 平台。它的平台 API 全部在 swinx 内部实现swinx/src/platform/linux),不依赖任何外部桥接库,也不使用 g_platformAPI

构建选择

swinx/CMakeLists.txt 中,Linux 走的是兜底分支:

if(CMAKE_SYSTEM_NAME MATCHES "OHOS|OpenHarmony|HarmonyOS|Android")
    include(mobile.cmake)
elseif(CMAKE_SYSTEM_NAME MATCHES "iOS")
    include(ios.cmake)
elseif(CMAKE_SYSTEM_NAME MATCHES Darwin)
    include(macos.cmake)
else()
    include(linux.cmake)     # ← Linux
endif()

swinx/linux.cmake 编译的源码集合为:

file(GLOB SRCS
    thirdparty/xcb-util-image/*.c
    thirdparty/xcb-util-renderutil/*.c
    thirdparty/xcb-util-keysyms/*.c
    thirdparty/xcb-util-wm/*.c
    thirdparty/xcb-util/*.c
    thirdparty/libxcb/*.c
    src/*.cpp
    src/cmnctl32/*.cpp
    src/cmnctl32/*.c
    src/platform/linux/*.cpp
    src/gdi/cairo/*.cpp
    )

即:swinx 公共层 + 通用控件 + Linux 平台层 + Cairo 2D 后端

第三方依赖:全部内置编译

swinx 刻意不依赖发行版的开发包,而是把关键库放在 swinx/thirdparty/ 内一起编译,以保证不同发行版上行为一致:

add_subdirectory(thirdparty/xkbcommon)
add_subdirectory(thirdparty/libxcb)
add_subdirectory(thirdparty/xcb-imdkit)
add_subdirectory(thirdparty/dbus-1.14.10)
内置库 作用
libxcb + xcb-util-* X11 协议客户端;窗口创建、属性、事件、键盘符号
xkbcommon 键盘布局与按键映射(keyboard.cpp
xcb-imdkit 输入法支持,走 XIM 协议(imm.cpp 中的 xcb_xim_*
dbus-1.14.10 通用对话框走 D-Bus portal(dlghelper.cpp
cairo / pixman-1 / freetype / fontconfig 2D 绘制与字体(来自 swinx/thirdparty

最终链接:

target_link_libraries(swinx
    cairo xkbcommon xcb-imdkit dbus-1
    ${SWINX_LIBS}      # dl xcb uuid atomic m stdc++ ${ALSA_LIBRARIES}
)

系统侧只需要提供 libxcblibuuid、C++ 运行库等基础库。

窗口系统与事件泵

swinx/src/platform/linux/SConnection.cpp 中,swinx 自己建立 X11 连接并驱动消息循环:

connection = xcb_connect(nullptr, &screenNum);
if (int errCode = xcb_connection_has_error(connection) > 0) {
    SLOG_STME() << "xcb_connect failed, error=" << errCode;
}

消息泵基于 poll() 阻塞等待,被唤醒后用 xcb_poll_for_event() 排空事件队列,再转换为 Win32 消息投递给 SOUI:

int ret = poll(fds, nfds, -1);              // 阻塞等待 X 连接 / 唤醒管道 / 定时器
xcb_generic_event_t *event = xcb_poll_for_event(connection);

这也是 GetMessage / PeekMessage 在 Linux 上的底层实现——SOUI 业务侧的消息循环写法与 Windows 完全一致。

关于 Wayland

linux.cmake 只编译 xcb 相关代码,swinx 目前没有原生 Wayland 后端。在 Wayland 桌面环境下通过 XWayland 兼容层运行。

2D 绘制:Cairo

GDI 调用由 swinx/src/gdi/cairo/ 翻译到 Cairo:

文件 作用
gdi.cpp DC、位图、画刷、画笔、BitBlt 等核心 GDI 实现
drawtext.cpp DrawText / TextOut 的布局与换行处理
cairo_show_text2.cpp 文本绘制的底层封装
builtin_image.cpp 内置图片解码

注意区分层次:Cairo 是 swinx 的 2D 后端;SOUI 上层通常仍使用 Render_Skia 渲染工厂绘制 UI,最终结果通过 Cairo 上屏。

桌面集成特性

Linux 平台层实现了以下桌面集成能力:

特性 实现文件 机制
托盘图标 STrayIconMgr.cpp 遵循 freedesktop 系统托盘协议:查找 _NET_SYSTEM_TRAY_S0 托盘窗口,通过 _NET_SYSTEM_TRAY_OPCODE 发送嵌入请求;按 _NET_SYSTEM_TRAY_VISUAL 创建 32 位视觉的图标窗口以支持透明
拖放 SDragdrop.cpp XDND 协议,对接 swinx 的 OLE 拖放接口
剪贴板 SClipboard.cpp X11 Selection 机制
输入法 imm.cpp 通过 xcb-imdkit 走 XIM 协议对接 fcitx / ibus
文件对话框 dlghelper.cpp 优先走 D-Bus org.freedesktop.portal(含 deepin/UOS 专用 portal 适配);D-Bus 不可用或调用失败时回退到 zenity

音频

ALSA 是可选依赖

pkg_check_modules(ALSA QUIET alsa)
if(ALSA_FOUND)
    message(STATUS "ALSA found, enabling native audio support")
    add_definitions(-DHAS_ALSA)
else()
    message(STATUS "ALSA not found, will use avplay fallback for audio, please install libasound2-dev")
endif()
  • 有 ALSA(libasound2-dev):PlaySound 走原生 ALSA 播放。
  • 无 ALSA:回退到调用外部 avplay 进程。

编译与运行注意事项

  1. WCHAR_SIZE=4:Linux 的 wchar_t 是 4 字节。业务代码不要假设宽字符是 2 字节,统一使用 SStringT / _T()
  2. 字体需显式加载:Linux 发行版字体差异大,建议随包分发字体并在 SAppCfg::DoConfig 之后调用 AddFontResource("simsun.ttc")
  3. 文件名大小写敏感:XML 布局、皮肤中引用的资源名必须与实际文件名完全一致。
  4. RPATH 设置:根 CMakeLists.txt 为非 Apple 平台设置了 CMAKE_INSTALL_RPATH=$ORIGIN,同时 linux.cmake 为 swinx 动态库设置 INSTALL_RPATH "$ORIGIN"-Wl,--export-dynamic,因此依赖库与可执行文件同目录即可运行。
  5. Release 会 strip:Linux 的 Release 配置追加了 -sCMAKE_CXX_FLAGS_RELEASE),需要符号时请用 Debug 或 RelWithDebInfo。
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)

相关文档