From 17244e6f6cf8039927d35de5b5c26ab4ec2b1751 Mon Sep 17 00:00:00 2001
From: osy <50960678+osy@users.noreply.github.com>
Date: Sun, 20 Sep 2026 00:30:12 -0500
Subject: [PATCH] input(iOS): let the controller Options and Home buttons be
mapped
Only the Menu button could be mapped to the guest. Options and Home were
left out because the system uses them for its own gestures (screenshots,
recording, opening the game overlay), so a press never did anything useful
for the guest.
Add both to the gamepad settings with the same choices as the other
buttons. They default to Disabled, which leaves the system gestures alone.
Once a button is mapped we ask the system to give up its gesture through
preferredSystemGestureState, which the system honours according to the
user's Home button setting.
Not tested with a physical controller.
Assisted-by: Claude:claude-fable-5-1
---
.../VMDisplayMetalViewController+Gamepad.h | 3 +
.../VMDisplayMetalViewController+Gamepad.m | 19 +
.../Display/VMDisplayMetalViewController.m | 2 +
Platform/iOS/Settings.bundle/Root.plist | 364 ++++++++++++++++++
.../iOS/Settings.bundle/en.lproj/Root.strings | Bin 4006 -> 4086 bytes
5 files changed, 388 insertions(+)
diff --git a/Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.h b/Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.h
index 13c8d3a7..f6214de2 100644
--- a/Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.h
+++ b/Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.h
@@ -23,6 +23,9 @@ NS_ASSUME_NONNULL_BEGIN
- (void)initGamepad;
+/// Takes the buttons mapped to the guest away from the system, or gives them back.
+- (void)setSystemGestureButtonsClaimed:(BOOL)isClaimed;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.m b/Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.m
index 53dc3bb9..b59f8cf0 100644
--- a/Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.m
+++ b/Platform/iOS/Display/VMDisplayMetalViewController+Gamepad.m
@@ -127,6 +127,25 @@ const CGFloat kThumbstickSpeedMultiplier = 1000; // in points per second
gamepad.buttonMenu.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
[_self gamepadButton:@"GCButtonMenu" pressed:pressed];
};
+
+ gamepad.buttonOptions.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
+ [_self gamepadButton:@"GCButtonOptions" pressed:pressed];
+ };
+
+ gamepad.buttonHome.pressedChangedHandler = ^(GCControllerButtonInput * _Nonnull button, float value, BOOL pressed) {
+ [_self gamepadButton:@"GCButtonHome" pressed:pressed];
+ };
+
+ [self setSystemGestureButtonsClaimed:YES];
+}
+
+- (void)setSystemGestureButtonsClaimed:(BOOL)isClaimed {
+ // the system uses these buttons for its own gestures, so we only ask for them while they are mapped to the guest
+ GCExtendedGamepad *gamepad = self.controller.extendedGamepad;
+ BOOL isOptionsClaimed = isClaimed && [self integerForSetting:@"GCButtonOptions"] != 0;
+ BOOL isHomeClaimed = isClaimed && [self integerForSetting:@"GCButtonHome"] != 0;
+ gamepad.buttonOptions.preferredSystemGestureState = isOptionsClaimed ? GCSystemGestureStateDisabled : GCSystemGestureStateEnabled;
+ gamepad.buttonHome.preferredSystemGestureState = isHomeClaimed ? GCSystemGestureStateDisabled : GCSystemGestureStateEnabled;
}
- (void)gamepadButton:(NSString *)identifier pressed:(BOOL)isPressed {
diff --git a/Platform/iOS/Display/VMDisplayMetalViewController.m b/Platform/iOS/Display/VMDisplayMetalViewController.m
index 093c260f..73e51c49 100644
--- a/Platform/iOS/Display/VMDisplayMetalViewController.m
+++ b/Platform/iOS/Display/VMDisplayMetalViewController.m
@@ -112,6 +112,7 @@ static const NSInteger kResizeTimeoutSecs = 5;
#if !TARGET_OS_VISION
[self startGCMouse];
#endif
+ [self setSystemGestureButtonsClaimed:YES];
[self.vmDisplay addRenderer:self.renderer];
}
@@ -120,6 +121,7 @@ static const NSInteger kResizeTimeoutSecs = 5;
#if !TARGET_OS_VISION
[self stopGCMouse];
#endif
+ [self setSystemGestureButtonsClaimed:NO];
[self.vmDisplay removeRenderer:self.renderer];
[self removeObserver:self forKeyPath:@"vmDisplay.displaySize"];
}
diff --git a/Platform/iOS/Settings.bundle/Root.plist b/Platform/iOS/Settings.bundle/Root.plist
index b7eacab9..1f5444eb 100644
--- a/Platform/iOS/Settings.bundle/Root.plist
+++ b/Platform/iOS/Settings.bundle/Root.plist
@@ -661,6 +661,370 @@
88
+
+ Type
+ PSMultiValueSpecifier
+ Title
+ Options
+ Key
+ GCButtonOptions
+ DefaultValue
+ 0
+ Titles
+
+ Disabled
+ Mouse Left Button
+ Mouse Right Button
+ Mouse Middle Button
+ Ctrl
+ Command/Windows
+ Option/Alt
+ Shift
+ Tab
+ Space
+ Enter
+ Backspace
+ Esc
+ Caps
+ `
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 0
+ -
+ =
+ [
+ ]
+ ;
+ '
+ \
+ ,
+ .
+ /
+ Ins
+ Home
+ PgUp
+ PgDn
+ Del
+ End
+ Up
+ Left
+ Down
+ Right
+ A
+ B
+ C
+ D
+ E
+ F
+ G
+ H
+ I
+ J
+ K
+ L
+ M
+ N
+ O
+ P
+ Q
+ R
+ S
+ T
+ U
+ V
+ W
+ X
+ Y
+ Z
+ F1
+ F2
+ F3
+ F4
+ F5
+ F6
+ F7
+ F8
+ F9
+ F10
+ F11
+ F12
+
+ Values
+
+ 0
+ -1
+ -3
+ -2
+ 29
+ 57435
+ 56
+ 42
+ 15
+ 57
+ 28
+ 14
+ 1
+ 58
+ 41
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 26
+ 27
+ 39
+ 40
+ 43
+ 51
+ 52
+ 53
+ 57426
+ 57415
+ 57417
+ 57425
+ 57427
+ 57423
+ 200
+ 203
+ 208
+ 205
+ 30
+ 48
+ 46
+ 32
+ 18
+ 33
+ 34
+ 35
+ 23
+ 36
+ 37
+ 38
+ 50
+ 49
+ 24
+ 25
+ 16
+ 19
+ 31
+ 20
+ 22
+ 47
+ 17
+ 45
+ 21
+ 44
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 87
+ 88
+
+
+
+ Type
+ PSMultiValueSpecifier
+ Title
+ Home
+ Key
+ GCButtonHome
+ DefaultValue
+ 0
+ Titles
+
+ Disabled
+ Mouse Left Button
+ Mouse Right Button
+ Mouse Middle Button
+ Ctrl
+ Command/Windows
+ Option/Alt
+ Shift
+ Tab
+ Space
+ Enter
+ Backspace
+ Esc
+ Caps
+ `
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 0
+ -
+ =
+ [
+ ]
+ ;
+ '
+ \
+ ,
+ .
+ /
+ Ins
+ Home
+ PgUp
+ PgDn
+ Del
+ End
+ Up
+ Left
+ Down
+ Right
+ A
+ B
+ C
+ D
+ E
+ F
+ G
+ H
+ I
+ J
+ K
+ L
+ M
+ N
+ O
+ P
+ Q
+ R
+ S
+ T
+ U
+ V
+ W
+ X
+ Y
+ Z
+ F1
+ F2
+ F3
+ F4
+ F5
+ F6
+ F7
+ F8
+ F9
+ F10
+ F11
+ F12
+
+ Values
+
+ 0
+ -1
+ -3
+ -2
+ 29
+ 57435
+ 56
+ 42
+ 15
+ 57
+ 28
+ 14
+ 1
+ 58
+ 41
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ 11
+ 12
+ 13
+ 26
+ 27
+ 39
+ 40
+ 43
+ 51
+ 52
+ 53
+ 57426
+ 57415
+ 57417
+ 57425
+ 57427
+ 57423
+ 200
+ 203
+ 208
+ 205
+ 30
+ 48
+ 46
+ 32
+ 18
+ 33
+ 34
+ 35
+ 23
+ 36
+ 37
+ 38
+ 50
+ 49
+ 24
+ 25
+ 16
+ 19
+ 31
+ 20
+ 22
+ 47
+ 17
+ 45
+ 21
+ 44
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 87
+ 88
+
+
Type
PSMultiValueSpecifier
diff --git a/Platform/iOS/Settings.bundle/en.lproj/Root.strings b/Platform/iOS/Settings.bundle/en.lproj/Root.strings
index be8941c7fc76946d8c5f9b9a4dc931a076c37827..e847b9cb4c0f933dec2883cef8700fbc03bf1769 100644
GIT binary patch
delta 84
zcmZ1`|4n{_8IQX^LjgkxLncE$LmophgA#)RgDns%F`$cEGjIV#J%H+R8B&qdK}9y}
I@>DVd0Mo$_aR2}S
delta 12
Tcmew+zf69E8PDc6o&sh7B3uN8