diff --git a/src/common/darktable.c b/src/common/darktable.c index 9a48b38bc72d..1ac35ea0bf2c 100644 --- a/src/common/darktable.c +++ b/src/common/darktable.c @@ -1616,7 +1616,7 @@ int dt_init(int argc, if(init_gui) { - darktable_splash_screen_create(NULL, FALSE); + dt_splash_screen_create(FALSE); } // detect cpu features and decide which codepaths to enable @@ -1629,12 +1629,12 @@ int dt_init(int argc, dt_datetime_init(); // initialize the database - darktable_splash_screen_set_progress(_("opening image library")); + dt_splash_screen_set_progress(_("opening image library")); darktable.db = dt_database_init(dbfilename_from_command, load_data, init_gui); if(darktable.db == NULL) { dt_print(DT_DEBUG_ALWAYS, "ERROR : cannot open database"); - darktable_splash_screen_destroy(); + dt_splash_screen_destroy(); return 1; } else if(!dt_database_get_lock_acquired(darktable.db)) @@ -1642,7 +1642,7 @@ int dt_init(int argc, gboolean image_loaded_elsewhere = FALSE; if(init_gui && argc > 1) { - darktable_splash_screen_set_progress(_("forwarding image(s) to running instance")); + dt_splash_screen_set_progress(_("forwarding image(s) to running instance")); // send the images to the other instance via dbus dt_print(DT_DEBUG_ALWAYS, @@ -1666,22 +1666,22 @@ int dt_init(int argc, } if(connection) g_object_unref(connection); } - darktable_splash_screen_destroy(); // dismiss splash screen before potentially showing error dialog + dt_splash_screen_destroy(); // dismiss splash screen before potentially showing error dialog if(!image_loaded_elsewhere && init_gui) dt_database_show_error(darktable.db); dt_print(DT_DEBUG_ALWAYS, "ERROR: can't acquire database lock, aborting."); return 1; } - darktable_splash_screen_set_progress(_("preparing database")); + dt_splash_screen_set_progress(_("preparing database")); dt_upgrade_maker_model(darktable.db); // init darktable tags table - darktable_splash_screen_set_progress(_("setting up tags table")); + dt_splash_screen_set_progress(_("setting up tags table")); dt_set_darktable_tags(); // Initialize the signal system - darktable_splash_screen_set_progress(_("initializing signals and control")); + dt_splash_screen_set_progress(_("initializing signals and control")); darktable.signals = dt_control_signal_init(); dt_control_init(init_gui); @@ -1700,7 +1700,7 @@ int dt_init(int argc, if(styledir) { dt_gui_process_events(); - darktable_splash_screen_set_progress(_("importing default styles")); + dt_splash_screen_set_progress(_("importing default styles")); dt_import_default_styles(styledir); g_free(styledir); } @@ -1720,14 +1720,15 @@ int dt_init(int argc, { if(dt_conf_get_bool("run_crawler_on_start") && !dt_gimpmode()) { - darktable_splash_screen_create(NULL, TRUE); // force the splash screen for the crawl even if user-disabled + dt_splash_screen_allow_create(TRUE); // allow splash screen if a message is to be displayed // scan for cases where the database and xmp files have different timestamps changed_xmp_files = dt_control_crawler_run(); if(!dt_conf_get_bool("show_splash_screen")) { - darktable_splash_screen_destroy(); + dt_splash_screen_destroy(); dt_gui_process_events(); // ensure that the splash screen is removed right away } + dt_splash_screen_allow_create(FALSE); // allow splash screen if a message is to be displayed } } @@ -1800,7 +1801,7 @@ int dt_init(int argc, darktable.guides = dt_guides_init(); #ifdef HAVE_GRAPHICSMAGICK - darktable_splash_screen_set_progress(_("initializing GraphicsMagick")); + dt_splash_screen_set_progress(_("initializing GraphicsMagick")); /* GraphicsMagick init */ #ifndef MAGICK_OPT_NO_SIGNAL_HANDER InitializeMagick(darktable.progname); @@ -1812,16 +1813,16 @@ int dt_init(int argc, #endif #elif defined HAVE_IMAGEMAGICK /* ImageMagick init */ - darktable_splash_screen_set_progress(_("initializing ImageMagick")); + dt_splash_screen_set_progress(_("initializing ImageMagick")); MagickWandGenesis(); #endif #ifdef HAVE_LIBHEIF - darktable_splash_screen_set_progress(_("initializing libheif")); + dt_splash_screen_set_progress(_("initializing libheif")); heif_init(NULL); #endif - darktable_splash_screen_set_progress(_("starting OpenCL")); + dt_splash_screen_set_progress(_("starting OpenCL")); darktable.opencl = (dt_opencl_t *)calloc(1, sizeof(dt_opencl_t)); if(init_gui) dt_control_add_job(DT_JOB_QUEUE_SYSTEM_BG, _detect_opencl_job_create(exclude_opencl)); @@ -1833,7 +1834,7 @@ int dt_init(int argc, dt_wb_presets_init(NULL); - darktable_splash_screen_set_progress(_("loading noise profiles")); + dt_splash_screen_set_progress(_("loading noise profiles")); darktable.noiseprofile_parser = dt_noiseprofile_init(noiseprofiles_from_command); // must come before mipmap_cache, because that one will need to access @@ -1850,14 +1851,14 @@ int dt_init(int argc, dt_metadata_init(); dt_pthread_mutex_unlock(&darktable.metadata_threadsafe); - darktable_splash_screen_set_progress(_("synchronizing local copies")); + dt_splash_screen_set_progress(_("synchronizing local copies")); dt_image_local_copy_synch(); #ifdef HAVE_GPHOTO2 // Initialize the camera control. this is done late so that the // gui can react to the signal sent but before switching to // lighttable! - darktable_splash_screen_set_progress(_("initializing camera control")); + dt_splash_screen_set_progress(_("initializing camera control")); darktable.camctl = dt_camctl_new(); #endif @@ -1867,11 +1868,11 @@ int dt_init(int argc, if(init_gui) { - darktable_splash_screen_set_progress(_("initializing GUI")); + dt_splash_screen_set_progress(_("initializing GUI")); if(dt_gui_gtk_init(darktable.gui)) { dt_print(DT_DEBUG_ALWAYS, "[dt_init] ERROR: can't init gui, aborting."); - darktable_splash_screen_destroy(); + dt_splash_screen_destroy(); return 1; } dt_bauhaus_init(); @@ -1893,11 +1894,11 @@ int dt_init(int argc, if(!darktable.develop) { dt_print(DT_DEBUG_ALWAYS, "[dt_init] ERROR: can't init develop system, aborting."); - darktable_splash_screen_destroy(); + dt_splash_screen_destroy(); return 1; } - darktable_splash_screen_set_progress(_("loading processing modules")); + dt_splash_screen_set_progress(_("loading processing modules")); darktable.imageio = (dt_imageio_t *)calloc(1, sizeof(dt_imageio_t)); dt_imageio_init(darktable.imageio); @@ -1911,7 +1912,7 @@ int dt_init(int argc, if(dt_ioppr_check_so_iop_order(darktable.iop, darktable.iop_order_list)) { dt_print(DT_DEBUG_ALWAYS, "[dt_init] ERROR: iop order looks bad, aborting."); - darktable_splash_screen_destroy(); + dt_splash_screen_destroy(); return 1; } @@ -1932,20 +1933,20 @@ int dt_init(int argc, if(init_gui) { - darktable_splash_screen_set_progress(_("loading utility modules")); + dt_splash_screen_set_progress(_("loading utility modules")); darktable.lib = (dt_lib_t *)calloc(1, sizeof(dt_lib_t)); dt_lib_init(darktable.lib); // init the gui part of views - darktable_splash_screen_set_progress(_("loading views")); + dt_splash_screen_set_progress(_("loading views")); dt_view_manager_gui_init(darktable.view_manager); } /* init lua last, since it's user made stuff it must be in the real environment */ #ifdef USE_LUA - darktable_splash_screen_set_progress(_("initializing Lua")); + dt_splash_screen_set_progress(_("initializing Lua")); // after the following Lua startup call, we can no longer use dt_gui_process_events() or we hang; - // this also means no more calls to darktable_splash_screen_set_progress() + // this also means no more calls to dt_splash_screen_set_progress() dt_lua_init(darktable.lua_state.state, lua_command); #endif @@ -1975,7 +1976,7 @@ int dt_init(int argc, { // If only one image is listed, attempt to load it in darkroom #ifndef USE_LUA // may cause UI hang since after LUA init - darktable_splash_screen_set_progress(_("importing image")); + dt_splash_screen_set_progress(_("importing image")); #endif dt_load_from_string(argv[1], TRUE, NULL); } @@ -2034,7 +2035,7 @@ int dt_init(int argc, // show the main window and restore its geometry to that saved in the config file gtk_widget_show_all(dt_ui_main_window(darktable.gui->ui)); dt_gui_gtk_load_config(); - darktable_splash_screen_destroy(); + dt_splash_screen_destroy(); // finally set the cursor to be the default. // for some reason this is needed on some systems to pick up the correctly themed cursor @@ -2094,7 +2095,7 @@ void dt_cleanup() const gboolean init_gui = (darktable.gui != NULL); // if(init_gui) -// darktable_exit_screen_create(NULL, FALSE); +// darktable_exit_screen_create(NULL); dt_stop_backthumbs_crawler(TRUE); @@ -2275,7 +2276,7 @@ void dt_cleanup() dt_exif_cleanup(); if(init_gui) - darktable_exit_screen_destroy(); + dt_exit_screen_destroy(); } /* The dt_print variations can be used with a combination of DT_DEBUG_ flags. diff --git a/src/control/crawler.c b/src/control/crawler.c index f5bec053640a..c0fbdc6bdc71 100644 --- a/src/control/crawler.c +++ b/src/control/crawler.c @@ -106,7 +106,7 @@ static void _set_modification_time(char *filename, if(info) g_clear_object(&info); } -// pregress update intervals in seconds +// progress update intervals in seconds #define FAST_UPDATE 0.2 #define SLOW_UPDATE 1.0 @@ -159,14 +159,15 @@ GList *dt_control_crawler_run(void) int flags = sqlite3_column_int(stmt, 4); ++image_count; - // update the progress message - five times per second for first four seconds, then once per second + // update the progress message - five times per second for first + // four seconds, then once per second. const double curr_time = dt_get_wtime(); if(curr_time >= last_time + ((curr_time - start_time > 4.0) ? SLOW_UPDATE : FAST_UPDATE)) { const double fraction = image_count / (double)total_images; - darktable_splash_screen_set_progress_percent(_("checking for updated sidecar files (%d%%)"), - fraction, - curr_time - start_time); + dt_splash_screen_set_progress_percent(_("checking for updated sidecar files (%d%%)"), + fraction, + curr_time - start_time); last_time = curr_time; } diff --git a/src/gui/gtk.c b/src/gui/gtk.c index 7816660a01d8..0d7ca5d765e1 100644 --- a/src/gui/gtk.c +++ b/src/gui/gtk.c @@ -1,6 +1,6 @@ /* This file is part of darktable, - Copyright (C) 2009-2025 darktable developers. + Copyright (C) 2009-2026 darktable developers. darktable is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -3083,7 +3083,7 @@ gboolean dt_gui_show_standalone_yes_no_dialog(const char *title, gtk_widget_show_all(window); // to prevent the splash screen from hiding the yes/no dialog - darktable_splash_screen_destroy(); + dt_splash_screen_destroy(); gtk_window_set_keep_above(GTK_WINDOW(window), TRUE); gtk_main(); diff --git a/src/gui/splash.c b/src/gui/splash.c index 57f10dade8b8..5c397b3b8271 100644 --- a/src/gui/splash.c +++ b/src/gui/splash.c @@ -1,6 +1,6 @@ /* This file is part of darktable, - Copyright (C) 2024-2025 darktable developers. + Copyright (C) 2024-2026 darktable developers. darktable is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -51,6 +51,30 @@ static GtkWidget *remaining_box = NULL; static GtkWidget *exit_screen = NULL; +static gboolean create_if_needed = FALSE; + +/* + SPLASH_DEBUG + 1 : don't splash create + 2 : force splash_screen reset to NULL + 3 : force no output + */ +#define DTS_NO_CREATE 1 +#define DTS_RESET_NULL 2 +#define DTS_NO_PROGRESS 4 +#define DTS_NO_DESTROY 8 +static int _d_level() +{ + const gchar *v = g_getenv ("SPLASH_DEBUG"); + int l = 0; + + if(v) + { + l = atoi(v); + } + return l; +} + static void _process_all_gui_events() { // give Gtk a chance to update the screen; we need to let the event @@ -126,9 +150,25 @@ static void _set_header_bar(GtkWidget *dialog) #endif } -void darktable_splash_screen_create(GtkWindow *parent_window, - const gboolean force) +void dt_splash_screen_allow_create(const gboolean allow_create) { + printf("[dt_splash_screen_allow_create] (%d)\n", allow_create); + create_if_needed = allow_create; +} + +void dt_splash_screen_create(const gboolean force) +{ + printf("[dt_splash_screen_create] (force:%d) (%lx)\n", force, (size_t)splash_screen); + + if(_d_level() & DTS_RESET_NULL && !force) + { + printf(" reset\n"); + splash_screen = NULL; + } + if(_d_level() & DTS_NO_CREATE) + { + return; + } // no-op if the splash has already been created; if not, only run if // the splash screen is enabled in the config or we are told to // create it regardless. @@ -137,9 +177,12 @@ void darktable_splash_screen_create(GtkWindow *parent_window, || dt_check_gimpmode("thumb") || (!dt_conf_get_bool("show_splash_screen") && !force)) { + printf(" no create (conf)\n"); return; } + printf(" do create\n"); + // a simple gtk_dialog_new() leaves us unable to setup the header // bar, so use .._with_buttons and just specify a NULL strings to // have no buttons. We need to pretend to actually have one button, @@ -151,7 +194,7 @@ void darktable_splash_screen_create(GtkWindow *parent_window, #endif splash_screen = gtk_dialog_new_with_buttons(_("darktable starting"), - parent_window, flags, + NULL, flags, NULL, GTK_RESPONSE_NONE, // <-- fake button list for compiler NULL); @@ -241,10 +284,17 @@ void darktable_splash_screen_create(GtkWindow *parent_window, _process_all_gui_events(); } -void darktable_splash_screen_set_progress(const char *msg) +void dt_splash_screen_set_progress(const char *msg) { + printf("[dt_splash_screen_set_progress] (%s)\n", msg); + if(_d_level() & DTS_NO_PROGRESS) + return; + if(!splash_screen && create_if_needed) + dt_splash_screen_create(TRUE); + if(splash_screen) { + printf(" do output\n"); gtk_label_set_text(GTK_LABEL(progress_text), msg); gtk_widget_show(progress_text); if(showing_remaining) @@ -255,14 +305,23 @@ void darktable_splash_screen_set_progress(const char *msg) _process_all_gui_events(); gdk_display_sync(gdk_display_get_default()); } + else + printf(" not initialized\n"); } -void darktable_splash_screen_set_progress_percent(const char *msg, - const double fraction, - const double elapsed) +void dt_splash_screen_set_progress_percent(const char *msg, + const double fraction, + const double elapsed) { + printf("[dt_splash_screen_set_progress_percent] (%s)\n", msg); + if(_d_level() & DTS_NO_PROGRESS) + return; + if(!splash_screen && create_if_needed) + dt_splash_screen_create(TRUE); + if(splash_screen) { + printf(" do output\n"); const int percent = round(100.0 * fraction); char *text = g_strdup_printf(msg, percent); gtk_label_set_text(GTK_LABEL(progress_text), text); @@ -287,22 +346,31 @@ void darktable_splash_screen_set_progress_percent(const char *msg, showing_remaining = TRUE; _process_all_gui_events(); } + else + printf(" not initialized\n"); } -void darktable_splash_screen_destroy() +void dt_splash_screen_destroy() { + printf("[dt_splash_screen_destroy] (%lx)\n", (size_t)splash_screen); + if(_d_level() & DTS_NO_DESTROY) + return; if(splash_screen) { + printf(" do\n"); gtk_widget_destroy(progress_text); progress_text = NULL; gtk_widget_destroy(splash_screen); splash_screen = NULL; } + else + printf(" not initialized\n"); } -void darktable_exit_screen_create(GtkWindow *parent_window, - const gboolean force) +void dt_exit_screen_create(const gboolean force) { + printf("[dt_exit_screen_create] (force:%d) SHOULD NEVER BE CALLED\n", force); + // no-op if the exit screen has already been created; if not, only // run if the splash screen is enabled in the config or we are told // to create it regardless @@ -326,7 +394,7 @@ void darktable_exit_screen_create(GtkWindow *parent_window, #endif exit_screen = - gtk_dialog_new_with_buttons(_("darktable shutdown"), parent_window, flags, + gtk_dialog_new_with_buttons(_("darktable shutdown"), NULL, flags, NULL, GTK_RESPONSE_NONE, // <-- fake button list for compiler NULL); @@ -352,13 +420,19 @@ void darktable_exit_screen_create(GtkWindow *parent_window, dt_gui_process_events(); } -void darktable_exit_screen_destroy() +void dt_exit_screen_destroy() { + printf("[dt_exit_screen_destroy] (%lx)\n", (size_t)exit_screen); + if(_d_level() & DTS_NO_DESTROY) + return; if(exit_screen) { + printf(" do\n"); gtk_widget_destroy(exit_screen); exit_screen = NULL; } + else + printf(" not initialized\n"); } // clang-format off diff --git a/src/gui/splash.h b/src/gui/splash.h index 8d10cd4753a9..3c5e408af289 100644 --- a/src/gui/splash.h +++ b/src/gui/splash.h @@ -1,6 +1,6 @@ /* This file is part of darktable, - Copyright (C) 2024 darktable developers. + Copyright (C) 2024-2026 darktable developers. darktable is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,13 +18,16 @@ #include -void darktable_splash_screen_create(GtkWindow *parent, gboolean force); -void darktable_splash_screen_set_progress(const char *msg); -void darktable_splash_screen_set_progress_percent(const char *msg, double fraction, double elapsed); -void darktable_splash_screen_destroy(); +void dt_splash_screen_create(const gboolean force); +void dt_splash_screen_allow_create(const gboolean allow_create); +void dt_splash_screen_set_progress(const char *msg); +void dt_splash_screen_set_progress_percent(const char *msg, + const double fraction, + const double elapsed); +void dt_splash_screen_destroy(); -void darktable_exit_screen_create(GtkWindow *parent, gboolean force); -void darktable_exit_screen_destroy(); +void dt_exit_screen_create(const gboolean force); +void dt_exit_screen_destroy(void); // clang-format off // modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py