Skip to content

feat(input): extend game vibration strength#44

Merged
qiin2333 merged 8 commits into
masterfrom
codex/gamepad-vibration-gain
Jun 18, 2026
Merged

feat(input): extend game vibration strength#44
qiin2333 merged 8 commits into
masterfrom
codex/gamepad-vibration-gain

Conversation

@qiin2333

@qiin2333 qiin2333 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

改了啥呀

  • 不再新增单独的“手柄震动增益”设置,改为扩展原有“震动强度”滑块到 0%-200%。
  • 100% 表示串流游戏原始震动强度;超过 100% 时 UI 明示这是 app 增益,仍受硬件/协议上限限制。
  • 外接手柄按该百分比缩放 rumble / trigger rumble,并 clamp 到 Moonlight rumble 上限 65535。
  • 设备马达回退仍按 100% 封顶,不假装系统马达能突破上限,杂鱼幻觉退退退。
  • 音频振动仍走自己的开关和强度,不吃这个游戏震动增益。
  • 修正 NativeHidController 里把 0..65535 rumble 值再次乘 RUMBLE_MAX 的旧问题。

为啥要改

  • 用户只需要理解一个“震动强度”:100% 是原始强度,100% 以上是 app 侧补偿。
  • HarmonyOS 没有外接手柄统一系统增益 API,所以这里保持诚实,不宣称系统级放大。

验证

  • git diff --check
  • GitHub Actions Build (debug) passed on earlier PR revisions; latest push will rerun.
  • 本机 NODE_PATH=/Users/mac/Program/moonlight-harmony/hvigor/node_modules node hvigorw.js tasks --no-daemon 仍受 DEVECO_SDK_HOME 无效影响未完成。

Summary by CodeRabbit

发布说明

  • 改进
    • 优化游戏手柄振动强度设置体验,将振动反馈强度范围调整为 0-200(100% 为原始强度)
    • 改进设置界面中的振动强度滑块配置,提供更精确的振动反馈控制
    • 增强了振动强度数值的规范化处理,确保设置的一致性和稳定性

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@qiin2333, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 6 minutes and 22 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6787ed02-2151-4605-b399-e7094238eeca

📥 Commits

Reviewing files that changed from the base of the PR and between 48c849c and 43e3bb3.

📒 Files selected for processing (5)
  • entry/src/main/ets/pages/SettingsPageV2.ets
  • entry/src/main/ets/service/SettingsService.ets
  • entry/src/main/ets/service/input/GamepadManager.ets
  • entry/src/main/ets/service/input/GamepadVibrationService.ets
  • entry/src/main/ets/viewmodel/StreamViewModel.ets
📝 Walkthrough

Walkthrough

PR 将手柄震动配置从设备级 vibrateFallbackStrength 迁移至游戏串流级 gameVibrationStrength,新增规范化与增益换算逻辑。涵盖 StreamConfig 常量与接口定义、SettingsService 读写、SettingsPageV2 UI 滑块、GamepadVibrationService 增益换算、以及 NativeHidController 缩放修复。

Changes

游戏串流震动强度功能

Layer / File(s) Summary
游戏震动强度常量、接口与规范化函数
entry/src/main/ets/model/StreamConfig.ets
新增 GAME_VIBRATION_STRENGTH_MIN/MAX/ORIGINAL/DEFAULT/STEP 常量和 normalizeGameVibrationStrength() 函数;StreamConfig 接口字段从 vibrateFallbackStrength 改为 gameVibrationStrength;默认配置使用新常量。
SettingsService 字段与读写迁移
entry/src/main/ets/service/SettingsService.ets
导入游戏震动强度常量和规范化函数;getStreamConfig()getInputSettings() 中字段从 vibrateFallbackStrength 改为 gameVibrationStrength,并对读取值进行规范化;InputSettings 接口字段同步更新;存储键注释调整。
SettingsPageV2 状态与 UI 滑块迁移
entry/src/main/ets/pages/SettingsPageV2.ets
导入游戏震动强度常量和规范化函数;新增 gameVibrationStrength 状态;loadSettings 中读取并规范化持久化值;滑块范围改为 GAME_VIBRATION_STRENGTH_MIN/MAX/STEP,拖动时规范化后持久化;UI 文案从"手柄振动反馈"改为"串流游戏震动反馈"。
GamepadVibrationService 震动强度应用与增益换算
entry/src/main/ets/service/input/GamepadVibrationService.ets
私有字段从 deviceVibrateEnabled/deviceVibrateStrength 改为 vibrationFeedbackEnabled/gameVibrationStrengthsetSettings 规范化输入并在禁用时停止;新增 applyGameVibrationStrength/clampRumbleValue 私有方法;USB 普通震动、扳机震动、设备震动回退均应用增益换算与钳制。
GamepadManager/NativeHidController/StreamViewModel 驱动层与调用链更新
entry/src/main/ets/service/input/GamepadManager.ets, entry/src/main/ets/service/usbdriver/NativeHidController.ets, entry/src/main/ets/viewmodel/StreamViewModel.ets
GamepadManager 导入增益常量,文档改为游戏震动描述;NativeHidController 移除 RUMBLE_MAX 导入,rumble 方法改为通过 clampRumbleValue 钳制而非乘以 RUMBLE_MAX 缩放;StreamViewModel 直接使用 streamConfig.enableVibrationgameVibrationStrength 调用 setDeviceVibrate

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了主要变更:扩展游戏震动强度到0-200%范围,覆盖了StreamConfig常量、接口字段调整、规范化逻辑及多个服务层的震动强度处理更新。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/gamepad-vibration-gain

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
entry/src/main/ets/service/usbdriver/NativeHidController.ets (1)

667-673: ⚡ Quick win

在驱动边界补充 rumble 范围钳制,降低上游异常值外溢风险

这里已修复二次缩放,建议再加一层 0..65535 钳制,保证 Native 命令入口自身满足协议范围,不依赖上游永远正确。

🔧 建议修改
-    // Native parser expects Moonlight rumble values in the same 0..65535 range as AbstractController.
+    // Native parser expects Moonlight rumble values in the same 0..65535 range as AbstractController.
+    const clampRumble = (v: number) => Math.max(0, Math.min(65535, Math.round(v)));
     const cmd = this.nativeParser.createRumbleCommand(
       this.vendorId,
       this.productId,
-      Math.round(lowFreqMotor),
-      Math.round(highFreqMotor)
+      clampRumble(lowFreqMotor),
+      clampRumble(highFreqMotor)
     );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@entry/src/main/ets/service/usbdriver/NativeHidController.ets` around lines
667 - 673, The createRumbleCommand call in NativeHidController needs additional
defensive clamping for the rumble motor values. Add a clamping layer to ensure
both lowFreqMotor and highFreqMotor are bounded to the valid 0..65535 range
before being rounded and passed to the createRumbleCommand method. This should
be done by applying Math.max and Math.min constraints to each value so that even
if upstream provides out-of-range values, the native command entry receives
values that comply with the protocol specification.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@entry/src/main/ets/pages/SettingsPageV2.ets`:
- Around line 529-530: The gamepadVibrationGain property is being assigned
directly from the preferences without validating that it falls within the
acceptable MIN/MAX bounds. When loading the vibration gain value using
PreferencesUtil.get with SettingsKeys.GAMEPAD_VIBRATION_GAIN, immediately clamp
the retrieved value to the valid range (between the minimum and maximum allowed
values for gamepad vibration gain). If the clamping operation modifies the
value, write the corrected value back to the preferences to ensure consistency
between the UI state and stored configuration.

In `@entry/src/main/ets/service/input/GamepadVibrationService.ets`:
- Line 75: The gamepadGain value at line 75 may be NaN, and using
Math.max/Math.min with NaN will propagate the NaN value through to lines 238/243
where it's used in the controller?.rumble() call, resulting in invalid
rumble(NaN, NaN) calls. Add Number.isFinite protection for the gamepadGain
parameter before the clamping operation on line 75 to validate it is a finite
number, and if not finite, use a default valid value instead of allowing NaN to
propagate. Additionally, add similar Number.isFinite checks at the rumble
invocation points (around lines 238/243) to ensure only valid finite values are
passed to the rumble method.

In `@entry/src/main/ets/service/SettingsService.ets`:
- Line 605: The gamepadVibrationGain value read from persistent storage at line
605 (and similarly at line 750) needs to be validated and clamped to the valid
range of 50-200 to ensure consistency with the configuration contract. After
retrieving the persisted value using getNumber with the
GAMEPAD_VIBRATION_GAIN_DEFAULT constant, add boundary validation logic to clamp
the value between 50 and 200 (inclusive) before returning or using it, ensuring
that any out-of-range persisted values do not propagate to downstream components
like StreamConfig and InputSettings. Apply the same normalization logic at both
locations where gamepadVibrationGain values are retrieved.

---

Nitpick comments:
In `@entry/src/main/ets/service/usbdriver/NativeHidController.ets`:
- Around line 667-673: The createRumbleCommand call in NativeHidController needs
additional defensive clamping for the rumble motor values. Add a clamping layer
to ensure both lowFreqMotor and highFreqMotor are bounded to the valid 0..65535
range before being rounded and passed to the createRumbleCommand method. This
should be done by applying Math.max and Math.min constraints to each value so
that even if upstream provides out-of-range values, the native command entry
receives values that comply with the protocol specification.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d57b6a38-cc93-4caf-a104-cdacccda846d

📥 Commits

Reviewing files that changed from the base of the PR and between 970d8fd and 54c963e.

📒 Files selected for processing (7)
  • entry/src/main/ets/model/StreamConfig.ets
  • entry/src/main/ets/pages/SettingsPageV2.ets
  • entry/src/main/ets/service/SettingsService.ets
  • entry/src/main/ets/service/input/GamepadManager.ets
  • entry/src/main/ets/service/input/GamepadVibrationService.ets
  • entry/src/main/ets/service/usbdriver/NativeHidController.ets
  • entry/src/main/ets/viewmodel/StreamViewModel.ets

Comment thread entry/src/main/ets/pages/SettingsPageV2.ets Outdated
Comment thread entry/src/main/ets/service/input/GamepadVibrationService.ets Outdated
Comment thread entry/src/main/ets/service/SettingsService.ets Outdated
@qiin2333 qiin2333 changed the title feat(input): add gamepad vibration gain feat(input): extend game vibration strength Jun 18, 2026
@qiin2333

Copy link
Copy Markdown
Contributor Author

实现已按最新方向收敛:不再新增单独的手柄震动增益设置,而是复用原有 震动强度 滑杆并扩展到 0-200%。\n\n- 100% = 串流原始震动强度\n- >100% = app 侧放大,会在协议上限内钳制,不突破系统/硬件上限\n- 设备马达回退仍按 100% 封顶,音频振动不吃这层游戏震动放大\n- 早前 CodeRabbit walkthrough 里提到的 gamepadVibrationGain 是旧实现描述,当前代码已移除该字段/设置键

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@entry/src/main/ets/service/input/GamepadVibrationService.ets`:
- Around line 66-77: The setSettings method in GamepadVibrationService only
calls stopAll() when vibration is disabled (wasEnabled && !enabled), but it
should also stop vibration when the strength is set to 0 even if enabled remains
true. After normalizing the game vibration strength with
normalizeGameVibrationStrength(strength), add an additional check: if the
resulting strength value is 0, immediately call stopAll() to prevent residual
vibration from continuing when strength is adjusted to zero while the vibration
feature remains enabled.

In `@entry/src/main/ets/service/SettingsService.ets`:
- Around line 603-605: The getNumber() function uses parseInt(value) ||
defaultValue which incorrectly treats the string "0" as a falsy value, causing
it to fall back to the default value instead of returning 0. This breaks
legitimate 0% configuration values. Fix this by modifying the getNumber()
function to explicitly check if the parsed value is null or undefined rather
than relying on falsy evaluation, ensuring that valid 0 values are preserved and
only missing/invalid values trigger the fallback to defaultValue. This fix
applies to both the VIBRATE_FALLBACK_STRENGTH call at line 603 and the similar
pattern at line 748.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 01cd8552-2ea7-4302-b7e3-37aa27bf5740

📥 Commits

Reviewing files that changed from the base of the PR and between 54c963e and 48c849c.

📒 Files selected for processing (7)
  • entry/src/main/ets/model/StreamConfig.ets
  • entry/src/main/ets/pages/SettingsPageV2.ets
  • entry/src/main/ets/service/SettingsService.ets
  • entry/src/main/ets/service/input/GamepadManager.ets
  • entry/src/main/ets/service/input/GamepadVibrationService.ets
  • entry/src/main/ets/service/usbdriver/NativeHidController.ets
  • entry/src/main/ets/viewmodel/StreamViewModel.ets
✅ Files skipped from review due to trivial changes (1)
  • entry/src/main/ets/service/input/GamepadManager.ets
🚧 Files skipped from review as they are similar to previous changes (2)
  • entry/src/main/ets/service/usbdriver/NativeHidController.ets
  • entry/src/main/ets/model/StreamConfig.ets

Comment thread entry/src/main/ets/service/input/GamepadVibrationService.ets
Comment thread entry/src/main/ets/service/SettingsService.ets
@qiin2333 qiin2333 merged commit 68195ab into master Jun 18, 2026
2 checks passed
@qiin2333 qiin2333 deleted the codex/gamepad-vibration-gain branch June 18, 2026 05:43
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.

1 participant