mirror of https://github.com/GNOME/gimp.git
app, libgimp*, pdb, plug-ins: reimplement generic inter-process transient window.
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.
This commit is contained in:
parent
bf210243f2
commit
58b3b14082
|
@ -321,17 +321,17 @@ gimp_get_empty_display (Gimp *gimp)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
guint32
|
||||
GBytes *
|
||||
gimp_get_display_window_id (Gimp *gimp,
|
||||
GimpDisplay *display)
|
||||
{
|
||||
g_return_val_if_fail (GIMP_IS_GIMP (gimp), -1);
|
||||
g_return_val_if_fail (GIMP_IS_DISPLAY (display), -1);
|
||||
g_return_val_if_fail (GIMP_IS_GIMP (gimp), NULL);
|
||||
g_return_val_if_fail (GIMP_IS_DISPLAY (display), NULL);
|
||||
|
||||
if (gimp->gui.display_get_window_id)
|
||||
return gimp->gui.display_get_window_id (display);
|
||||
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GimpDisplay *
|
||||
|
|
|
@ -54,7 +54,7 @@ struct _GimpGui
|
|||
|
||||
GimpObject * (* get_window_strategy) (Gimp *gimp);
|
||||
GimpDisplay * (* get_empty_display) (Gimp *gimp);
|
||||
guint32 (* display_get_window_id) (GimpDisplay *display);
|
||||
GBytes * (* display_get_window_id) (GimpDisplay *display);
|
||||
GimpDisplay * (* display_create) (Gimp *gimp,
|
||||
GimpImage *image,
|
||||
GimpUnit unit,
|
||||
|
@ -122,7 +122,7 @@ GimpDisplay * gimp_get_display_by_id (Gimp *gimp,
|
|||
gint ID);
|
||||
gint gimp_get_display_id (Gimp *gimp,
|
||||
GimpDisplay *display);
|
||||
guint32 gimp_get_display_window_id (Gimp *gimp,
|
||||
GBytes * gimp_get_display_window_id (Gimp *gimp,
|
||||
GimpDisplay *display);
|
||||
GimpDisplay * gimp_create_display (Gimp *gimp,
|
||||
GimpImage *image,
|
||||
|
|
|
@ -74,7 +74,7 @@ static void gimp_pdb_progress_progress_set_value (GimpProgress *progress
|
|||
gdouble percentage);
|
||||
static gdouble gimp_pdb_progress_progress_get_value (GimpProgress *progress);
|
||||
static void gimp_pdb_progress_progress_pulse (GimpProgress *progress);
|
||||
static guint32 gimp_pdb_progress_progress_get_window_id (GimpProgress *progress);
|
||||
static GBytes * gimp_pdb_progress_progress_get_window_id (GimpProgress *progress);
|
||||
|
||||
|
||||
static GObjectClass *parent_class = NULL;
|
||||
|
@ -237,14 +237,13 @@ gimp_pdb_progress_set_property (GObject *object,
|
|||
}
|
||||
}
|
||||
|
||||
static gdouble
|
||||
gimp_pdb_progress_run_callback (GimpPdbProgress *progress,
|
||||
GimpProgressCommand command,
|
||||
const gchar *text,
|
||||
gdouble value)
|
||||
static void
|
||||
gimp_pdb_progress_run_callback (GimpPdbProgress *progress,
|
||||
GimpProgressCommand command,
|
||||
const gchar *text,
|
||||
gdouble value,
|
||||
GBytes **handle)
|
||||
{
|
||||
gdouble retval = 0;
|
||||
|
||||
if (progress->callback_name && ! progress->callback_busy)
|
||||
{
|
||||
GimpValueArray *return_vals;
|
||||
|
@ -270,17 +269,16 @@ gimp_pdb_progress_run_callback (GimpPdbProgress *progress,
|
|||
g_type_name (G_TYPE_FROM_INSTANCE (progress)));
|
||||
}
|
||||
else if (gimp_value_array_length (return_vals) >= 2 &&
|
||||
G_VALUE_HOLDS_DOUBLE (gimp_value_array_index (return_vals, 1)))
|
||||
handle != NULL &&
|
||||
G_VALUE_HOLDS_BOXED (gimp_value_array_index (return_vals, 1)))
|
||||
{
|
||||
retval = g_value_get_double (gimp_value_array_index (return_vals, 1));
|
||||
*handle = g_value_dup_boxed (gimp_value_array_index (return_vals, 1));
|
||||
}
|
||||
|
||||
gimp_value_array_unref (return_vals);
|
||||
|
||||
progress->callback_busy = FALSE;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static GimpProgress *
|
||||
|
@ -294,7 +292,7 @@ gimp_pdb_progress_progress_start (GimpProgress *progress,
|
|||
{
|
||||
gimp_pdb_progress_run_callback (pdb_progress,
|
||||
GIMP_PROGRESS_COMMAND_START,
|
||||
message, 0.0);
|
||||
message, 0.0, NULL);
|
||||
|
||||
pdb_progress->active = TRUE;
|
||||
pdb_progress->value = 0.0;
|
||||
|
@ -314,7 +312,7 @@ gimp_pdb_progress_progress_end (GimpProgress *progress)
|
|||
{
|
||||
gimp_pdb_progress_run_callback (pdb_progress,
|
||||
GIMP_PROGRESS_COMMAND_END,
|
||||
NULL, 0.0);
|
||||
NULL, 0.0, NULL);
|
||||
|
||||
pdb_progress->active = FALSE;
|
||||
pdb_progress->value = 0.0;
|
||||
|
@ -338,7 +336,7 @@ gimp_pdb_progress_progress_set_text (GimpProgress *progress,
|
|||
if (pdb_progress->active)
|
||||
gimp_pdb_progress_run_callback (pdb_progress,
|
||||
GIMP_PROGRESS_COMMAND_SET_TEXT,
|
||||
message, 0.0);
|
||||
message, 0.0, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -351,7 +349,7 @@ gimp_pdb_progress_progress_set_value (GimpProgress *progress,
|
|||
{
|
||||
gimp_pdb_progress_run_callback (pdb_progress,
|
||||
GIMP_PROGRESS_COMMAND_SET_VALUE,
|
||||
NULL, percentage);
|
||||
NULL, percentage, NULL);
|
||||
pdb_progress->value = percentage;
|
||||
}
|
||||
}
|
||||
|
@ -373,18 +371,19 @@ gimp_pdb_progress_progress_pulse (GimpProgress *progress)
|
|||
if (pdb_progress->active)
|
||||
gimp_pdb_progress_run_callback (pdb_progress,
|
||||
GIMP_PROGRESS_COMMAND_PULSE,
|
||||
NULL, 0.0);
|
||||
NULL, 0.0, NULL);
|
||||
}
|
||||
|
||||
static guint32
|
||||
static GBytes *
|
||||
gimp_pdb_progress_progress_get_window_id (GimpProgress *progress)
|
||||
{
|
||||
GimpPdbProgress *pdb_progress = GIMP_PDB_PROGRESS (progress);
|
||||
GBytes *handle = NULL;
|
||||
|
||||
return (guint32)
|
||||
gimp_pdb_progress_run_callback (pdb_progress,
|
||||
GIMP_PROGRESS_COMMAND_GET_WINDOW,
|
||||
NULL, 0.0);
|
||||
gimp_pdb_progress_run_callback (pdb_progress,
|
||||
GIMP_PROGRESS_COMMAND_GET_WINDOW,
|
||||
NULL, 0.0, &handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
GimpPdbProgress *
|
||||
|
|
|
@ -205,7 +205,7 @@ gimp_progress_pulse (GimpProgress *progress)
|
|||
progress_iface->pulse (progress);
|
||||
}
|
||||
|
||||
guint32
|
||||
GBytes *
|
||||
gimp_progress_get_window_id (GimpProgress *progress)
|
||||
{
|
||||
GimpProgressInterface *progress_iface;
|
||||
|
@ -217,7 +217,7 @@ gimp_progress_get_window_id (GimpProgress *progress)
|
|||
if (progress_iface->get_window_id)
|
||||
return progress_iface->get_window_id (progress);
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
|
@ -44,7 +44,7 @@ struct _GimpProgressInterface
|
|||
gdouble (* get_value) (GimpProgress *progress);
|
||||
void (* pulse) (GimpProgress *progress);
|
||||
|
||||
guint32 (* get_window_id) (GimpProgress *progress);
|
||||
GBytes * (* get_window_id) (GimpProgress *progress);
|
||||
|
||||
gboolean (* message) (GimpProgress *progress,
|
||||
Gimp *gimp,
|
||||
|
@ -74,7 +74,7 @@ void gimp_progress_set_value (GimpProgress *progress,
|
|||
gdouble gimp_progress_get_value (GimpProgress *progress);
|
||||
void gimp_progress_pulse (GimpProgress *progress);
|
||||
|
||||
guint32 gimp_progress_get_window_id (GimpProgress *progress);
|
||||
GBytes * gimp_progress_get_window_id (GimpProgress *progress);
|
||||
|
||||
gboolean gimp_progress_message (GimpProgress *progress,
|
||||
Gimp *gimp,
|
||||
|
|
|
@ -55,7 +55,7 @@ static void gimp_sub_progress_set_value (GimpProgress *prog
|
|||
gdouble percentage);
|
||||
static gdouble gimp_sub_progress_get_value (GimpProgress *progress);
|
||||
static void gimp_sub_progress_pulse (GimpProgress *progress);
|
||||
static guint32 gimp_sub_progress_get_window_id (GimpProgress *progress);
|
||||
static GBytes * gimp_sub_progress_get_window_id (GimpProgress *progress);
|
||||
static gboolean gimp_sub_progress_message (GimpProgress *progress,
|
||||
Gimp *gimp,
|
||||
GimpMessageSeverity severity,
|
||||
|
@ -224,7 +224,7 @@ gimp_sub_progress_pulse (GimpProgress *progress)
|
|||
gimp_progress_pulse (sub->progress);
|
||||
}
|
||||
|
||||
static guint32
|
||||
static GBytes *
|
||||
gimp_sub_progress_get_window_id (GimpProgress *progress)
|
||||
{
|
||||
GimpSubProgress *sub = GIMP_SUB_PROGRESS (progress);
|
||||
|
@ -232,7 +232,7 @@ gimp_sub_progress_get_window_id (GimpProgress *progress)
|
|||
if (sub->progress)
|
||||
return gimp_progress_get_window_id (sub->progress);
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -106,7 +106,7 @@ static void gimp_display_progress_set_value (GimpProgress *progre
|
|||
gdouble percentage);
|
||||
static gdouble gimp_display_progress_get_value (GimpProgress *progress);
|
||||
static void gimp_display_progress_pulse (GimpProgress *progress);
|
||||
static guint32 gimp_display_progress_get_window_id (GimpProgress *progress);
|
||||
static GBytes * gimp_display_progress_get_window_id (GimpProgress *progress);
|
||||
static gboolean gimp_display_progress_message (GimpProgress *progress,
|
||||
Gimp *gimp,
|
||||
GimpMessageSeverity severity,
|
||||
|
@ -319,7 +319,7 @@ gimp_display_progress_pulse (GimpProgress *progress)
|
|||
gimp_progress_pulse (GIMP_PROGRESS (display->priv->shell));
|
||||
}
|
||||
|
||||
static guint32
|
||||
static GBytes *
|
||||
gimp_display_progress_get_window_id (GimpProgress *progress)
|
||||
{
|
||||
GimpDisplayImpl *display = GIMP_DISPLAY_IMPL (progress);
|
||||
|
@ -327,7 +327,7 @@ gimp_display_progress_get_window_id (GimpProgress *progress)
|
|||
if (display->priv->shell)
|
||||
return gimp_progress_get_window_id (GIMP_PROGRESS (display->priv->shell));
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -99,15 +99,16 @@ gimp_display_shell_progress_pulse (GimpProgress *progress)
|
|||
gimp_progress_pulse (GIMP_PROGRESS (statusbar));
|
||||
}
|
||||
|
||||
static guint32
|
||||
static GBytes *
|
||||
gimp_display_shell_progress_get_window_id (GimpProgress *progress)
|
||||
{
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (progress));
|
||||
GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (progress);
|
||||
GBytes *handle = NULL;
|
||||
|
||||
if (GTK_IS_WINDOW (toplevel))
|
||||
return gimp_window_get_native_id (GTK_WINDOW (toplevel));
|
||||
if (shell->window_handle)
|
||||
handle = g_bytes_ref (shell->window_handle);
|
||||
|
||||
return 0;
|
||||
return handle;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include <gdk/gdkwayland.h>
|
||||
#endif
|
||||
|
||||
#include "libgimpbase/gimpbase.h"
|
||||
#include "libgimpmath/gimpmath.h"
|
||||
#include "libgimpcolor/gimpcolor.h"
|
||||
|
@ -583,6 +587,8 @@ gimp_display_shell_constructed (GObject *object)
|
|||
G_CALLBACK (gimp_display_shell_canvas_grab_notify),
|
||||
shell);
|
||||
|
||||
gimp_widget_set_native_handle (GTK_WIDGET (shell), &shell->window_handle);
|
||||
|
||||
g_signal_connect (shell->canvas, "realize",
|
||||
G_CALLBACK (gimp_display_shell_canvas_realize),
|
||||
shell);
|
||||
|
@ -847,6 +853,17 @@ gimp_display_shell_dispose (GObject *object)
|
|||
|
||||
shell->display = NULL;
|
||||
|
||||
if (shell->window_handle != NULL)
|
||||
{
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()) &&
|
||||
/* The GdkWindow is likely already destroyed. */
|
||||
gtk_widget_get_window (GTK_WIDGET (shell)) != NULL)
|
||||
gdk_wayland_window_unexport_handle (gtk_widget_get_window (GTK_WIDGET (shell)));
|
||||
#endif
|
||||
g_clear_pointer (&shell->window_handle, g_bytes_unref);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ struct _GimpDisplayShell
|
|||
|
||||
GimpDisplay *display;
|
||||
|
||||
GBytes *window_handle;
|
||||
|
||||
GimpUIManager *popup_manager;
|
||||
GdkMonitor *initial_monitor;
|
||||
|
||||
|
|
|
@ -283,10 +283,7 @@ progress_error_dialog (GimpProgress *progress)
|
|||
}
|
||||
else
|
||||
{
|
||||
guint32 window_id = gimp_progress_get_window_id (progress);
|
||||
|
||||
if (window_id)
|
||||
gimp_window_set_transient_for (GTK_WINDOW (dialog), window_id);
|
||||
gimp_window_set_transient_for (GTK_WINDOW (dialog), progress);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ static GFile * gui_get_theme_dir (Gimp *gimp);
|
|||
static GFile * gui_get_icon_theme_dir (Gimp *gimp);
|
||||
static GimpObject * gui_get_window_strategy (Gimp *gimp);
|
||||
static GimpDisplay * gui_get_empty_display (Gimp *gimp);
|
||||
static guint32 gui_display_get_window_id (GimpDisplay *display);
|
||||
static GBytes * gui_display_get_window_id (GimpDisplay *display);
|
||||
static GimpDisplay * gui_display_create (Gimp *gimp,
|
||||
GimpImage *image,
|
||||
GimpUnit unit,
|
||||
|
@ -374,7 +374,7 @@ gui_get_empty_display (Gimp *gimp)
|
|||
return display;
|
||||
}
|
||||
|
||||
static guint32
|
||||
static GBytes *
|
||||
gui_display_get_window_id (GimpDisplay *display)
|
||||
{
|
||||
GimpDisplay *disp = GIMP_DISPLAY (display);
|
||||
|
@ -382,13 +382,11 @@ gui_display_get_window_id (GimpDisplay *display)
|
|||
|
||||
if (shell)
|
||||
{
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (shell));
|
||||
|
||||
if (GTK_IS_WINDOW (toplevel))
|
||||
return gimp_window_get_native_id (GTK_WINDOW (toplevel));
|
||||
if (shell)
|
||||
return g_bytes_ref (shell->window_handle);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static GimpDisplay *
|
||||
|
@ -703,12 +701,7 @@ gui_pdb_dialog_new (Gimp *gimp,
|
|||
gimp_docked_set_show_button_bar (GIMP_DOCKED (view), FALSE);
|
||||
|
||||
if (progress)
|
||||
{
|
||||
guint32 window_id = gimp_progress_get_window_id (progress);
|
||||
|
||||
if (window_id)
|
||||
gimp_window_set_transient_for (GTK_WINDOW (dialog), window_id);
|
||||
}
|
||||
gimp_window_set_transient_for (GTK_WINDOW (dialog), progress);
|
||||
|
||||
gtk_widget_show (dialog);
|
||||
|
||||
|
|
|
@ -144,20 +144,20 @@ display_get_window_handle_invoker (GimpProcedure *procedure,
|
|||
gboolean success = TRUE;
|
||||
GimpValueArray *return_vals;
|
||||
GimpDisplay *display;
|
||||
gint window = 0;
|
||||
GBytes *handle = NULL;
|
||||
|
||||
display = g_value_get_object (gimp_value_array_index (args, 0));
|
||||
|
||||
if (success)
|
||||
{
|
||||
window = (gint32) gimp_get_display_window_id (gimp, display);
|
||||
handle = gimp_get_display_window_id (gimp, display);
|
||||
}
|
||||
|
||||
return_vals = gimp_procedure_get_return_values (procedure, success,
|
||||
error ? *error : NULL);
|
||||
|
||||
if (success)
|
||||
g_value_set_int (gimp_value_array_index (return_vals, 1), window);
|
||||
g_value_take_boxed (gimp_value_array_index (return_vals, 1), handle);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
@ -326,7 +326,8 @@ register_display_procs (GimpPDB *pdb)
|
|||
"gimp-display-get-window-handle");
|
||||
gimp_procedure_set_static_help (procedure,
|
||||
"Get a handle to the native window for an image display.",
|
||||
"This procedure returns a handle to the native window for a given image display. For example in the X backend of GDK, a native window handle is an Xlib XID. A value of 0 is returned for an invalid display or if this function is unimplemented for the windowing system that is being used.",
|
||||
"This procedure returns a handle to the native window for a given image display.\n"
|
||||
"It can be different types of data depending on the platform you are running on. For example in the X backend of GDK, a native window handle is an Xlib XID whereas on Wayland, it is a string handle. A value of NULL is returned for an invalid display or if this function is unimplemented for the windowing system that is being used.",
|
||||
NULL);
|
||||
gimp_procedure_set_static_attribution (procedure,
|
||||
"Sven Neumann <sven@gimp.org>",
|
||||
|
@ -339,11 +340,11 @@ register_display_procs (GimpPDB *pdb)
|
|||
FALSE,
|
||||
GIMP_PARAM_READWRITE));
|
||||
gimp_procedure_add_return_value (procedure,
|
||||
g_param_spec_int ("window",
|
||||
"window",
|
||||
"The native window handle or 0",
|
||||
G_MININT32, G_MAXINT32, 0,
|
||||
GIMP_PARAM_READWRITE));
|
||||
g_param_spec_boxed ("handle",
|
||||
"handle",
|
||||
"The native window handle or NULL",
|
||||
G_TYPE_BYTES,
|
||||
GIMP_PARAM_READWRITE));
|
||||
gimp_pdb_register_procedure (pdb, procedure);
|
||||
g_object_unref (procedure);
|
||||
|
||||
|
|
|
@ -189,14 +189,14 @@ progress_get_window_handle_invoker (GimpProcedure *procedure,
|
|||
{
|
||||
gboolean success = TRUE;
|
||||
GimpValueArray *return_vals;
|
||||
gint window = 0;
|
||||
GBytes *handle = NULL;
|
||||
|
||||
GimpPlugIn *plug_in = gimp->plug_in_manager->current_plug_in;
|
||||
|
||||
if (plug_in && plug_in->open)
|
||||
{
|
||||
if (! gimp->no_interface)
|
||||
window = gimp_plug_in_progress_get_window_id (plug_in);
|
||||
handle = gimp_plug_in_progress_get_window_id (plug_in);
|
||||
}
|
||||
else
|
||||
success = FALSE;
|
||||
|
@ -205,7 +205,7 @@ progress_get_window_handle_invoker (GimpProcedure *procedure,
|
|||
error ? *error : NULL);
|
||||
|
||||
if (success)
|
||||
g_value_set_int (gimp_value_array_index (return_vals, 1), window);
|
||||
g_value_take_boxed (gimp_value_array_index (return_vals, 1), handle);
|
||||
|
||||
return return_vals;
|
||||
}
|
||||
|
@ -414,19 +414,20 @@ register_progress_procs (GimpPDB *pdb)
|
|||
gimp_object_set_static_name (GIMP_OBJECT (procedure),
|
||||
"gimp-progress-get-window-handle");
|
||||
gimp_procedure_set_static_help (procedure,
|
||||
"Returns the native window ID of the toplevel window this plug-in's progress is displayed in.",
|
||||
"This function returns the native window ID of the toplevel window this plug-in\'s progress is displayed in.",
|
||||
"Returns the native handle of the toplevel window this plug-in's progress is displayed in.",
|
||||
"This function returns the native handle allowing to identify the toplevel window this plug-in's progress is displayed in.\n"
|
||||
"This handle can be of various types (integer, string, etc.) depending on the platform you are running on which is why it returns a GBytes. There are usually no reasons to call this directly.",
|
||||
NULL);
|
||||
gimp_procedure_set_static_attribution (procedure,
|
||||
"Michael Natterer <mitch@gimp.org>",
|
||||
"Michael Natterer",
|
||||
"2004");
|
||||
gimp_procedure_add_return_value (procedure,
|
||||
g_param_spec_int ("window",
|
||||
"window",
|
||||
"The progress bar's toplevel window",
|
||||
G_MININT32, G_MAXINT32, 0,
|
||||
GIMP_PARAM_READWRITE));
|
||||
g_param_spec_boxed ("handle",
|
||||
"handle",
|
||||
"The progress bar's toplevel window's handle",
|
||||
G_TYPE_BYTES,
|
||||
GIMP_PARAM_READWRITE));
|
||||
gimp_pdb_register_procedure (pdb, procedure);
|
||||
g_object_unref (procedure);
|
||||
|
||||
|
|
|
@ -233,7 +233,7 @@ gimp_plug_in_progress_pulse (GimpPlugIn *plug_in)
|
|||
gimp_progress_pulse (proc_frame->progress);
|
||||
}
|
||||
|
||||
guint32
|
||||
GBytes *
|
||||
gimp_plug_in_progress_get_window_id (GimpPlugIn *plug_in)
|
||||
{
|
||||
GimpPlugInProcFrame *proc_frame;
|
||||
|
|
|
@ -34,7 +34,7 @@ void gimp_plug_in_progress_set_text (GimpPlugIn *plug_in,
|
|||
void gimp_plug_in_progress_set_value (GimpPlugIn *plug_in,
|
||||
gdouble percentage);
|
||||
void gimp_plug_in_progress_pulse (GimpPlugIn *plug_in);
|
||||
guint32 gimp_plug_in_progress_get_window_id (GimpPlugIn *plug_in);
|
||||
GBytes * gimp_plug_in_progress_get_window_id (GimpPlugIn *plug_in);
|
||||
|
||||
gboolean gimp_plug_in_progress_install (GimpPlugIn *plug_in,
|
||||
const gchar *progress_callback);
|
||||
|
|
|
@ -104,7 +104,7 @@ static void gimp_file_dialog_progress_set_value (GimpProgress *p
|
|||
gdouble percentage);
|
||||
static gdouble gimp_file_dialog_progress_get_value (GimpProgress *progress);
|
||||
static void gimp_file_dialog_progress_pulse (GimpProgress *progress);
|
||||
static guint32 gimp_file_dialog_progress_get_window_id (GimpProgress *progress);
|
||||
static GBytes * gimp_file_dialog_progress_get_window_id (GimpProgress *progress);
|
||||
|
||||
static void gimp_file_dialog_add_user_dir (GimpFileDialog *dialog,
|
||||
GUserDirectory directory);
|
||||
|
@ -368,6 +368,8 @@ gimp_file_dialog_constructed (GObject *object)
|
|||
dialog->progress = gimp_progress_box_new ();
|
||||
gtk_box_pack_end (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
|
||||
dialog->progress, FALSE, FALSE, 0);
|
||||
|
||||
gimp_widget_set_native_handle (GTK_WIDGET (dialog), &dialog->window_handle);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -575,12 +577,12 @@ gimp_file_dialog_progress_pulse (GimpProgress *progress)
|
|||
gimp_progress_pulse (GIMP_PROGRESS (dialog->progress));
|
||||
}
|
||||
|
||||
static guint32
|
||||
static GBytes *
|
||||
gimp_file_dialog_progress_get_window_id (GimpProgress *progress)
|
||||
{
|
||||
GimpFileDialog *dialog = GIMP_FILE_DIALOG (progress);
|
||||
|
||||
return gimp_window_get_native_id (GTK_WINDOW (dialog));
|
||||
return dialog->window_handle;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -38,6 +38,8 @@ struct _GimpFileDialog
|
|||
{
|
||||
GtkFileChooserDialog parent_instance;
|
||||
|
||||
GBytes *window_handle;
|
||||
|
||||
Gimp *gimp;
|
||||
GimpImage *image;
|
||||
|
||||
|
|
|
@ -447,12 +447,7 @@ gimp_help_browser_error (Gimp *gimp,
|
|||
-1);
|
||||
|
||||
if (progress)
|
||||
{
|
||||
guint32 window_id = gimp_progress_get_window_id (progress);
|
||||
|
||||
if (window_id)
|
||||
gimp_window_set_transient_for (GTK_WINDOW (dialog), window_id);
|
||||
}
|
||||
gimp_window_set_transient_for (GTK_WINDOW (dialog), progress);
|
||||
|
||||
gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
|
||||
"%s", primary);
|
||||
|
@ -781,12 +776,7 @@ gimp_help_query_alt_user_manual (GimpIdleHelp *idle_help)
|
|||
idle_help->query_dialog = GTK_DIALOG (dialog);
|
||||
|
||||
if (idle_help->progress)
|
||||
{
|
||||
guint32 window_id = gimp_progress_get_window_id (idle_help->progress);
|
||||
|
||||
if (window_id)
|
||||
gimp_window_set_transient_for (GTK_WINDOW (dialog), window_id);
|
||||
}
|
||||
gimp_window_set_transient_for (GTK_WINDOW (dialog), idle_help->progress);
|
||||
|
||||
gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
|
||||
_("The GIMP user manual is not installed "
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
#include "gegl/gimp-babl.h"
|
||||
|
||||
#include "core/gimp.h"
|
||||
#include "core/gimpprogress.h"
|
||||
#include "core/gimptoolinfo.h"
|
||||
|
||||
#include "gimpaccellabel.h"
|
||||
|
@ -87,11 +88,15 @@ typedef struct
|
|||
gchar *settings_value;
|
||||
} BlinkStep;
|
||||
|
||||
static void gimp_widget_blink_after (GtkWidget *widget,
|
||||
gint ms_timeout);
|
||||
static void gimp_search_widget_rec (GtkWidget *widget,
|
||||
BlinkSearch *data);
|
||||
static void gimp_blink_free_script (GList *blink_scenario);
|
||||
static void gimp_widget_blink_after (GtkWidget *widget,
|
||||
gint ms_timeout);
|
||||
static void gimp_search_widget_rec (GtkWidget *widget,
|
||||
BlinkSearch *data);
|
||||
static void gimp_blink_free_script (GList *blink_scenario);
|
||||
|
||||
static gboolean gimp_window_transient_on_mapped (GtkWidget *widget,
|
||||
GdkEventAny *event,
|
||||
GimpProgress *progress);
|
||||
|
||||
|
||||
GtkWidget *
|
||||
|
@ -905,54 +910,7 @@ gimp_window_set_hint (GtkWindow *window,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_window_get_native_id:
|
||||
* @window: a #GtkWindow
|
||||
*
|
||||
* This function is used to pass a window handle to plug-ins so that
|
||||
* they can set their dialog windows transient to the parent window.
|
||||
*
|
||||
* Returns: a native window ID of the window's #GdkWindow or 0
|
||||
* if the window isn't realized yet
|
||||
*/
|
||||
guint32
|
||||
gimp_window_get_native_id (GtkWindow *window)
|
||||
{
|
||||
GdkWindow *surface;
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
|
||||
|
||||
surface = gtk_widget_get_window (GTK_WIDGET (window));
|
||||
if (!surface) /* aka window is not yet realized */
|
||||
return 0;
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (GDK_IS_WIN32_WINDOW (surface))
|
||||
return GPOINTER_TO_INT (GDK_WINDOW_HWND (gtk_widget_get_window (GTK_WIDGET (window))));
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
if (GDK_IS_X11_WINDOW (surface))
|
||||
return GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (window)));
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW (surface))
|
||||
g_debug ("Getting window ID for progress not supported on Wayland yet");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef GDK_WINDOWING_WIN32
|
||||
static void
|
||||
gimp_window_transient_realized (GtkWidget *window,
|
||||
GdkWindow *parent)
|
||||
{
|
||||
if (gtk_widget_get_realized (window))
|
||||
gdk_window_set_transient_for (gtk_widget_get_window (window), parent);
|
||||
}
|
||||
|
||||
/* similar to what we have in libgimp/gimpui.c */
|
||||
static GdkWindow *
|
||||
gimp_get_foreign_window (guint32 window)
|
||||
|
@ -973,37 +931,15 @@ gimp_get_foreign_window (guint32 window)
|
|||
#endif
|
||||
|
||||
void
|
||||
gimp_window_set_transient_for (GtkWindow *window,
|
||||
guint32 parent_ID)
|
||||
gimp_window_set_transient_for (GtkWindow *window,
|
||||
GimpProgress *parent)
|
||||
{
|
||||
/* Cross-process transient-for is broken in gdk/win32 <= 2.10.6. It
|
||||
* causes hangs, at least when used as by the gimp and script-fu
|
||||
* processes. In some newer GTK+ version it will be fixed to be a
|
||||
* no-op. If it eventually is fixed to actually work, change this to
|
||||
* a run-time check of GTK+ version. Remember to change also the
|
||||
* function with the same name in libgimp/gimpui.c
|
||||
*
|
||||
* Note: this hanging bug is still happening with GTK+3 as of 2019-10,
|
||||
* with steps described in comment 4 in:
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=359538
|
||||
*/
|
||||
#ifndef GDK_WINDOWING_WIN32
|
||||
GdkWindow *parent;
|
||||
g_signal_connect_after (window, "map-event",
|
||||
G_CALLBACK (gimp_window_transient_on_mapped),
|
||||
parent);
|
||||
|
||||
parent = gimp_get_foreign_window (parent_ID);
|
||||
if (! parent)
|
||||
return;
|
||||
|
||||
if (gtk_widget_get_realized (GTK_WIDGET (window)))
|
||||
gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (window)),
|
||||
parent);
|
||||
|
||||
g_signal_connect_object (window, "realize",
|
||||
G_CALLBACK (gimp_window_transient_realized),
|
||||
parent, 0);
|
||||
|
||||
g_object_unref (parent);
|
||||
#endif
|
||||
if (gtk_widget_get_mapped (GTK_WIDGET (window)))
|
||||
gimp_window_transient_on_mapped (GTK_WIDGET (window), NULL, parent);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -2570,3 +2506,65 @@ gimp_utils_are_menu_path_identical (const gchar *path1,
|
|||
|
||||
return identical;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_window_transient_on_mapped (GtkWidget *window,
|
||||
GdkEventAny *event,
|
||||
GimpProgress *progress)
|
||||
{
|
||||
GBytes *handle;
|
||||
gboolean transient_set = FALSE;
|
||||
|
||||
handle = gimp_progress_get_window_id (progress);
|
||||
|
||||
if (handle == NULL)
|
||||
return FALSE;
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()))
|
||||
{
|
||||
char *wayland_handle;
|
||||
|
||||
wayland_handle = (char *) g_bytes_get_data (handle, NULL);
|
||||
gdk_wayland_window_set_transient_for_exported (gtk_widget_get_window (window),
|
||||
wayland_handle);
|
||||
transient_set = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Cross-process transient-for is broken in gdk/win32 <= 2.10.6. It
|
||||
* causes hangs, at least when used as by the gimp and script-fu
|
||||
* processes. In some newer GTK+ version it will be fixed to be a
|
||||
* no-op. If it eventually is fixed to actually work, change this to
|
||||
* a run-time check of GTK+ version. Remember to change also the
|
||||
* function with the same name in libgimp/gimpui.c
|
||||
*
|
||||
* Note: this hanging bug is still happening with GTK+3 as of 2019-10,
|
||||
* with steps described in comment 4 in:
|
||||
* https://bugzilla.gnome.org/show_bug.cgi?id=359538
|
||||
*/
|
||||
#ifndef GDK_WINDOWING_WIN32
|
||||
if (! transient_set)
|
||||
{
|
||||
GdkWindow *parent;
|
||||
guint32 *handle_data;
|
||||
guint32 parent_ID;
|
||||
gsize handle_size;
|
||||
|
||||
handle_data = (guint32 *) g_bytes_get_data (handle, &handle_size);
|
||||
g_return_val_if_fail (handle_size == sizeof (guint32), FALSE);
|
||||
parent_ID = *handle_data;
|
||||
|
||||
parent = gimp_get_foreign_window (parent_ID);
|
||||
|
||||
if (parent)
|
||||
gdk_window_set_transient_for (gtk_widget_get_window (window), parent);
|
||||
|
||||
transient_set = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
g_bytes_unref (handle);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -71,9 +71,8 @@ gboolean gimp_get_style_color (GtkWidget *widget
|
|||
GdkRGBA *color);
|
||||
void gimp_window_set_hint (GtkWindow *window,
|
||||
GimpWindowHint hint);
|
||||
guint32 gimp_window_get_native_id (GtkWindow *window);
|
||||
void gimp_window_set_transient_for (GtkWindow *window,
|
||||
guint32 parent_ID);
|
||||
GimpProgress *progress);
|
||||
void gimp_widget_set_accel_help (GtkWidget *widget,
|
||||
GimpAction *action);
|
||||
|
||||
|
|
|
@ -156,21 +156,23 @@ gimp_display_delete (GimpDisplay *display)
|
|||
* Get a handle to the native window for an image display.
|
||||
*
|
||||
* This procedure returns a handle to the native window for a given
|
||||
* image display. For example in the X backend of GDK, a native window
|
||||
* handle is an Xlib XID. A value of 0 is returned for an invalid
|
||||
* display or if this function is unimplemented for the windowing
|
||||
* system that is being used.
|
||||
* image display.
|
||||
* It can be different types of data depending on the platform you are
|
||||
* running on. For example in the X backend of GDK, a native window
|
||||
* handle is an Xlib XID whereas on Wayland, it is a string handle. A
|
||||
* value of NULL is returned for an invalid display or if this function
|
||||
* is unimplemented for the windowing system that is being used.
|
||||
*
|
||||
* Returns: The native window handle or 0.
|
||||
* Returns: (transfer full): The native window handle or NULL.
|
||||
*
|
||||
* Since: 2.4
|
||||
**/
|
||||
gint
|
||||
GBytes *
|
||||
gimp_display_get_window_handle (GimpDisplay *display)
|
||||
{
|
||||
GimpValueArray *args;
|
||||
GimpValueArray *return_vals;
|
||||
gint window = 0;
|
||||
GBytes *handle = NULL;
|
||||
|
||||
args = gimp_value_array_new_from_types (NULL,
|
||||
GIMP_TYPE_DISPLAY, display,
|
||||
|
@ -182,11 +184,11 @@ gimp_display_get_window_handle (GimpDisplay *display)
|
|||
gimp_value_array_unref (args);
|
||||
|
||||
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
|
||||
window = GIMP_VALUES_GET_INT (return_vals, 1);
|
||||
handle = GIMP_VALUES_DUP_BYTES (return_vals, 1);
|
||||
|
||||
gimp_value_array_unref (return_vals);
|
||||
|
||||
return window;
|
||||
return handle;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -35,7 +35,7 @@ G_BEGIN_DECLS
|
|||
gboolean gimp_display_id_is_valid (gint display_id);
|
||||
GimpDisplay* gimp_display_new (GimpImage *image);
|
||||
gboolean gimp_display_delete (GimpDisplay *display);
|
||||
gint gimp_display_get_window_handle (GimpDisplay *display);
|
||||
GBytes* gimp_display_get_window_handle (GimpDisplay *display);
|
||||
gboolean gimp_display_present (GimpDisplay *display);
|
||||
gboolean gimp_displays_flush (void);
|
||||
gboolean gimp_displays_reconnect (GimpImage *old_image,
|
||||
|
|
|
@ -394,7 +394,7 @@ G_BEGIN_DECLS
|
|||
#define GIMP_VALUES_DUP_BYTES(args, n) \
|
||||
g_value_dup_boxed (gimp_value_array_index (args, n))
|
||||
|
||||
#define GIMP_VALUES_SET_BYTES(args, n, value, length) \
|
||||
#define GIMP_VALUES_SET_BYTES(args, n, value) \
|
||||
g_value_set_boxed (gimp_value_array_index (args, n), value)
|
||||
|
||||
#define GIMP_VALUES_TAKE_BYTES(args, n, value, length) \
|
||||
|
|
|
@ -89,15 +89,15 @@ gimp_progress_install_vtable (const GimpProgressVtable *vtable,
|
|||
|
||||
progress_data = g_slice_new0 (GimpProgressData);
|
||||
|
||||
progress_data->progress_callback = progress_callback;
|
||||
progress_data->vtable.start = vtable->start;
|
||||
progress_data->vtable.end = vtable->end;
|
||||
progress_data->vtable.set_text = vtable->set_text;
|
||||
progress_data->vtable.set_value = vtable->set_value;
|
||||
progress_data->vtable.pulse = vtable->pulse;
|
||||
progress_data->vtable.get_window = vtable->get_window;
|
||||
progress_data->data = user_data;
|
||||
progress_data->data_destroy = user_data_destroy;
|
||||
progress_data->progress_callback = progress_callback;
|
||||
progress_data->vtable.start = vtable->start;
|
||||
progress_data->vtable.end = vtable->end;
|
||||
progress_data->vtable.set_text = vtable->set_text;
|
||||
progress_data->vtable.set_value = vtable->set_value;
|
||||
progress_data->vtable.pulse = vtable->pulse;
|
||||
progress_data->vtable.get_window_handle = vtable->get_window_handle;
|
||||
progress_data->data = user_data;
|
||||
progress_data->data_destroy = user_data_destroy;
|
||||
|
||||
procedure = gimp_procedure_new (plug_in,
|
||||
progress_callback,
|
||||
|
@ -384,15 +384,16 @@ gimp_temp_progress_run (GimpProcedure *procedure,
|
|||
case GIMP_PROGRESS_COMMAND_GET_WINDOW:
|
||||
{
|
||||
GimpValueArray *return_vals;
|
||||
guint64 window_id = 0;
|
||||
GBytes *window_handle = NULL;
|
||||
|
||||
if (progress_data->vtable.get_window)
|
||||
window_id = progress_data->vtable.get_window (progress_data->data);
|
||||
if (progress_data->vtable.get_window_handle)
|
||||
window_handle = progress_data->vtable.get_window_handle (progress_data->data);
|
||||
|
||||
return_vals = gimp_procedure_new_return_values (procedure,
|
||||
GIMP_PDB_SUCCESS,
|
||||
NULL);
|
||||
GIMP_VALUES_SET_DOUBLE (return_vals, 1, window_id);
|
||||
GIMP_VALUES_SET_BYTES (return_vals, 1, window_handle);
|
||||
g_bytes_unref (window_handle);
|
||||
g_free (text);
|
||||
|
||||
return return_vals;
|
||||
|
|
|
@ -79,9 +79,9 @@ typedef void (* GimpProgressVtablePulseFunc) (gpointer user_data);
|
|||
* GimpProgressVtableGetWindowFunc:
|
||||
* @user_data: (closure): User data
|
||||
*
|
||||
* Returns: the ID of the window where the progress is displayed.
|
||||
* Returns: the handle of the window where the progress is displayed.
|
||||
*/
|
||||
typedef guint64 (* GimpProgressVtableGetWindowFunc) (gpointer user_data);
|
||||
typedef GBytes * (* GimpProgressVtableGetWindowFunc) (gpointer user_data);
|
||||
|
||||
|
||||
typedef struct _GimpProgressVtable GimpProgressVtable;
|
||||
|
@ -93,7 +93,7 @@ typedef struct _GimpProgressVtable GimpProgressVtable;
|
|||
* @set_text: sets a new text on the progress.
|
||||
* @set_value: sets a new percentage on the progress.
|
||||
* @pulse: makes the progress pulse.
|
||||
* @get_window: returns the ID of the window where the progress is displayed.
|
||||
* @get_window_handle: returns the handle of the window where the progress is displayed.
|
||||
* @_gimp_reserved1: reserved pointer for future expansion.
|
||||
* @_gimp_reserved2: reserved pointer for future expansion.
|
||||
* @_gimp_reserved3: reserved pointer for future expansion.
|
||||
|
@ -110,7 +110,7 @@ struct _GimpProgressVtable
|
|||
GimpProgressVtableSetTextFunc set_text;
|
||||
GimpProgressVtableSetValueFunc set_value;
|
||||
GimpProgressVtablePulseFunc pulse;
|
||||
GimpProgressVtableGetWindowFunc get_window;
|
||||
GimpProgressVtableGetWindowFunc get_window_handle;
|
||||
|
||||
/* Padding for future expansion. Must be initialized with NULL! */
|
||||
void (* _gimp_reserved1) (void);
|
||||
|
|
|
@ -219,22 +219,25 @@ gimp_progress_end (void)
|
|||
/**
|
||||
* gimp_progress_get_window_handle:
|
||||
*
|
||||
* Returns the native window ID of the toplevel window this plug-in's
|
||||
* Returns the native handle of the toplevel window this plug-in's
|
||||
* progress is displayed in.
|
||||
*
|
||||
* This function returns the native window ID of the toplevel window
|
||||
* this plug-in\'s progress is displayed in.
|
||||
* This function returns the native handle allowing to identify the
|
||||
* toplevel window this plug-in's progress is displayed in.
|
||||
* This handle can be of various types (integer, string, etc.)
|
||||
* depending on the platform you are running on which is why it returns
|
||||
* a GBytes. There are usually no reasons to call this directly.
|
||||
*
|
||||
* Returns: The progress bar's toplevel window.
|
||||
* Returns: (transfer full): The progress bar's toplevel window's handle.
|
||||
*
|
||||
* Since: 2.2
|
||||
**/
|
||||
gint
|
||||
GBytes *
|
||||
gimp_progress_get_window_handle (void)
|
||||
{
|
||||
GimpValueArray *args;
|
||||
GimpValueArray *return_vals;
|
||||
gint window = 0;
|
||||
GBytes *handle = NULL;
|
||||
|
||||
args = gimp_value_array_new_from_types (NULL,
|
||||
G_TYPE_NONE);
|
||||
|
@ -245,11 +248,11 @@ gimp_progress_get_window_handle (void)
|
|||
gimp_value_array_unref (args);
|
||||
|
||||
if (GIMP_VALUES_GET_ENUM (return_vals, 0) == GIMP_PDB_SUCCESS)
|
||||
window = GIMP_VALUES_GET_INT (return_vals, 1);
|
||||
handle = GIMP_VALUES_DUP_BYTES (return_vals, 1);
|
||||
|
||||
gimp_value_array_unref (return_vals);
|
||||
|
||||
return window;
|
||||
return handle;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -38,7 +38,7 @@ G_GNUC_INTERNAL gboolean _gimp_progress_update (gdouble percentag
|
|||
gboolean gimp_progress_pulse (void);
|
||||
gboolean gimp_progress_set_text (const gchar *message);
|
||||
gboolean gimp_progress_end (void);
|
||||
gint gimp_progress_get_window_handle (void);
|
||||
GBytes* gimp_progress_get_window_handle (void);
|
||||
G_GNUC_INTERNAL gboolean _gimp_progress_install (const gchar *progress_callback);
|
||||
G_GNUC_INTERNAL gboolean _gimp_progress_uninstall (const gchar *progress_callback);
|
||||
gboolean gimp_progress_cancel (const gchar *progress_callback);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
|
@ -35,6 +36,8 @@
|
|||
#include <gdk/gdkwayland.h>
|
||||
#endif
|
||||
|
||||
#include "libgimpwidgets/gimpwidgets.h"
|
||||
|
||||
#include "gimpuitypes.h"
|
||||
|
||||
#include "gimp.h"
|
||||
|
@ -52,21 +55,27 @@
|
|||
**/
|
||||
|
||||
|
||||
static void gimp_progress_bar_dispose (GObject *object);
|
||||
|
||||
static void gimp_progress_bar_start (const gchar *message,
|
||||
gboolean cancelable,
|
||||
gpointer user_data);
|
||||
static void gimp_progress_bar_end (gpointer user_data);
|
||||
static void gimp_progress_bar_set_text (const gchar *message,
|
||||
gpointer user_data);
|
||||
static void gimp_progress_bar_set_value (gdouble percentage,
|
||||
gpointer user_data);
|
||||
static void gimp_progress_bar_pulse (gpointer user_data);
|
||||
static guint64 gimp_progress_bar_get_window (gpointer user_data);
|
||||
typedef struct _GimpProgressBarPrivate
|
||||
{
|
||||
GBytes *window_handle;
|
||||
} GimpProgressBarPrivate;
|
||||
|
||||
|
||||
G_DEFINE_TYPE (GimpProgressBar, gimp_progress_bar, GTK_TYPE_PROGRESS_BAR)
|
||||
static void gimp_progress_bar_dispose (GObject *object);
|
||||
|
||||
static void gimp_progress_bar_start (const gchar *message,
|
||||
gboolean cancelable,
|
||||
gpointer user_data);
|
||||
static void gimp_progress_bar_end (gpointer user_data);
|
||||
static void gimp_progress_bar_set_text (const gchar *message,
|
||||
gpointer user_data);
|
||||
static void gimp_progress_bar_set_value (gdouble percentage,
|
||||
gpointer user_data);
|
||||
static void gimp_progress_bar_pulse (gpointer user_data);
|
||||
static GBytes * gimp_progress_bar_get_window_handle (gpointer user_data);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GimpProgressBar, gimp_progress_bar, GTK_TYPE_PROGRESS_BAR)
|
||||
|
||||
#define parent_class gimp_progress_bar_parent_class
|
||||
|
||||
|
@ -82,25 +91,29 @@ gimp_progress_bar_class_init (GimpProgressBarClass *klass)
|
|||
static void
|
||||
gimp_progress_bar_init (GimpProgressBar *bar)
|
||||
{
|
||||
GimpProgressVtable vtable = { 0, };
|
||||
GimpProgressVtable vtable = { 0, };
|
||||
GimpProgressBarPrivate *priv = gimp_progress_bar_get_instance_private (bar);
|
||||
|
||||
gtk_progress_bar_set_text (GTK_PROGRESS_BAR (bar), " ");
|
||||
gtk_progress_bar_set_ellipsize (GTK_PROGRESS_BAR (bar), PANGO_ELLIPSIZE_END);
|
||||
|
||||
vtable.start = gimp_progress_bar_start;
|
||||
vtable.end = gimp_progress_bar_end;
|
||||
vtable.set_text = gimp_progress_bar_set_text;
|
||||
vtable.set_value = gimp_progress_bar_set_value;
|
||||
vtable.pulse = gimp_progress_bar_pulse;
|
||||
vtable.get_window = gimp_progress_bar_get_window;
|
||||
vtable.start = gimp_progress_bar_start;
|
||||
vtable.end = gimp_progress_bar_end;
|
||||
vtable.set_text = gimp_progress_bar_set_text;
|
||||
vtable.set_value = gimp_progress_bar_set_value;
|
||||
vtable.pulse = gimp_progress_bar_pulse;
|
||||
vtable.get_window_handle = gimp_progress_bar_get_window_handle;
|
||||
|
||||
bar->progress_callback = gimp_progress_install_vtable (&vtable, bar, NULL);
|
||||
|
||||
gimp_widget_set_native_handle (GTK_WIDGET (bar), &priv->window_handle);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_progress_bar_dispose (GObject *object)
|
||||
{
|
||||
GimpProgressBar *bar = GIMP_PROGRESS_BAR (object);
|
||||
GimpProgressBar *bar = GIMP_PROGRESS_BAR (object);
|
||||
GimpProgressBarPrivate *priv = gimp_progress_bar_get_instance_private (bar);
|
||||
|
||||
if (bar->progress_callback)
|
||||
{
|
||||
|
@ -108,6 +121,17 @@ gimp_progress_bar_dispose (GObject *object)
|
|||
bar->progress_callback = NULL;
|
||||
}
|
||||
|
||||
if (priv->window_handle != NULL)
|
||||
{
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()) &&
|
||||
/* The GdkWindow is likely already destroyed. */
|
||||
gtk_widget_get_window (GTK_WIDGET (bar)) != NULL)
|
||||
gdk_wayland_window_unexport_handle (gtk_widget_get_window (GTK_WIDGET (bar)));
|
||||
#endif
|
||||
g_clear_pointer (&priv->window_handle, g_bytes_unref);
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@ -180,47 +204,13 @@ gimp_progress_bar_pulse (gpointer user_data)
|
|||
gtk_main_iteration ();
|
||||
}
|
||||
|
||||
static guint64
|
||||
gimp_window_get_native_id (GtkWindow *window)
|
||||
static GBytes *
|
||||
gimp_progress_bar_get_window_handle (gpointer user_data)
|
||||
{
|
||||
GdkWindow *surface;
|
||||
GimpProgressBar *bar = GIMP_PROGRESS_BAR (user_data);
|
||||
GimpProgressBarPrivate *priv = gimp_progress_bar_get_instance_private (bar);
|
||||
|
||||
g_return_val_if_fail (GTK_IS_WINDOW (window), 0);
|
||||
|
||||
surface = gtk_widget_get_window (GTK_WIDGET (window));
|
||||
if (!surface) /* aka window is not yet realized */
|
||||
return 0;
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (GDK_IS_WIN32_WINDOW (surface))
|
||||
return GPOINTER_TO_INT (GDK_WINDOW_HWND (gtk_widget_get_window (GTK_WIDGET (window))));
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
if (GDK_IS_X11_WINDOW (surface))
|
||||
return GPOINTER_TO_INT (GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (window))));
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW (surface))
|
||||
g_debug ("Getting window ID for progress not supported on Wayland yet");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static guint64
|
||||
gimp_progress_bar_get_window (gpointer user_data)
|
||||
{
|
||||
GimpProgressBar *bar = GIMP_PROGRESS_BAR (user_data);
|
||||
GtkWidget *toplevel;
|
||||
|
||||
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (bar));
|
||||
|
||||
if (GTK_IS_WINDOW (toplevel))
|
||||
return gimp_window_get_native_id (GTK_WINDOW (toplevel));
|
||||
|
||||
return 0;
|
||||
return g_bytes_ref (priv->window_handle);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
286
libgimp/gimpui.c
286
libgimp/gimpui.c
|
@ -32,6 +32,10 @@
|
|||
#include <Cocoa/Cocoa.h>
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include <gdk/gdkwayland.h>
|
||||
#endif
|
||||
|
||||
#include "gimp.h"
|
||||
#include "gimpui.h"
|
||||
|
||||
|
@ -55,25 +59,26 @@
|
|||
|
||||
/* local function prototypes */
|
||||
|
||||
static void gimp_ui_help_func (const gchar *help_id,
|
||||
gpointer help_data);
|
||||
static void gimp_ui_theme_changed (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event_type,
|
||||
GtkCssProvider *css_provider);
|
||||
static void gimp_ensure_modules (void);
|
||||
#ifndef GDK_WINDOWING_WIN32
|
||||
static void gimp_window_transient_realized (GtkWidget *window,
|
||||
GdkWindow *parent);
|
||||
#endif
|
||||
static gboolean gimp_window_set_transient_for (GtkWindow *window,
|
||||
GdkWindow *parent);
|
||||
static void gimp_ui_help_func (const gchar *help_id,
|
||||
gpointer help_data);
|
||||
static void gimp_ui_theme_changed (GFileMonitor *monitor,
|
||||
GFile *file,
|
||||
GFile *other_file,
|
||||
GFileMonitorEvent event_type,
|
||||
GtkCssProvider *css_provider);
|
||||
static void gimp_ensure_modules (void);
|
||||
|
||||
#ifdef GDK_WINDOWING_QUARTZ
|
||||
static gboolean gimp_osx_focus_window (gpointer);
|
||||
static gboolean gimp_osx_focus_window (gpointer);
|
||||
#endif
|
||||
|
||||
#ifndef GDK_WINDOWING_WIN32
|
||||
static GdkWindow * gimp_ui_get_foreign_window (guint32 window);
|
||||
#endif
|
||||
static gboolean gimp_window_transient_on_mapped (GtkWidget *window,
|
||||
GdkEventAny *event,
|
||||
GimpDisplay *display);
|
||||
|
||||
|
||||
static gboolean gimp_ui_initialized = FALSE;
|
||||
|
||||
|
@ -174,84 +179,6 @@ gimp_ui_init (const gchar *prog_name)
|
|||
gimp_ui_initialized = TRUE;
|
||||
}
|
||||
|
||||
static GdkWindow *
|
||||
gimp_ui_get_foreign_window (guint32 window)
|
||||
{
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
|
||||
return gdk_x11_window_foreign_new_for_display (gdk_display_get_default (),
|
||||
window);
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
return gdk_win32_window_foreign_new_for_display (gdk_display_get_default (),
|
||||
(HWND) (uintptr_t) window);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_ui_get_display_window:
|
||||
* @display: a #GimpDisplay.
|
||||
*
|
||||
* Returns the #GdkWindow of a display window. The purpose is to allow
|
||||
* to make plug-in dialogs transient to the image display as explained
|
||||
* with gdk_window_set_transient_for().
|
||||
*
|
||||
* You shouldn't have to call this function directly. Use
|
||||
* gimp_window_set_transient_for_display() instead.
|
||||
*
|
||||
* Returns: (nullable) (transfer full): A reference to a #GdkWindow or %NULL.
|
||||
* You should unref the window using g_object_unref() as
|
||||
* soon as you don't need it any longer.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
GdkWindow *
|
||||
gimp_ui_get_display_window (GimpDisplay *display)
|
||||
{
|
||||
guint32 window;
|
||||
|
||||
g_return_val_if_fail (gimp_ui_initialized, NULL);
|
||||
|
||||
window = gimp_display_get_window_handle (display);
|
||||
if (window)
|
||||
return gimp_ui_get_foreign_window (window);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_ui_get_progress_window:
|
||||
*
|
||||
* Returns the #GdkWindow of the window this plug-in's progress bar is
|
||||
* shown in. Use it to make plug-in dialogs transient to this window
|
||||
* as explained with gdk_window_set_transient_for().
|
||||
*
|
||||
* You shouldn't have to call this function directly. Use
|
||||
* gimp_window_set_transient() instead.
|
||||
*
|
||||
* Returns: (transfer full): A reference to a #GdkWindow or %NULL.
|
||||
* You should unref the window using g_object_unref() as
|
||||
* soon as you don't need it any longer.
|
||||
*
|
||||
* Since: 2.4
|
||||
*/
|
||||
GdkWindow *
|
||||
gimp_ui_get_progress_window (void)
|
||||
{
|
||||
guint32 window;
|
||||
|
||||
g_return_val_if_fail (gimp_ui_initialized, NULL);
|
||||
|
||||
window = gimp_progress_get_window_handle ();
|
||||
if (window)
|
||||
return gimp_ui_get_foreign_window (window);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef GDK_WINDOWING_QUARTZ
|
||||
static void
|
||||
gimp_window_transient_show (GtkWidget *window)
|
||||
|
@ -269,8 +196,8 @@ gimp_window_transient_show (GtkWidget *window)
|
|||
* @display: display of the image window that should become the parent
|
||||
*
|
||||
* Indicates to the window manager that @window is a transient dialog
|
||||
* associated with the GIMP image window that is identified by it's
|
||||
* display ID. See gdk_window_set_transient_for () for more information.
|
||||
* associated with the GIMP image window that is identified by its
|
||||
* display. See gdk_window_set_transient_for () for more information.
|
||||
*
|
||||
* Most of the time you will want to use the convenience function
|
||||
* gimp_window_set_transient().
|
||||
|
@ -283,22 +210,14 @@ gimp_window_set_transient_for_display (GtkWindow *window,
|
|||
{
|
||||
g_return_if_fail (gimp_ui_initialized);
|
||||
g_return_if_fail (GTK_IS_WINDOW (window));
|
||||
g_return_if_fail (GIMP_IS_DISPLAY (display));
|
||||
|
||||
if (! gimp_window_set_transient_for (window,
|
||||
gimp_ui_get_display_window (display)))
|
||||
{
|
||||
/* if setting the window transient failed, at least set
|
||||
* WIN_POS_CENTER, which will center the window on the screen
|
||||
* where the mouse is (see bug #684003).
|
||||
*/
|
||||
gtk_window_set_position (window, GTK_WIN_POS_CENTER);
|
||||
g_signal_connect_after (window, "map-event",
|
||||
G_CALLBACK (gimp_window_transient_on_mapped),
|
||||
display);
|
||||
|
||||
#ifdef GDK_WINDOWING_QUARTZ
|
||||
g_signal_connect (window, "show",
|
||||
G_CALLBACK (gimp_window_transient_show),
|
||||
NULL);
|
||||
#endif
|
||||
}
|
||||
if (gtk_widget_get_mapped (GTK_WIDGET (window)))
|
||||
gimp_window_transient_on_mapped (GTK_WIDGET (window), NULL, display);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -317,17 +236,12 @@ gimp_window_set_transient (GtkWindow *window)
|
|||
g_return_if_fail (gimp_ui_initialized);
|
||||
g_return_if_fail (GTK_IS_WINDOW (window));
|
||||
|
||||
if (! gimp_window_set_transient_for (window, gimp_ui_get_progress_window ()))
|
||||
{
|
||||
/* see above */
|
||||
gtk_window_set_position (window, GTK_WIN_POS_CENTER);
|
||||
g_signal_connect_after (window, "map-event",
|
||||
G_CALLBACK (gimp_window_transient_on_mapped),
|
||||
NULL);
|
||||
|
||||
#ifdef GDK_WINDOWING_QUARTZ
|
||||
g_signal_connect (window, "show",
|
||||
G_CALLBACK (gimp_window_transient_show),
|
||||
NULL);
|
||||
#endif
|
||||
}
|
||||
if (gtk_widget_get_mapped (GTK_WIDGET (window)))
|
||||
gimp_window_transient_on_mapped (GTK_WIDGET (window), NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -401,49 +315,6 @@ gimp_ensure_modules (void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef GDK_WINDOWING_WIN32
|
||||
static void
|
||||
gimp_window_transient_realized (GtkWidget *window,
|
||||
GdkWindow *parent)
|
||||
{
|
||||
if (gtk_widget_get_realized (window))
|
||||
gdk_window_set_transient_for (gtk_widget_get_window (window), parent);
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
gimp_window_set_transient_for (GtkWindow *window,
|
||||
GdkWindow *parent)
|
||||
{
|
||||
gtk_window_set_transient_for (window, NULL);
|
||||
|
||||
/* To know why it is disabled on Win32, see
|
||||
* gimp_window_set_transient_for() in app/widgets/gimpwidgets-utils.c.
|
||||
*/
|
||||
#ifndef GDK_WINDOWING_WIN32
|
||||
g_signal_handlers_disconnect_matched (window, G_SIGNAL_MATCH_FUNC,
|
||||
0, 0, NULL,
|
||||
gimp_window_transient_realized,
|
||||
NULL);
|
||||
|
||||
if (! parent)
|
||||
return FALSE;
|
||||
|
||||
if (gtk_widget_get_realized (GTK_WIDGET (window)))
|
||||
gdk_window_set_transient_for (gtk_widget_get_window (GTK_WIDGET (window)),
|
||||
parent);
|
||||
|
||||
g_signal_connect_object (window, "realize",
|
||||
G_CALLBACK (gimp_window_transient_realized),
|
||||
parent, 0);
|
||||
g_object_unref (parent);
|
||||
|
||||
return TRUE;
|
||||
#endif
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#ifdef GDK_WINDOWING_QUARTZ
|
||||
static gboolean
|
||||
gimp_osx_focus_window (gpointer user_data)
|
||||
|
@ -452,3 +323,94 @@ gimp_osx_focus_window (gpointer user_data)
|
|||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef GDK_WINDOWING_WIN32
|
||||
static GdkWindow *
|
||||
gimp_ui_get_foreign_window (guint32 window)
|
||||
{
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
|
||||
return gdk_x11_window_foreign_new_for_display (gdk_display_get_default (),
|
||||
window);
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
return gdk_win32_window_foreign_new_for_display (gdk_display_get_default (),
|
||||
(HWND) (uintptr_t) window);
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
gimp_window_transient_on_mapped (GtkWidget *window,
|
||||
GdkEventAny *event,
|
||||
GimpDisplay *display)
|
||||
{
|
||||
GBytes *handle;
|
||||
gboolean transient_set = FALSE;
|
||||
|
||||
if (display != NULL)
|
||||
handle = gimp_display_get_window_handle (display);
|
||||
else
|
||||
handle = gimp_progress_get_window_handle ();
|
||||
|
||||
if (handle == NULL)
|
||||
return FALSE;
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_DISPLAY (gdk_display_get_default ()))
|
||||
{
|
||||
char *wayland_handle;
|
||||
|
||||
wayland_handle = (char *) g_bytes_get_data (handle, NULL);
|
||||
gdk_wayland_window_set_transient_for_exported (gtk_widget_get_window (window),
|
||||
wayland_handle);
|
||||
transient_set = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* To know why it is disabled on Win32, see
|
||||
* gimp_window_set_transient_for() in app/widgets/gimpwidgets-utils.c.
|
||||
*/
|
||||
#ifndef GDK_WINDOWING_WIN32
|
||||
if (! transient_set)
|
||||
{
|
||||
GdkWindow *parent;
|
||||
guint32 *handle_data;
|
||||
guint32 parent_ID;
|
||||
gsize handle_size;
|
||||
|
||||
handle_data = (guint32 *) g_bytes_get_data (handle, &handle_size);
|
||||
g_return_val_if_fail (handle_size == sizeof (guint32), FALSE);
|
||||
parent_ID = *handle_data;
|
||||
|
||||
parent = gimp_ui_get_foreign_window (parent_ID);
|
||||
|
||||
if (parent)
|
||||
gdk_window_set_transient_for (gtk_widget_get_window (window), parent);
|
||||
|
||||
transient_set = TRUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (! transient_set)
|
||||
{
|
||||
/* if setting the window transient failed, at least set
|
||||
* WIN_POS_CENTER, which will center the window on the screen
|
||||
* where the mouse is (see bug #684003).
|
||||
*/
|
||||
gtk_window_set_position (GTK_WINDOW (window), GTK_WIN_POS_CENTER);
|
||||
|
||||
#ifdef GDK_WINDOWING_QUARTZ
|
||||
g_signal_connect (window, "show",
|
||||
G_CALLBACK (gimp_window_transient_show),
|
||||
NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
g_bytes_unref (handle);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -73,8 +73,6 @@ EXPORTS
|
|||
gimp_save_procedure_dialog_add_metadata
|
||||
gimp_save_procedure_dialog_get_type
|
||||
gimp_save_procedure_dialog_new
|
||||
gimp_ui_get_display_window
|
||||
gimp_ui_get_progress_window
|
||||
gimp_ui_init
|
||||
gimp_vectors_combo_box_get_type
|
||||
gimp_vectors_combo_box_new
|
||||
|
|
|
@ -57,11 +57,7 @@ G_BEGIN_DECLS
|
|||
|
||||
void gimp_ui_init (const gchar *prog_name);
|
||||
|
||||
GdkWindow * gimp_ui_get_progress_window (void);
|
||||
|
||||
void gimp_window_set_transient (GtkWindow *window);
|
||||
|
||||
GdkWindow * gimp_ui_get_display_window (GimpDisplay *display);
|
||||
void gimp_window_set_transient_for_display (GtkWindow *window,
|
||||
GimpDisplay *display);
|
||||
|
||||
|
|
|
@ -497,6 +497,7 @@ EXPORTS
|
|||
gimp_widget_get_monitor
|
||||
gimp_widget_set_bound_property
|
||||
gimp_widget_set_identifier
|
||||
gimp_widget_set_native_handle
|
||||
gimp_widget_track_monitor
|
||||
gimp_widgets_error_quark
|
||||
gimp_widgets_init
|
||||
|
|
|
@ -26,6 +26,16 @@
|
|||
#include <gegl.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
#include <gdk/gdkwin32.h>
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
#include <gdk/gdkx.h>
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
#include <gdk/gdkwayland.h>
|
||||
#endif
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
|
@ -61,6 +71,17 @@
|
|||
**/
|
||||
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
static void gimp_widget_wayland_window_exported (GdkWindow *window,
|
||||
const char *handle,
|
||||
GBytes **phandle);
|
||||
#endif
|
||||
|
||||
static gboolean gimp_widget_set_handle_on_mapped (GtkWidget *widget,
|
||||
GdkEventAny *event,
|
||||
GBytes **phandle);
|
||||
|
||||
|
||||
static GtkWidget *
|
||||
find_mnemonic_widget (GtkWidget *widget,
|
||||
gint level)
|
||||
|
@ -1036,3 +1057,113 @@ gimp_widget_get_color_transform (GtkWidget *widget,
|
|||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* gimp_widget_set_native_handle:
|
||||
* @widget: a #GtkWindow
|
||||
* @handle: (out): pointer to store the native handle as a #GBytes.
|
||||
*
|
||||
* 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).
|
||||
*
|
||||
* 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
|
||||
* this function.
|
||||
*
|
||||
* This convenience function is safe to use even before @widget is
|
||||
* visible as it will will the handle once it is mapped.
|
||||
*/
|
||||
void
|
||||
gimp_widget_set_native_handle (GtkWidget *widget,
|
||||
GBytes **handle)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
g_return_if_fail (gtk_widget_get_has_window (widget));
|
||||
|
||||
gtk_widget_add_events (widget, GDK_STRUCTURE_MASK);
|
||||
g_signal_connect (widget, "map-event",
|
||||
G_CALLBACK (gimp_widget_set_handle_on_mapped),
|
||||
handle);
|
||||
|
||||
if (gtk_widget_get_mapped (widget))
|
||||
gimp_widget_set_handle_on_mapped (widget, NULL, handle);
|
||||
}
|
||||
|
||||
|
||||
/* Private functions */
|
||||
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
static void
|
||||
gimp_widget_wayland_window_exported (GdkWindow *window,
|
||||
const char *handle,
|
||||
GBytes **phandle)
|
||||
{
|
||||
GBytes *wayland_handle;
|
||||
|
||||
wayland_handle = g_bytes_new (handle, strlen (handle));
|
||||
|
||||
g_bytes_unref (*phandle);
|
||||
*phandle = wayland_handle;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
gimp_widget_set_handle_on_mapped (GtkWidget *widget,
|
||||
GdkEventAny *event,
|
||||
GBytes **phandle)
|
||||
{
|
||||
GdkWindow *surface;
|
||||
GBytes *handle = NULL;
|
||||
#if defined (GDK_WINDOWING_WIN32) || defined (GDK_WINDOWING_X11)
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel (widget);
|
||||
|
||||
widget = toplevel;
|
||||
#endif
|
||||
|
||||
g_clear_pointer (phandle, g_bytes_unref);
|
||||
|
||||
surface = gtk_widget_get_window (GTK_WIDGET (widget));
|
||||
g_return_val_if_fail (surface != NULL, FALSE);
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (GDK_IS_WIN32_WINDOW (surface))
|
||||
{
|
||||
guint32 id;
|
||||
|
||||
id = GPOINTER_TO_INT (GDK_WINDOW_HWND (gtk_widget_get_window (GTK_WIDGET (widget))));
|
||||
handle = g_bytes_new (&id, sizeof (guint32));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
if (GDK_IS_X11_WINDOW (surface))
|
||||
{
|
||||
guint32 id;
|
||||
|
||||
id = GDK_WINDOW_XID (gtk_widget_get_window (GTK_WIDGET (widget)));
|
||||
handle = g_bytes_new (&id, sizeof (guint32));
|
||||
}
|
||||
#endif
|
||||
#ifdef GDK_WINDOWING_WAYLAND
|
||||
if (GDK_IS_WAYLAND_WINDOW (surface))
|
||||
{
|
||||
/* I don't run this on "realize" event because somehow it locks
|
||||
* the whole processus in Wayland. The "map-event" happens
|
||||
* slightly after the window became visible and I didn't
|
||||
* experience any lock.
|
||||
*/
|
||||
if (! gdk_wayland_window_export_handle (surface,
|
||||
(GdkWaylandWindowExported) gimp_widget_wayland_window_exported,
|
||||
phandle, NULL))
|
||||
g_printerr ("%s: gdk_wayland_window_export_handle() failed. "
|
||||
"It will not be possible to set windows in other processes as transient to this display shell.\n",
|
||||
G_STRFUNC);
|
||||
}
|
||||
#endif
|
||||
|
||||
*phandle = handle;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -65,6 +65,8 @@ GimpColorTransform * gimp_widget_get_color_transform (GtkWidget *widget,
|
|||
GimpColorRenderingIntent proof_intent,
|
||||
gboolean proof_bpc);
|
||||
|
||||
void gimp_widget_set_native_handle (GtkWidget *widget,
|
||||
GBytes **handle);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -145,9 +145,13 @@ sub display_get_window_handle {
|
|||
|
||||
$help = <<'HELP';
|
||||
This procedure returns a handle to the native window for a given image
|
||||
display. For example in the X backend of GDK, a native window handle is
|
||||
an Xlib XID. A value of 0 is returned for an invalid display or if this
|
||||
function is unimplemented for the windowing system that is being used.
|
||||
display.
|
||||
|
||||
It can be different types of data depending on the platform you are running on.
|
||||
For example in the X backend of GDK, a native window handle is an Xlib
|
||||
XID whereas on Wayland, it is a string handle. A value of NULL is
|
||||
returned for an invalid display or if this function is unimplemented for
|
||||
the windowing system that is being used.
|
||||
HELP
|
||||
|
||||
&neo_pdb_misc('2005', '2.4');
|
||||
|
@ -158,14 +162,14 @@ HELP
|
|||
);
|
||||
|
||||
@outargs = (
|
||||
{ name => 'window', type => 'int32',
|
||||
desc => 'The native window handle or 0' }
|
||||
{ name => 'handle', type => 'bytes',
|
||||
desc => 'The native window handle or NULL' }
|
||||
);
|
||||
|
||||
%invoke = (
|
||||
code => <<'CODE'
|
||||
{
|
||||
window = (gint32) gimp_get_display_window_id (gimp, display);
|
||||
handle = gimp_get_display_window_id (gimp, display);
|
||||
}
|
||||
CODE
|
||||
);
|
||||
|
|
|
@ -180,17 +180,20 @@ CODE
|
|||
}
|
||||
|
||||
sub progress_get_window_handle {
|
||||
$blurb = 'Returns the native window ID of the toplevel window this plug-in\'s progress is displayed in.';
|
||||
$blurb = 'Returns the native handle of the toplevel window this plug-in\'s progress is displayed in.';
|
||||
|
||||
$help = <<'HELP';
|
||||
This function returns the native window ID of the toplevel window this plug-in\'s progress is displayed in.
|
||||
This function returns the native handle allowing to identify the toplevel window this plug-in's progress is displayed in.
|
||||
|
||||
This handle can be of various types (integer, string, etc.) depending on the platform you are running on which is why it
|
||||
returns a GBytes. There are usually no reasons to call this directly.
|
||||
HELP
|
||||
|
||||
&mitch_pdb_misc('2004', '2.2');
|
||||
|
||||
@outargs = (
|
||||
{ name => 'window', type => 'int32',
|
||||
desc => 'The progress bar\'s toplevel window' }
|
||||
{ name => 'handle', type => 'bytes',
|
||||
desc => 'The progress bar\'s toplevel window\'s handle' }
|
||||
);
|
||||
|
||||
%invoke = (
|
||||
|
@ -201,7 +204,7 @@ HELP
|
|||
if (plug_in && plug_in->open)
|
||||
{
|
||||
if (! gimp->no_interface)
|
||||
window = gimp_plug_in_progress_get_window_id (plug_in);
|
||||
handle = gimp_plug_in_progress_get_window_id (plug_in);
|
||||
}
|
||||
else
|
||||
success = FALSE;
|
||||
|
|
|
@ -136,8 +136,18 @@ screenshot_freedesktop_shoot (GdkMonitor *monitor,
|
|||
if (GDK_IS_X11_DISPLAY (gdk_display_get_default ()))
|
||||
{
|
||||
GdkWindow *window;
|
||||
GBytes *handle;
|
||||
guint32 *handle_data;
|
||||
guint32 window_id;
|
||||
gsize handle_size;
|
||||
|
||||
window = gimp_ui_get_progress_window ();
|
||||
handle = gimp_progress_get_window_handle ();
|
||||
handle_data = (guint32 *) g_bytes_get_data (handle, &handle_size);
|
||||
g_return_val_if_fail (handle_size == sizeof (guint32), GIMP_PDB_EXECUTION_ERROR);
|
||||
window_id = *handle_data;
|
||||
g_bytes_unref (handle);
|
||||
|
||||
window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), window_id);
|
||||
if (window)
|
||||
{
|
||||
gint id;
|
||||
|
|
Loading…
Reference in New Issue