From 246139fb049c2239c75277474cff313778e5ccbf Mon Sep 17 00:00:00 2001 From: Bartosz Taudul Date: Fri, 21 Aug 2026 20:06:44 +0200 Subject: [PATCH] Show the NFD error message in the file selector failure popup. When the native dialog failed, the popup said "File selector cannot be displayed. Check nfd library implementation for details." but never showed any details: NFD_GetError() was never read, so the actual failure reason (e.g. the xdg-desktop-portal lacking a FileChooser implementation on the session) was invisible and the user was stuck without a way to open or save traces. Capture NFD_GetError() into a static string when NFD_OpenDialogU8_With()/NFD_SaveDialogU8_With() return NFD_ERROR and display it in the popup. The copy is required: the returned pointer references NFD-internal storage (the D-Bus error message or a static buffer) that is overwritten by the next NFD call or cleared on shutdown. In TRACY_NO_FILESELECTOR builds no NFD exists, so the previous fallback line is kept there. The error is shown as a single line (TextUnformatted) rather than wrapped: in an AlwaysAutoResize window the wrap width is derived from the previous frame's window size, which feeds back into the auto-size and oscillates, converging to a narrow multi-line column for a ~110 character D-Bus message. --- profiler/src/main.cpp | 10 +++++++++- profiler/src/profiler/TracyFileselector.cpp | 21 +++++++++++++++++++++ profiler/src/profiler/TracyFileselector.hpp | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/profiler/src/main.cpp b/profiler/src/main.cpp index 6e9efff3..8477a50f 100644 --- a/profiler/src/main.cpp +++ b/profiler/src/main.cpp @@ -1280,7 +1280,15 @@ static void DrawContents() if( ImGui::BeginPopupModal( "File selector is not available", nullptr, ImGuiWindowFlags_AlwaysAutoResize ) ) { ImGui::TextUnformatted( "File selector cannot be displayed." ); - ImGui::TextUnformatted( "Check nfd library implementation for details." ); + if( const auto err = tracy::Fileselector::GetError() ) + { + ImGui::Separator(); + ImGui::TextUnformatted( err ); + } + else + { + ImGui::TextUnformatted( "Check nfd library implementation for details." ); + } ImGui::Separator(); if( ImGui::Button( "Ok" ) ) ImGui::CloseCurrentPopup(); ImGui::EndPopup(); diff --git a/profiler/src/profiler/TracyFileselector.cpp b/profiler/src/profiler/TracyFileselector.cpp index 48be8f2d..bbe811bc 100644 --- a/profiler/src/profiler/TracyFileselector.cpp +++ b/profiler/src/profiler/TracyFileselector.cpp @@ -1,5 +1,6 @@ #include "TracyFileselector.hpp" +#include #ifndef TRACY_NO_FILESELECTOR # ifdef __EMSCRIPTEN__ # include @@ -15,6 +16,7 @@ static bool s_hasFailed = false; #if !defined TRACY_NO_FILESELECTOR && !defined __EMSCRIPTEN__ static nfdwindowhandle_t s_windowHandle; +static std::string s_error; #endif void Init( size_t type, void* handle ) @@ -48,6 +50,15 @@ bool HasFailed() } } +const char* GetError() +{ +#if !defined TRACY_NO_FILESELECTOR && !defined __EMSCRIPTEN__ + return s_error.empty() ? nullptr : s_error.c_str(); +#else + return nullptr; +#endif +} + #ifdef __EMSCRIPTEN__ static std::function s_openFileCallback; @@ -99,6 +110,11 @@ static bool OpenFileImpl( const char* ext, const char* desc, const std::function } else { + if( res == NFD_ERROR ) + { + const auto err = NFD_GetError(); + if( err ) s_error = err; + } return res != NFD_ERROR; } # endif @@ -125,6 +141,11 @@ static bool SaveFileImpl( const char* ext, const char* desc, const std::function } else { + if( res == NFD_ERROR ) + { + const auto err = NFD_GetError(); + if( err ) s_error = err; + } return res != NFD_ERROR; } #endif diff --git a/profiler/src/profiler/TracyFileselector.hpp b/profiler/src/profiler/TracyFileselector.hpp index 25a6ae1b..c51693c8 100644 --- a/profiler/src/profiler/TracyFileselector.hpp +++ b/profiler/src/profiler/TracyFileselector.hpp @@ -10,6 +10,7 @@ namespace tracy::Fileselector void Init( size_t type, void* handle ); void Shutdown(); bool HasFailed(); +const char* GetError(); void OpenFile( const char* ext, const char* desc, const std::function& callback ); void SaveFile( const char* ext, const char* desc, const std::function& callback );