SL-18996 [WIP] MacOS make picker dialogs non-modal to avoid disconnects #1
parent
e3a90ba4c1
commit
2398a28af6
|
|
@ -678,6 +678,30 @@ bool LLFilePicker::doNavChooseDialog(ELoadFilter filter)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool LLFilePicker::doNavChooseDialogModeless(ELoadFilter filter,
|
||||
void (*callback)(bool, std::vector<std::string> &,void*),
|
||||
void *userdata)
|
||||
{
|
||||
// if local file browsing is turned off, return without opening dialog
|
||||
if ( check_local_file_access_enabled() == false )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
gViewerWindow->getWindow()->beforeDialog();
|
||||
|
||||
std::vector<std::string> *allowed_types=navOpenFilterProc(filter);
|
||||
|
||||
doLoadDialogModeless(allowed_types,
|
||||
mPickOptions,
|
||||
callback,
|
||||
userdata);
|
||||
|
||||
gViewerWindow->getWindow()->afterDialog();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LLFilePicker::doNavSaveDialog(ESaveFilter filter, const std::string& filename)
|
||||
{
|
||||
|
||||
|
|
@ -852,18 +876,52 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter, bool blocking)
|
|||
return success;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLFilePicker::getOpenFileModeless(ELoadFilter filter,
|
||||
void (*callback)(bool, std::vector<std::string> &, void*),
|
||||
void *userdata)
|
||||
{
|
||||
if( mLocked )
|
||||
return FALSE;
|
||||
|
||||
// if local file browsing is turned off, return without opening dialog
|
||||
if ( check_local_file_access_enabled() == false )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
mPickOptions &= ~F_MULTIPLE;
|
||||
mPickOptions |= F_FILE;
|
||||
|
||||
if (filter == FFLOAD_DIRECTORY) //This should only be called from lldirpicker.
|
||||
{
|
||||
|
||||
mPickOptions |= ( F_NAV_SUPPORT | F_DIRECTORY );
|
||||
mPickOptions &= ~F_FILE;
|
||||
}
|
||||
|
||||
if (filter == FFLOAD_ALL) // allow application bundles etc. to be traversed; important for DEV-16869, but generally useful
|
||||
{
|
||||
mPickOptions |= F_NAV_SUPPORT;
|
||||
}
|
||||
|
||||
return doNavChooseDialogModeless(filter, callback, userdata);
|
||||
}
|
||||
|
||||
BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking)
|
||||
{
|
||||
if( mLocked )
|
||||
return FALSE;
|
||||
|
||||
BOOL success = FALSE;
|
||||
|
||||
// if local file browsing is turned off, return without opening dialog
|
||||
if ( check_local_file_access_enabled() == false )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
BOOL success = FALSE;
|
||||
|
||||
reset();
|
||||
|
||||
|
|
@ -897,6 +955,27 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter, bool blocking)
|
|||
return success;
|
||||
}
|
||||
|
||||
|
||||
BOOL LLFilePicker::getMultipleOpenFilesModeless( ELoadFilter filter, void (*callback)(bool, std::vector<std::string> &, void*), void *userdata )
|
||||
{
|
||||
if( mLocked )
|
||||
return FALSE;
|
||||
|
||||
// if local file browsing is turned off, return without opening dialog
|
||||
if ( check_local_file_access_enabled() == false )
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
reset();
|
||||
|
||||
mPickOptions |= F_FILE;
|
||||
|
||||
mPickOptions |= F_MULTIPLE;
|
||||
|
||||
return doNavChooseDialogModeless(filter, callback, userdata);
|
||||
}
|
||||
|
||||
BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename, bool blocking)
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -115,7 +115,11 @@ public:
|
|||
// open the dialog. This is a modal operation
|
||||
BOOL getSaveFile( ESaveFilter filter = FFSAVE_ALL, const std::string& filename = LLStringUtil::null, bool blocking = true);
|
||||
BOOL getOpenFile( ELoadFilter filter = FFLOAD_ALL, bool blocking = true );
|
||||
// Todo: implement getOpenFileModeless and getMultipleOpenFilesModeless
|
||||
// for windows and use directly instead of ugly LLFilePickerThread
|
||||
BOOL getOpenFileModeless( ELoadFilter filter, void (*callback)(bool, std::vector<std::string> &, void*), void *userdata); // MAC only.
|
||||
BOOL getMultipleOpenFiles( ELoadFilter filter = FFLOAD_ALL, bool blocking = true );
|
||||
BOOL getMultipleOpenFilesModeless( ELoadFilter filter, void (*callback)(bool, std::vector<std::string> &, void*), void *userdata ); // MAC only
|
||||
|
||||
// Get the filename(s) found. getFirstFile() sets the pointer to
|
||||
// the start of the structure and allows the start of iteration.
|
||||
|
|
@ -166,6 +170,7 @@ private:
|
|||
std::vector<std::string> mFileVector;
|
||||
|
||||
bool doNavChooseDialog(ELoadFilter filter);
|
||||
bool doNavChooseDialogModeless(ELoadFilter filter, void (*callback)(bool, std::vector<std::string>&, void*), void *userdata);
|
||||
bool doNavSaveDialog(ESaveFilter filter, const std::string& filename);
|
||||
std::vector<std::string>* navOpenFilterProc(ELoadFilter filter);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -41,6 +41,12 @@
|
|||
//void modelessPicker();
|
||||
std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types,
|
||||
unsigned int flags);
|
||||
|
||||
void doLoadDialogModeless(const std::vector<std::string>* allowed_types,
|
||||
unsigned int flags,
|
||||
void (*callback)(bool, std::vector<std::string>&, void*),
|
||||
void *userdata);
|
||||
|
||||
std::string* doSaveDialog(const std::string* file,
|
||||
const std::string* type,
|
||||
const std::string* creator,
|
||||
|
|
|
|||
|
|
@ -29,27 +29,22 @@
|
|||
#include <iostream>
|
||||
#include "llfilepicker_mac.h"
|
||||
|
||||
std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types,
|
||||
unsigned int flags)
|
||||
NSOpenPanel *init_panel(const std::vector<std::string>* allowed_types, unsigned int flags)
|
||||
{
|
||||
int i, result;
|
||||
|
||||
//Aura TODO: We could init a small window and release it at the end of this routine
|
||||
//for a modeless interface.
|
||||
int i;
|
||||
|
||||
NSOpenPanel *panel = [NSOpenPanel openPanel];
|
||||
//NSString *fileName = nil;
|
||||
NSMutableArray *fileTypes = nil;
|
||||
|
||||
|
||||
if ( allowed_types && !allowed_types->empty())
|
||||
if ( allowed_types && !allowed_types->empty())
|
||||
{
|
||||
fileTypes = [[NSMutableArray alloc] init];
|
||||
|
||||
for (i=0;i<allowed_types->size();++i)
|
||||
{
|
||||
[fileTypes addObject:
|
||||
[NSString stringWithCString:(*allowed_types)[i].c_str()
|
||||
[fileTypes addObject:
|
||||
[NSString stringWithCString:(*allowed_types)[i].c_str()
|
||||
encoding:[NSString defaultCStringEncoding]]];
|
||||
}
|
||||
}
|
||||
|
|
@ -62,21 +57,30 @@ std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_t
|
|||
[panel setCanChooseFiles: ( (flags & F_FILE)?true:false )];
|
||||
[panel setTreatsFilePackagesAsDirectories: ( flags & F_NAV_SUPPORT ) ];
|
||||
|
||||
std::vector<std::string>* outfiles = NULL;
|
||||
|
||||
if (fileTypes)
|
||||
{
|
||||
[panel setAllowedFileTypes:fileTypes];
|
||||
result = [panel runModal];
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
// I suggest it's better to open the last path and let this default to home dir as necessary
|
||||
// for consistency with other OS X apps
|
||||
//
|
||||
//[panel setDirectoryURL: fileURLWithPath(NSHomeDirectory()) ];
|
||||
result = [panel runModal];
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_types,
|
||||
unsigned int flags)
|
||||
{
|
||||
int result;
|
||||
|
||||
NSOpenPanel *panel = init_panel(allowed_types,flags);
|
||||
|
||||
result = [panel runModal];
|
||||
|
||||
std::vector<std::string>* outfiles = NULL;
|
||||
|
||||
if (result == NSOKButton)
|
||||
{
|
||||
|
|
@ -97,6 +101,40 @@ std::vector<std::string>* doLoadDialog(const std::vector<std::string>* allowed_t
|
|||
return outfiles;
|
||||
}
|
||||
|
||||
void doLoadDialogModeless(const std::vector<std::string>* allowed_types,
|
||||
unsigned int flags,
|
||||
void (*callback)(bool, std::vector<std::string> &, void*),
|
||||
void *userdata)
|
||||
{
|
||||
// Note: might need to return and save this panel
|
||||
// so that it does not close immediately
|
||||
NSOpenPanel *panel = init_panel(allowed_types,flags);
|
||||
|
||||
[panel beginWithCompletionHandler:^(NSModalResponse result)
|
||||
{
|
||||
if (result == NSOKButton)
|
||||
{
|
||||
std::vector<std::string> outfiles;
|
||||
NSArray *filesToOpen = [panel URLs];
|
||||
int i, count = [filesToOpen count];
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
|
||||
for (i=0; i<count; i++) {
|
||||
NSString *aFile = [[filesToOpen objectAtIndex:i] path];
|
||||
std::string *afilestr = new std::string([aFile UTF8String]);
|
||||
outfiles.push_back(*afilestr);
|
||||
}
|
||||
callback(true, outfiles, userdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
callback(false, outfiles, userdata);
|
||||
}
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
std::string* doSaveDialog(const std::string* file,
|
||||
const std::string* type,
|
||||
|
|
|
|||
|
|
@ -124,6 +124,16 @@ void LLFilePickerThread::getFile()
|
|||
{
|
||||
#if LL_WINDOWS
|
||||
start();
|
||||
#elif LL_DARWIN
|
||||
if (!mIsSaveDialog)
|
||||
{
|
||||
runModeless();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Todo: implement Modeless
|
||||
run();
|
||||
}
|
||||
#else
|
||||
run();
|
||||
#endif
|
||||
|
|
@ -166,7 +176,70 @@ void LLFilePickerThread::run()
|
|||
LLMutexLock lock(sMutex);
|
||||
sDeadQ.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFilePickerThread::runModeless()
|
||||
{
|
||||
BOOL result = FALSE;
|
||||
LLFilePicker picker;
|
||||
|
||||
if (mIsSaveDialog)
|
||||
{
|
||||
// TODO: not implemented
|
||||
/*if (picker.getSaveFile(mSaveFilter, mProposedName, blocking))
|
||||
{
|
||||
mResponses.push_back(picker.getFirstFile());
|
||||
}*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mIsGetMultiple)
|
||||
{
|
||||
result = picker.getMultipleOpenFilesModeless(mLoadFilter, modelessCallback, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = picker.getOpenFileModeless(mLoadFilter, modelessCallback, this);
|
||||
}
|
||||
}
|
||||
|
||||
if (!result)
|
||||
{
|
||||
LLMutexLock lock(sMutex);
|
||||
sDeadQ.push(this);
|
||||
}
|
||||
}
|
||||
|
||||
void LLFilePickerThread::modelessCallback(bool result,
|
||||
std::vector<std::string> &responses,
|
||||
void *user_data)
|
||||
{
|
||||
LLFilePickerThread *picker = (LLFilePickerThread*)user_data;
|
||||
if (result)
|
||||
{
|
||||
if (picker->mIsGetMultiple)
|
||||
{
|
||||
picker->mResponses = responses;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<std::string>::iterator iter = responses.begin();
|
||||
while (iter != responses.end())
|
||||
{
|
||||
if (!iter->empty())
|
||||
{
|
||||
picker->mResponses.push_back(*iter);
|
||||
break;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
LLMutexLock lock(sMutex);
|
||||
sDeadQ.push(picker);
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
|
|||
|
|
@ -105,6 +105,8 @@ public:
|
|||
void getFile();
|
||||
|
||||
virtual void run();
|
||||
void runModeless();
|
||||
static void modelessCallback(bool result, std::vector<std::string> &responses, void *user_data);
|
||||
|
||||
virtual void notify(const std::vector<std::string>& filenames) = 0;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue