fix(input): handle touch and mouse transitions - #3223
Open
NihilDigit wants to merge 1 commit into
Open
Conversation
NihilDigit
force-pushed
the
fix/gesture-family-by-input-device
branch
4 times, most recently
from
July 30, 2026 04:44
45e1d78 to
792ad32
Compare
Input method is a runtime property, not a platform one: a Windows 2-in-1 with a touchscreen and an Android tablet with a mouse attached both switch back and forth. Track the pointer type actually in use and derive the gesture family from it, falling back to the platform default until the first pointer event arrives. Gate gestures on the down event's pointer type rather than by swapping modifiers at composition time. Committing the family on press would recompose and interrupt the gesture being recognised, so the first interaction after a switch was lost; mounting stays unconditional and the filtering happens per event. Controls that stay on screen — the volume control, the controller auto-hide — key off whether the device has a mouse at all instead, so they don't flicker as the user alternates between finger and mouse. Keep the desktop cursor modifier's chain shape identical across its two branches. It wraps the whole player and reads the detached slider's visibility, so a swipe-to-seek begun while the controller was hidden flipped it, rebuilt the nodes below it and cancelled the very gesture that had requested the slider. GestureFamily is left holding only the click/double-click conventions plus autoHideController; the swipe, long-press and scroll flags no longer gate anything and are removed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
NihilDigit
force-pushed
the
fix/gesture-family-by-input-device
branch
from
July 30, 2026 05:34
326cf80 to
76e4514
Compare
NihilDigit
marked this pull request as ready for review
July 30, 2026 05:37
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GestureFamily此前由平台决定:桌面MOUSE,Android 与 iOSTOUCH。但输入方式是运行时属性,带触屏的 Windows 二合一、外接鼠标的 Android 平板都会在触摸与鼠标之间来回切换,EpisodeVideo.kt里的 TODO 记录了这个限制。本 PR 改为按最近实际使用的指针设备决定手势约定。纯触摸设备只产生触摸事件,纯键鼠设备只产生鼠标事件,两者行为与改动前一致。受影响的只有混合设备。
行为变化
Windows 二合一,用触摸操作:
亮度调节在桌面仍然没有,
brightnessController是NoOpLevelController。Android 平板,接鼠标操作:
组合期门控为什么不可行
让
GestureFamily跟随运行时输入方式,再照旧用它决定挂哪些修饰符,会在两处失败。手势识别期间写快照状态会触发重组,打断正在识别的手势。在按下事件里提交输入源,点击直接丢失。
不在按下时提交,组合期读到的值就滞后一次。切换设备后的第一次手势仍按上一个设备的约定处理,用户要操作两次才生效。
因此输入源状态按用途拆开,手势门控从组合期下移到事件层。
实现
输入源状态
ActiveInputSourceState拆出三个字段:currentlatesthasSeenMousetrackActiveInputSource在根节点观察指针类型,不消费事件。Enter/Exit即使用户正在用手指也会带着PointerType.Mouse到达(鼠标指针仍停在窗口里),因此只采信Press、Move、Release、Scroll。手势按 down 事件过滤
修饰符无条件挂载,是否响应取决于本次手势 down 事件的
PointerType:touchDragOnly()。requiredPointerType = Touch。touchHorizontalScrollOnly()。它只消费 nested scroll 的目标方向,不消费原始指针位移,因此页面内滚动条与 Slider 的鼠标拖动不受影响。touchOnly参数,在嵌套滚动链上拦截非触摸的下拉。是否挂载只取决于能力,即亮度与音量 controller 是否为
NoOpLevelController。切换设备后的第一次滑动不会因为修饰符尚未挂上而丢失。Stylus 与 Eraser 归一为 Touch,笔与手指采用同一套约定。
追番页的分页此前是
if (isMobile())的结构性分支,桌面端不创建HorizontalPager,标签点击里的animateScrollToPage因此一直在空转。现在统一挂载。常驻 UI 按设备有没有鼠标
全屏音量控件与控制器自动隐藏改用
hasPointerDevice,它读hasSeenMouse,观察到一次鼠标事件即为真且不再变回。按当前输入方式判断会让这些控件随用户在手指与鼠标之间切换而反复显隐。键盘音量键的作用目标改按平台判断。桌面没有系统级 AudioManager,音量由 mediamp 提供,这是平台差异而非输入方式差异。
滚轮调节音量取消 family 门控,滚轮只可能来自鼠标。
桌面光标修饰符
cursorVisibility两个分支此前链长不同:visible为真时只有testTag,为假时多一个pointerHoverIcon。它包住整个播放器,输入里又含 detached slider 的可见性,于是控制器隐藏时开始的横滑 seek 会翻转它,重建下游节点,取消掉刚刚请求 slider 的那次手势。现在两个分支保持相同结构,只切换PointerIcon。GestureFamily 的收缩
只保留点击与双击约定和
autoHideController。滑动、长按、滚轮的六个门控字段不再有引用,一并移除。已知限制
Windows 上笔(
PT_PEN)仍由系统合成 AWT 鼠标序列,桌面端因此把笔当鼠标处理。WindowsPointerInput只桥接PT_TOUCH,代码中留有 TODO。Android 上笔走 Touch 约定。验证
新增
PointerTypeDragFilterTest、PullToRefreshInputTest,扩充EpisodeVideoControllerTest。手动验证:Windows 二合一设备,触摸与鼠标交替操作播放器。