Merge pull request #16874 from SerenaKit/serena/darwin-browse-button

Browse button on Darwin platforms, rename some classes/functions
This commit is contained in:
Henrik Rydgård 2023-02-01 17:21:53 +01:00 committed by GitHub
commit ce40744cdd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 101 additions and 51 deletions

View file

@ -1150,8 +1150,8 @@ elseif(IOS)
ios/iCade/iCadeReaderView.h
ios/iCade/iCadeReaderView.m
ios/iCade/iCadeState.h
UI/DarwinMemoryStickManager.mm
UI/DarwinMemoryStickManager.h
UI/DarwinFileSystemServices.mm
UI/DarwinFileSystemServices.h
Common/Battery/AppleBatteryClient.m
)
@ -1172,7 +1172,7 @@ elseif(IOS)
set_source_files_properties(ios/main.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
set_source_files_properties(ios/CameraHelper.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
set_source_files_properties(ios/LocationHelper.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
set_source_files_properties(UI/DarwinMemoryStickManager.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
set_source_files_properties(UI/DarwinFileSystemServices.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
set_source_files_properties(Common/Battery/AppleBatteryClient.m PROPERTIES COMPILE_FLAGS -fobjc-arc)
set(TargetBin PPSSPP)
elseif(USING_QT_UI)
@ -1231,8 +1231,8 @@ elseif(TARGET SDL2::SDL2)
endif()
set(nativeExtraLibs ${nativeExtraLibs} SDL2::SDL2)
if(APPLE)
set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm SDL/SDLCocoaMetalLayer.h SDL/SDLCocoaMetalLayer.mm UI/DarwinMemoryStickManager.mm Common/Battery/AppleBatteryClient.m)
set_source_files_properties(UI/DarwinMemoryStickManager.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm SDL/SDLCocoaMetalLayer.h SDL/SDLCocoaMetalLayer.mm UI/DarwinFileSystemServices.mm UI/DarwinFileSystemServices.h Common/Battery/AppleBatteryClient.m)
set_source_files_properties(UI/DarwinFileSystemServices.mm PROPERTIES COMPILE_FLAGS -fobjc-arc)
set_source_files_properties(Common/Battery/AppleBatteryClient.m PROPERTIES COMPILE_FLAGS -fobjc-arc)
set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY} ${IOKIT_LIBRARY})
elseif(USING_EGL)

View file

@ -58,6 +58,9 @@ SDLJoystick *joystick = NULL;
#include "SDLGLGraphicsContext.h"
#include "SDLVulkanGraphicsContext.h"
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
#include "UI/DarwinFileSystemServices.h"
#endif
GlobalUIState lastUIState = UISTATE_MENU;
GlobalUIState GetUIState();
@ -185,7 +188,18 @@ void System_SendMessage(const char *command, const char *parameter) {
} else if (!strcmp(command, "audio_resetDevice")) {
StopSDLAudioDevice();
InitSDLAudioDevice();
}
}
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
else if (!strcmp(command, "browse_folder")) {
DarwinDirectoryPanelCallback callback = [] (Path thePathChosen) {
NativeMessageReceived("browse_folder", thePathChosen.c_str());
};
DarwinFileSystemServices services;
services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectorites = */ true);
}
#endif
}
void System_AskForPermission(SystemPermission permission) {}

View file

@ -1,12 +1,11 @@
//
// DarwinMemoryStickManager.h
// DarwinFileSystemServices.h
// PPSSPP
//
// Created by Serena on 20/01/2023.
//
#ifndef DarwinMemoryStickManager_h
#define DarwinMemoryStickManager_h
#pragma once
#include "ppsspp_config.h"
#include "Common/File/Path.h"
@ -15,15 +14,14 @@
typedef std::function<void (Path)> DarwinDirectoryPanelCallback;
/// A Class to manage the memory stick on Darwin (macOS, iOS) platforms,
/// consisting of meth(od)s to present the directory panel
/// to choose the user preferred memory stick directory,
/// to determine the appropriate memory stick directory,
/// and to *set* the preferred memory stick directory.
class DarwinMemoryStickManager {
/// A Class providing help functions to work with the FileSystem
/// on Darwin platforms.
class DarwinFileSystemServices {
public:
/// Present a pannel to choose the directory as the memory stick manager.
void presentDirectoryPanel(DarwinDirectoryPanelCallback);
void presentDirectoryPanel(DarwinDirectoryPanelCallback,
bool allowFiles = false,
bool allowDirectories = true);
static Path appropriateMemoryStickDirectoryToUse();
static void setUserPreferredMemoryStickDirectory(Path);
@ -34,5 +32,3 @@ private:
void *__pickerDelegate = NULL;
#endif // PPSSPP_PLATFORM(IOS)
};
#endif /* DarwinMemoryStickManager_h */

View file

@ -1,5 +1,5 @@
//
// DarwinMemoryStickManager.mm
// DarwinFileSystemServices.mm
// PPSSPP
//
// Created by Serena on 20/01/2023.
@ -7,12 +7,12 @@
#include "ppsspp_config.h"
#include "Core/Config.h"
#include "DarwinMemoryStickManager.h"
#include "DarwinFileSystemServices.h"
#include <dispatch/dispatch.h>
#include <CoreServices/CoreServices.h>
#if !__has_feature(objc_arc)
#error Must be built with ARC, please revise the flags for DarwinMemoryStickManager.mm to include -fobjc-arc.
#error Must be built with ARC, please revise the flags for DarwinFileSystemServices.mm to include -fobjc-arc.
#endif
#if __has_include(<UIKit/UIKit.h>)
@ -32,10 +32,8 @@
}
- (void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray<NSURL *> *)urls {
// Notice: we could've hardcoded behaviour here to call
// `DarwinMemoryStickManager::setUserPreferredMemoryStickDirectory`
// But for the sake of flexibility in the future, i'll just call a provided callback.
if (urls.count >= 1) self.callback(Path(urls[0].path.UTF8String));
if (urls.count >= 1)
self.callback(Path(urls[0].path.UTF8String));
}
@end
@ -44,36 +42,51 @@
#include <AppKit/AppKit.h>
#endif // __has_include(<UIKit/UIKit.h>)
void DarwinMemoryStickManager::presentDirectoryPanel(DarwinDirectoryPanelCallback callback) {
void DarwinFileSystemServices::presentDirectoryPanel(DarwinDirectoryPanelCallback callback,
bool allowFiles,
bool allowDirectories) {
dispatch_async(dispatch_get_main_queue(), ^{
#if PPSSPP_PLATFORM(MAC)
NSOpenPanel *panel = [[NSOpenPanel alloc] init];
panel.allowsMultipleSelection = NO;
panel.canChooseFiles = NO;
panel.canChooseDirectories = YES;
panel.allowedFileTypes = @[(__bridge NSString *)kUTTypeFolder];
panel.canChooseFiles = allowFiles;
panel.canChooseDirectories = allowDirectories;
// if (!allowFiles && allowDirectories)
// panel.allowedFileTypes = @[(__bridge NSString *)kUTTypeFolder];
NSModalResponse modalResponse = [panel runModal];
if (modalResponse == NSModalResponseOK && panel.URLs && panel.URLs.firstObject)
if (modalResponse == NSModalResponseOK && panel.URLs.firstObject)
callback(Path(panel.URLs.firstObject.path.UTF8String));
#elif PPSSPP_PLATFORM(IOS)
if (UIWindow *window = [UIApplication.sharedApplication keyWindow]) {
if (UIViewController *viewController = window.rootViewController) {
NSString *folderUTType = (__bridge NSString *)kUTTypeFolder;
UIDocumentPickerViewController *pickerVC = [[UIDocumentPickerViewController alloc]
initWithDocumentTypes:@[folderUTType] inMode:UIDocumentPickerModeOpen];
// What if you wanted to go to heaven, but then God showed you the next few lines?
// serious note: have to do this, because __pickerDelegate has to stay retained as a class property
__pickerDelegate = (void *)CFBridgingRetain([[DocumentPickerDelegate alloc] initWithCallback:callback]);
pickerVC.delegate = (__bridge DocumentPickerDelegate *)__pickerDelegate;
[viewController presentViewController:pickerVC animated:true completion:nil];
}
}
UIViewController *rootViewController = UIApplication.sharedApplication
.keyWindow
.rootViewController;
// get current window view controller
if (!rootViewController)
return;
NSMutableArray<NSString *> *types = [NSMutableArray array];
UIDocumentPickerMode pickerMode = UIDocumentPickerModeOpen;
if (allowDirectories)
[types addObject: (__bridge NSString *)kUTTypeFolder];
if (allowFiles) {
[types addObject: (__bridge NSString *)kUTTypeItem];
pickerMode = UIDocumentPickerModeImport;
}
UIDocumentPickerViewController *pickerVC = [[UIDocumentPickerViewController alloc] initWithDocumentTypes: types inMode: pickerMode];
// What if you wanted to go to heaven, but then God showed you the next few lines?
// serious note: have to do this, because __pickerDelegate has to stay retained as a class property
__pickerDelegate = (void *)CFBridgingRetain([[DocumentPickerDelegate alloc] initWithCallback:callback]);
pickerVC.delegate = (__bridge DocumentPickerDelegate *)__pickerDelegate;
[rootViewController presentViewController:pickerVC animated:true completion:nil];
#endif
});
}
Path DarwinMemoryStickManager::appropriateMemoryStickDirectoryToUse() {
Path DarwinFileSystemServices::appropriateMemoryStickDirectoryToUse() {
NSString *userPreferred = [[NSUserDefaults standardUserDefaults] stringForKey:@(PreferredMemoryStickUserDefaultsKey)];
if (userPreferred)
return Path(userPreferred.UTF8String);
@ -81,7 +94,7 @@ Path DarwinMemoryStickManager::appropriateMemoryStickDirectoryToUse() {
return __defaultMemoryStickPath();
}
Path DarwinMemoryStickManager::__defaultMemoryStickPath() {
Path DarwinFileSystemServices::__defaultMemoryStickPath() {
#if PPSSPP_PLATFORM(IOS)
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)
objectAtIndex:0];
@ -91,7 +104,7 @@ Path DarwinMemoryStickManager::__defaultMemoryStickPath() {
#endif
}
void DarwinMemoryStickManager::setUserPreferredMemoryStickDirectory(Path path) {
void DarwinFileSystemServices::setUserPreferredMemoryStickDirectory(Path path) {
[[NSUserDefaults standardUserDefaults] setObject:@(path.c_str())
forKey:@(PreferredMemoryStickUserDefaultsKey)];
g_Config.memStickDirectory = path;

View file

@ -76,7 +76,7 @@
#include "GPU/Common/FramebufferManagerCommon.h"
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
#include "UI/DarwinMemoryStickManager.h"
#include "UI/DarwinFileSystemServices.h"
#endif
#if defined(_WIN32) && !PPSSPP_PLATFORM(UWP)
@ -1228,9 +1228,9 @@ UI::EventReturn GameSettingsScreen::OnJitAffectingSetting(UI::EventParams &e) {
UI::EventReturn GameSettingsScreen::OnChangeMemStickDir(UI::EventParams &e) {
#if PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
DarwinMemoryStickManager memoryStickManager;
DarwinFileSystemServices memoryStickManager;
DarwinDirectoryPanelCallback callback = [] (Path thePathChosen) {
DarwinMemoryStickManager::setUserPreferredMemoryStickDirectory(thePathChosen);
DarwinFileSystemServices::setUserPreferredMemoryStickDirectory(thePathChosen);
};
memoryStickManager.presentDirectoryPanel(callback);

View file

@ -62,6 +62,10 @@
#include "GPU/GPUInterface.h"
#include "Common/Data/Text/I18n.h"
#if PPSSPP_PLATFORM(IOS) || PPSSPP_PLATFORM(MAC)
#include "UI/DarwinFileSystemServices.h" // For the browser
#endif
#include "Core/HLE/sceUmd.h"
bool MainScreen::showHomebrewTab = false;
@ -691,9 +695,15 @@ void GameBrowser::Refresh() {
if (System_GetPropertyBool(SYSPROP_HAS_ADDITIONAL_STORAGE)) {
topBar->Add(new Choice(ImageID("I_SDCARD"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::StorageClick);
}
#if PPSSPP_PLATFORM(IOS) || PPSSPP_PLATFORM(MAC)
// on Darwin, we don't show the 'Browse' text alongside the image
// we show just the image, because we don't need to emphasize the button on Darwin
topBar->Add(new Choice(ImageID("I_FOLDER_OPEN"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::BrowseClick);
#else
if (System_GetPropertyBool(SYSPROP_HAS_FOLDER_BROWSER)) {
topBar->Add(new Choice(mm->T("Browse"), ImageID("I_FOLDER_OPEN"), new LayoutParams(WRAP_CONTENT, 64.0f)))->OnClick.Handle(this, &GameBrowser::BrowseClick);
}
#endif
} else {
topBar->Add(new Spacer(new LinearLayoutParams(FILL_PARENT, 64.0f, 1.0f)));
}

View file

@ -142,7 +142,7 @@
#endif
#if PPSSPP_PLATFORM(IOS) || PPSSPP_PLATFORM(MAC)
#include "UI/DarwinMemoryStickManager.h"
#include "UI/DarwinFileSystemServices.h"
#endif
#include <Core/HLE/Plugins.h>
@ -544,11 +544,11 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
#elif PPSSPP_PLATFORM(IOS)
g_Config.defaultCurrentDirectory = g_Config.internalDataDirectory;
g_Config.memStickDirectory = DarwinMemoryStickManager::appropriateMemoryStickDirectoryToUse();
g_Config.memStickDirectory = DarwinFileSystemServices::appropriateMemoryStickDirectoryToUse();
g_Config.flash0Directory = Path(std::string(external_dir)) / "flash0";
#elif PPSSPP_PLATFORM(MAC)
g_Config.defaultCurrentDirectory = Path(getenv("HOME"));
g_Config.memStickDirectory = DarwinMemoryStickManager::appropriateMemoryStickDirectoryToUse();
g_Config.memStickDirectory = DarwinFileSystemServices::appropriateMemoryStickDirectoryToUse();
g_Config.flash0Directory = Path(std::string(external_dir)) / "flash0";
#elif PPSSPP_PLATFORM(SWITCH)
g_Config.memStickDirectory = g_Config.internalDataDirectory / "config/ppsspp";
@ -1260,6 +1260,15 @@ void HandleGlobalMessage(const std::string &msg, const std::string &value) {
else if (msg == "app_resumed" || msg == "got_focus") {
// Assume that the user may have modified things.
MemoryStick_NotifyWrite();
} else if (msg == "browse_folder") {
Path thePath = Path(value);
File::FileInfo info;
if (!File::GetFileInfo(thePath, &info))
return;
if (info.isDirectory)
NativeMessageReceived("browse_folderSelect", thePath.c_str());
else
NativeMessageReceived("browse_fileSelect", thePath.c_str());
}
}

View file

@ -20,6 +20,7 @@
#include "Common/System/System.h"
#include "Common/StringUtils.h"
#include "Common/Profiler/Profiler.h"
#include "UI/DarwinFileSystemServices.h"
static int (*csops)(pid_t pid, unsigned int ops, void * useraddr, size_t usersize);
static boolean_t (*exc_server)(mach_msg_header_t *, mach_msg_header_t *);
@ -201,6 +202,13 @@ void System_SendMessage(const char *command, const char *parameter) {
g_safeInsetTop = top;
g_safeInsetBottom = bottom;
}
} else if (!strcmp(command, "browse_folder")) {
DarwinDirectoryPanelCallback callback = [] (Path thePathChosen) {
NativeMessageReceived("browse_folder", thePathChosen.c_str());
};
DarwinFileSystemServices services;
services.presentDirectoryPanel(callback, /* allowFiles = */ true, /* allowDirectorites = */ true);
}
}