Skip to content

Commit

Permalink
Feature: option to disable control overlay when a mouse or game contr…
Browse files Browse the repository at this point in the history
…oller is connected

To be paired with incoming game controller configuration, as right now the keyboard cannot be opened with this enabled and a controller connected.
  • Loading branch information
crystall1nedev committed Mar 13, 2023
1 parent 6ebe3f2 commit e96111c
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 138 deletions.
1 change: 1 addition & 0 deletions Natives/LauncherPreferences.m
Expand Up @@ -141,6 +141,7 @@ void loadPreferences(BOOL reset) {
setDefaultValueForPref(envPrefDict, @"java_home", @"java-8-openjdk");
setDefaultValueForPref(envPrefDict, @"renderer", @"auto");
setDefaultValueForPref(envPrefDict, @"fullscreen_airplay", @YES);
setDefaultValueForPref(envPrefDict, @"hardware_hide", @NO);
fillDefaultWarningDict();
setDefaultValueForPref(prefDict, @"force_unsupported_launch", @NO);
setDefaultValueForPref(prefDict, @"slideable_hotbar", @NO);
Expand Down
281 changes: 143 additions & 138 deletions Natives/LauncherPreferencesViewController.m
Expand Up @@ -38,196 +38,201 @@ - (NSString *)imageName {
- (void)viewDidLoad
{
[super viewDidLoad];

[self initViewCreation];

self.prefDetailVisible = self.navigationController == nil;

self.tableView = [[TOInsetGroupedTableView alloc] init];
self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

if (self.navigationController == nil) {
self.tableView.alpha = 0.9;
}

BOOL(^whenNotInGame)() = ^BOOL(){
return self.navigationController != nil;
};

self.prefSections = @[@"general", @"video", @"control", @"java", @"debug"];
self.prefSectionsVisibility = [[NSMutableArray alloc] initWithCapacity:self.prefSections.count];
for (int i = 0; i < self.prefSections.count; i++) {
[self.prefSectionsVisibility addObject:@NO];
}

self.prefContents = @[
@[
// General settings
// General settings
@{@"icon": @"cube"},
@{@"key": @"game_directory",
@"icon": @"folder",
@"type": self.typeChildPane,
@"enableCondition": ^BOOL(){
return whenNotInGame() && !getenv("DEMO_LOCK");
},
@"class": LauncherPrefGameDirViewController.class,
@"icon": @"folder",
@"type": self.typeChildPane,
@"enableCondition": ^BOOL(){
return whenNotInGame() && !getenv("DEMO_LOCK");
},
@"class": LauncherPrefGameDirViewController.class,
},
@{@"key": @"check_sha",
@"hasDetail": @YES,
@"icon": @"lock.shield",
@"type": self.typeSwitch,
@"enableCondition": whenNotInGame
@"hasDetail": @YES,
@"icon": @"lock.shield",
@"type": self.typeSwitch,
@"enableCondition": whenNotInGame
},
@{@"key": @"cosmetica",
@"hasDetail": @YES,
@"icon": @"eyeglasses",
@"type": self.typeSwitch,
@"enableCondition": whenNotInGame
@"hasDetail": @YES,
@"icon": @"eyeglasses",
@"type": self.typeSwitch,
@"enableCondition": whenNotInGame
},
@{@"key": @"debug_logging",
@"hasDetail": @YES,
@"icon": @"doc.badge.gearshape",
@"type": self.typeSwitch,
@"action": ^(BOOL enabled){
debugLogEnabled = enabled;
NSLog(@"Debug log enabled: %@", enabled ? @"YES" : @"NO");
}
@"hasDetail": @YES,
@"icon": @"doc.badge.gearshape",
@"type": self.typeSwitch,
@"action": ^(BOOL enabled){
debugLogEnabled = enabled;
NSLog(@"Debug log enabled: %@", enabled ? @"YES" : @"NO");
}
},
@{@"key": @"jitstreamer_server",
@"hasDetail": @YES,
@"icon": @"hare",
@"type": self.typeTextField,
@"enableCondition": whenNotInGame
@"hasDetail": @YES,
@"icon": @"hare",
@"type": self.typeTextField,
@"enableCondition": whenNotInGame
},
@{@"key": @"enable_altkit",
@"hasDetail": @YES,
@"icon": @"network",
@"type": self.typeSwitch,
@"enableCondition": whenNotInGame
@"hasDetail": @YES,
@"icon": @"network",
@"type": self.typeSwitch,
@"enableCondition": whenNotInGame
},
@{@"key": @"appicon",
@"hasDetail": @YES,
@"icon": @"paintbrush",
@"type": self.typePickField,
@"enableCondition": ^BOOL(){
return UIApplication.sharedApplication.supportsAlternateIcons;
},
@"action": ^void(NSString *iconName) {
if ([iconName isEqualToString:@"AppIcon-Light"]) {
iconName = nil;
}
[UIApplication.sharedApplication setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
if (error == nil) return;
NSLog(@"Error in appicon: %@", error);
showDialog(self, localize(@"Error", nil), error.localizedDescription);
}];
},
@"pickKeys": @[
@"hasDetail": @YES,
@"icon": @"paintbrush",
@"type": self.typePickField,
@"enableCondition": ^BOOL(){
return UIApplication.sharedApplication.supportsAlternateIcons;
},
@"action": ^void(NSString *iconName) {
if ([iconName isEqualToString:@"AppIcon-Light"]) {
iconName = nil;
}
[UIApplication.sharedApplication setAlternateIconName:iconName completionHandler:^(NSError * _Nullable error) {
if (error == nil) return;
NSLog(@"Error in appicon: %@", error);
showDialog(self, localize(@"Error", nil), error.localizedDescription);
}];
},
@"pickKeys": @[
@"AppIcon-Light",
@"AppIcon-Dark"
],
@"pickList": @[
localize(@"preference.title.appicon-default", nil),
localize(@"preference.title.appicon-dark", nil)
]
],
@"pickList": @[
localize(@"preference.title.appicon-default", nil),
localize(@"preference.title.appicon-dark", nil)
]
},
@{@"key": @"hidden_sidebar",
@"hasDetail": @YES,
@"icon": @"sidebar.leading",
@"type": self.typeSwitch,
@"enableCondition": whenNotInGame
@"hasDetail": @YES,
@"icon": @"sidebar.leading",
@"type": self.typeSwitch,
@"enableCondition": whenNotInGame
},
@{@"key": @"reset_warnings",
@"icon": @"exclamationmark.triangle",
@"type": self.typeButton,
@"enableCondition": whenNotInGame,
@"action": ^void(){
resetWarnings();
}
@"icon": @"exclamationmark.triangle",
@"type": self.typeButton,
@"enableCondition": whenNotInGame,
@"action": ^void(){
resetWarnings();
}
},
@{@"key": @"reset_settings",
@"icon": @"trash",
@"type": self.typeButton,
@"enableCondition": whenNotInGame,
@"requestReload": @YES,
@"showConfirmPrompt": @YES,
@"destructive": @YES,
@"action": ^void(){
loadPreferences(YES);
[self.tableView reloadData];
}
@"icon": @"trash",
@"type": self.typeButton,
@"enableCondition": whenNotInGame,
@"requestReload": @YES,
@"showConfirmPrompt": @YES,
@"destructive": @YES,
@"action": ^void(){
loadPreferences(YES);
[self.tableView reloadData];
}
},
@{@"key": @"erase_demo_data",
@"icon": @"trash",
@"type": self.typeButton,
@"enableCondition": ^BOOL(){
NSString *demoPath = [NSString stringWithFormat:@"%s/.demo", getenv("POJAV_HOME")];
int count = [NSFileManager.defaultManager contentsOfDirectoryAtPath:demoPath error:nil].count;
return whenNotInGame() && count > 0;
},
@"showConfirmPrompt": @YES,
@"destructive": @YES,
@"action": ^void(){
NSString *demoPath = [NSString stringWithFormat:@"%s/.demo", getenv("POJAV_HOME")];
NSError *error;
if([NSFileManager.defaultManager removeItemAtPath:demoPath error:&error]) {
[NSFileManager.defaultManager createDirectoryAtPath:demoPath
withIntermediateDirectories:YES attributes:nil error:nil];
if ([getPreference(@"selected_version_type") intValue] == 0 && getenv("DEMO_LOCK")) {
[(LauncherNavigationController *)self.navigationController reloadVersionList:0];
}
} else {
NSLog(@"Error in erase_demo_data: %@", error);
showDialog(self, localize(@"Error", nil), error.localizedDescription);
}
}
@"icon": @"trash",
@"type": self.typeButton,
@"enableCondition": ^BOOL(){
NSString *demoPath = [NSString stringWithFormat:@"%s/.demo", getenv("POJAV_HOME")];
int count = [NSFileManager.defaultManager contentsOfDirectoryAtPath:demoPath error:nil].count;
return whenNotInGame() && count > 0;
},
@"showConfirmPrompt": @YES,
@"destructive": @YES,
@"action": ^void(){
NSString *demoPath = [NSString stringWithFormat:@"%s/.demo", getenv("POJAV_HOME")];
NSError *error;
if([NSFileManager.defaultManager removeItemAtPath:demoPath error:&error]) {
[NSFileManager.defaultManager createDirectoryAtPath:demoPath
withIntermediateDirectories:YES attributes:nil error:nil];
if ([getPreference(@"selected_version_type") intValue] == 0 && getenv("DEMO_LOCK")) {
[(LauncherNavigationController *)self.navigationController reloadVersionList:0];
}
} else {
NSLog(@"Error in erase_demo_data: %@", error);
showDialog(self, localize(@"Error", nil), error.localizedDescription);
}
}
}
], @[
// Video and renderer settings
// Video and renderer settings
@{@"icon": @"video"},
@{@"key": @"renderer",
@"icon": @"cpu",
@"type": self.typePickField,
@"enableCondition": whenNotInGame,
@"pickKeys": @[
@"auto",
@ RENDERER_NAME_GL4ES,
@ RENDERER_NAME_MTL_ANGLE,
@ RENDERER_NAME_VK_ZINK
],
@"pickList": @[
localize(@"preference.title.renderer.auto", nil),
localize(@"preference.title.renderer.gl4es", nil),
localize(@"preference.title.renderer.angle", nil),
localize(@"preference.title.renderer.zink", nil)
]
@"icon": @"cpu",
@"type": self.typePickField,
@"enableCondition": whenNotInGame,
@"pickKeys": @[
@"auto",
@ RENDERER_NAME_GL4ES,
@ RENDERER_NAME_MTL_ANGLE,
@ RENDERER_NAME_VK_ZINK
],
@"pickList": @[
localize(@"preference.title.renderer.auto", nil),
localize(@"preference.title.renderer.gl4es", nil),
localize(@"preference.title.renderer.angle", nil),
localize(@"preference.title.renderer.zink", nil)
]
},
@{@"key": @"resolution",
@"hasDetail": @YES,
@"icon": @"viewfinder",
@"type": self.typeSlider,
@"min": @(25),
@"max": @(150)
@"hasDetail": @YES,
@"icon": @"viewfinder",
@"type": self.typeSlider,
@"min": @(25),
@"max": @(150)
},
@{@"key": @"fullscreen_airplay",
@"hasDetail": @YES,
@"icon": @"airplayvideo",
@"type": self.typeSwitch,
@"action": ^(BOOL enabled){
if (self.navigationController != nil) return;
if (@available(iOS 13.0, *)) {
if (UIApplication.sharedApplication.connectedScenes.count < 2) return;
}
if (enabled) {
[self.presentingViewController performSelector:@selector(switchToExternalDisplay)];
} else {
[self.presentingViewController performSelector:@selector(switchToInternalDisplay)];
}
}
@"hasDetail": @YES,
@"icon": @"airplayvideo",
@"type": self.typeSwitch,
@"action": ^(BOOL enabled){
if (self.navigationController != nil) return;
if (@available(iOS 13.0, *)) {
if (UIApplication.sharedApplication.connectedScenes.count < 2) return;
}
if (enabled) {
[self.presentingViewController performSelector:@selector(switchToExternalDisplay)];
} else {
[self.presentingViewController performSelector:@selector(switchToInternalDisplay)];
}
}
}
], @[
// Control settings
// Control settings
@{@"icon": @"gamecontroller"},
@{@"key": @"hardware_hide",
@"icon": @"eye.slash",
@"hasDetail": @"YES",
@"type": self.typeSwitch,
},
@{@"key": @"gesture_mouse",
@"icon": @"cursorarrow.click",
@"hasDetail": @YES,
Expand Down
12 changes: 12 additions & 0 deletions Natives/SurfaceViewController.m
Expand Up @@ -211,6 +211,9 @@ - (void)viewDidLoad
self.mousePointerView.hidden = isGrabbing;
virtualMouseEnabled = YES;
[self setNeedsUpdateOfPrefersPointerLocked];
if([getPreference(@"hardware_hide") boolValue]) {
self.ctrlView.hidden = YES;
}
}];
self.mouseDisconnectCallback = [[NSNotificationCenter defaultCenter] addObserverForName:GCMouseDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
NSLog(@"Input: Mouse disconnected!");
Expand All @@ -220,6 +223,9 @@ - (void)viewDidLoad
mouse.mouseInput.middleButton.pressedChangedHandler = nil;
mouse.mouseInput.rightButton.pressedChangedHandler = nil;
[self setNeedsUpdateOfPrefersPointerLocked];
if([getPreference(@"hardware_hide") boolValue]) {
self.ctrlView.hidden = NO;
}
}];
if (GCMouse.current != nil) {
[self registerMouseCallbacks: GCMouse.current];
Expand All @@ -234,11 +240,17 @@ - (void)viewDidLoad
[ControllerInput registerControllerCallbacks:controller];
self.mousePointerView.hidden = isGrabbing;
virtualMouseEnabled = YES;
if([getPreference(@"hardware_hide") boolValue]) {
self.ctrlView.hidden = YES;
}
}];
self.controllerDisconnectCallback = [[NSNotificationCenter defaultCenter] addObserverForName:GCControllerDidDisconnectNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
NSLog(@"Input: Controller disconnected!");
GCController* controller = note.object;
[ControllerInput unregisterControllerCallbacks:controller];
if([getPreference(@"hardware_hide") boolValue]) {
self.ctrlView.hidden = NO;
}
}];
if (GCController.controllers.count == 1) {
[ControllerInput registerControllerCallbacks:GCController.controllers.firstObject];
Expand Down
2 changes: 2 additions & 0 deletions Natives/en.lproj/Localizable.strings
Expand Up @@ -177,6 +177,8 @@

"preference.title.fullscreen_airplay" = "Fullscreen AirPlay";
"preference.detail.fullscreen_airplay" = "Allows presenting fullscreen game window on the external display rather than mirroring everything on screen.";
"preference.title.hardware_hide" = "Hide controls when hardware is connected";
"preference.detail.hardware_hide" = "Enable the behaviour of automatically disabling the on-screen control overlay when a mouse or game controller is connected.";
"preference.title.gesture_mouse" = "Mouse gestures";
"preference.detail.gesture_mouse" = "Enables gestures, such as tap to place block, hold to break block, scrolling with 2 fingers";
"preference.title.gesture_hotbar" = "Hotbar gestures";
Expand Down
Binary file modified Natives/resources/Assets.car
Binary file not shown.

0 comments on commit e96111c

Please sign in to comment.