Files
e2hang 96cb28fe08 feat: multi-layer eventFilter for window drag + text input fix + Qt platform xcb
- Fix window drag: install eventFilter on live2d_container, central, and
  _live2d_widget; fix super() call in dynamic class
- Fix text input: remove WA_TransparentForMouseEvents from _chat_container
- Force QT_QPA_PLATFORM=xcb on Linux (wayland has mouse event issues)
- Add HealthTracker module, update AgentBrain with health integration
- Update scheduler and memory modules
- Add v5_modify documentation

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 23:36:58 +08:00
..

v5_modify — 窗口拖拽与文本输入修复

故障描述

  1. 窗口无法拖动:鼠标左键点击并拖动窗口区域时,窗口不跟随移动。
  2. 聊天输入框无法输入文字:在输入框中点击后无法输入文字。

环境

  • 平台Linux (Fedora 40)
  • Qt 平台xcbWayland 下存在鼠标事件兼容性问题)
  • Python3.13 + PySide6
  • 桌宠窗口无边框、置顶、Tool 类型

故障 1窗口拖动失效

根因分析

问题 Asuper() 在动态类中调用失败

PetWindow 使用 type() 动态创建,eventFilter 方法中调用 super().eventFilter() 在 PySide6 中会导致 SystemError 或属性错误。

问题 B鼠标事件未到达事件过滤器

  • WA_TransparentForMouseEvents 属性使 QWebEngineView 将鼠标事件传递给下层窗口
  • QWebEngineView 本身没有安装事件过滤器,所以即使 live2d_container 安装了过滤器,WebEngineView 仍然先接收并处理了 MouseButtonPress 事件
  • 事件类型 68 (ChildAdded)69 (ChildPolished) 能到达过滤器,但 MouseButtonPress (2) 始终没有触发

问题 CWayland vs X11 平台差异

QT_QPA_PLATFORM=wayland 时 Qt 的鼠标事件分发机制与 xcb 不同,导致事件冒泡行为不一致。xcb 平台下事件能正常到达过滤器。

修复方案

1. 修复 eventFilter 中的 super() 调用

# 错误 ❌
return super().eventFilter(obj, event)

# 正确 ✅
return self._QtWidgets.QMainWindow.eventFilter(self, obj, event)

2. 多层事件过滤器安装

在三个层级同时安装事件过滤器:

# _init_ui 中
live2d_container.installEventFilter(self)   # Live2D 容器
central.installEventFilter(self)             # 中央部件

# _init_live2d 中
self._live2d_widget.installEventFilter(self)  # Live2D WebEngineView 控件

3. eventFilter 中添加 Live2D 控件判断

is_live2d_target = (hasattr(self, '_live2d_widget') 
                    and self._live2d_widget is not None 
                    and obj == self._live2d_widget)
if obj != live2d_container and obj != self.centralWidget() and not is_live2d_target:
    return self._QtWidgets.QMainWindow.eventFilter(self, obj, event)

4. Qt 平台强制使用 xcb

# main.py
if sys.platform.startswith("linux") and os.environ.get("QT_QPA_PLATFORM") is None:
    os.environ["QT_QPA_PLATFORM"] = "xcb"  # 而非 wayland

5. 启用 Hover 事件属性

central.setAttribute(self._QtCore.Qt.WidgetAttribute.WA_Hover)

故障 2聊天输入框无法输入

根因分析

_chat_container(包含输入框的部件)错误地设置了 WA_TransparentForMouseEvents 属性,导致鼠标事件穿透该部件,下层的 live2d_container 接收到事件并触发拖拽流程,输入框无法获得焦点。

修复方案

移除了 _chat_container 上的 WA_TransparentForMouseEvents 属性,让输入框可以正常接收鼠标事件。

# 已移除此错误设置
# self._chat_container.setAttribute(self._QtCore.Qt.WidgetAttribute.WA_TransparentForMouseEvents)

修改的文件

文件 修改内容
main.py 默认平台改为 xcb
ui/pet_window.py 事件过滤器多层安装、修复 super() 调用、启用 WA_Hover

验证方法

/home/e2hang/miniforge3/envs/ezvibe/bin/python3 main.py
  • 鼠标左键按住 Live2D 区域或窗口主体可拖动窗口
  • 聊天输入框可正常输入文字
  • 按钮点击正常
  • ⚠️ Live2D 渲染在 X11 下可能存在 SSL handshake 警告,不影响功能

相关技术点

  • QMainWindow.eventFilter() vs super().eventFilter() 在动态类中的差异
  • WA_TransparentForMouseEvents 与鼠标事件传递
  • Qt 平台插件:xcb vs wayland 的事件分发差异
  • 多层事件过滤器覆盖:容器 → 中央部件 → 子控件