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.
This commit is contained in:
Bartosz Taudul
2026-08-21 20:06:44 +02:00
parent 5257132d97
commit 246139fb04
3 changed files with 31 additions and 1 deletions

View File

@@ -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();

View File

@@ -1,5 +1,6 @@
#include "TracyFileselector.hpp"
#include <string>
#ifndef TRACY_NO_FILESELECTOR
# ifdef __EMSCRIPTEN__
# include <emscripten.h>
@@ -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<void(const char*)> 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

View File

@@ -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<void(const char*)>& callback );
void SaveFile( const char* ext, const char* desc, const std::function<void(const char*)>& callback );