summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2023-01-25 20:53:01 +0200
committerakleshchev <117672381+akleshchev@users.noreply.github.com>2023-01-27 17:25:18 +0200
commit2398a28af6f6c225c77b77bef422d1d2dec4a2bb (patch)
tree518dd7f9e6bb477d74016e8b787594bf9299e9c1
parente3a90ba4c1b7fffbb27361155dd67f86097f9a4d (diff)
SL-18996 [WIP] MacOS make picker dialogs non-modal to avoid disconnects #1
-rw-r--r--indra/newview/llfilepicker.cpp83
-rw-r--r--indra/newview/llfilepicker.h5
-rw-r--r--indra/newview/llfilepicker_mac.h6
-rw-r--r--indra/newview/llfilepicker_mac.mm68
-rw-r--r--indra/newview/llviewermenufile.cpp73
-rw-r--r--indra/newview/llviewermenufile.h2
6 files changed, 220 insertions, 17 deletions
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 3669fb1eeb..06cb78741e 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -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)
{
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index 04ba4416d7..04adeb8526 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -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
diff --git a/indra/newview/llfilepicker_mac.h b/indra/newview/llfilepicker_mac.h
index e0b7e2e8ce..d6b69bb856 100644
--- a/indra/newview/llfilepicker_mac.h
+++ b/indra/newview/llfilepicker_mac.h
@@ -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,
diff --git a/indra/newview/llfilepicker_mac.mm b/indra/newview/llfilepicker_mac.mm
index 1438e4dc0a..f6892f40fa 100644
--- a/indra/newview/llfilepicker_mac.mm
+++ b/indra/newview/llfilepicker_mac.mm
@@ -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,
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index fdf1d04c09..259ae7c1fb 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -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
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index beeac418d9..7cb2cf0d11 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -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;
};