From ccde514bdb357ecb88a9624baf74d6d2a4bf52fc Mon Sep 17 00:00:00 2001 From: Bruno Lopes Date: Fri, 31 Oct 2025 13:25:43 -0300 Subject: [PATCH] libgimp: Output CLI messages to the parent console like Linux and macOS Closes: #15192 and #7413. Maybe helps with #3603 too. Loosely based on https://github.com/endlessm/rufus/blob/master/src/rufus.c The input is right now clunky, needs to use proper API to halt input and get CTRL+C in the future, but output on terminal is a big plus that pays off. (cherry picked from commit 9e795acba707eb0d1b67dcf1c59a103360aeda49) --- app-tools/gimp-debug-tool.c | 18 +++++++++++++-- app-tools/meson.build | 1 + app/main.c | 44 +++++++++++++------------------------ libgimp/gimp.c | 8 +++++++ meson.build | 12 ---------- meson_options.txt | 1 - 6 files changed, 40 insertions(+), 44 deletions(-) diff --git a/app-tools/gimp-debug-tool.c b/app-tools/gimp-debug-tool.c index da6f862f99..ef726aedc3 100644 --- a/app-tools/gimp-debug-tool.c +++ b/app-tools/gimp-debug-tool.c @@ -25,6 +25,8 @@ * So we call instead a separate program, then exit. */ +#include "config.h" + #include #include #include @@ -34,6 +36,9 @@ #include #include #include +#ifdef G_OS_WIN32 +#include +#endif #include @@ -56,10 +61,19 @@ main (int argc, gchar *error; GtkWidget *dialog; +#ifdef G_OS_WIN32 + if (AttachConsole (ATTACH_PARENT_PROCESS) != 0) + { + freopen ("CONOUT$", "w", stdout); + freopen ("CONOUT$", "w", stderr); + _flushall (); + } +#endif + if (argc != 6 && argc != 8) { - g_print ("Usage: gimp-debug-tool-2.0 [PROGRAM] [PID] [REASON] [MESSAGE] [BT_FILE] " - "([LAST_VERSION] [RELEASE_TIMESTAMP])\n"); + g_print ("Usage: gimp-debug-tool-%s [PROGRAM] [PID] [REASON] [MESSAGE] [BT_FILE] " + "([LAST_VERSION] [RELEASE_TIMESTAMP])\n", GIMP_APP_VERSION); exit (EXIT_FAILURE); } diff --git a/app-tools/meson.build b/app-tools/meson.build index a78fe5aaae..e94b6e706f 100644 --- a/app-tools/meson.build +++ b/app-tools/meson.build @@ -19,6 +19,7 @@ gimp_debug_tool = executable('gimp-debug-tool' + exec_ver, libappwidgets, libgimpbase, ], + win_subsystem: 'windows', install: true, install_dir: gimp_debug_tool_dir ) diff --git a/app/main.c b/app/main.c index 44a96b56b9..b0631c5e83 100644 --- a/app/main.c +++ b/app/main.c @@ -116,9 +116,9 @@ static void gimp_init_i18n (void); static void gimp_init_malloc (void); #if defined (G_OS_WIN32) && !defined (GIMP_CONSOLE_COMPILATION) -static void gimp_open_console_window (void); +static void gimp_attach_console_window (void); #else -#define gimp_open_console_window() /* as nothing */ +#define gimp_attach_console_window() /* as nothing */ #endif static const gchar *system_gimprc = NULL; @@ -562,9 +562,7 @@ main (int argc, gint retval; gint i; -#ifdef ENABLE_WIN32_DEBUG_CONSOLE - gimp_open_console_window (); -#endif + gimp_attach_console_window (); #if defined(ENABLE_RELOCATABLE_RESOURCES) && defined(__APPLE__) /* remove MacOS session identifier from the command line args */ @@ -748,7 +746,7 @@ main (int argc, (strcmp (arg, "-?") == 0) || (strncmp (arg, "--help-", 7) == 0)) { - gimp_open_console_window (); + gimp_attach_console_window (); } #endif } @@ -780,7 +778,7 @@ main (int argc, { if (error) { - gimp_open_console_window (); + gimp_attach_console_window (); g_print ("%s\n", error->message); g_error_free (error); } @@ -844,7 +842,7 @@ main (int argc, #endif if (no_interface || be_verbose || console_messages || batch_commands != NULL) - gimp_open_console_window (); + gimp_attach_console_window (); if (no_interface) new_instance = TRUE; @@ -943,29 +941,17 @@ WinMain (struct HINSTANCE__ *hInstance, static void wait_console_window (void) { - FILE *console = g_fopen ("CONOUT$", "w"); - - SetConsoleTitleW (g_utf8_to_utf16 (_("GIMP output. Type any character to close this window."), -1, NULL, NULL, NULL)); - fprintf (console, _("(Type any character to close this window)\n")); - fflush (console); - _getch (); + g_print (_ ("(Type any character to close this window)\n")); } static void -gimp_open_console_window (void) +gimp_attach_console_window (void) { - if (((HANDLE) _get_osfhandle (fileno (stdout)) == INVALID_HANDLE_VALUE || - (HANDLE) _get_osfhandle (fileno (stderr)) == INVALID_HANDLE_VALUE) && AllocConsole ()) + if (AttachConsole (ATTACH_PARENT_PROCESS) != 0) { - if ((HANDLE) _get_osfhandle (fileno (stdout)) == INVALID_HANDLE_VALUE) - freopen ("CONOUT$", "w", stdout); - - if ((HANDLE) _get_osfhandle (fileno (stderr)) == INVALID_HANDLE_VALUE) - freopen ("CONOUT$", "w", stderr); - - SetConsoleTitleW (g_utf8_to_utf16 (_("GIMP output. You can minimize " - "this window, but don't close " - "it."), -1, NULL, NULL, NULL)); + freopen ("CONOUT$", "w", stdout); + freopen ("CONOUT$", "w", stderr); + _flushall (); atexit (wait_console_window); } @@ -1035,7 +1021,7 @@ gimp_option_dump_gimprc (const gchar *option_name, { GimpConfigDumpFormat format = GIMP_CONFIG_DUMP_NONE; - gimp_open_console_window (); + gimp_attach_console_window (); if (strcmp (option_name, "--dump-gimprc") == 0) format = GIMP_CONFIG_DUMP_GIMPRC; @@ -1107,7 +1093,7 @@ gimp_option_dump_pdb_procedures_deprecated (const gchar *option_name, static void gimp_show_version_and_exit (void) { - gimp_open_console_window (); + gimp_attach_console_window (); gimp_version_show (be_verbose); app_exit (EXIT_SUCCESS); @@ -1116,7 +1102,7 @@ gimp_show_version_and_exit (void) static void gimp_show_license_and_exit (void) { - gimp_open_console_window (); + gimp_attach_console_window (); gimp_version_show (be_verbose); g_print ("\n%s\n\n", GIMP_LICENSE); diff --git a/libgimp/gimp.c b/libgimp/gimp.c index 9afb52ef52..93cf12b8a2 100644 --- a/libgimp/gimp.c +++ b/libgimp/gimp.c @@ -200,6 +200,14 @@ gimp_main (GType plug_in_type, gint i, j, k; + /* Make plugins output available on console */ + if (AttachConsole (ATTACH_PARENT_PROCESS) != 0) + { + freopen ("CONOUT$", "w", stdout); + freopen ("CONOUT$", "w", stderr); + _flushall (); + } + /* Reduce risks */ SetDllDirectoryW (L""); diff --git a/meson.build b/meson.build index d018f26c99..454c754d06 100644 --- a/meson.build +++ b/meson.build @@ -620,18 +620,6 @@ appstream = dependency('appstream', version: '>='+appstream_minver) libarchive = dependency('libarchive') - -################################################################################ -# Check for debug console (Win32) - -if platform_windows - enable_win32_debug_console = get_option('win32-debug-console').enabled() or \ - (get_option('win32-debug-console').auto() and (not stable or not release)) - conf.set('ENABLE_WIN32_DEBUG_CONSOLE', enable_win32_debug_console) - # When we'll depend on meson >= 1.1.0, we can just use: - # conf.set('ENABLE_WIN32_DEBUG_CONSOLE', get_option('win32-debug-console').enable_auto_if(not stable or not release).enabled()) -endif - ################################################################################ # Check for 32-bit DLLs (Win32 64-bit) diff --git a/meson_options.txt b/meson_options.txt index 1266292337..778e7161d7 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,7 +1,6 @@ # Build properties option('ansi', type: 'boolean', value: false, description: 'Turn on strict ansi') option('enable-console-bin',type: 'boolean', value: true, description: 'Build a console-only binary which does not link GTK') -option('win32-debug-console',type:'feature', value: 'auto', description: 'Open a console when starting the program') option('enable-multiproc', type: 'boolean', value: true, description: 'Support for multiple processors') option('profiling', type: 'boolean', value: false, description: 'Enable profiling') option('windows-installer', type: 'boolean', value: false, description: 'Generate files needed for the Inno Windows installer')