ElyShow:左侧缩略图条不能滚动(同窗口右侧属性栏滚轮正常) #1

Closed
opened 2026-10-13 11:26:19 +00:00 by Cecil · 2 comments

环境

  • ElyShow 0.1.3 AppImage(本地验证版本)。
  • 同一问题的代码在 v0.1.4 未变:
  • 系统:EndeavourOS(Arch 系),内核 7.2.9。
  • 会话:原生 Wayland(sway 1.12 + wlroots 0.19.3 + libinput 1.32),窗口 shell: xdg_shell,wm具体为sway
  • 渲染:GPUI(gpui-pre-linux 0.3.8、gpui-pre-wgpu 0.3.8)+ Vulkan/wgpu。

复现步骤

  1. 打开一个页数超过窗口高度的演示文稿(本例 75 页)。
  2. 把指针放到左侧缩略图条上。
  3. 滚动鼠标滚轮。

实际结果

  • 缩略图条完全不动,也没有滚动条图样。
  • 缩略图列表在第 7 页处被窗口底边截断,看不到第 8 页及以后。
  • 同一时刻、同一窗口,把指针移到右侧属性栏滚动:正常滚动。

期望结果

指针在左侧缩略图条上时,滚轮滚动缩略图列表,能滚到最后一页。

证据

注入方式:uinput 合成 REL_WHEEL(与真实鼠标滚轮同一条 libinput → sway → 客户端路径),不涉及点击。

测试 位置 注入 5 格滚轮后的像素差异
对照 foot 终端 整窗约 53,000 像素变化,内容滚动 ✅
同一窗口 ElyShow 右侧属性栏 整窗约 35,000 像素变化,面板内容整体上移一行 ✅
同一窗口 ElyShow 左侧缩略图条 整窗仅约 39 像素(光标抖动),侧栏区域 0 像素变化 ❌

三项在同一分钟内、同一窗口、同一注入设备上依次完成。右栏能滚说明滚轮事件已到达该窗口,因此与系统输入栈、合成设备无关。

已经排除的原因

  • 不是合成设备的问题:同一个合成设备在 foot 终端与 ElyShow 右栏都能滚动。
  • 不是 wlroots/GPUI 的滚轮解析问题:wlroots 0.19.3 每格发 axis_source=wheel + axis_value120=±120;gpui-pre-linux-0.3.8 的 wayland/client.rs 对 axis_source == Wheel 的连续 axis 事件主动
    return,改用 AxisValue120/AxisDiscrete 累积成 ScrollDelta::Lines。右栏正常消费同一事件。
  • 不是「窗口太小」:窗口 1520×881 逻辑像素,缩略图内容约 75 × 98 px ≈ 7958 px。

源码线索

左侧栏(apps/ely-show/src/slides.rs,impl Render for Strip):

let list = div()
    .id("show-strip")
    ...
    .size_full()
    .overflow_y_scroll()      // 没有 track_scroll,也没有用 ScrollArea
    .flex().flex_col().gap_2().p_2()
    .children(slides);
div()
    .size_full()
    .child(ContextMenu::new("show-strip-menu", popup(cx)).child(list))

ContextMenu 的宿主 div 是 div().id(..).relative()(src/menus/hosts.rs),高度 auto;list 的 size_full() 落在它下面。

右侧栏(apps/ely-show/src/design.rs:159,能滚动):

  ScrollArea::new("show-panel-scroll").vertical().size_full().child( ... )

ScrollArea 自己的根 div 带 size_full(),内部 scroll-body 还 track_scroll(&handle)(src/layout/scroll.rs)。

建议排查两点:

  1. list 的滚动范围(content_size - bounds)是否为 0。按 taffy 0.13 单独建模(outer(size_full) → wrapper(auto) → list(size_full, overflow_y_scroll),75 行 × 98 px)算出的范围 > 0,所以布
    局这一路不能单独解释,需要真窗口确认。
  2. GPUI 是否给该 div 注册了滚轮监听:gpui-pre 的 Div::paint_scroll_listener 只在 self.scroll_offset 为 Some 时注册,而 scroll_offset 来自元素状态(需要元素有 global id);命中判断是
    hitbox.should_handle_scroll(window),即 hitbox 是否在 window.mouse_hit_test.ids 里。

可能的修法(任选其一):

  • 把 strip 换成组件:ScrollArea::new("show-strip-scroll").vertical().size_full().track_scroll(&handle),与右栏一致;
  • 或者给包装 div(ContextMenu 宿主或 strip 根)补上 h_full(),让 size_full() 落在一个高度已确定的父盒上。

回归建议:真窗口测试里把指针放在缩略图条上滚一格,断言列表偏移变化(组件库 src/lists/tests/mod.rs 已有 simulate_event(ScrollWheelEvent{..}) 的写法可参考)。


以上 issue 为 LLM 生成,如有影响敬请见谅。

# 环境 - ElyShow 0.1.3 AppImage(本地验证版本)。 - 同一问题的代码在 v0.1.4 未变: - 系统:EndeavourOS(Arch 系),内核 7.2.9。 - 会话:原生 Wayland(sway 1.12 + wlroots 0.19.3 + libinput 1.32),窗口 shell: xdg_shell,wm具体为sway - 渲染:GPUI(gpui-pre-linux 0.3.8、gpui-pre-wgpu 0.3.8)+ Vulkan/wgpu。 # 复现步骤 1. 打开一个页数超过窗口高度的演示文稿(本例 75 页)。 2. 把指针放到左侧缩略图条上。 3. 滚动鼠标滚轮。 # 实际结果 - 缩略图条完全不动,也没有滚动条图样。 - 缩略图列表在第 7 页处被窗口底边截断,看不到第 8 页及以后。 - 同一时刻、同一窗口,把指针移到右侧属性栏滚动:正常滚动。 # 期望结果 指针在左侧缩略图条上时,滚轮滚动缩略图列表,能滚到最后一页。 # 证据 注入方式:uinput 合成 REL_WHEEL(与真实鼠标滚轮同一条 libinput → sway → 客户端路径),不涉及点击。 | 测试 | 位置 | 注入 5 格滚轮后的像素差异 | |---|---|---| | 对照 | foot 终端 | 整窗约 53,000 像素变化,内容滚动 ✅ | | 同一窗口 | ElyShow 右侧属性栏 | 整窗约 35,000 像素变化,面板内容整体上移一行 ✅ | | 同一窗口 | ElyShow 左侧缩略图条 | 整窗仅约 39 像素(光标抖动),侧栏区域 0 像素变化 ❌ | 三项在同一分钟内、同一窗口、同一注入设备上依次完成。右栏能滚说明滚轮事件已到达该窗口,因此与系统输入栈、合成设备无关。 # 已经排除的原因 - 不是合成设备的问题:同一个合成设备在 foot 终端与 ElyShow 右栏都能滚动。 - 不是 wlroots/GPUI 的滚轮解析问题:wlroots 0.19.3 每格发 axis_source=wheel + axis_value120=±120;gpui-pre-linux-0.3.8 的 wayland/client.rs 对 axis_source == Wheel 的连续 axis 事件主动 return,改用 AxisValue120/AxisDiscrete 累积成 ScrollDelta::Lines。右栏正常消费同一事件。 - 不是「窗口太小」:窗口 1520×881 逻辑像素,缩略图内容约 75 × 98 px ≈ 7958 px。 # 源码线索 左侧栏(apps/ely-show/src/slides.rs,impl Render for Strip): ```rust let list = div() .id("show-strip") ... .size_full() .overflow_y_scroll() // 没有 track_scroll,也没有用 ScrollArea .flex().flex_col().gap_2().p_2() .children(slides); div() .size_full() .child(ContextMenu::new("show-strip-menu", popup(cx)).child(list)) ``` ContextMenu 的宿主 div 是 div().id(..).relative()(src/menus/hosts.rs),高度 auto;list 的 size_full() 落在它下面。 右侧栏(apps/ely-show/src/design.rs:159,能滚动): ```rust ScrollArea::new("show-panel-scroll").vertical().size_full().child( ... ) ``` ScrollArea 自己的根 div 带 size_full(),内部 scroll-body 还 track_scroll(&handle)(src/layout/scroll.rs)。 建议排查两点: 1. list 的滚动范围(content_size - bounds)是否为 0。按 taffy 0.13 单独建模(outer(size_full) → wrapper(auto) → list(size_full, overflow_y_scroll),75 行 × 98 px)算出的范围 > 0,所以布 局这一路不能单独解释,需要真窗口确认。 2. GPUI 是否给该 div 注册了滚轮监听:gpui-pre 的 Div::paint_scroll_listener 只在 self.scroll_offset 为 Some 时注册,而 scroll_offset 来自元素状态(需要元素有 global id);命中判断是 hitbox.should_handle_scroll(window),即 hitbox 是否在 window.mouse_hit_test.ids 里。 可能的修法(任选其一): - 把 strip 换成组件:ScrollArea::new("show-strip-scroll").vertical().size_full().track_scroll(&handle),与右栏一致; - 或者给包装 div(ContextMenu 宿主或 strip 根)补上 h_full(),让 size_full() 落在一个高度已确定的父盒上。 回归建议:真窗口测试里把指针放在缩略图条上滚一格,断言列表偏移变化(组件库 src/lists/tests/mod.rs 已有 simulate_event(ScrollWheelEvent{..}) 的写法可参考)。 --- 以上 issue 为 LLM 生成,如有影响敬请见谅。
Owner

感谢,我欢迎LLM生成issue。

感谢,我欢迎LLM生成issue。
Owner

fixed

fixed
Sign in to join this conversation.
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ZacharyZhang-NY/ElyOffice#1