Similar to previous commit. If we don't want people to use this function
yet need to export it, at least don't expose the declaration in shipped
headers and even less in the API docs.
Even though it's not public yet (and won't really be for GIMP 3.0), I
created a new concept of "GIMP Extension" (.gex files) which bundles
various types of data for GIMP, such as plug-ins but also brushes and
other resources, themes, icons, etc.
Having 2 different concepts named the same is confusing, especially
since one of them is not really self-explaining IMO (why are "always-ON"
plug-ins called "extensions"?). So even though this is the older
concept, and since we are anyway massively breaking the API for GIMP
3.0, let's rename this older concept. "Persistent Plug-Ins" is much more
self-defining.
This should also fix the build on Windows wich fails with:
> ../app/app.c:537:7: error: call to undeclared function 'gimp_signal_private'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
Right now, running GIMP non-interactively (i.e. either as gimp-console
or with --no-interface) without --quit, the process was still exiting
immediately, yet not properly cleaning after itself. This is a
regression, since there used to be use cases with people wanting
long-running GIMP (for instance with a long-running plug-in waiting for
input through whatever inter-process communication method).
With this commit:
* GIMP now continues running when run non-interactively without --quit;
* It will catch SIGINT (typically Ctrl-C) and will quit cleanly when the
signal happens.
* At the end of the normal process (processing command line options,
such as opening images or running batch commands) and before going
on-hold, it will display some info text saying that the process can be
exited with SIGINT and informing that --quit exists if you were in
fact intending to quit immediately after the normal process actions.
* This also fixes the "gimp_finalize: list of contexts not empty upon
exit" WARNING we had when it was exiting without --quit (because of no
proper cleanup).
Note that I add some CLI text which ideally should be localized. But
since we are in string freeze, I am letting them untranslated with a
TODO (also assuming CLI-using people have more chances being used to
English, which may be or not a wrong assumption; but anyway most people
don't read the terminal output, and people running GIMP
non-interactively are even less).
Since this was not just an enhancement but also really a regression fix,
I prefer to do this now despite the string freeze and lack of
localization.
The other way around, we were going to have the quick'n dirty exit for
the whole 3.0 stable branch, which is obviously not what we want. We
want the clean exit for all developer builds, even within a stable
branch.
This is the only "language" from the list whose name is special and
should be localized at runtime, yet before we set any Preferences
language. It needs to be localized as the System Language itself which
will be run-dependant.
For instance, if your system is in French, it will be displayed as
"Langue système" but if you change your system to Korean, at next run,
it would show "시스템 언어". It is a per-run localization, independant
from the language selected in Preferences, and even less dependant from
build-time system language.
Since the Image Recovery dialog is blocking the main process (and requires an
answer to be done first), let's simply move down the Welcome dialog to after
this answer was given. This way, we simply won't have both dialogs in the same
time.
… clean-exiting on all dev code (whether stable or unstable branches).
This is because the dirty exit prevents the on-exit crashes which seem to happen
somewhere in the memory cleanup (which apparently corrupts memory but all crash
traces don't show the proper area where the issue actually hapened). So let's
have release exit the process without issue (at least all important user-facing
data is saved properly by then), while not hiding the issue to developers.
Also on dev code, the GIMP_DIRTY_EXIT will allow to go anyway for the quick
exit() path, so that for instance one can work on other pieces of code without
feeling bothered by the constant crashes on exit.
For the record, the crashes we are talking about appear when you update to a
recent GLib, after the removal of GSlice implementation (which is basically now
just a malloc/free alias). There may be issues in our usage of GSlice though we
also experience crashes even just with commit 69e9ba80e on GLib which hints at
issues in our GObject/GType code.
Right now, our actions are added both in the GActionMap (a.k.a. as
GApplication|GtkApplication) and with the old GtkActionGroup API. The later code
is meant to be removed soon.
A major difference with the old implementation is that we don't add the actions
in separate action groups. Even though GLib has a GActionGroup concept, these
don't seem to be used at all when adding actions on the GtkApplication level.
It might mean that eventually we will even remove the GimpActionGroup code and
move everything up one level.
Of course, I am still evaluating if we really want an action group concept, in
which case, we could simply recreate it, but I'm actually unsure how useful it
is. The only place where I see a use to this is in the shortcut settings (to
organize actions by groups), but even there, it was rarely useful to me. I
usually rather search for actions by text search anyway.
- app_activate_callback() moved with other private functions.
- Removing the `if (app)` test in app_activate_callback() as we don't
set it to NULL anymore. The app variable is always set.
- As a consequence of the previous point, change signature of
app_exit_after_callback() which doesn't have to change the value of
app anymore.
- Don't emit direcly the "exit" signal from app_activate_callback(). We
must call `gimp_exit (gimp, TRUE);` instead, which does more than just
emitting this signal. It also takes care of cleaning any remaining
images without a display. If we don't do this, we are leaking
GeglBuffer when opening images from command lines while quitting
immediately with --quit.
- Get rid of gimp_core_app_set_values() which was completely bypassing
the fact that all the properties of a GimpCoreApp were construct-only.
Instead make these proper properties. I use a trick used in other
interface, creating a gimp_container_view_install_properties() which
is called from child classes.
The point of GimpCoreApp is not just to share a common interface, it's
rather to weakly simulate some kind of multi-inheritance in GObject.
Since we want both GimpApp and GimpConsoleApp to inherit from a same
parent class while we also want them to inherit either from
GtkApplication and GApplication respectively (yet without linking to
GTK in this second case), we are stuck as far as normal GObject
inheritance goes. This is why we use an interface to which we add a
private struct through a GQuark trick. We want the property settings
and function implementations to also be part of this shared code.
- Get rid of all the abstract methods of GimpCoreApp of the form
get_*(). These are useless as we don't expect these to have different
implementation depending on the actual child class. Once again, our
main goal was to simulate multiple inheritance rather than actually
have an interface with various implementations.
- Make "no-splash" a property of GimpApp, because it's cleaner this way.
- Fix gimp_core_app_private_finalize().
- don't use #pragma once, it's not standard. Just use include guards.
- Fix includes: order was wrong, include from the source, not other
headers, etc.
- Clean various other details, coding styles, fix several more bugs and
more…
Reviewer's message (Jehan): This was a work-in-progress by Niels, which
we only keep in this state because Lukas worked over it. I have rebased
and fix-amended many broken part of this commit, because various things
had been changed in these areas of code since this commit was initially
written.
Since localization is fully handled plug-in side now (see #8124), we
need to make sure the query functions are run again for all plug-ins
when the UI language changes (otherwise we might end up with
localizations from the previously used languages).
We were already reloading plug-ins when explicitly changing the lang in
the Preferences, but this new implementation is much better as it's
generic. In particular, it will also handle the case when the system
language changes (or when you play with locale environment variables).
Call gimp_exit() rather than emitting the signal ourselves. This way in
particular, the still-opened images are properly freed and we avoid
GeglBuffer leaks from images we might have created in a batch script, or
the images loaded in command lines.
If you call GIMP with batch commands and ask it to quit immediately, you
are likely interested by failure information. For this reason, let's now
report exit code other than success, but only in such case. In
particular, even if the batch commands fail, but GIMP is not set to exit
immediately, we continue reporting SUCCESS run at the very end (when
exiting interactively).
Note that I hardcode a few exit values, as standardly found on Linux
(but not using headers which may not be found on all platforms; in
particular, Windows apparently doesn't use any standard code other than
0 for success, from what my searches return).
Additionally, when several commands are requested, GIMP will now stop at
the first failing and will return its error code, and print a message on
stderr to easily report the failed command for easier debugging.
Instead of asking for the script to call gimp_quit() which is not too
proper (because this is actually meant to exit the script, not GIMP
itself. Scripts should not have the ability to basically kill the main
GIMP process), let's add a `--quit` option which does what it says: it
quits GIMP immediately (after having processed any task on command line,
such as running batch scripts).
See discussions in issue #7376.
This should fix various hard-to-reproduce cases of:
> (gimp-2.99:50596): Gimp-Core-WARNING **: 00:42:45.324: gimp_finalize: list of contexts not empty upon exit (2 contexts left)
>
> stale context: (null)
> stale context: PDB Context
We had these warnings happening randomly at exit and not always
reproduceable with the same steps. I had it reproduced much more easily
when working with CLI scripts exiting GIMP immediately. The context were
actually properly unref-ed but simply we had to wait a bit for events to
be processed before destroying the main GIMP object.
Thinking again, this is simply the version of the config files, mapping
to the application version. Even though it's not really a user-visible
string (except in config files themselves), I find this a much more
elegant name than the ugly "last-run-version" (which is not even true
anymore once startup passed; it's only the last-run version info at very
beginning of the startup process).
This will be used by the update check to verify you are running a new
version since last time. In the future, it might even allow to handle
some types of config migrations if ever we update some things in-between
micro releases. Until now, we could only detect minor updates through
the config folder name (and even this was limited as the config folder
can be specified, in which case we would not even know what version the
files were for).
Maybe we could start also warning in cases of downgrading too, which can
break some configuration files (though there is not much we can do about
it other than warn as there is no time machine!).
Last point: if the new config value "last-run-version" doesn't exist, it
simply means the config folder was run for a GIMP before this point in
time/commit. So we just show the welcome dialog.
When running tests, the data are not meant to be necessarily installed.
Therefore icons won't be found when calling gimp_widgets_init().
Add some special-casing to find them relatively to the install
directory.
Fix the search for previous folders, which was broken as it was
specifically expecting 1-digit numbers so far.
The differences of the GIMP 3 config import are:
- update sizes and positions in the sessionrc according to the scale
factor, because GTK2 doesn't have scale support. It means that, e.g.
with a 2× display, all sizes and positions in GIMP 2.x must be divided
by 2 (otherwise the first thing many people will get when testing GIMP
3 for the first time is an off-screen window).
Of course, I even wondered if it would not be nice to just drop the
sessionrc altogether and start with a nice blank slate, but then you
also lose the opened dock and their organization and some settings
(such as whether you chose single or multi window mode, etc.).
- scripts/ and plug-ins/ are not imported. Probably makes no sense so
far as they would end up broken (but maybe it's not true for all
script-fu scripts?).
- Set the software as `initialized` later, and in particular after all
recovered images (from crash) then all command line images were
opened. The reason is that the DBus calls have necessarily been made
after GIMP was started (typically could be images double-clicked
through GUI). We don't want them to appear before the images given in
command line (or worse, some before and some after).
- Process DBus service's data queue as a FIFO. The image requested first
will be loaded first.
- When a DBus call happens while GIMP is not initialized or restored,
switch to a timeout handler. The problem with idle handlers is that
they would be attempted too often (probably even more during startup
when no user event happens). This is good for actions we want to
happen reasonably quickly (like would be normally DBus calls), but not
when we are unsure of program availability schedule (i.e. at startup).
Here not only the handler would run a lot uselessly but it would
likely even slow the startup down by doing so. So while GIMP is not
initialized, switch to half-a-second timeout handler, then only switch
back to idle handler when we are properly initialized and GIMP is
ready to answer calls in a timely manner.
… DBus calls.
In particular, Aryeom would start GIMP and directly double click some
image to be loaded in GIMP in the very short while when splash is
visible. Previous code would wait for the `restored` flag to be TRUE.
This was nearly it as we can actually start loading images as soon as
the 'restore' signal has passed. Yet the flag is set in the main
handler, but we actually also need the <Image> UI manager to exist,
which is created in gui_restore_after_callback() (so also a 'restore'
handler, yet after the main signal handler, i.e. after `restored` is set
to TRUE). Without this, gui_display_create() would fail with a CRITICAL,
hence file_open_with_proc_and_display() as well.
I could have tried to set the `restored` flag later, maybe with some
clever signal handling trick (and handle both the GUI and non-GUI cases,
i.e. I cannot set the flag inside gui_restore_after_callback() as it
would break the non-GUI cases). Instead I go for a simpler logics with a
new `initialized` flag which is only meant to be set once, once
everything has been loaded, i.e. once you can consider GIMP to be fully
running hence ready to process any common runtime command.
When checking for updates, write the new timestamp and version info
to Gimp::edit_config, instead of Gimp::config, and rely on its
auto-save mechanism to save the changes, in order to avoid having
to save Gimp::config on exit, which overrides modified settings
that require a restart, such as the UI language, as they are only
reflected in Gimp::edit_config.
This fixes the bug, but can cause the new update info to be
discarded if the Preferences dialog is open while checking for
updates, and is subsequently canceled. Ideally, the update info
should live in a separate file, rather than in gimprc.
When an update is available, a big frame is visible, proposing to go to
the download page. Now a button is also available to explicitly request
for an update check in other cases (bypassing the wait delay for a
future startup).
GIMP will now process the remote gimp_versions json file to look if one
is using the last version of GIMP. This initial code doesn't act up yet
on this information. This will come in further commits.
Here are the characteristics:
- Since this requires internet access, a new checkbox is available in
the Preferences dialog, allowing to disable version checks. Note that
it is enabled by default as it is an important security feature, but
it has to be deactivatable.
- The remote access is done as an async operation because we don't want
it to block the startup in any way (for whatever reason). Also it
doesn't output errors if it fails to not be a bother (you don't
technically need internet access for an image program).
- We don't check at every startup. At each successful check, we save a
timestamp to prevent too frequent useless checks (I set it the timer
to a week or more for now).
There are no replacements. Just we must make sure that all GTK+/GDK
calls are run from the main thread, which is already what we were doing.
Actually I don't even think these were doing anything as we were not
calling gdk_threads_init() so the default lock functions were not set
anyway. These were just bogus calls.
Initialize GimpBacktrace earlier on in the startup process, so that
the Windows backend installs the thread-name exception handler
early enough to catch threads created before app_run() (in
particular, the GEGL worker threads).
In app_exit_after_callback(), call gimp_gegl_exit() before
gegl_exit() when performing a quick shut-down in stable versions,
so that gimp-parallel, and, in particular, the async thread pool,
is properly shut down. Code running in the async thread pool may
use GEGL (in particular, now the drawable previews are rendered
asynchronously), and calling gegl_exit() while it's still running
is unsafe.
This reverts commit 94b028bc39c7250997ee9883793e6649bf2490c7.
Dunno what breaks here, it just crashes, leave the commits there
instead of rebasing them away, as reminder...
Remove the log handlers registered in errors_init(), in
errors_exit(), and call errors_exit() before destroying the Gimp
instance, since the log handlers depend on it. This avoids
segfaulting if a message is logged after destroying the Gimp
instance.
As proposed on IRC. This will allow people to debug their fonts (for
instance when there are permission issues or whatnot) by knowing the
list of problematic fonts in an error dialog at startup (and not only on
terminal).
Add gimp-parallel.[cc,h], which provides a set of parallel
algorithms.
These currently include:
- gimp_parallel_distribute(): Calls a callback function in
parallel on multiple threads, passing it the current thread
index, and the total number of threads. Allows specifying the
maximal number of threads used.
- gimp_parallel_distribute_range(): Splits a range of integers
between multiple threads, passing the sub-range to a callback
function. Allows specifying the minimal sub-range size.
- gimp_parallel_distribute_area(): Splits a rectangular area
between multiple threads, passing the sub-area to a callback
function. Allows specifying the minimal sub-area.
The callback function is passed using an appropriately-typed
function pointer, and a user-data pointer. Additionally, when used
in a C++ file, each of the above functions has an overloaded
template version, taking the callback through a generic parameter,
without a user-data pointer, which allows using function objects.
The debug menu is currently not included in stable versions.
Include the menu unconditionally, but hide it, and its associated
actions, by default in stable versions. Allow enabling the menu
using a new --show-debug-menu command-line option, in the same vein
as --show-playground.
Since error handling is based on preferences, the config needs to be
loaded first. Otherwise the gimp->config object does not exist yet and
we get a bunch of "'G_IS_OBJECT (object)' failed" assertion which
recurse in error handling when trying to get the "debug-policy"
property.
Just init the error handling later. It means it won't handle early
loading code, but that is not much of an issue.
Since commit d916fedf92, GIMP has had the hidden feature to salvage
images (if possible) during a crash into a backup folder. This commit
finishes the feature by opening a dialog proposing to try and recover
the salvaged images.
This is not perfect yet since it doesn't "remember" the XCF path (in
case it was a previously saved image). The images open as new unsaved
and dirty images, but directly from the contents at crash time. For now,
it is up to people to figure out what they correspond to, if relevant.
I had to shuffle a bit the order of initialization since we were
creating a folder for the crash logs, as well as one for the backups a
bit too early. So now I move errors_init() after configuration folder
creation/migration, and I create both these folders in this function
(especially since gimp_init_signal_handlers() is run even earlier).
For this later reason, I also check for backtrace_file and backup_path
being allocated in gimp_eek() since it is also possible for signals
happening before errors_init(). In such a case, we will simply bypass
the GUI error handler (terminal error handler still possible) and the
backup (anyway there is nothing to backup at this point).
I could also try to create these 2 directories at the last second, when
needed. But since we are trying to do the strict minimum during crash
handling, it is better to do whatever can be done earlier.
The feature already exists in our code and produces backtraces upon a
crash into a file. The only difference is that we are now getting the
file contents and showing it in our new debug dialog, so that it works
similarly on all platform (and therefore making the debug info visible
to people, otherwise they would never report, even though the data is
generated).
The difference with gdb/lldb is that it doesn't allow backtraces at
random points (for debugging non-fatal yet bad errors). Also the API has
just 2 functions and in particular an ExcHndlInit() but no way to unload
the feature. So we don't need the debugging page in Preferences because
the switch option would not work. On Windows, the feature will be
decided at build time only.
Last point: the code is untested on Windows so far. I assume it would
work, but there is at least one point I am unsure of: will ExcHndl have
already generated the backtrace file when gimpdebug runs? If not, I will
have to let gimp die first to be able to get the backtrace.