From 82ff4344f65f91c3536212ecd06934d389b2063e Mon Sep 17 00:00:00 2001 From: Carbon Cowboy <254348425+carboncowboy@users.noreply.github.com> Date: Sat, 31 Jan 2026 21:59:51 -0800 Subject: Add clickable notification for saved screenshots Display notification with filepath after screenshot is saved to disk. Clicking the notification opens the system file browser to reveal the saved file. Fixes #5329 --- indra/llfilesystem/lldir.cpp | 47 ++++++++++++++++++++++++++++++++++++++++++++ indra/llfilesystem/lldir.h | 3 +++ 2 files changed, 50 insertions(+) (limited to 'indra/llfilesystem') diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp index 190539cea5..7d547ca4be 100644 --- a/indra/llfilesystem/lldir.cpp +++ b/indra/llfilesystem/lldir.cpp @@ -44,6 +44,7 @@ #include "stringize.h" #include "llstring.h" #include +#include "llprocess.h" #include #include @@ -1100,6 +1101,52 @@ LLDir::SepOff LLDir::needSep(const std::string& path, const std::string& name) c return SepOff(false, 0); } +void LLDir::openDir(const std::string& filepath) +{ + if (filepath.empty()) + { + LL_WARNS() << "Cannot open file browser: filepath is empty" << LL_ENDL; + return; + } + + // Extract directory path from full filepath + std::string dir_path = getDirName(filepath); + + LLProcess::Params params; + +#if LL_WINDOWS + // Windows: Use explorer.exe with /select flag to highlight the file + std::string system_root = LLStringUtil::getenv("SystemRoot", "C:\\Windows"); + params.executable = system_root + "\\explorer.exe"; + params.args.add("/select,"); + params.args.add(filepath); +#elif LL_DARWIN + // macOS: Use 'open' command with -R flag to reveal in Finder + params.executable = "/usr/bin/open"; + params.args.add("-R"); + params.args.add(filepath); +#elif LL_LINUX + // Linux: Use xdg-open to open the directory + // Note: Most file managers don't support file selection, so we open the directory + params.executable = "/usr/bin/xdg-open"; + params.args.add(dir_path); +#else + LL_WARNS() << "Platform not supported for file browser opening" << LL_ENDL; + return; +#endif + + params.autokill = false; // Don't kill the file browser when viewer exits + + if (!LLProcess::create(params)) + { + LL_WARNS() << "Failed to open file browser for: " << filepath << LL_ENDL; + } + else + { + LL_INFOS() << "Opened file browser for: " << filepath << LL_ENDL; + } +} + void dir_exists_or_crash(const std::string &dir_name) { #if LL_WINDOWS diff --git a/indra/llfilesystem/lldir.h b/indra/llfilesystem/lldir.h index b0d2b6aada..3c8e2e2da6 100644 --- a/indra/llfilesystem/lldir.h +++ b/indra/llfilesystem/lldir.h @@ -194,6 +194,9 @@ class LLDir virtual void dumpCurrentDirectories(LLError::ELevel level = LLError::LEVEL_DEBUG); + // Open the system file browser to reveal a file or directory + void openDir(const std::string& filepath); + // Utility routine std::string buildSLOSCacheDir() const; -- cgit v1.3 From 556728c04a5cfb82ed4f7bd19b9b25b101e127c3 Mon Sep 17 00:00:00 2001 From: Carbon Cowboy <254348425+carboncowboy@users.noreply.github.com> Date: Mon, 2 Feb 2026 17:18:45 -0800 Subject: Improve windir detection in LLDir::openDir --- indra/llfilesystem/lldir.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'indra/llfilesystem') diff --git a/indra/llfilesystem/lldir.cpp b/indra/llfilesystem/lldir.cpp index 7d547ca4be..22bb50074a 100644 --- a/indra/llfilesystem/lldir.cpp +++ b/indra/llfilesystem/lldir.cpp @@ -1116,7 +1116,16 @@ void LLDir::openDir(const std::string& filepath) #if LL_WINDOWS // Windows: Use explorer.exe with /select flag to highlight the file - std::string system_root = LLStringUtil::getenv("SystemRoot", "C:\\Windows"); + std::string system_root = LLStringUtil::getenv("SystemRoot"); + if (system_root.empty()) + { + system_root = LLStringUtil::getenv("WINDIR"); + } + if (system_root.empty()) + { + LL_WARNS() << "Neither SystemRoot nor WINDIR environment variable is set" << LL_ENDL; + system_root = "C:\\Windows"; // Last resort fallback + } params.executable = system_root + "\\explorer.exe"; params.args.add("/select,"); params.args.add(filepath); -- cgit v1.3 From e83f6a291c32d9f3b88660e7770216c83e4f85ff Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev <117672381+akleshchev@users.noreply.github.com> Date: Wed, 11 Feb 2026 05:09:51 +0200 Subject: #5405 Stalls on LLFileSystem::getExists --- indra/llaudio/llaudioengine.cpp | 1 + indra/llfilesystem/llfilesystem.cpp | 18 +++++++----------- indra/newview/llviewerwearable.cpp | 1 + 3 files changed, 9 insertions(+), 11 deletions(-) (limited to 'indra/llfilesystem') diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 613c408157..6f2f7eae61 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -225,6 +225,7 @@ void LLAudioEngine::updateChannels() void LLAudioEngine::idle() { + LL_PROFILE_ZONE_SCOPED_CATEGORY_MEDIA; // "Update" all of our audio sources, clean up dead ones. // Primarily does position updating, cleanup of unused audio sources. // Also does regeneration of the current priority of each audio source. diff --git a/indra/llfilesystem/llfilesystem.cpp b/indra/llfilesystem/llfilesystem.cpp index 541266af4f..728ff396ef 100644 --- a/indra/llfilesystem/llfilesystem.cpp +++ b/indra/llfilesystem/llfilesystem.cpp @@ -77,11 +77,10 @@ bool LLFileSystem::getExists(const LLUUID& file_id, const LLAssetType::EType fil LL_PROFILE_ZONE_SCOPED; const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type); - llifstream file(filename, std::ios::binary); - if (file.is_open()) + boost::system::error_code ec; + if (boost::filesystem::exists(filename, ec) && boost::filesystem::is_regular_file(filename, ec)) { - file.seekg(0, std::ios::end); - return file.tellg() > 0; + return boost::filesystem::file_size(filename, ec) > 0; } return false; } @@ -120,15 +119,12 @@ S32 LLFileSystem::getFileSize(const LLUUID& file_id, const LLAssetType::EType fi { const std::string filename = LLDiskCache::metaDataToFilepath(file_id, file_type); - S32 file_size = 0; - llifstream file(filename, std::ios::binary); - if (file.is_open()) + boost::system::error_code ec; + if (boost::filesystem::exists(filename, ec) && boost::filesystem::is_regular_file(filename, ec)) { - file.seekg(0, std::ios::end); - file_size = (S32)file.tellg(); + return static_cast(boost::filesystem::file_size(filename, ec)); } - - return file_size; + return 0; } bool LLFileSystem::read(U8* buffer, S32 bytes) diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 583fb25330..50af9756a3 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -96,6 +96,7 @@ LLViewerWearable::~LLViewerWearable() // virtual LLWearable::EImportResult LLViewerWearable::importStream( std::istream& input_stream, LLAvatarAppearance* avatarp ) { + LL_PROFILE_ZONE_SCOPED_CATEGORY_AVATAR; // suppress texlayerset updates while wearables are being imported. Layersets will be updated // when the wearables are "worn", not loaded. Note state will be restored when this object is destroyed. LLOverrideBakedTextureUpdate stop_bakes(false); -- cgit v1.3