Conversation
WalkthroughAdds an RTS touch-controls feature: sidebar toggle + gear, persistent MMKV-backed gesture settings and picker dialog, X11/WinUIBridge trackpad API, a new RtsTouchOverlayView handling multi-touch→mouse/keyboard mapping, and many supporting smali listeners, dialogs, layouts, drawables, and id resources. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Sidebar as SidebarControlsFragment
participant Manager as InputControlsManager
participant Overlay as RtsTouchOverlayView
participant Dialog as RtsGestureConfigDialog
participant Bridge as WinUIBridge
User->>Sidebar: tap RTS switch
Sidebar->>Manager: setRtsTouchControlsEnabled(value)
Manager-->>Sidebar: persisted
Sidebar->>Overlay: enable/disable overlay
User->>Sidebar: tap gear
Sidebar->>Dialog: instantiate & show
Dialog->>Manager: getRtsTouchControlsEnabled(), getRtsGestureEnabled(), getRtsGestureAction()
Manager-->>Dialog: state & actions
User->>Dialog: change gesture/action
Dialog->>Manager: setRtsGestureAction/Enabled(...)
Manager-->>Dialog: persisted
Dialog->>Dialog: updateActionLabelForKey()
User->>Overlay: perform multi-touch gesture
Overlay->>Bridge: warp/touch -> game coords / send input events
Bridge-->>Overlay: (controller interactions / callbacks)
Estimated Code Review Effort🎯 5 (Critical) | ⏱️ ~120 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
patches/diffs/res/values/strings.xml.patch (2)
51-62: Confirm the blank labels are intentional.
Self-closing strings will render empty UI labels; if unintended, restore text.
66-73: Confirm these settings are meant to be blank.
Empty strings will hide labels for item 61 and its description.
🤖 Fix all issues with AI agents
In `@patches/diffs/res/values/strings.xml.patch`:
- Around line 124-151: The pull contains a duplicated block of RTS string
resources (e.g., rts_gesture_settings, rts_gesture_settings_title,
rts_gesture_tap, rts_gesture_long_press, rts_gesture_double_tap,
rts_gesture_drag, rts_gesture_pinch, rts_gesture_two_finger_drag,
rts_action_left_click, rts_action_right_click, rts_action_double_left_click,
rts_action_drag_left_click, rts_action_scroll_wheel, rts_action_plus_minus,
rts_action_page_up_down, rts_action_middle_mouse, rts_action_wasd_keys,
rts_action_arrow_keys, winemu_sidebar_rts_touch_controls) which will cause
resource merge/build failures; remove this duplicated block from the patch so
only the original definitions remain (delete the added <string name="...">
entries listed above and keep the singular definitions already present).
In `@patches/diffs/res/values/styles.xml.patch`:
- Around line 17-22: The patch contains a duplicated hunk adding the same style
RtsGestureConfigDialogTheme twice; remove the second duplicate hunk so the style
definition appears only once in the patch, leaving a single <style
name="RtsGestureConfigDialogTheme" ...> block (keep the existing attributes
android:windowBackground, android:windowFrame, android:windowIsFloating,
android:windowNoTitle) and delete the repeated addition to avoid duplicate
resource errors when applying the patch.
In
`@patches/diffs/smali_classes5/com/xj/pcvirtualbtn/inputcontrols/InputControlsManager.smali.patch`:
- Around line 9-39: The new getRtsTouchControlsEnabled and
setRtsTouchControlsEnabled methods call z() without checking for null, risking
an NPE; update both to mirror the null-guard pattern used in
getRtsGestureEnabled/setRtsGestureEnabled: call z(), check if the returned MMKV
object is null, return a safe default (false) from getRtsTouchControlsEnabled if
null, and in setRtsTouchControlsEnabled simply skip the invoke-virtual v(...) if
z() returns null so you only call MMKV.v(...) when z() != null.
In `@patches/files_to_add.txt`:
- Line 1: The listed path string "original/META-INF/MANIFEST.MF" contains a
hidden BOM/zero‑width character at the start; open the file that defines the
paths (patches/files_to_add.txt) and remove the invisible character so the entry
becomes "original/META-INF/MANIFEST.MF" exactly, then save with UTF‑8 without
BOM to ensure tooling recognizes the exact path.
- Around line 2860-2907: The files_to_add list contains a duplicated RTS block
(entries like res/color/rts_checkbox_tint.xml,
res/drawable/rts_checkbox_button.xml, res/layout/rts_gesture_config_dialog.xml
and the smali entries under smali_classes4/com/xj/winemu/sidebar/* and
smali_classes5/com/xj/pcvirtualbtn/inputcontrols/RangeScrollerRtsTask.smali
appear twice); remove the second repeated block so each RTS resource and smali
path appears only once in patches/files_to_add.txt, ensuring the unique entries
(e.g., rts_checkbox_tint.xml, RtsGestureConfigDialog.smali,
RangeScrollerRtsTask.smali) remain exactly one time.
In `@patches/new_files/res/layout/rts_action_picker_item.xml`:
- Around line 21-28: The ImageView with id "checkbox" in
rts_action_picker_item.xml is missing a contentDescription so screen readers
won't announce selection; add a localized string resource named rts_selected (or
reuse an existing "Selected" string) and set
android:contentDescription="@string/rts_selected" on the ImageView with id
"checkbox" (and optionally ensure accessibility visibility with
android:importantForAccessibility if needed).
In
`@patches/new_files/smali_classes4/com/xj/winemu/sidebar/RtsGestureConfigDialog.smali`:
- Around line 145-262: The code uses hard-coded label literals in TextView
setText and const-string usages (e.g., the "PINCH"/"TWO_FINGER_DRAG"
const-strings, and setText calls that build "Scroll Wheel", "+/- Keys", "Page
Up/Down", "Middle Mouse Pan", "WASD Keys", "Arrow Keys") which prevents
localization; replace each literal with resource lookups
(context.getString(R.string.<name>)) and use those string resources in the
setText calls (and where appropriate for displayed tags), keeping the existing
logic around InputControlsManager.getRtsGestureAction and the
setOnClickListener/setTag calls intact; apply the same replacement pattern to
the other analogous blocks noted in the review.
- Around line 453-457: RtsGestureConfigDialog.smali is calling the wrong
InputControlsManager variant and method signature; replace the invocations that
reference com/xj/winemu/mapping/InputControlsManager (the two-parameter call)
with calls to com/xj/pcvirtualbtn/inputcontrols/InputControlsManager and use the
single-argument getRtsGestureAction(Ljava/lang/String;)I method so the dialog
consistently uses the same manager and signature as the other calls (e.g., the
existing correct usages elsewhere in the file).
In
`@patches/new_files/smali_classes4/com/xj/winemu/sidebar/RtsGestureConfigDialog`$CloseClickListener.smali:
- Around line 19-25: The constructor for
RtsGestureConfigDialog$CloseClickListener assigns the instance field this$0
before calling the superclass constructor; move the iput-object p1, p0,
Lcom/xj/winemu/sidebar/RtsGestureConfigDialog$CloseClickListener;->this$0:Lcom/xj/winemu/sidebar/RtsGestureConfigDialog;
so that it occurs after invoke-direct {p0}, Ljava/lang/Object;-><init>()V (i.e.,
call Object.<init>() first, then store p1 into this$0) to comply with JVM
verification rules.
In
`@patches/new_files/smali_classes4/com/xj/winemu/view/RtsTouchOverlayView.smali`:
- Around line 842-858: The double-tap detection currently uses hardcoded
constants (250ms via the const-wide/16 v8, 0xfa instruction and 50.0f via
const/high16 v8, 0x42480000) in RtsTouchOverlayView.smali when comparing
timestamps and distances against lastTapX/lastTapY; update these to the
PR-specified 300ms and 30px (or refactor to read configurable values from a
class constant/field or settings API) so the cmp-long and cmpg-float checks use
300ms and 30.0f respectively; locate the tap-handling block around comparisons
to lastTapX/lastTapY and replace the literal constants or wire them to a
configurable field (e.g., DOUBLE_TAP_TIMEOUT_MS / DOUBLE_TAP_SLOP_PX) used in
the cmp-long/cmpg-float logic.
- Around line 249-256: The code presses the middle mouse whenever
getRtsGestureAction("TWO_FINGER_DRAG") returns 0, even when the TWO_FINGER_DRAG
feature is disabled; update the condition so that before calling
RtsTouchOverlayView.pressMiddleButton() you first check the TWO_FINGER_DRAG
enabled flag via InputControlsManager.getRtsGestureAction("TWO_FINGER_DRAG") and
only call pressMiddleButton() when that call indicates the gesture is enabled
and the action equals the expected value (i.e., gate the middle-button press
behind the feature-enabled check rather than solely the action==0 check).
- Around line 1602-1635: The sendPlusMinusKey method currently invokes
X11Controller->p with modifiers hardcoded to 0, so using KEYCODE_EQUALS (70)
emits "=" instead of "+"; update sendPlusMinusKey to set the appropriate shift
modifier when p is called for the plus branch (e.g., set modifiers to the shift
bit value used by X11Controller, or alternatively use KEYCODE_NUMPAD_ADD (0x51)
for plus) and ensure the invoke-virtual calls pass that modifiers variable (not
0) for both press and release; locate sendPlusMinusKey and X11Controller->p
invocations to change the const/4 v3 (modifiers) and/or replace the plus keycode
constant accordingly.
In
`@patches/new_files/smali_classes5/com/xj/pcvirtualbtn/inputcontrols/RangeScrollerRtsTask.smali`:
- Line 26: Update the inaccurate inline comment in RangeScrollerRtsTask.smali
that reads "Set rtslongPress flag to true (held for 1 second)" to reflect the
PR-specified 300 ms trigger time; locate the comment near the rtslongPress flag
handling in the RangeScrollerRtsTask class and change the duration text to "300
ms" so the comment matches the implemented behavior.
🧹 Nitpick comments (14)
patches/diffs/smali_classes4/com/winemu/openapi/WinUIBridge.smali.patch (1)
9-15: Behavioral change: exception to silent return on null X11Controller.The original code threw a
NullPointerExceptionviaIntrinsics.y()whenX11Controllerwas null. Now it returns silently. While this prevents crashes, it also silently ignores cases where the controller should have been initialized.Consider whether this silent failure is appropriate for all callers of this code path, or if logging a warning would help diagnose unexpected null states during development.
patches/new_files/smali_classes4/com/xj/winemu/view/RtsTouchOverlayView.smali (1)
826-941: Prefer event time + scaled touch slop instead of System.currentTimeMillis and raw px thresholds.Using
MotionEvent.getDownTime()/getEventTime()andViewConfiguration‑based thresholds makes gestures resilient to clock changes and DPI differences.patches/new_files/res/drawable/rts_checkbox_unchecked.xml (1)
1-7: Consider using a color resource for theming.Hardcoded stroke colors make dark/light theme tuning harder. Moving this to a
@colorresource keeps the checkbox consistent with future theme updates.♻️ Suggested change
- <stroke android:width="@dimen/mw_2dp" android:color="#ff888e99" /> + <stroke android:width="@dimen/mw_2dp" android:color="@color/rts_checkbox_border" />Add
@color/rts_checkbox_borderto an appropriate colors file (or reuse an existing neutral border color).patches/new_files/smali_classes4/com/xj/winemu/sidebar/RtsGestureConfigDialog$DismissListener.smali (1)
19-28: Silent exception swallowing hides potential bugs.The catch block silently discards all
Throwables, including programming errors (Error,RuntimeException). This makes debugging difficult ifapplyPendingSelectionIfAny()fails unexpectedly. Additionally, Line 27 (const/4 v1, 0x0) is dead code—the value is never used.Consider at minimum logging the exception, or narrowing the catch to specific expected exceptions:
♻️ Suggested improvement
:catch_err - const/4 v1, 0x0 + # At minimum, log the error for debugging + # invoke-static {v0}, Lcom/xj/winemu/util/Logger;->logError(Ljava/lang/Throwable;)V return-voidpatches/new_files/res/layout/rts_action_picker_dialog.xml (2)
35-42: AddcontentDescriptionto check icons for accessibility.The check mark ImageViews lack
contentDescription, which screen readers need to convey the selected state to users. Consider adding a description or usingandroid:importantForAccessibility="no"if the parent conveys selection state.♻️ Suggested fix for one instance (apply to all three)
<ImageView android:id="@id/rts_action_option_0_check" android:layout_width="@dimen/mw_24dp" android:layout_height="@dimen/mw_24dp" android:layout_gravity="end|center_vertical" android:layout_marginEnd="@dimen/mw_16dp" android:src="@drawable/ic_checked_checkbox" - android:visibility="gone" /> + android:visibility="gone" + android:importantForAccessibility="no" />Also applies to: 63-70, 91-98
18-99: Consider extracting repeated option layout to reduce duplication.The three option blocks are nearly identical. While acceptable for a fixed small dialog, extracting the common structure to an
<include>or inflating dynamically would improve maintainability if more options are added later.patches/new_files/res/layout/rts_gesture_config_dialog.xml (2)
61-66: Extract hardcoded colors tocolors.xmlfor maintainability.Multiple hardcoded color values (
#ff888e99,#0affffff,#ff3b82f6) are repeated throughout the layout. Extracting these tocolors.xmlimproves maintainability and enables theming.Also applies to: 89-94, 117-122, 145-150, 181-181, 215-215
42-219: High duplication across gesture rows.The six gesture configuration rows share a common structure. Consider creating a reusable compound view or using
<include>with different attributes to reduce duplication and ease future modifications.patches/new_files/smali_classes4/com/xj/winemu/sidebar/RtsGestureConfigDialog$CloseClickListener.smali (1)
31-44: Silent exception swallowing in onClick.Similar to
DismissListener, the catch block silently discards allThrowables. While the null checks are good defensive coding, consider at least logging unexpected errors for debugging purposes.patches/new_files/smali_classes4/com/xj/winemu/sidebar/RtsGestureConfigDialog$AppPopupDismissListener.smali (1)
17-21: Inconsistent error handling compared to sibling listeners.Unlike
DismissListenerandCloseClickListener, this listener lacks a try-catch around theapplyPendingSelectionIfAny()call. If an exception occurs, it will propagate and potentially crash the app. Consider adding consistent error handling across all listener implementations.♻️ Suggested fix for consistency
.method public onDismiss(Landroidx/appcompat/widget/PopupMenu;)V - .locals 1 + .locals 2 + :try_start iget-object v0, p0, Lcom/xj/winemu/sidebar/RtsGestureConfigDialog$AppPopupDismissListener;->owner:Lcom/xj/winemu/sidebar/RtsGestureConfigDialog; + if-eqz v0, :cond_end invoke-virtual {v0}, Lcom/xj/winemu/sidebar/RtsGestureConfigDialog;->applyPendingSelectionIfAny()V + :try_end + .catch Ljava/lang/Throwable; {:try_start .. :try_end} :catch_err + :catch_err + :cond_end return-void .end methodpatches/new_files/smali_classes4/com/xj/winemu/sidebar/RtsGestureConfigDialog$WidgetPopupDismissListener.smali (1)
17-28: Avoid swallowing allThrowableinonDismiss.Catching
Throwableand ignoring it hides real failures (includingErrors). Prefer catchingExceptionand logging/reporting, or at least logging before returning.patches/new_files/smali_classes4/com/xj/winemu/sidebar/RtsGestureConfigDialog$ResetClickListener.smali (1)
33-46: Guard against re‑showing the dialog while it’s already visible.
show()is called unconditionally afterrefreshUI(). If the dialog is still showing or the host activity is finishing, this can cause window leaks or flicker. Consider checkingisShowing()/ lifecycle state before callingshow().patches/new_files/smali_classes4/com/xj/winemu/sidebar/RtsGestureConfigDialog$PickerOptionClickListener.smali (1)
23-57: Don’t swallow failures silently; keep the click UX consistent.If persistence or label update throws, the exception is swallowed and the dialog stays open with no feedback. Consider logging/reporting and/or dismissing in a finally-style path (or showing a toast) so the user isn’t left in limbo.
patches/new_files/smali_classes4/com/xj/winemu/sidebar/RtsGestureConfigDialog$PendingClickListener.smali (1)
19-53: Consider logging exceptions instead of fully swallowing them.
Silent failures here make it hard to diagnose why a selection didn’t persist or update the UI.
| <string name="winemu_sidebar_key_map_alpha">Touch Control Opacity</string> | ||
| <string name="winemu_sidebar_key_mapping">Input Mapping</string> | ||
| <string name="winemu_sidebar_key_mouse_speed">Mouse Speed</string> | ||
| + <string name="winemu_sidebar_rts_touch_controls">RTS Touch Controls</string> | ||
| + <string name="rts_gesture_settings">RTS Gesture Settings</string> | ||
| + <string name="rts_gesture_settings_title">RTS Gesture Settings</string> | ||
| + <string name="rts_gesture_settings_close">Close</string> | ||
| + <string name="rts_gesture_settings_reset">Reset to Defaults</string> | ||
| + <string name="rts_gesture_tap">Tap</string> | ||
| + <string name="rts_gesture_long_press">Long Press (300ms)</string> | ||
| + <string name="rts_gesture_double_tap">Double-Tap</string> | ||
| + <string name="rts_gesture_drag">Drag Finger</string> | ||
| + <string name="rts_gesture_pinch">Pinch In/Out</string> | ||
| + <string name="rts_gesture_two_finger_drag">Two-Finger Drag</string> | ||
| + <string name="rts_action_left_click">Left Click</string> | ||
| + <string name="rts_action_right_click">Right Click</string> | ||
| + <string name="rts_action_double_left_click">Double Left Click</string> | ||
| + <string name="rts_action_drag_left_click">Drag Left Click</string> | ||
| + <string name="rts_action_scroll_wheel">Mouse Wheel Scroll</string> | ||
| + <string name="rts_action_plus_minus">+/- Keys</string> | ||
| + <string name="rts_action_page_up_down">Page Up/Down</string> | ||
| + <string name="rts_action_middle_mouse">Middle Mouse Button</string> | ||
| + <string name="rts_action_wasd_keys">WASD Keys</string> | ||
| + <string name="rts_action_arrow_keys">Arrow Keys</string> | ||
| + <string name="winemu_sidebar_fps_touch_controls">FPS Touch Controls</string> | ||
| <string name="winemu_sidebar_performance">Performance</string> | ||
| <string name="winemu_sidebar_screen_brightness">Screen Brightness</string> | ||
| <string name="winemu_sidebar_switch_input_mapping">Switch Touch Control Layout</string> No newline at end of file |
There was a problem hiding this comment.
Remove duplicated RTS string keys to avoid resource merge failures.
These keys already appear above; duplicated resource names will cause build errors.
🧹 Remove the duplicated RTS strings block
- <string name="winemu_sidebar_rts_touch_controls">RTS Touch Controls</string>
- <string name="rts_gesture_settings">RTS Gesture Settings</string>
- <string name="rts_gesture_settings_title">RTS Gesture Settings</string>
- <string name="rts_gesture_settings_close">Close</string>
- <string name="rts_gesture_settings_reset">Reset to Defaults</string>
- <string name="rts_gesture_tap">Tap</string>
- <string name="rts_gesture_long_press">Long Press (300ms)</string>
- <string name="rts_gesture_double_tap">Double-Tap</string>
- <string name="rts_gesture_drag">Drag Finger</string>
- <string name="rts_gesture_pinch">Pinch In/Out</string>
- <string name="rts_gesture_two_finger_drag">Two-Finger Drag</string>
- <string name="rts_action_left_click">Left Click</string>
- <string name="rts_action_right_click">Right Click</string>
- <string name="rts_action_double_left_click">Double Left Click</string>
- <string name="rts_action_drag_left_click">Drag Left Click</string>
- <string name="rts_action_scroll_wheel">Mouse Wheel Scroll</string>
- <string name="rts_action_plus_minus">+/- Keys</string>
- <string name="rts_action_page_up_down">Page Up/Down</string>
- <string name="rts_action_middle_mouse">Middle Mouse Button</string>
- <string name="rts_action_wasd_keys">WASD Keys</string>
- <string name="rts_action_arrow_keys">Arrow Keys</string>
- <string name="winemu_sidebar_fps_touch_controls">FPS Touch Controls</string>🤖 Prompt for AI Agents
In `@patches/diffs/res/values/strings.xml.patch` around lines 124 - 151, The pull
contains a duplicated block of RTS string resources (e.g., rts_gesture_settings,
rts_gesture_settings_title, rts_gesture_tap, rts_gesture_long_press,
rts_gesture_double_tap, rts_gesture_drag, rts_gesture_pinch,
rts_gesture_two_finger_drag, rts_action_left_click, rts_action_right_click,
rts_action_double_left_click, rts_action_drag_left_click,
rts_action_scroll_wheel, rts_action_plus_minus, rts_action_page_up_down,
rts_action_middle_mouse, rts_action_wasd_keys, rts_action_arrow_keys,
winemu_sidebar_rts_touch_controls) which will cause resource merge/build
failures; remove this duplicated block from the patch so only the original
definitions remain (delete the added <string name="..."> entries listed above
and keep the singular definitions already present).
| + <style name="RtsGestureConfigDialogTheme" parent="Theme.AppCompat.Dialog"> | ||
| + <item name="android:windowBackground">@android:color/transparent</item> | ||
| + <item name="android:windowFrame">@null</item> | ||
| + <item name="android:windowIsFloating">true</item> | ||
| + <item name="android:windowNoTitle">true</item> | ||
| + </style> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, locate and read the patch file
find . -name "styles.xml.patch" -type fRepository: Producdevity/gamehub-lite
Length of output: 112
🏁 Script executed:
cat -n ./patches/diffs/res/values/styles.xml.patchRepository: Producdevity/gamehub-lite
Length of output: 2028
Remove the duplicate hunk in the patch.
The patch file contains two identical hunks (both with header @@ -3360,4 +3357,10 @@) that add the same RtsGestureConfigDialogTheme style definition at lines 17-22 and 28-33. This will cause duplicate resource errors or patch conflicts when applied. Keep only one hunk.
🛠️ Remove the second duplicate hunk
-@@ -3360,4 +3357,10 @@
- <item name="materialCalendarStyle">@style/Theme.MaterialComponents.Light</item>
- <item name="materialCalendarTheme">@style/Theme.MaterialComponents.Light</item>
- </style>
-+ <style name="RtsGestureConfigDialogTheme" parent="Theme.AppCompat.Dialog">
-+ <item name="android:windowBackground">@android:color/transparent</item>
-+ <item name="android:windowFrame">@null</item>
-+ <item name="android:windowIsFloating">true</item>
-+ <item name="android:windowNoTitle">true</item>
-+ </style>
- </resources>🤖 Prompt for AI Agents
In `@patches/diffs/res/values/styles.xml.patch` around lines 17 - 22, The patch
contains a duplicated hunk adding the same style RtsGestureConfigDialogTheme
twice; remove the second duplicate hunk so the style definition appears only
once in the patch, leaving a single <style name="RtsGestureConfigDialogTheme"
...> block (keep the existing attributes android:windowBackground,
android:windowFrame, android:windowIsFloating, android:windowNoTitle) and delete
the repeated addition to avoid duplicate resource errors when applying the
patch.
| +.method public static getRtsTouchControlsEnabled()Z | ||
| + .locals 3 | ||
| + | ||
| + invoke-static {}, Lcom/xj/pcvirtualbtn/inputcontrols/InputControlsManager;->z()Lcom/tencent/mmkv/MMKV; | ||
| + | ||
| + move-result-object v0 | ||
| + | ||
| + const-string v1, "sp_k_enable_rts_touch_controls_global" | ||
| + | ||
| + const/4 v2, 0x0 | ||
| + | ||
| + invoke-virtual {v0, v1, v2}, Lcom/tencent/mmkv/MMKV;->c(Ljava/lang/String;Z)Z | ||
| + | ||
| + move-result v0 | ||
| + | ||
| + return v0 | ||
| +.end method | ||
| + | ||
| +.method public static setRtsTouchControlsEnabled(Z)V | ||
| + .locals 2 | ||
| + | ||
| + invoke-static {}, Lcom/xj/pcvirtualbtn/inputcontrols/InputControlsManager;->z()Lcom/tencent/mmkv/MMKV; | ||
| + | ||
| + move-result-object v0 | ||
| + | ||
| + const-string v1, "sp_k_enable_rts_touch_controls_global" | ||
| + | ||
| + invoke-virtual {v0, v1, p0}, Lcom/tencent/mmkv/MMKV;->v(Ljava/lang/String;Z)Z | ||
| + | ||
| + return-void | ||
| +.end method |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, check if the patch file exists and read its full content
if [ -f "patches/diffs/smali_classes5/com/xj/pcvirtualbtn/inputcontrols/InputControlsManager.smali.patch" ]; then
echo "=== Patch file content ==="
cat "patches/diffs/smali_classes5/com/xj/pcvirtualbtn/inputcontrols/InputControlsManager.smali.patch"
else
echo "Patch file not found. Checking for similar files..."
find . -name "*InputControlsManager*" -type f | head -20
fiRepository: Producdevity/gamehub-lite
Length of output: 7376
Guard MMKV null for RTS enable getter/setter.
The newly added getRtsGestureEnabled, setRtsGestureEnabled, getRtsGestureAction, setRtsGestureAction, and resetRtsGestureSettings methods all include null checks for z(). The getRtsTouchControlsEnabled() and setRtsTouchControlsEnabled(Z)V methods lack this protection, creating an NPE risk if z() returns null. Align these two with the established null-guard pattern used throughout the rest of the patch.
🛠️ Proposed fix (null guard)
.method public static getRtsTouchControlsEnabled()Z
.locals 3
invoke-static {}, Lcom/xj/pcvirtualbtn/inputcontrols/InputControlsManager;->z()Lcom/tencent/mmkv/MMKV;
move-result-object v0
+ if-nez v0, :cond_mmkv_ok
+ const/4 v0, 0x0
+ return v0
+ :cond_mmkv_ok
const-string v1, "sp_k_enable_rts_touch_controls_global"
@@
.end method
.method public static setRtsTouchControlsEnabled(Z)V
.locals 2
invoke-static {}, Lcom/xj/pcvirtualbtn/inputcontrols/InputControlsManager;->z()Lcom/tencent/mmkv/MMKV;
move-result-object v0
+ if-nez v0, :cond_mmkv_ok
+ return-void
+ :cond_mmkv_ok
const-string v1, "sp_k_enable_rts_touch_controls_global"🤖 Prompt for AI Agents
In
`@patches/diffs/smali_classes5/com/xj/pcvirtualbtn/inputcontrols/InputControlsManager.smali.patch`
around lines 9 - 39, The new getRtsTouchControlsEnabled and
setRtsTouchControlsEnabled methods call z() without checking for null, risking
an NPE; update both to mirror the null-guard pattern used in
getRtsGestureEnabled/setRtsGestureEnabled: call z(), check if the returned MMKV
object is null, return a safe default (false) from getRtsTouchControlsEnabled if
null, and in setRtsTouchControlsEnabled simply skip the invoke-virtual v(...) if
z() returns null so you only call MMKV.v(...) when z() != null.
| .method public constructor <init>(Lcom/xj/winemu/sidebar/RtsGestureConfigDialog;)V | ||
| .locals 0 | ||
|
|
||
| iput-object p1, p0, Lcom/xj/winemu/sidebar/RtsGestureConfigDialog$CloseClickListener;->this$0:Lcom/xj/winemu/sidebar/RtsGestureConfigDialog; | ||
| invoke-direct {p0}, Ljava/lang/Object;-><init>()V | ||
| return-void | ||
| .end method |
There was a problem hiding this comment.
Constructor field assignment before super() call.
Line 22 assigns this$0 before Object.<init>() is invoked on Line 23. While Dalvik/ART may tolerate this, it violates the JVM specification where super() must complete before accessing instance fields. This could cause issues with strict verifiers or future runtime changes.
♻️ Suggested fix
.method public constructor <init>(Lcom/xj/winemu/sidebar/RtsGestureConfigDialog;)V
.locals 0
- iput-object p1, p0, Lcom/xj/winemu/sidebar/RtsGestureConfigDialog$CloseClickListener;->this$0:Lcom/xj/winemu/sidebar/RtsGestureConfigDialog;
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
+ iput-object p1, p0, Lcom/xj/winemu/sidebar/RtsGestureConfigDialog$CloseClickListener;->this$0:Lcom/xj/winemu/sidebar/RtsGestureConfigDialog;
return-void
.end method📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| .method public constructor <init>(Lcom/xj/winemu/sidebar/RtsGestureConfigDialog;)V | |
| .locals 0 | |
| iput-object p1, p0, Lcom/xj/winemu/sidebar/RtsGestureConfigDialog$CloseClickListener;->this$0:Lcom/xj/winemu/sidebar/RtsGestureConfigDialog; | |
| invoke-direct {p0}, Ljava/lang/Object;-><init>()V | |
| return-void | |
| .end method | |
| .method public constructor <init>(Lcom/xj/winemu/sidebar/RtsGestureConfigDialog;)V | |
| .locals 0 | |
| invoke-direct {p0}, Ljava/lang/Object;-><init>()V | |
| iput-object p1, p0, Lcom/xj/winemu/sidebar/RtsGestureConfigDialog$CloseClickListener;->this$0:Lcom/xj/winemu/sidebar/RtsGestureConfigDialog; | |
| return-void | |
| .end method |
🤖 Prompt for AI Agents
In
`@patches/new_files/smali_classes4/com/xj/winemu/sidebar/RtsGestureConfigDialog`$CloseClickListener.smali
around lines 19 - 25, The constructor for
RtsGestureConfigDialog$CloseClickListener assigns the instance field this$0
before calling the superclass constructor; move the iput-object p1, p0,
Lcom/xj/winemu/sidebar/RtsGestureConfigDialog$CloseClickListener;->this$0:Lcom/xj/winemu/sidebar/RtsGestureConfigDialog;
so that it occurs after invoke-direct {p0}, Ljava/lang/Object;-><init>()V (i.e.,
call Object.<init>() first, then store p1 into this$0) to comply with JVM
verification rules.
| # Check TWO_FINGER_DRAG action - only press middle mouse if action is 0 | ||
| const-string v2, "TWO_FINGER_DRAG" | ||
| invoke-static {v2}, Lcom/xj/pcvirtualbtn/inputcontrols/InputControlsManager;->getRtsGestureAction(Ljava/lang/String;)I | ||
| move-result v2 | ||
| if-nez v2, :cond_skip_middle_press | ||
| # Action 0: Press middle mouse to initiate camera pan | ||
| invoke-virtual {p0}, Lcom/xj/winemu/view/RtsTouchOverlayView;->pressMiddleButton()V | ||
| :cond_skip_middle_press |
There was a problem hiding this comment.
Respect TWO_FINGER_DRAG enabled flag before pressing middle button.
Right now the middle button is pressed whenever action=0, even if TWO_FINGER_DRAG is disabled. This still injects an unintended middle‑button drag on two‑finger touches.
🛠️ Proposed fix (gate middle press)
const-string v2, "TWO_FINGER_DRAG"
invoke-static {v2}, Lcom/xj/pcvirtualbtn/inputcontrols/InputControlsManager;->getRtsGestureAction(Ljava/lang/String;)I
move-result v2
- if-nez v2, :cond_skip_middle_press
- # Action 0: Press middle mouse to initiate camera pan
- invoke-virtual {p0}, Lcom/xj/winemu/view/RtsTouchOverlayView;->pressMiddleButton()V
+ # Only press if gesture enabled and action = middle mouse
+ const-string v3, "TWO_FINGER_DRAG"
+ invoke-static {v3}, Lcom/xj/pcvirtualbtn/inputcontrols/InputControlsManager;->getRtsGestureEnabled(Ljava/lang/String;)Z
+ move-result v3
+ if-eqz v3, :cond_skip_middle_press
+ if-nez v2, :cond_skip_middle_press
+ invoke-virtual {p0}, Lcom/xj/winemu/view/RtsTouchOverlayView;->pressMiddleButton()V🤖 Prompt for AI Agents
In
`@patches/new_files/smali_classes4/com/xj/winemu/view/RtsTouchOverlayView.smali`
around lines 249 - 256, The code presses the middle mouse whenever
getRtsGestureAction("TWO_FINGER_DRAG") returns 0, even when the TWO_FINGER_DRAG
feature is disabled; update the condition so that before calling
RtsTouchOverlayView.pressMiddleButton() you first check the TWO_FINGER_DRAG
enabled flag via InputControlsManager.getRtsGestureAction("TWO_FINGER_DRAG") and
only call pressMiddleButton() when that call indicates the gesture is enabled
and the action equals the expected value (i.e., gate the middle-button press
behind the feature-enabled check rather than solely the action==0 check).
| const-wide/16 v8, 0xfa # 250ms window | ||
| cmp-long v10, v4, v8 | ||
| if-gez v10, :cond_no_double_tap | ||
|
|
||
| iget v6, p0, Lcom/xj/winemu/view/RtsTouchOverlayView;->lastTapX:F | ||
| sub-float v6, v2, v6 | ||
| invoke-static {v6}, Ljava/lang/Math;->abs(F)F | ||
| move-result v6 | ||
| iget v7, p0, Lcom/xj/winemu/view/RtsTouchOverlayView;->lastTapY:F | ||
| sub-float v7, v3, v7 | ||
| invoke-static {v7}, Ljava/lang/Math;->abs(F)F | ||
| move-result v7 | ||
| const/high16 v8, 0x42480000 # 50.0f distance window | ||
| cmpg-float v9, v6, v8 | ||
| if-gtz v9, :cond_no_double_tap | ||
| cmpg-float v6, v7, v8 | ||
| if-gtz v6, :cond_no_double_tap |
There was a problem hiding this comment.
Double‑tap window doesn’t match the stated spec (250 ms / 50 px vs 300 ms / 30 px).
If the PR requirement is 300 ms and 30 px, please align the constants or make them configurable.
🛠️ Suggested constant update
- const-wide/16 v8, 0xfa # 250ms window
+ const-wide/16 v8, 0x12c # 300ms window
@@
- const/high16 v8, 0x42480000 # 50.0f distance window
+ const/high16 v8, 0x41f00000 # 30.0f distance window📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const-wide/16 v8, 0xfa # 250ms window | |
| cmp-long v10, v4, v8 | |
| if-gez v10, :cond_no_double_tap | |
| iget v6, p0, Lcom/xj/winemu/view/RtsTouchOverlayView;->lastTapX:F | |
| sub-float v6, v2, v6 | |
| invoke-static {v6}, Ljava/lang/Math;->abs(F)F | |
| move-result v6 | |
| iget v7, p0, Lcom/xj/winemu/view/RtsTouchOverlayView;->lastTapY:F | |
| sub-float v7, v3, v7 | |
| invoke-static {v7}, Ljava/lang/Math;->abs(F)F | |
| move-result v7 | |
| const/high16 v8, 0x42480000 # 50.0f distance window | |
| cmpg-float v9, v6, v8 | |
| if-gtz v9, :cond_no_double_tap | |
| cmpg-float v6, v7, v8 | |
| if-gtz v6, :cond_no_double_tap | |
| const-wide/16 v8, 0x12c # 300ms window | |
| cmp-long v10, v4, v8 | |
| if-gez v10, :cond_no_double_tap | |
| iget v6, p0, Lcom/xj/winemu/view/RtsTouchOverlayView;->lastTapX:F | |
| sub-float v6, v2, v6 | |
| invoke-static {v6}, Ljava/lang/Math;->abs(F)F | |
| move-result v6 | |
| iget v7, p0, Lcom/xj/winemu/view/RtsTouchOverlayView;->lastTapY:F | |
| sub-float v7, v3, v7 | |
| invoke-static {v7}, Ljava/lang/Math;->abs(F)F | |
| move-result v7 | |
| const/high16 v8, 0x41f00000 # 30.0f distance window | |
| cmpg-float v9, v6, v8 | |
| if-gtz v9, :cond_no_double_tap | |
| cmpg-float v6, v7, v8 | |
| if-gtz v6, :cond_no_double_tap |
🤖 Prompt for AI Agents
In
`@patches/new_files/smali_classes4/com/xj/winemu/view/RtsTouchOverlayView.smali`
around lines 842 - 858, The double-tap detection currently uses hardcoded
constants (250ms via the const-wide/16 v8, 0xfa instruction and 50.0f via
const/high16 v8, 0x42480000) in RtsTouchOverlayView.smali when comparing
timestamps and distances against lastTapX/lastTapY; update these to the
PR-specified 300ms and 30px (or refactor to read configurable values from a
class constant/field or settings API) so the cmp-long and cmpg-float checks use
300ms and 30.0f respectively; locate the tap-handling block around comparisons
to lastTapX/lastTapY and replace the literal constants or wire them to a
configurable field (e.g., DOUBLE_TAP_TIMEOUT_MS / DOUBLE_TAP_SLOP_PX) used in
the cmp-long/cmpg-float logic.
| .method public sendPlusMinusKey(I)V | ||
| .locals 4 | ||
|
|
||
| iget-object v0, p0, Lcom/xj/winemu/view/RtsTouchOverlayView;->a:Lcom/winemu/openapi/WinUIBridge; | ||
| if-eqz v0, :cond_end | ||
|
|
||
| iget-object v1, v0, Lcom/winemu/openapi/WinUIBridge;->k:Lcom/winemu/core/controller/X11Controller; | ||
| if-eqz v1, :cond_end | ||
|
|
||
| # Determine keycode: plus = 0x51 (81 = KEYCODE_NUMPAD_ADD), minus = 0x4e (78 = KEYCODE_MINUS) | ||
| # Actually using KEYCODE_EQUALS (70) with shift for plus, KEYCODE_MINUS (69) for minus | ||
| const/4 v2, 0x1 | ||
| if-ne p1, v2, :cond_minus | ||
| # Plus key (KEYCODE_EQUALS = 70 in Android, will map to = which often is +) | ||
| const/16 v2, 0x46 # 70 = KEYCODE_EQUALS | ||
| goto :cond_send | ||
|
|
||
| :cond_minus | ||
| # Minus key (KEYCODE_MINUS = 69) | ||
| const/16 v2, 0x45 # 69 = KEYCODE_MINUS | ||
|
|
||
| :cond_send | ||
| # Send key press | ||
| const/4 v3, 0x0 # modifiers = 0 | ||
| const/4 p1, 0x1 # isDown = true | ||
| invoke-virtual {v1, v3, v2, p1}, Lcom/winemu/core/controller/X11Controller;->p(IIZ)V | ||
|
|
||
| # Send key release | ||
| const/4 p1, 0x0 # isDown = false | ||
| invoke-virtual {v1, v3, v2, p1}, Lcom/winemu/core/controller/X11Controller;->p(IIZ)V | ||
|
|
||
| :cond_end | ||
| return-void | ||
| .end method |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -type f -name "*.smali" -o -name "*.java" | grep -i "x11controller" | head -20Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
rg -t java -t smali "class X11Controller" -A 10Repository: Producdevity/gamehub-lite
Length of output: 98
🏁 Script executed:
rg -t java -t smali "def p\(IIZ\)" -A 20Repository: Producdevity/gamehub-lite
Length of output: 98
🏁 Script executed:
rg "KEYCODE_EQUALS\|KEYCODE_NUMPAD_ADD\|0x46\|0x51" -t smali -t java -B 2 -A 2Repository: Producdevity/gamehub-lite
Length of output: 98
🏁 Script executed:
find . -type f \( -name "*.java" -o -name "*.smali" \) | grep -i controller | head -20Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
rg "X11Controller" -A 5 -B 2 | head -100Repository: Producdevity/gamehub-lite
Length of output: 10598
🏁 Script executed:
rg "\.p\(IIZ" -B 5 -A 10 | head -50Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
ls -la patches/new_files/smali_classes4/com/winemu/ 2>/dev/null || echo "Path not found, searching for alternatives"Repository: Producdevity/gamehub-lite
Length of output: 111
🏁 Script executed:
find . -path "*/winemu/*" -name "*.smali" -o -path "*/winemu/*" -name "*.java" | head -20Repository: Producdevity/gamehub-lite
Length of output: 1661
🏁 Script executed:
find . -type f -name "X11Controller.smali" | head -5Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
find . -path "*/com/winemu/core/controller/X11Controller.smali" -exec cat {} \;Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
rg "method.*p\(" patches/ -A 30 | head -100Repository: Producdevity/gamehub-lite
Length of output: 1964
🏁 Script executed:
rg "SHIFT\|0x02\|KeyEvent" patches/new_files/ -B 2 -A 2 | head -80Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
find patches -name "*X11Controller*" -type f | head -10Repository: Producdevity/gamehub-lite
Length of output: 150
🏁 Script executed:
cat patches/files_to_patch.txt | grep -i x11Repository: Producdevity/gamehub-lite
Length of output: 130
🏁 Script executed:
rg "\.method.*p\(IIZ\)" patches -A 50 | head -120Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
rg "sendPlusMinusKey" patches -B 5 -A 50 | head -150Repository: Producdevity/gamehub-lite
Length of output: 16433
🏁 Script executed:
cat patches/diffs/smali_classes4/com/winemu/core/controller/X11Controller.smali.patch | head -300Repository: Producdevity/gamehub-lite
Length of output: 776
🏁 Script executed:
cat patches/diffs/smali_classes4/com/winemu/core/controller/X11Controller.smali.patch | grep -A 60 "\.method.*p(IIZ"Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
find patches -name "*.patch" -o -name "*.smali" | xargs grep -l "\.p(IIZ" | head -10Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
rg "\.method.*\bp\(IIZ" patches/diffs -A 80 | head -200Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
# Search for where X11Controller p() method might be defined or modified
cat patches/diffs/smali_classes4/com/winemu/core/controller/X11Controller.smali.patch | wc -lRepository: Producdevity/gamehub-lite
Length of output: 71
🏁 Script executed:
# Check if there's an original X11Controller file that shows p() method
rg "public.*p\(.*I.*I.*Z" patches -B 2 -A 30 | head -150Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
rg "X11Controller;->p\(" patches -B 3 -A 3 | head -200Repository: Producdevity/gamehub-lite
Length of output: 5805
🏁 Script executed:
rg "const.*0x02\|SHIFT\|MOD_" patches/new_files -B 1 -A 1 | head -80Repository: Producdevity/gamehub-lite
Length of output: 51
🏁 Script executed:
# Look at the original comment in the code more carefully
cat patches/new_files/smali_classes4/com/xj/winemu/view/RtsTouchOverlayView.smali | grep -A 30 "sendPlusMinusKey"Repository: Producdevity/gamehub-lite
Length of output: 3783
KEYCODE_EQUALS emits "=" without shift modifier, not "+".
The code comment claims to use shift for the plus key, but modifiers are hardcoded to 0. Without a shift modifier (typically 0x01 or similar), KEYCODE_EQUALS produces the "=" character. Consider passing an appropriate shift modifier for the plus case, or use KEYCODE_NUMPAD_ADD which produces "+" directly without shift dependency.
🤖 Prompt for AI Agents
In
`@patches/new_files/smali_classes4/com/xj/winemu/view/RtsTouchOverlayView.smali`
around lines 1602 - 1635, The sendPlusMinusKey method currently invokes
X11Controller->p with modifiers hardcoded to 0, so using KEYCODE_EQUALS (70)
emits "=" instead of "+"; update sendPlusMinusKey to set the appropriate shift
modifier when p is called for the plus branch (e.g., set modifiers to the shift
bit value used by X11Controller, or alternatively use KEYCODE_NUMPAD_ADD (0x51)
for plus) and ensure the invoke-virtual calls pass that modifiers variable (not
0) for both press and release; locate sendPlusMinusKey and X11Controller->p
invocations to change the const/4 v3 (modifiers) and/or replace the plus keycode
constant accordingly.
| .method public run()V | ||
| .locals 2 | ||
|
|
||
| # Set rtslongPress flag to true (held for 1 second) |
There was a problem hiding this comment.
Comment inconsistency: "1 second" vs PR-specified "300 ms".
The comment states the flag is set when "held for 1 second," but the PR description specifies "hold for 300 ms to trigger a right-click." Please verify the correct duration and update the comment accordingly to avoid future maintenance confusion.
🤖 Prompt for AI Agents
In
`@patches/new_files/smali_classes5/com/xj/pcvirtualbtn/inputcontrols/RangeScrollerRtsTask.smali`
at line 26, Update the inaccurate inline comment in RangeScrollerRtsTask.smali
that reads "Set rtslongPress flag to true (held for 1 second)" to reflect the
PR-specified 300 ms trigger time; locate the comment near the rtslongPress flag
handling in the RangeScrollerRtsTask class and change the duration text to "300
ms" so the comment matches the implemented behavior.
- Removed UTF-8 BOM from strings.xml.patch and styles.xml.patch - Removed duplicate RTS string entries from strings.xml.patch - Removed duplicate RtsGestureConfigDialogTheme from styles.xml.patch - Removed 24 duplicate file entries from files_to_add.txt Addresses maintainer feedback from PR Producdevity#73
…3/gamehub-lite into rts-touch-controls
Regenerated ids.xml.patch from source using git diff. Now has proper hunk headers with multiple sections: - @@ -2309,6 +2309,18 @@ (adds 12 RTS IDs) - @@ -2596,6 +2608,7 @@ (adds switch_rts_touch_controls) - @@ -3344,4 +3357,13 @@ (adds action option IDs)
Removed UTF-8 BOM from: - winemu_sidebar_controls_fragment.xml.patch - strings.xml.patch - styles.xml.patch - SidebarControlsFragment.smali.patch - InputControlsManager.smali.patch
RTS Controls feature list:
Tap to Click - Tap anywhere to move cursor and click (Like move cursor to touchpoint on Winlator)
Drag for Box Selection - Drag finger to create selection box (left mouse button held during drag)
Long Press for Right-Click - Hold finger for 300ms to trigger right-click
Double-Tap for Double-Click - Tap twice within 300ms and 30 pixels to double-click
Two-Finger Pan for Camera* - Drag with two fingers to pan camera
Pinch-to-Zoom* - Pinch two fingers inward to zoom out, pinch outward to zoom in (mouse wheel scroll)
Toggle Switch - Enable/disable RTS controls in Settings > Controls tab (in the side overlay menu when you're in a game).
The two gestures that have an asterisk can be customized in the RTS Gesture Settings menu. This is just the first implementation of touch gestures, will keep an eye out for suggestions, bugs, etc.
Summary by CodeRabbit
New Features
UI Updates
Style
✏️ Tip: You can customize this high-level summary in your review settings.