8000 fix(linux): 修复隐藏窗口标题栏导致的高 CPU 与点击失焦 by Ultra-Logos · Pull Request #3567 · bggRGjQaUbCoE/PiliPlus · GitHub
[go: up one dir, main page]

Skip to content

fix(linux): 修复隐藏窗口标题栏导致的高 CPU 与点击失焦 - #3567

Open
Ultra-Logos wants to merge 1 commit into
bggRGjQaUbCoE:mainfrom
Ultra-Logos:fix/linux-hide-titlebar-cpu
Open

Ultra-Logos wants to merge 1 commit into
bggRGjQaUbCoE:mainfrom
Ultra-Logos:fix/linux-hide-titlebar-cpu

Conversation

@Ultra-Logos
Copy link
Copy Markdown
  • 新增 Linux 窗口 channel;showWindowTitleBar=false 时写入 hide_title_bar 标记,runner 启动时跳过 GtkHeaderBar,避免 GTK 与 nativeapi 的 shadow width 在 0/132 之间反复切换
  • 设置项切换时同步创建/删除标记文件
  • 旧配置首次启动通过 relaxShadow 持续清零阴影 gutter,立即消除高 CPU,下次启动走无 GtkHeaderBar 的正常路径

- 新增 Linux 窗口 channel;showWindowTitleBar=false 时写入 hide_title_bar 标记,runner 启动时跳过 GtkHeaderBar,避免 GTK 与 nativeapi 的 shadow width 在 0/132 之间反复切换
- 设置项切换时同步创建/删除标记文件
- 旧配置首次启动通过 relaxShadow 持续清零阴影 gutter,立即消除高 CPU,下次启动走无 GtkHeaderBar 的正常路径
@Ultra-Logos
Copy link
Copy Markdown
Author

症状描述

环境

  • PiliPlus 2.2.0.2(Linux 安装版,本地源码同版本)
  • KDE Plasma / Wayland(kwin_wayland,WAYLAND_DISPLAY=wayland-1)
  • GTK 3.24.52
  • Flutter 3.47.9
  • window_manager 0.6.0 + nativeapi / cnativeapi 0.5.10

复现步骤

  1. 打开“设置 → 样式”,关闭“显示窗口标题栏”;
  2. 完全退出 PiliPlus;
  3. 重新启动 PiliPlus;
  4. 不进行任何操作,观察 CPU 和界面响应。

实际表现

  1. CPU 异常高:启动后主线程(GTK main)持续约 99–101%,基本跑满一个核心;即使窗口空闲、没有任何鼠标操作也不会降下来。
  2. 整个 GUI 严重卡顿:滚动、动画、窗口拖动/缩放、按钮点击都有明显延迟,应用几乎不可用。
  3. 点击顶栏按钮会失焦:点击窗口上层的日/夜间模式切换按钮、设置按钮时,窗口会直接失去焦点,按钮操作不跟手。
  4. 持续整窗重绘:WAYLAND_DEBUG=1 可见客户端约每 19ms 重复提交一次窗口几何和绘制:
    • xdg_surface.set_window_geometry(132,132,2048,1280)
    • input region (132,132,1916,1148)
    • 约 52fps 提交 4624×3088 的 buffer
  5. 不是 Flutter 绘制问题:top -H 中 io.flutter.raster 只有约 18 ticks,而 GTK 主线程接近 100%,说明瓶颈在 GTK 主循环/窗口几何路径,不在 Flutter raster。
  6. 重新开启标题栏后恢复正常:把“显示窗口标题栏”改回开启并重启,启动后 CPU 可降到 0,卡顿和失焦都消失。

补充观测:4 秒内 GTK 收到约 444 次 GDK_EXPOSE、296 次 GDK_CONFIGURE、42 次 GDK_MOTION_NOTIFY;但 6 秒内来自 compositor 的 xdg_toplevel.configure 只有约 3 次,说明大量 configure 是客户端内部反复重配置产生的,不是 KWin 持续下发。

初步定位

该问题只出现在“隐藏标题栏”路径:

  • runner 仍创建了 GtkHeaderBar(CSD,client_decorated=true);
  • nativeapi 同时为窗口预留了 132px 的阴影 gutter;
  • GTK 在 gtk/gtkwindow.c:7371-7381 的 update_realized_window_properties() 中调用 update_shadow_width(0,0,0,0);
  • nativeapi 的 linux_shadow::Allocated 随后通过 DeclareGutter 把 shadow width 设回 132,132,132,132;
  • GDK Wayland 因 margin 变化重新计算窗口尺寸,触发新的 configure/allocate;
  • 形成 0 ↔ 132 无限循环,导致持续整窗重绘、高 CPU,以及输入区域/窗口几何异常,和顶栏按钮点击失焦的现象吻合。

gdb 断点已确认 gdk_window_set_shadow_width 的参数严格交替:

ARGS 0 0 0 0          # 调用者 libgtk-3.so
ARGS 132 132 132 132  # 调用者 nativeapi::linux_shadow::DeclareGutter

已验证的规避/佐证

  • LD_PRELOAD 空实现 gdk_window_set_shadow_width 后,CPU 立即降为 0;
  • 创建 ~/.local/share/com.example.piliplus/use_ssd 让 runner 不创建 GtkHeaderBar 后,CPU 为 0;
  • 运行时把 gtk_container_set_border_width(window, 0) 可立即终止循环,但本次运行会失去 nativeapi 阴影;
  • 运行时调用 gtk_window_set_titlebar(window, NULL) 虽然能降 CPU,但会导致 FlView 渲染面创建失败(Impeller Could not determine GL version / Failed to create platform view rendering surface),因此不适合作为修复方案。

期望行为

关闭“显示窗口标题栏”并重启后:

  • 不应出现持续高 CPU 或整窗重绘;
  • 顶栏按钮点击不应导致窗口失焦;
  • 窗口输入区域和几何应与实际内容一致;
  • 重新开启标题栏后行为保持正常。

范围说明

目前至少在 KDE Plasma Wayland 上稳定复现;X11 环境尚未验证。问题只在 showWindowTitleBar=false 时出现,和是否使用 use_ssd/是否创建 GtkHeaderBar 强相关。

@burindow8102
Copy link
Copy Markdown

同一个 132px gutter,但现象可能不在这个 PR 的范围内,想确认一下。

症状描述

环境

  • PiliPlus 2.2.0+5598(Fedora RPM)
  • Fedora 44,KDE Plasma 6.8.2,KWin Wayland
  • GTK 3.24.52
  • 2560x1600 @165hz,缩放 1.25

复现步骤

  1. 设置 → 样式 → 关闭「显示窗口标题栏」;
  2. 完全退出 PiliPlus,重新启动;
  3. 用 KWin 记录窗口的 client 尺寸;
  4. 再退出、再启动,重复 2~3 次。

实际表现

  1. 窗口每次启动宽高各 +264px:
    • 第 1 次:1180x720
    • 第 2 次:1444x984
    • 第 3 次:1708x1248
  2. 最后被工作区卡在 2048x1280,窗口比工作区还大。

初步定位

看起来 bounds 存的是 frame(含 gutter),恢复时又当 client 用。WAYLAND_DEBUG=1 里能看到:

set_window_geometry(0,0,1180,720)
→ set_window_geometry(132,132,1444,984)

# 下次启动
set_window_geometry(0,0,1444,984)
→ set_window_geometry(132,132,1708,1248)

已验证的规避/佐证

  • 用 use_ssd(同样跳过 GtkHeaderBar)实测 gutter 还在、尺寸照样 +264,所以这个 PR 的改动可能不覆盖它;
  • 打开「显示窗口标题栏」后窗口尺寸稳定,不再放大。

想确认

请你判断这块要不要一起修。需要的话我把完整的 WAYLAND_DEBUG 日志、三次启动的尺寸记录和 KWin 几何整理好补充上来;如果更适合单独跟踪,我就另开一个 issue 并在这里回链,不占用这个 PR 的讨论。谢谢。

@Ultra-Logos
Copy link
Copy Markdown
Author

@burindow8102

同一个 132px gutter,但现象可能不在这个 PR 的范围内,想确认一下。

症状描述

环境

  • PiliPlus 2.2.0+5598(Fedora RPM)
  • Fedora 44,KDE Plasma 6.8.2,KWin Wayland
  • GTK 3.24.52
  • 2560x1600 @165hz,缩放 1.25

复现步骤

  1. 设置 → 样式 → 关闭「显示窗口标题栏」;
  2. 完全退出 PiliPlus,重新启动;
  3. 用 KWin 记录窗口的 client 尺寸;
  4. 再退出、再启动,重复 2~3 次。

实际表现

  1. 窗口每次启动宽高各 +264px:

    • 第 1 次:1180x720
    • 第 2 次:1444x984
    • 第 3 次:1708x1248
  2. 最后被工作区卡在 2048x1280,窗口比工作区还大。

初步定位

看起来 bounds 存的是 frame(含 gutter),恢复时又当 client 用。WAYLAND_DEBUG=1 里能看到:

set_window_geometry(0,0,1180,720)
→ set_window_geometry(132,132,1444,984)

# 下次启动
set_window_geometry(0,0,1444,984)
→ set_window_geometry(132,132,1708,1248)

已验证的规避/佐证

  • 用 use_ssd(同样跳过 GtkHeaderBar)实测 gutter 还在、尺寸照样 +264,所以这个 PR 的改动可能不覆盖它;
  • 打开「显示窗口标题栏」后窗口尺寸稳定,不再放大。

想确认

请你判断这块要不要一起修。需要的话我把完整的 WAYLAND_DEBUG 日志、三次启动的尺寸记录和 KWin 几何整理好补充上来;如果更适合单独跟踪,我就另开一个 issue 并在这里回链,不占用这个 PR 的讨论。谢谢。

感谢反馈,这个现象和本 PR 不是同一个问题。
本 PR 只处理了隐藏标题栏后 GTK CSD 与 nativeapi shadow 之间 0↔132 的重绘循环,没有改变 nativeapi 的 gutter 和窗口尺寸持久化逻辑。你用 use_ssd 仍然 +264 也说明它独立于 GtkHeaderBar。
我看了 nativeapi 0.5.10 的 Linux 实现,初步判断是:窗口尚未 viewable 时 GetContentSize() 回退到 gdk_window_get_width(),返回了包含 132px gutter 的 surface 尺寸;而下次启动 SetBounds() 在 map 前拿不到 decorations,又把保存值当 content,再叠加一次 gutter,所以每次 +264。这个应该单开 issue 修,最好报到 libnativeapi/nativeapi。
麻烦你把完整的 WAYLAND_DEBUG、三次启动的尺寸记录和 KWin 几何整理到新 issue 里,我在本 PR 里回链即可。感谢!

@Tobiichi-Origuchi
Tobiichi-Origuchi commented Nov 11, 2026 •
Copy link
Copy Markdown
Contributor

@burindow8102
Copy link
Copy Markdown

已在 #3569 跟踪这个尺寸放大问题(附了完整 WAYLAND_DEBUG 和三次启动记录),并引用了 f13e7a2。等 cnativeapi 发布包含该提交的版本后我重新构建实测,有结果会回来反馈。感谢指路!

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

0