libgimpwidgets: clean documentation and implementation.

- Added some link annotations to other types or functions.
- Rename argument @handle to @window_handle in
  gimp_widget_set_native_handle() docs to be similar to the same
  argument of gimp_widget_free_native_handle().
- Fix annotation of the handle to (inout) though I do wonder if this can
  really be usable in bindings anyway because of the asynchronous logic.
  Maybe these functions should be skipped for bindings?
- Better docs globally, and in particular remove implementation details
  in gimp_widget_free_native_handle() docs. The point is that the handle
  is to be considered opaque data and you have to run this when you ran
  gimp_widget_set_native_handle(). No need to talk about Wayland or
  explain that it's a GBytes or meanings of "handle".
- Also clean the free() implementation with far too many comments, and
  in particular we don't need to check if the handle is NULL.
  g_clear_pointer() steps out by itself if the pointed data is NULL.
This commit is contained in:
Jehan 2025-10-23 17:16:40 +02:00
parent 822c26f709
commit b879deb323
2 changed files with 34 additions and 48 deletions

View file

@ -1116,27 +1116,35 @@ gimp_widget_get_render_space (GtkWidget *widget,
/**
* gimp_widget_set_native_handle:
* @widget: a #GtkWindow
* @handle: (out): pointer to store the native handle as a #GBytes.
* @widget: a widget to get a handle for.
* @window_handle: (inout): pointer to store the native handle as a [struct@GLib.Bytes].
*
* This function is used to store the handle representing @window into
* @handle so that it can later be reused to set other windows as
* transient to this one (even in other processes, such as plug-ins).
* This function is to be used in custom widget construction to store
* the window handle representing @widget into @window_handle so that it
* can later be reused to set other windows as transient to this one
* (even across processes, such as in-between plug-ins), e.g. using
* [func@GimpUi.window_set_transient_for].
*
* Depending on the platform, the actual content of @handle can be
* various types. Moreover it may be filled asynchronously in a
* callback, so you should not assume that @handle is set after running
* Depending on the platform, the actual content of @window_handle can be
* various types and should therefore be considered an opaque data.
* Moreover it may be filled asynchronously in a callback, so you should
* not assume that @window_handle is set after running
* this function.
*
* This convenience function is safe to use even before @widget is
* visible as it will set the handle once it is mapped.
*
* Free @window_handle on `dispose()` or `finalize()` with
* [func@GimpUi.widget_free_native_handle].
*
* Since: 3.0
*/
void
gimp_widget_set_native_handle (GtkWidget *widget,
GBytes **handle)
GBytes **window_handle)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (handle != NULL && *handle == NULL);
g_return_if_fail (window_handle != NULL && *window_handle == NULL);
/* This may seem overly complicated but there is a reason: "map-event" can
* only be received by widgets with their own windows (see description of
@ -1151,74 +1159,52 @@ gimp_widget_set_native_handle (GtkWidget *widget,
gtk_widget_add_events (widget, GDK_STRUCTURE_MASK);
g_signal_connect (widget, "map-event",
G_CALLBACK (gimp_widget_set_handle_on_mapped),
handle);
window_handle);
}
else
{
g_signal_connect (widget, "realize",
G_CALLBACK (gimp_widget_set_handle_on_realize),
handle);
window_handle);
}
if (gtk_widget_get_realized (widget))
gimp_widget_set_handle_on_mapped (widget, NULL, handle);
gimp_widget_set_handle_on_mapped (widget, NULL, window_handle);
}
/**
* gimp_widget_free_native_handle:
* @widget: a #GtkWindow
* @window_handle: (out): same pointer previously passed to set_native_handle
* @widget: a widget we got a handle for.
* @window_handle: (inout): same pointer previously passed to [func@GimpUi.widget_set_native_handle].
*
* Disposes a widget's native window handle created asynchronously after
* a previous call to gimp_widget_set_native_handle.
* This disposes what the pointer points to, a *GBytes, if any.
* Call this when the widget and the window handle it owns is being disposed.
* Disposes a widget's native window handle created, possibly
* asynchronously, by a previous call to [func@GimpUi.widget_set_native_handle].
* Call this function on `dispose()` or `finalize()`.
*
* This should be called at least once, paired with set_native_handle.
* This knows how to free @window_handle, especially that on some platforms,
* an asynchronous callback must be canceled else it might call back
* with the pointer, after the widget and its private is freed.
* Depending on the platform, this function may also execute other
* necessary clean up so you should call it and not simply free the
* [struct@GLib.Bytes] yourself.
*
* This is safe to call when deferenced @window_handle is NULL,
* when the window handle was never actually set,
* on Wayland where actual setting is asynchronous.
* This is safe to call even if deferenced @window_handle is %NULL, i.e.
* that you don't have to check if the window handle was actually set.
*
* !!! The word "handle" has two meanings.
* A "window handle" is an ID of a window.
* A "handle" also commonly means a pointer to a pointer, in this case **GBytes.
* @window_handle is both kinds of handle.
* Since: 3.0
*/
void
gimp_widget_free_native_handle (GtkWidget *widget,
GBytes **window_handle)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
/* window-handle as pointer to pointer must not be NULL. */
g_return_if_fail (window_handle != NULL);
#ifdef GDK_WINDOWING_WAYLAND
/* Cancel the asynch callback which has a pointer into widget's private.
* Cancel regardless whether callback has already come.
*/
if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()) &&
/* The GdkWindow is likely already destroyed. */
gtk_widget_get_window (widget) != NULL)
gdk_wayland_window_unexport_handle (gtk_widget_get_window (widget));
#endif
/* On some platforms, window_handle may be NULL when an asynch callback has not come yet.
* The dereferenced pointer is the window handle.
*/
if (*window_handle != NULL)
{
/* On all platforms *window_handle is-a allocated GBytes.
* A GBytes is NOT a GObject and there is no way to ensure is-a GBytes.
*
* g_clear_pointer takes a pointer to pointer and unrefs at the pointer.
*/
g_clear_pointer (window_handle, g_bytes_unref);
}
/* Else no GBytes was ever allocated. */
g_clear_pointer (window_handle, g_bytes_unref);
}
/**

View file

@ -68,7 +68,7 @@ const Babl * gimp_widget_get_render_space (GtkWidget *widget,
GimpColorConfig *config);
void gimp_widget_set_native_handle (GtkWidget *widget,
GBytes **handle);
GBytes **window_handle);
void gimp_widget_free_native_handle (GtkWidget *widget,
GBytes **window_handle);