Instead of passing a guint32, pass the proper type, since our the HANDLE type
can be 64-bit on Windows (according to links I found).
I was hoping it might be the reason for the breakage under Windows, though I
also found Microsoft documentation saying that the 64-bit handle can be safely
truncated: https://learn.microsoft.com/en-us/windows/win32/winprog64/interprocess-communication?redirectedfrom=MSDN
Nevertheless I'd appreciate testing again from NikcDC or anyone else, as I
reactivated setting transient between processes on Windows.
Note that I also pass the proper types on X11 now (Window), even though guint32
worked fine. Better be thorough.
Having windows ID as guint32 is a mistake. Different systems have
different protocols. In Wayland in particular, Windows handles are
exchanged as strings. What this commit does is the following:
In core:
- get_window_id() virtual function in core GimpProgress is changed to
return a GBytes, as a generic "data" to represent a window differently
on different systems.
- All implementations of get_window_id() in various classes implementing
this interface are updated accordingly:
* GimpSubProgress
* GimpDisplay returns the handle of its shell.
* GimpDisplayShell now creates its window handle at construction with
libgimpwidget's gimp_widget_set_native_handle() and simply return
this handle every time it's requested.
* GimpFileDialog also creates its window handle at construction with
gimp_widget_set_native_handle().
- gimp_window_set_transient_for() in core is changed to take a
GimpProgress as argument (instead of a guint32 ID), requests and
process the ID itself, according to the running platform. In
particular, the following were improved:
* Unlike old code, it will work even if the window is not visible yet.
In such a case, the function simply adds a signal handler to set
transient at mapping. It makes it easier to use it at construction
in a reliable way.
* It now works for Wayland too, additionally to X11.
- GimpPdbProgress now exchanges a GBytes too with the command
GIMP_PROGRESS_COMMAND_GET_WINDOW.
- display_get_window_id() in gimp-gui.h also returns a GBytes now.
PDB/libgimp:
- gimp_display_get_window_handle() and gimp_progress_get_window_handle()
now return a GBytes to represent a window handle in an opaque way
(depending on the running platform).
In libgimp:
- GimpProgress's get_window() virtual function changed to return a
GBytes and renamed get_window_handle().
- In particular GimpProgressBar is the only implementation of
get_window_handle(). It creates its handle at object construction with
libgimpwidget's gimp_widget_set_native_handle() and the virtual
method's implementation simply returns the GBytes.
In libgimpUi:
- gimp_ui_get_display_window() and gimp_ui_get_progress_window() were
removed. We should not assume anymore that it is possible to create a
GdkWindow to be used. For instance this is not possible with Wayland
which has its own way to set a window transient with a string handle.
- gimp_window_set_transient_for_display() and
gimp_window_set_transient() now use an internal implementation similar
to core gimp_window_set_transient_for(), with the same improvements
(works even at construction when the window is not visible yet + works
for Wayland too).
In libgimpwidgets:
- New gimp_widget_set_native_handle() is a helper function used both in
core and libgimp* libraries for widgets which we want to be usable as
possible parents. It takes care of getting the relevant window handle
(depending on the running platform) and stores it in a given pointer,
either immediately or after a callback once the widget is mapped. So
it can be used at construction. Also it sets a handle for X11 or
Wayland.
In plug-ins:
- Screenshot uses the new gimp_progress_get_window_handle() directly now
in its X11 code path and creates out of it a GdkWindows itself with
gdk_x11_window_foreign_new_for_display().
Our inter-process transient implementation only worked for X11, and with
this commit, it works for Wayland too.
There is code for Windows but it is currently disabled as it apparently
hangs (there is a comment in-code which links to this old report:
https://bugzilla.gnome.org/show_bug.cgi?id=359538). NikcDC tested
yesterday with re-enabling the code and said they experienced a freeze.
;-(
Finally there is no infrastructure yet to make this work on macOS and
apparently there is no implementation of window handle in GDK for macOS
that I could find. I'm not sure if macOS doesn't have this concept of
setting transient on another processus's window or GDK is simply lacking
the implementation.
… is set.
The order for thumbnail creation in gimp_imagefile_create_thumbnail() is now:
1. If there is a GimpThumbnailProcedure, it is run first.
2. Otherwise we check if a thumbnail is in the metadata.
3. As last resort, we just load the full image.
Part of the fix was to copy gimp_image_metadata_load_thumbnail() into the core
code. I have been wondering if we could not drop the same function from libgimp
and remove the GimpThumbnailProcedure frome file-jpeg, since it just uses the
metadata thumbnail and it is the only plug-in using this code.
Also it is much faster to run this in core and it's generic function which makes
thumbnail loading from Exif data working for every format supported by Exiv2.
On the other hand, the file-jpeg thumbnail procedure also gathers a few more
useful information, such as the color model (in a reliably manner, since based
on JPEG header, unlike from metadata which may be wrong).
The various information (width, height, image type and number of layers) are
those of the full image, not of the thumbnail. Make it clear in the docs of
GimpRunThumbnailFunc.
Additionally:
- file-xmc was returning the proper information but variables were wrongly
named, which was confusing.
- Fix file-ico thumbnail proc which was returning the thumbnail width/height.
- In file-darktable, initialize width/height to 0 so that we just don't show any
size when we don't get the information. It's better not to show anything than
completely wrong information (the thumbnail target size).
… than a GimpValueArray.
Similar to other GimpProcedure, move to using a config object. A difference is
that thumbnail procedures are always run non-interactively.
Also fixing WMF load thumbnail procedure: the dimension computation was wrong
when the image was wider than tall.
… a GimpProcedureConfig for arguments.
This also factorizes the code to load metadata. By default, a GimpLoadProcedure
will try and load metadata from a file (if Exiv2 knows the format). The run()
function will be allowed to edit the GimpMetadata object but also the load flags
before it is actually attached to the image, allowing plug-ins to have custom
metadata handling code when needed.
This is just a method to simplify transforming a GimpChoice argument into an
enum value, which is easier to deal with, in C. It also allows to benefit from
switch() warnings or the like to make sure no cases are missing.
Developers won't have to maintain manually a list of the possible values in the
help string. It can now be generated from the GimpChoice and will be therefore
ensured to always be up-to-date, and nicely formatted.
I also add some pango markup to the type helper texts to differentiate it from
the main argument docs.
These will replace the int arguments used in place of enums. The problem of int
arguments used as list of choices is that it makes calling PDB functions very
opaque. This is especially bad when a list is long, so you constantly have to
refer to the documentation to understand what a series of numbers mean in
argument lists.
And the second issue is that plug-in developers have to manually maintain a list
of values both in the GUI and in the documentation string. This help text may
get out-of-sync, may end up with missing values or whatnot. Also if it is used
as tooltips, it makes for very weird tooltips in the graphical interface, with
an overlong technical list of int-values mapping which should ideally only be
made visible in the PDB procedure browser listing.
Now gimp_procedure_dialog_get_label() can work both with an existing property ID
or a new property ID. In the former case, it will simply sync the label with the
procedure argument, which will make it easy to update the label contents. In the
latter case, it just initialize with the provided text.
The expectation of 2 references per object in gimp_plug_in_destroy_proxies() was
wrong. It is true during most of the plug-in life, because both the
GimpProcedure and the GimpPlugIn have a hash-table keeping their own reference
to it, except that in gimp_plug_in_pop_procedure(), we release the reference
owned by the procedure with _gimp_procedure_destroy_proxies() first. So at this
point of the object life, its reference count is supposed to be 1.
The source of the bug was in fact in _gimp_plug_in_get_*() (where * can be
display, image, item or resource) which was behaving differently the first time
it is called for an object with the successive calls. In the first call only, it
was creating then refing into the table (so the object started directly with 2
references) whereas on successive calls, it just returned the hashtable-looked
up reference. In other words, it behaved as a (transfer full) on the first call
and (transfer none) on successive calls. And so did all public API which were
making use of this infrastructure (in particular gimp_*_get_by_id() functions).
The widget_creator_func() given to gimp_prop_chooser_factory() will create an
object which will take its own reference. We must release the one we got with
g_object_get().
Metadata handling is also integrated in this API:
* while giving a possibility to disable metadata saving if you want to do it
yourself (e.g. in file-heif), by setting a NULL MimeType;
* and the GimpMetadata object is added as run() argument, allowing one to edit
the metadata during the run, while still letting the infrastucture handle the
save (e.g. in file-jpeg);
* or to save intermediate metadata with gimp_procedure_config_save_metadata()
(e.g. in file-tiff).
While we definitely should not use this inside app/, because having the private
structure easily accessible as a member is very convenient, it is clear that it
makes for a much nicer public signature. Also the priv member is of no help to
third-party developers using this API to make plug-ins and is better hidden in
such a case.
This will be useful for plug-in developers but also for us. Seeing we leak the
config object is often a good indication that something is wrong in our handling
of internal references (since everything relies on the config object in plug-ins
now, in particular all the GUI).
I was clearly confused when I wrote this. The sinking part matters to take
ownership of a reference in the widgets table, but we don't need to ref widgets
again before inserting them in containers. We were leaking widgets and as a
consequence the config object (and as a second consequence, some objects such as
resources for resource-selection widgets).
Same as with gimp_procedure_new2(), I will end up renaming the function to
gimp_image_procedure_new() once all usage of this function will have been ported
to the new function using GimpProcedureConfig instead of GimpValueArray
arguments.
The one in GimpResourceSelect is a very nice example of why using config objects
is much nicer, getting arguments by their name instead of an index (which in
this case had to be tracked down by a private function to handle different
cases).
Also in gimp_procedure_config_begin_run(), make sure we sync the arguments with
the config object first thing, even in interactive and with-last-vals case
(where the args may be further overridden). This was especially important for
Script-fu scripts as the image and drawable were not provided separately, so we
need to make sure that the config file has the right values.
Otherwise we will always try to reuse previous values or use the default,
bypassing the actual passed values.
I encountered this issue while porting file-glob and realizing that the
"pattern" argument was always passed to NULL, ignoring the explicitly set
pattern.
When a procedure has no run-mode argument, we should simply not assume anything
and use the passed arguments (which is what the non-interactive mode does).
This function allows to change the sensitivity of a widget depending on the
value of another property.
We already had gimp_procedure_dialog_set_sensitive() except it was only syncing
with a boolean property, whereas the new function can compare with any property
type.
This new function is meant to replace gimp_procedure_new() when all plug-in
usage will have been switched.
This function creates the GimpProcedureConfig object on behalf of the plug-in
and calls gimp_procedure_config_begin_run() and gimp_procedure_config_end_run().
This way we ensure that all plug-in calls with successful result are properly
stored without asking the developer not to forget to call these (if a "good
practice" is in fact something we request to do every time, especially for good
user experience, we might as well make it rather a core process).
Advantages:
* Better interactive experience: using any plug-in will result in saved
previously used settings.
* for developers, working on config objects is also much more comfortable than
working on GValueArray;
* step forward for the future macro infrastructure: if we can ensure that all
plug-in calls are properly logged, then we can replay plug-in actions, in
NON_INTERACTIVE with the same settings.
from plug-in
I get a critical error when calling gimp_text_layer_new and the function
doesn't return a GimpTextLayer:
(file-psd:47120): LibGimp-CRITICAL **: 16:00:59.035:
gimp_gp_param_to_value: type name GimpTextLayer is not registered
Adding the above line to libgimp/gimp.c fixes the problem.
Looking further, the @help is only used in gimp_proc_view_new() so far (for the
Procedure Browser) where the blurb and argument descriptions are already
localized. It makes no sense to only keep this in English. So let's ask to have
both arguments translated.
Now clearly we should not ask for @help to be mandatory. Very often, it makes no
sense to have a longer help string (the small blurb and the few arguments may be
very self-explanatory). So I make this argument nullable.
There is only the @help_id which I wonder if we could not have a simpler
function gimp_procedure_set_documentation_uri(). Indeed while having a unified
infrastructure with a XML summary and help IDs and whatelse makes sense for GIMP
as a whole, I think that many third-party plug-ins would work much better with a
very simple direct URL. Or it could even be a GFile to a local file (for
plug-ins which want to embed their documentation in the plug-in folder for
instance). To be continued…
I add a new class method deserialize_create() to GimpConfigInterface which
returns the GimpConfig object per deserialization, instead of modifying an
existing bare object.
This matters for cases like our GimpResource (and later our GimpItem) classes
which are fully managed by libgimp and should be unique objects per actual
resource. It should even be possible to compare the pointer itself for identity.
That's why we need to let GimpResource create the object (in reality request it
to the infra and only ref it) through this new class method.
With this commit and the previous ones, all GimpResource are now properly stored
as plug-in settings (e.g. the "film" plug-in has a font setting which is now
properly remembered).
These identifiers are not portable (across various installations and therefore
not for XCF either), but at least they are reasonably identifying data on a same
installation (unlike GimpResource's int ID which is only valid within a single
session) which makes them very fine for plug-in settings storage.
When a data file disappears, we fallback to the context default data instead.
This finds the core resource knowing its type, name, collection and internal
state (in other words, the values returned by _gimp_resource_get_identifiers()).
Rather than reimplementing the same checks for every possible resource data
type, just do it once and redirect to the correct factory container.
For the libgimp API, we leave per-type functions `gimp_*_get_by_name()` (where *
can be brush|gradient|font|palette|pattern so far), but internally they all use
gimp_pdb_get_resource().
Note that eventually we want these functions to return a list of resources as it
should be possible to have several resources of a given type with the same name
(since they are made by third-party who might have had the same idea of a name).
We use US English which uses behavior. So we replace all occurrences of
behaviour.
Most notable is File Open behavior in preferences. Besides that several
mentions in function documentation and a few in comments.
Resources are stored by the plug-in infrastructure and their memory should not
be managed by plug-in code.
My commit 4f69995b46 was crappy and modified a generated function. I was just
too tired with all the heat in here, I guess!
Similarly to how we handled image items, all resources are handled and stored by
the plug-in infrastructure and should not be destroyed. This wrong annotation
was triggering bindings to unref resources when going out of scope, hence
crashing plug-ins.