From 8f36798035793196f54d9d2b4c4d5ebe523d64c7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Tue, 2 Jul 2024 15:36:08 +0200 Subject: [PATCH] IO: added io.PlatformOpenInShellFn handler to open a link/folder/file in OS shell, added IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS. (#7660) --- docs/CHANGELOG.txt | 3 +++ imconfig.h | 1 + imgui.cpp | 41 +++++++++++++++++++++++++++++++++++++++-- imgui.h | 7 ++++++- 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a0957c5c8..87038d978 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,9 @@ Breaking changes: Other changes: +- IO: added io.PlatformOpenInShellFn handler to open a link/folder/file in OS shell. (#7660) + Default to use ShellExecute() under Windows, and system("") under Mac/Linux/etc. + Added IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS to disable default implementation. - Debug Tools: Added IMGUI_DEBUG_LOG(), ImGui::DebugLog() in public API. (#5855) Debug log entries add a imgui frame counter prefix + are redirected to ShowDebugLogWindow() and other configurable locations. Always call IMGUI_DEBUG_LOG() for maximum stripping in caller code. diff --git a/imconfig.h b/imconfig.h index 1feaa6edc..62365fb9b 100644 --- a/imconfig.h +++ b/imconfig.h @@ -42,6 +42,7 @@ //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME). //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). +//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default io.PlatformOpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")). //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) diff --git a/imgui.cpp b/imgui.cpp index 239dc228b..0e34267ab 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -1015,7 +1015,7 @@ CODE #endif // [Windows] OS specific includes (optional) -#if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) +#if defined(_WIN32) && defined(IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) && defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) && defined(IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) #define IMGUI_DISABLE_WIN32_FUNCTIONS #endif #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) @@ -1034,6 +1034,7 @@ CODE // The UWP and GDK Win32 API subsets don't support clipboard nor IME functions #define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS #define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS +#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS #endif #endif @@ -1124,6 +1125,7 @@ static void WindowSettingsHandler_WriteAll(ImGuiContext*, ImGuiSetti static const char* GetClipboardTextFn_DefaultImpl(void* user_data_ctx); static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text); static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatformImeData* data); +static void PlatformOpenInShellFn_DefaultImpl(ImGuiContext* ctx, const char* path); namespace ImGui { @@ -1369,6 +1371,7 @@ ImGuiIO::ImGuiIO() // Note: Initialize() will setup default clipboard/ime handlers. BackendPlatformName = BackendRendererName = NULL; BackendPlatformUserData = BackendRendererUserData = BackendLanguageUserData = NULL; + PlatformOpenInShellUserData = NULL; PlatformLocaleDecimalPoint = '.'; // Input (NB: we already have memset zero the entire structure!) @@ -3712,6 +3715,7 @@ void ImGui::Initialize() g.IO.GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations g.IO.SetClipboardTextFn = SetClipboardTextFn_DefaultImpl; g.IO.ClipboardUserData = (void*)&g; // Default implementation use the ImGuiContext as user data (ideally those would be arguments to the function) + g.IO.PlatformOpenInShellFn = PlatformOpenInShellFn_DefaultImpl; g.IO.SetPlatformImeDataFn = SetPlatformImeDataFn_DefaultImpl; // Create default viewport @@ -14200,6 +14204,10 @@ static void ImGui::UpdateViewportsNewFrame() //----------------------------------------------------------------------------- // [SECTION] PLATFORM DEPENDENT HELPERS //----------------------------------------------------------------------------- +// - Default clipboard handlers +// - Default shell function handlers +// - Default IME handlers +//----------------------------------------------------------------------------- #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS) @@ -14325,7 +14333,36 @@ static void SetClipboardTextFn_DefaultImpl(void* user_data_ctx, const char* text g.ClipboardHandlerData[(int)(text_end - text)] = 0; } +#endif // Default clipboard handlers + +//----------------------------------------------------------------------------- + +#if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS) +#include // ShellExecuteA() +#ifdef _MSC_VER +#pragma comment(lib, "shell32") #endif +static void PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char* path) +{ + ::ShellExecuteA(NULL, "open", path, NULL, NULL, SW_SHOWDEFAULT); +} +#elif !defined(IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS)) +static void PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char* path) +{ +#if __APPLE__ + const char* open_executable = "open"; +#else + const char* open_executable = "xdg-open"; +#endif + ImGuiTextBuffer buf; + buf.appendf("%s \"%s\"", open_executable, path); + system(buf.c_str()); +} +#else +static void PlatformOpenInShellFn_DefaultImpl(ImGuiContext*, const char*) {} +#endif // Default shell handlers + +//----------------------------------------------------------------------------- // Win32 API IME support (for Asian languages, etc.) #if defined(_WIN32) && !defined(IMGUI_DISABLE_WIN32_FUNCTIONS) && !defined(IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS) @@ -14363,7 +14400,7 @@ static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport* viewport, ImGuiPlatf static void SetPlatformImeDataFn_DefaultImpl(ImGuiViewport*, ImGuiPlatformImeData*) {} -#endif +#endif // Default IME handlers //----------------------------------------------------------------------------- // [SECTION] METRICS/DEBUGGER WINDOW diff --git a/imgui.h b/imgui.h index 21728df87..20529dd1b 100644 --- a/imgui.h +++ b/imgui.h @@ -28,7 +28,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.91.0 WIP" -#define IMGUI_VERSION_NUM 19091 +#define IMGUI_VERSION_NUM 19092 #define IMGUI_HAS_TABLE /* @@ -2240,6 +2240,11 @@ struct ImGuiIO void (*SetClipboardTextFn)(void* user_data, const char* text); void* ClipboardUserData; + // Optional: Open link/folder/file in OS Shell + // (default to use ShellExecuteA() on Windows, system() on Linux/Mac) + void (*PlatformOpenInShellFn)(ImGuiContext* ctx, const char* path); + void* PlatformOpenInShellUserData; + // Optional: Notify OS Input Method Editor of the screen position of your cursor for text input position (e.g. when using Japanese/Chinese IME on Windows) // (default to use native imm32 api on Windows) void (*SetPlatformImeDataFn)(ImGuiViewport* viewport, ImGuiPlatformImeData* data);