Make pickerview functional; Rewrite instance manager
This commit is contained in:
1 parent
9c5bea91c8
commit
2a64640c19
6 files changed
+302
-13
No files matched your search
@@ -118,6 +118,7 @@ add_executable(PojavLauncher
|
||||
LauncherPreferences.m
|
||||
LauncherPreferencesViewController.m
|
||||
LauncherPreferencesViewController2.m
|
||||
LauncherPrefGameDirViewController.m
|
||||
LauncherSplitViewController.m
|
||||
LauncherViewController.m
|
||||
LoginViewController.m
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface LauncherPrefGameDirViewController : UITableViewController
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
#import "LauncherPreferences.h"
|
||||
#import "LauncherPrefGameDirViewController.h"
|
||||
#import "TOInsetGroupedTableView.h"
|
||||
#import "ios_uikit_bridge.h"
|
||||
|
||||
@interface LauncherPrefGameDirViewController ()<UITextFieldDelegate>
|
||||
@property NSMutableArray *array;
|
||||
@end
|
||||
|
||||
@implementation LauncherPrefGameDirViewController
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
[self setTitle:NSLocalizedString(@"preference.title.game_directory", nil)];
|
||||
|
||||
self.array = [[NSMutableArray alloc] init];
|
||||
[self.array addObject:@"default"];
|
||||
|
||||
self.tableView = [[TOInsetGroupedTableView alloc] init];
|
||||
self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
|
||||
self.tableView.sectionFooterHeight = 50;
|
||||
|
||||
NSString *path = [NSString stringWithFormat:@"%s/instances", getenv("POJAV_HOME")];
|
||||
|
||||
NSFileManager *fm = NSFileManager.defaultManager;
|
||||
NSArray *files = [fm contentsOfDirectoryAtPath:path error:nil];
|
||||
BOOL isDir;
|
||||
for (NSString *file in files) {
|
||||
[fm fileExistsAtPath:path isDirectory:(&isDir)];
|
||||
if (isDir && ![file isEqualToString:@"default"]) {
|
||||
[self.array addObject:file];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return self.array.count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
UITextField *view;
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
|
||||
if (cell == nil) {
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
|
||||
|
||||
if (indexPath.row == 0) {
|
||||
cell.textLabel.text = self.array[indexPath.row];
|
||||
} else {
|
||||
view = [[UITextField alloc] initWithFrame:CGRectMake(20, 10, cell.bounds.size.width/2, cell.bounds.size.height-20)];
|
||||
[view addTarget:view action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
|
||||
view.autocorrectionType = UITextAutocorrectionTypeNo;
|
||||
view.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
||||
view.autoresizingMask = UIViewAutoresizingFlexibleWidth;
|
||||
view.delegate = self;
|
||||
view.returnKeyType = UIReturnKeyDone;
|
||||
[cell.contentView addSubview:view];
|
||||
}
|
||||
}
|
||||
if (indexPath.row > 0) {
|
||||
view = cell.contentView.subviews.lastObject;
|
||||
view.placeholder = self.array[indexPath.row];
|
||||
view.text = self.array[indexPath.row];
|
||||
}
|
||||
|
||||
if ([getPreference(@"game_directory") isEqualToString:self.array[indexPath.row]]) {
|
||||
cell.accessoryType = UITableViewCellAccessoryCheckmark;
|
||||
} else {
|
||||
cell.accessoryType = UITableViewCellAccessoryNone;
|
||||
}
|
||||
|
||||
// TODO: display size in the detail label
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (UIView *)tableView:(UITableView *)tableView
|
||||
viewForFooterInSection:(NSInteger)section
|
||||
{
|
||||
UITextField *view = [[UITextField alloc] init];
|
||||
[view addTarget:view action:@selector(resignFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
|
||||
view.autocorrectionType = UITextAutocorrectionTypeNo;
|
||||
view.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
||||
view.delegate = self;
|
||||
view.placeholder = @"add game directory";
|
||||
view.returnKeyType = UIReturnKeyDone;
|
||||
return view;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
setPreference(@"game_directory", self.array[indexPath.row]);
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:NO];
|
||||
for (int i = 0; i < self.array.count; i++) {
|
||||
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
|
||||
if (i == indexPath.row) {
|
||||
cell.accessoryType = UITableViewCellAccessoryCheckmark;
|
||||
} else {
|
||||
cell.accessoryType = UITableViewCellAccessoryNone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (UIContextMenuConfiguration *)tableView:(UITableView *)tableView contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point API_AVAILABLE(ios(13.0))
|
||||
{
|
||||
// You can't delete or rename the default instance, though there will be a reset action (TODO)
|
||||
if (indexPath.row == 0) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
if (@available(iOS 13.0, *)) {
|
||||
UIAction *delete = [UIAction actionWithTitle:@"Delete" image:[UIImage systemImageNamed:@"trash"] identifier:@"deleteAction" handler:^(__kindof UIAction * _Nonnull action) {
|
||||
[self actionDeleteAtIndexPath:indexPath];
|
||||
}];
|
||||
delete.attributes = UIMenuElementAttributesDestructive;
|
||||
|
||||
UIAction *rename = [UIAction actionWithTitle:@"Rename" image:[UIImage systemImageNamed:@"pencil"] identifier:@"editAction" handler:^(__kindof UIAction * _Nonnull action) {
|
||||
UITableViewCell *view = [self.tableView cellForRowAtIndexPath:indexPath];
|
||||
[view.contentView.subviews.lastObject becomeFirstResponder];
|
||||
}];
|
||||
|
||||
return [UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:nil actionProvider:^UIMenu * _Nullable(NSArray<UIMenuElement *> * _Nonnull suggestedActions) {
|
||||
return [UIMenu menuWithTitle:self.array[indexPath.row] children:@[delete, rename]];
|
||||
}];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (editingStyle == UITableViewCellEditingStyleDelete) {
|
||||
[self actionDeleteAtIndexPath:indexPath];
|
||||
}
|
||||
}
|
||||
|
||||
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if (indexPath.row == 0) {
|
||||
// TODO: Reset action?
|
||||
return UITableViewCellEditingStyleNone;
|
||||
} else {
|
||||
return UITableViewCellEditingStyleDelete;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)actionDeleteAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
UITableViewCell *view = [self.tableView cellForRowAtIndexPath:indexPath];
|
||||
NSString *title = NSLocalizedString(@"preference.title.confirm", nil);
|
||||
NSString *message = [NSString stringWithFormat:NSLocalizedString(@"preference.title.confirm.delete_game_directory", nil), self.array[indexPath.row]];
|
||||
UIAlertController *confirmAlert = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
confirmAlert.popoverPresentationController.sourceView = view;
|
||||
confirmAlert.popoverPresentationController.sourceRect = view.bounds;
|
||||
UIAlertAction *ok = [UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil) style:UIAlertActionStyleDestructive handler:^(UIAlertAction * _Nonnull action) {
|
||||
NSString *directory = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), self.array[indexPath.row]];
|
||||
NSError *error;
|
||||
if([[NSFileManager defaultManager] removeItemAtPath:directory error:&error]) {
|
||||
if ([getPreference(@"game_directory") isEqualToString:self.array[indexPath.row]]) {
|
||||
setPreference(@"game_directory", self.array[0]);
|
||||
[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]].accessoryType = UITableViewCellAccessoryCheckmark;
|
||||
}
|
||||
[self.array removeObjectAtIndex:indexPath.row];
|
||||
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
|
||||
} else {
|
||||
showDialog(self, NSLocalizedString(@"Error", nil), error.localizedDescription);
|
||||
}
|
||||
}];
|
||||
UIAlertAction *cancel = [UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil];
|
||||
[confirmAlert addAction:cancel];
|
||||
[confirmAlert addAction:ok];
|
||||
[self presentViewController:confirmAlert animated:YES completion:nil];
|
||||
}
|
||||
|
||||
#pragma mark UITextField
|
||||
|
||||
- (void)textFieldDidEndEditing:(UITextField *)sender {
|
||||
BOOL isFooterView = sender.superview == self.tableView;
|
||||
if (!sender.hasText || [sender.text isEqualToString:sender.placeholder]) {
|
||||
if (isFooterView) {
|
||||
return;
|
||||
}
|
||||
sender.text = sender.placeholder;
|
||||
return;
|
||||
}
|
||||
|
||||
NSError *error;
|
||||
|
||||
NSString *dest = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), sender.text];
|
||||
if (isFooterView) {
|
||||
[[NSFileManager defaultManager] createDirectoryAtPath:dest withIntermediateDirectories:NO attributes:nil error:&error];
|
||||
} else {
|
||||
NSString *source = [NSString stringWithFormat:@"%s/instances/%@", getenv("POJAV_HOME"), sender.placeholder];
|
||||
[NSFileManager.defaultManager moveItemAtPath:source toPath:dest error:&error];
|
||||
}
|
||||
|
||||
if (error == nil) {
|
||||
setPreference(@"game_directory", sender.text);
|
||||
if (isFooterView) {
|
||||
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.array.count inSection:0];
|
||||
[self.array addObject:sender.text];
|
||||
[self.tableView beginUpdates];
|
||||
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
|
||||
[self.tableView endUpdates];
|
||||
[self tableView:self.tableView didSelectRowAtIndexPath:indexPath];
|
||||
// Clear text
|
||||
sender.text = @"";
|
||||
} else {
|
||||
int index = [self.array indexOfObject:sender.placeholder];
|
||||
self.array[index] = sender.placeholder = sender.text;
|
||||
}
|
||||
} else {
|
||||
// Restore to the previous name if we encounter an error
|
||||
if (!isFooterView) {
|
||||
sender.text = sender.placeholder;
|
||||
}
|
||||
showDialog(self, NSLocalizedString(@"Error", nil), error.localizedDescription);
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
|
||||
CGRect frame = textField.frame;
|
||||
frame.size.width = MAX(50, textField.intrinsicContentSize.width + 10);
|
||||
textField.frame = frame;
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -4,6 +4,7 @@
|
||||
#import "DBNumberedSlider.h"
|
||||
#import "LauncherPreferences.h"
|
||||
#import "LauncherPreferencesViewController2.h"
|
||||
#import "LauncherPrefGameDirViewController.h"
|
||||
#import "TOInsetGroupedTableView.h"
|
||||
|
||||
#include "utils.h"
|
||||
@@ -14,7 +15,7 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *);
|
||||
@property NSArray<NSString*>* prefSections;
|
||||
@property NSArray<NSArray<NSDictionary*>*>* prefContents;
|
||||
|
||||
@property CreateView typeButton, typePickField, typeTextField, typeSlider, typeSwitch;
|
||||
@property CreateView typeButton, typeChildPane, typePickField, typeTextField, typeSlider, typeSwitch;
|
||||
@end
|
||||
|
||||
@implementation LauncherPreferencesViewController2
|
||||
@@ -35,8 +36,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *);
|
||||
// General settings
|
||||
@{@"key": @"game_directory",
|
||||
@"icon": @"folder",
|
||||
@"type": self.typePickField,
|
||||
@"pickList": @[@"default", @"TODO"]
|
||||
@"type": self.typeChildPane,
|
||||
@"class": LauncherPrefGameDirViewController.class,
|
||||
},
|
||||
@{@"key": @"home_symlink",
|
||||
@"icon": @"link",
|
||||
@@ -73,7 +74,18 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *);
|
||||
@{@"key": @"renderer",
|
||||
@"icon": @"cpu",
|
||||
@"type": self.typePickField,
|
||||
@"pickList": @[@"gl4es", @"zink", @"wip"]
|
||||
@"pickKeys": @[
|
||||
@"auto",
|
||||
@ RENDERER_NAME_GL4ES,
|
||||
@ RENDERER_NAME_MTL_ANGLE,
|
||||
@ RENDERER_NAME_VK_ZINK
|
||||
],
|
||||
@"pickList": @[
|
||||
NSLocalizedString(@"preference.title.renderer.auto", nil),
|
||||
NSLocalizedString(@"preference.title.renderer.gl4es", nil),
|
||||
NSLocalizedString(@"preference.title.renderer.tinygl4angle", nil),
|
||||
NSLocalizedString(@"preference.title.renderer.zink", nil)
|
||||
]
|
||||
},
|
||||
@{@"key": @"resolution",
|
||||
@"icon": @"viewfinder",
|
||||
@@ -171,10 +183,14 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *);
|
||||
- (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
|
||||
if (cell == nil) {
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"cell"];
|
||||
}
|
||||
// Reset cell properties, as it could be reused
|
||||
cell.accessoryType = UITableViewCellAccessoryNone;
|
||||
cell.accessoryView = nil;
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
cell.textLabel.textColor = nil;
|
||||
cell.detailTextLabel.text = nil;
|
||||
|
||||
NSDictionary *item = self.prefContents[indexPath.section][indexPath.row];
|
||||
NSString *key = item[@"key"];
|
||||
@@ -206,11 +222,16 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *);
|
||||
|
||||
self.typeButton = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) {
|
||||
BOOL destructive = [item[@"destructive"] boolValue];
|
||||
cell.accessoryView = nil;
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleGray;
|
||||
cell.textLabel.textColor = destructive ? UIColor.systemRedColor : UIColor.systemBlueColor;
|
||||
};
|
||||
|
||||
self.typeChildPane = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) {
|
||||
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleGray;
|
||||
cell.detailTextLabel.text = getPreference(key);
|
||||
};
|
||||
|
||||
/*
|
||||
self.typePickField = ^void(UITableViewCell *cell, NSString *key, NSDictionary *item) {
|
||||
cell.accessoryView = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width / 2, cell.bounds.size.height)];
|
||||
@@ -238,9 +259,11 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *);
|
||||
UITextField *view = (UITextField *)cell.accessoryView;
|
||||
UIPickerView *picker = [[UIPickerView alloc] init];
|
||||
objc_setAssociatedObject(picker, @"item", item, OBJC_ASSOCIATION_ASSIGN);
|
||||
objc_setAssociatedObject(picker, @"view", cell.accessoryView, OBJC_ASSOCIATION_ASSIGN);
|
||||
picker.delegate = weakSelf;
|
||||
picker.dataSource = weakSelf;
|
||||
[picker reloadAllComponents];
|
||||
[picker selectRow:[item[@"pickKeys"] indexOfObject:getPreference(key)] inComponent:0 animated:NO];
|
||||
UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 0.0, weakSelf.view.frame.size.width, 44.0)];
|
||||
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
|
||||
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:view action:@selector(resignFirstResponder)];
|
||||
@@ -296,7 +319,18 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *);
|
||||
#pragma mark - UIPickerView
|
||||
|
||||
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
|
||||
|
||||
NSDictionary *item = objc_getAssociatedObject(pickerView, @"item");
|
||||
UITextField *view = objc_getAssociatedObject(pickerView, @"view");
|
||||
|
||||
// If there is key, use it
|
||||
if (item[@"pickKeys"] != nil) {
|
||||
view.text = item[@"pickKeys"][row];
|
||||
} else {
|
||||
view.text = item[@"pickList"][row];
|
||||
}
|
||||
|
||||
// Save the preference
|
||||
[self textFieldDidEndEditing:view];
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView {
|
||||
@@ -347,12 +381,25 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *);
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:NO];
|
||||
|
||||
UITableViewCell *view = [self.tableView cellForRowAtIndexPath:indexPath];
|
||||
if (view.selectionStyle == UITableViewCellSelectionStyleNone) {
|
||||
// Ignore if selection style is none
|
||||
return;
|
||||
}
|
||||
NSDictionary *item = self.prefContents[indexPath.section][indexPath.row];
|
||||
|
||||
if (item[@"type"] == self.typeButton) {
|
||||
[self tableView:tableView invokeActionWithPromptAtIndexPath:indexPath];
|
||||
} else if (item[@"type"] == self.typeChildPane) {
|
||||
[self tableView:tableView openChildPaneAtIndexPath:indexPath];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark External UITableView functions
|
||||
|
||||
- (void)tableView:(UITableView *)tableView openChildPaneAtIndexPath:(NSIndexPath *)indexPath {
|
||||
NSDictionary *item = self.prefContents[indexPath.section][indexPath.row];
|
||||
UIViewController *vc = [[item[@"class"] alloc] init];
|
||||
[self.navigationController pushViewController:vc animated:YES];
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView invokeActionWithPromptAtIndexPath:(NSIndexPath *)indexPath {
|
||||
UITableViewCell *view = [self.tableView cellForRowAtIndexPath:indexPath];
|
||||
NSDictionary *item = self.prefContents[indexPath.section][indexPath.row];
|
||||
NSString *key = item[@"key"];
|
||||
|
||||
@@ -390,6 +437,8 @@ typedef void(^CreateView)(UITableViewCell *, NSString *, NSDictionary *);
|
||||
[self showAlertOnView:view title:title message:nil];
|
||||
}
|
||||
|
||||
#pragma mark UITextField
|
||||
|
||||
- (void)textFieldDidEndEditing:(UITextField *)sender {
|
||||
[self checkWarn:sender];
|
||||
NSString *key = objc_getAssociatedObject(sender, @"key");
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
"preference.title.confirm" = "Are you sure?";
|
||||
|
||||
"preference.title.game_directory" = "Minecraft game directory";
|
||||
"preference.title.confirm.delete_game_directory" = "The instance %@ will be deleted forever and cannot be restored.";
|
||||
"preference.title.home_symlink" = "Enable compatibility symlink";
|
||||
"preference.title.check_sha" = "Enable asset verification when launching";
|
||||
"preference.title.cosmetica" = "Enable Cosmetica integration";
|
||||
@@ -85,6 +86,11 @@
|
||||
"preference.title.done.reset_settings" = "All of the default settings have been restored.";
|
||||
|
||||
"preference.title.renderer" = "Game renderer";
|
||||
"preference.title.renderer.auto" = "Auto: gl4es or tinygl4angle";
|
||||
"preference.title.renderer.gl4es" = "gl4es 1.1.4 - exports OpenGL 2.1";
|
||||
"preference.title.renderer.tinygl4angle" = "tinygl4angle (1.17+) - exports OpenGL 3.2 (Core Profile, limited)";
|
||||
"preference.title.renderer.zink" = "Zink (Mesa 21.0) - exports OpenGL 4.1";
|
||||
|
||||
"preference.title.resolution" = "Game resolution";
|
||||
"preference.title.disable_gesture" = "Disable gestures";
|
||||
"preference.title.press_duration" = "Long-press duration";
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@
|
||||
|
||||
#define RENDERER_NAME_GL4ES "libgl4es_114.dylib"
|
||||
#define RENDERER_NAME_MTL_ANGLE "libtinygl4angle.dylib"
|
||||
#define RENDERER_NAME_VK_ZINK "libOSMesaOverride.dylib"
|
||||
#define RENDERER_NAME_VK_ZINK "libOSMesa.8.dylib"
|
||||
|
||||
#define SPECIALBTN_KEYBOARD -1
|
||||
#define SPECIALBTN_TOGGLECTRL -2
|
||||
|
||||
Reference in new issue
Block a user