Resolves#11004
During the port to GimpProcedureDialog, the code
that assigned the current monitor object for
Windows and MacOS was accidentally removed.
This patch restores this code in the proper place.
Resolves#10802.
Since the GimpProcedureDialog port, the Windows version
of the Screenshot plug-in has been missing the
"Screenshot Delay" option. This is because Windows did not
have the SCREENSHOT_CAN_DELAY_WINDOW_SHOT enum
set. Adding that back in restores the option.
MINGW64
- uses 0x601 as value for _WIN32_WINNT. No need for us to define
it to that value or even lower values in some places.
This also gets rid of: warning: "_WIN32_WINNT" redefined
- has 0x0502 for WINVER, so get rid of us setting it to 0x0500 in
gimp-app-test-utils.h. It also seems that the need to use G_OS_WIN32
has disappeared here.
- DIRECTINPUT_VERSION is 0x0800, no need for us to set it to that value.
- AI_ADDRCONFIG was apparently missing from the MINGW headers in the
past, but not anymore.
If we leave a space between the macro name and opening parenthese for argument
lists, the args are not considered macro args (which will be discovered when
using it). I experienced this issue while testing code on some plug-in
yesterday, so thought I might as well fix all these broken macros for casting to
the specific GimpPlugIn subclass, so that we won't have a next time.
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.
A lot less lines for the same functionalities!
This includes improvements too:
* "include-pointer" as new PDB argument;
* settings storage thanks to GimpProcedureDialog;
* it should hopefully work better in non-interactive (though it's untested).
The macOS and Windows screenshots are untested after this change, though they
should still work the same. Please report if there is any problem!
This is a placeholder which is not meant to appear in the menu. Our new system
uses placeholders internally, but plug-ins cannot make use of these.
Not sure anyway if this is so useful in the cases of plug-ins. At least, I don't
feel it is for these particular use cases.
- This is unneeded in all import procedures. See previous commit. Note though
that this is not because of a change in previous commit. This was already
useless previously. The file set with this PDB function was overridden by the
core anyway (i.e. even before the previous commits).
In app/file/file-import.c:file_import_image(), the imported file is correctly
set (so there is no need to set it from plug-in, which anyway libgimp's
gimp_image_set_file() was not doing) and the XCF file is reset to NULL
(rendering the call to gimp_image_set_file() in a GimpLoadProcedure useless).
- Similarly, this is a useless call in export procedures because
app/file/file-save.c:file_save() overrides such call too. I could only see one
such case for JPEG export, which was quite useless.
- Finally in other types of plug-ins, setting a non-XCF file extension was
interfering with the save feature (similarly to commit e6e73e14c7). I only
fixed the screenshot implementations doing such a thing.
- I left a few usages which will have to be looked at more in details later.
This is the consequence of previous commit. Plug-ins' label and
documentation are now localized before sending these data to GIMP core.
In other words, we replace N_() macros with basic gettext calls.
Hence avoiding the stderr messages. These are going to be localized with
centrally installed catalogs "gimp*-std-plugins", "gimp*-script-fu" and
"gimp*-python".
We now handle core plug-in localizations differently and in particular,
with kind of a reverse logic:
- We don't consider "gimp*-std-plugins" to be the default catalog
anymore. It made sense in the old world where we would consider the
core plug-ins to be the most important and numerous ones. But we want
to push a world where people are even more encouraged to develop their
own plug-ins. These won't use the standard catalog anymore (because
there are nearly no reasons that the strings are the same, it's only a
confusing logic). So let's explicitly set the standard catalogs with
DEFINE_STD_SET_I18N macro (which maps to a different catalog for
script-fu plug-ins).
- Doing something similar for Python plug-ins which have again their own
catalog.
- Getting rid of the INIT_I18N macro since now all the locale domain
binding is done automatically by libgimp when using the set_i18n()
method infrastructure.
On recent KDE, the screenshot plug-in fails with an authorization error,
unless we add a desktop file with a special KDE-only desktop entry to
give the permission, which seems a bit over-the-top (if we were to add a
desktop file for every plug-in, and with dedicated entries to every
desktop environment out there, it's never-ending). Of course, we are not
against either, but nobody has contributed a patch doing this in the
last year anyway.
Also Méven (KDE dev) was telling us that KDE recommends to use the
Freedesktop portal nowadays. So maybe let's just move on from the
KDE-specific portal, just as we did recently for the GNOME portal too.
This should hopefully take care of all permission issues and in the same
time simplifies the code.
Note that the Freedesktop API might miss some of the features (this was
one of the reason we were avoiding putting it as priority implementation
until now, to avoid feature regression), but the more we go, the less we
have a choice. It's either this or always fighting against the current.
… portal.
Otherwise, it first takes a screenshot and proposes to either share or
tweak the "Options" (in the GNOME shell implementation at least). Doing
the other way around is much more in line with how we had done it until
now with our custom dialogs.
GNOME Shell has started restricting access for it's Screenshot D-Bus API
to internal components only [1] for security reasons. In other words,
this will start failing, so remove it in favor of just using the
freedesktop portal, which should always work.
[1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1970
As explained in previous commits, the _peek_ call is advantageous
because:
- It is less bug-prone as we don't have to handle freeing the string. In
all the cases I changed, I even spotted at least 2 cases where we were
leaking a string (in file-mng, `temp_file_name` is never freed; and we
were also leaking in an error case of gfig).
- As a consequence of the previous point: simpler code with less lines.
- In local file cases, the _peek_ variant does not even need to allocate
an additional string.
- In other case, if we query several times the path, it is allocated
once and cached so it stays efficient.
- When possible, working on the GFile rather than on a path string may
be more robust. For instance I changed one g_unlink() into a
g_file_delete(). Actually most reading/writing should be done with the
GIO API when possible, but I didn't want to change too much code
logics on this commit.
The gimp_drawable_type() is an issue though as gimp_drawable_get_type()
is already defined as a common GObject API.
Though I'm actually wondering if GimpImageType is well called. Rather
than Type, shouldn't we go with ColorModel?
sed -i 's/\<gimp_drawable_bpp\>/gimp_drawable_get_bpp/g' "$@"
sed -i 's/\<gimp_drawable_width\>/gimp_drawable_get_width/g' "$@"
sed -i 's/\<gimp_drawable_height\>/gimp_drawable_get_height/g' "$@"
sed -i 's/\<gimp_drawable_offsets\>/gimp_drawable_get_offsets/g' "$@"
… org.freedesktop.portal.Desktop (X11 only).
If we don't set this parameter appropriately, the created dialog is not
modal/transient relatively to the main GIMP window. This is especially
annoying because in my tests (GNOME shell), the screenshot dialog would
appear behind GIMP window, which makes it feel like broken behavior.
Note that the supported handles are X11 only so far. We'll need to
generate the appropriate Wayland handles too (created from xdg_foreign
protocol).
Today I have only re-tested the GNOME implementation (in particular not
the KDE one) of the portal API org.freedesktop.portal.Screenshot but I
assume it is similar because the dbus function does not provide any
useful options anyway. This is why the portal comes with its own dialog
providing the various common screenshot features (delay, window picking,
area selection, etc.). Showing our dialog first is therefore redundant.
Also I updated setting the monitor profile only in the case where the
loaded image result from the portal did not have an embedded profile. To
be fair, the GNOME implementation at least does not embed a profile to
this day. So this is only for the future case where they will finally do
the right thing and embed the display profile (or for other desktops'
implementations where they maybe already do the right thing).
This was true in the "old world" where X11 support being built-in meant
that X11 screenshot would be usable. Now we must not only check it is
built, but also that we are actually running under X11. Otherwise with a
Wayland compositor, screenshot would fail. Also it meant that the
Freedesktop portal was never tried if both X11 and Wayland support were
built-in.
This gives a big cleanup in the meson.build files of the plug-ins.
It's also quite a bit more maintainable, since anything that changes in
libgimp's dependencies, linkage, ... doesn't have to be copy-pasted into
each plug-in.
In the screenshot plug-in, don't clean the image, since it's not
backed by any persistent source, and disable undo while modifying
it, so that the initial edit history is clean.
gimp_int_radio_group_new() was still complaining about the scope of
radio_button_callback(). Make it (scope notified) because it needs to
stay alive after the function returns and may be called multiple times.
Also adding a GDestroyNotify to free the callback data once the widget
is destroyed (additionally it will also serve as a notifier for bindings
to properly free the callback closure itself, not only it's data).
With this last one done, GObject Introspection generation now happens
without any warning output.
and in an attack of madness, changes almost all file plug-in
code to use GFile instead of filenames, which means passing
the GFile down to the bottom and get its filename at the very
end where it's actually needed.
It's an ancient concept from ancient times when we didn't have URIs
and only filenames (not to speak of GFile), and actually even from
before the ancient time before that ancient time when we first had
ones and zeros, and only had zeros.
Turn all ID param specs into object param specs (e.g. GimpParamImageID
becomes GimpParamImage) and convert between IDs and objects in
gimpgpparams.c directly above the the wire protocol, so all of app/,
libgimp/ and plug-ins/ can deal directly with objects down to the
lowest level and not care about IDs.
Use the actual object param specs for procedure arguments and return
values again instead of a plain g_param_spec_object() and bring back
the none_ok parameter.
This implies changing the PDB type checking functions to work on pure
integers instead of IDs (one can't check whether object creation is
possible if performing that check requires the object to already
exist).
For example gimp_foo_is_valid() becomes gimp_foo_id_is_valid() and is
not involved in automatic object creation magic at the protocol
level. Added wrappers which still say gimp_foo_is_valid() and take the
respective objects.
Adapted all code, and it all becomes nicer and less convoluted, even
the generated PDB wrappers in app/ and libgimp/.