mirror of
https://gitlab.gnome.org/GNOME/gimp.git
synced 2025-07-04 09:53:25 +00:00

This fixes this warning (as appeared with commit ad8b47bff7
):
[1/235] Compiling C object libgimpwidgets/libgimpwidgets-3.0.so.0.9900.17.p/gimpdialog.c.o
../../../../../../../dev/src/gimp/libgimpwidgets/gimpdialog.c:774:1: warning: ‘gimp_dialog_set_title_bar_theme’ defined but not used [-Wunused-function]
774 | gimp_dialog_set_title_bar_theme (GtkWidget *dialog)
We could either put the whole `gimp_dialog_set_title_bar_theme()` declaration,
definition and usage into #ifdef, or only the implementation (making the
function a no-op on non-Windows platforms). I chose the former. There was some
discussion that maybe some implementation may happen later for other platforms,
but until then, no need to call it needlessly (even more as we don't know when
any theoretical other implementation would happen).
816 lines
24 KiB
C
816 lines
24 KiB
C
/* LIBGIMP - The GIMP Library
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* gimpdialog.c
|
|
* Copyright (C) 2000-2003 Michael Natterer <mitch@gimp.org>
|
|
*
|
|
* This library is free software: you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see
|
|
* <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gegl.h>
|
|
#include <gtk/gtk.h>
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
|
|
#include "gimpwidgetstypes.h"
|
|
|
|
#include "gimpdialog.h"
|
|
#include "gimphelpui.h"
|
|
#include "gimpwidgetsutils.h"
|
|
|
|
#include "libgimp/libgimp-intl.h"
|
|
|
|
#ifdef G_OS_WIN32
|
|
#include <dwmapi.h>
|
|
#include <gdk/gdkwin32.h>
|
|
|
|
#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE
|
|
#define DWMWA_USE_IMMERSIVE_DARK_MODE 20
|
|
#endif
|
|
#endif
|
|
|
|
/**
|
|
* SECTION: gimpdialog
|
|
* @title: GimpDialog
|
|
* @short_description: Constructors for #GtkDialog's and action_areas as
|
|
* well as other dialog-related stuff.
|
|
*
|
|
* Constructors for #GtkDialog's and action_areas as well as other
|
|
* dialog-related stuff.
|
|
**/
|
|
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_HELP_FUNC,
|
|
PROP_HELP_ID,
|
|
PROP_PARENT
|
|
};
|
|
|
|
|
|
struct _GimpDialogPrivate
|
|
{
|
|
GimpHelpFunc help_func;
|
|
gchar *help_id;
|
|
GtkWidget *help_button;
|
|
|
|
GBytes *window_handle;
|
|
};
|
|
|
|
#define GET_PRIVATE(obj) (((GimpDialog *) (obj))->priv)
|
|
|
|
|
|
static void gimp_dialog_constructed (GObject *object);
|
|
static void gimp_dialog_dispose (GObject *object);
|
|
static void gimp_dialog_finalize (GObject *object);
|
|
static void gimp_dialog_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec);
|
|
static void gimp_dialog_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec);
|
|
|
|
static void gimp_dialog_hide (GtkWidget *widget);
|
|
static gboolean gimp_dialog_delete_event (GtkWidget *widget,
|
|
GdkEventAny *event);
|
|
|
|
static void gimp_dialog_close (GtkDialog *dialog);
|
|
|
|
static void gimp_dialog_response (GtkDialog *dialog,
|
|
gint response_id);
|
|
|
|
#ifdef G_OS_WIN32
|
|
static void gimp_dialog_set_title_bar_theme (GtkWidget *dialog);
|
|
#endif
|
|
|
|
G_DEFINE_TYPE_WITH_PRIVATE (GimpDialog, gimp_dialog, GTK_TYPE_DIALOG)
|
|
|
|
#define parent_class gimp_dialog_parent_class
|
|
|
|
static gboolean show_help_button = TRUE;
|
|
|
|
|
|
static void
|
|
gimp_dialog_class_init (GimpDialogClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
|
GtkDialogClass *dialog_class = GTK_DIALOG_CLASS (klass);
|
|
|
|
object_class->constructed = gimp_dialog_constructed;
|
|
object_class->dispose = gimp_dialog_dispose;
|
|
object_class->finalize = gimp_dialog_finalize;
|
|
object_class->set_property = gimp_dialog_set_property;
|
|
object_class->get_property = gimp_dialog_get_property;
|
|
|
|
widget_class->hide = gimp_dialog_hide;
|
|
widget_class->delete_event = gimp_dialog_delete_event;
|
|
|
|
dialog_class->close = gimp_dialog_close;
|
|
|
|
/**
|
|
* GimpDialog:help-func:
|
|
*
|
|
* Since: 2.2
|
|
**/
|
|
g_object_class_install_property (object_class, PROP_HELP_FUNC,
|
|
g_param_spec_pointer ("help-func",
|
|
"Help Func",
|
|
"The help function to call when F1 is hit",
|
|
GIMP_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
/**
|
|
* GimpDialog:help-id:
|
|
*
|
|
* Since: 2.2
|
|
**/
|
|
g_object_class_install_property (object_class, PROP_HELP_ID,
|
|
g_param_spec_string ("help-id",
|
|
"Help ID",
|
|
"The help ID to pass to help-func",
|
|
NULL,
|
|
GIMP_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT));
|
|
|
|
/**
|
|
* GimpDialog:parent:
|
|
*
|
|
* Since: 2.8
|
|
**/
|
|
g_object_class_install_property (object_class, PROP_PARENT,
|
|
g_param_spec_object ("parent",
|
|
"Parent",
|
|
"The dialog's parent widget",
|
|
GTK_TYPE_WIDGET,
|
|
GIMP_PARAM_WRITABLE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
}
|
|
|
|
static void
|
|
gimp_dialog_init (GimpDialog *dialog)
|
|
{
|
|
dialog->priv = gimp_dialog_get_instance_private (dialog);
|
|
|
|
g_signal_connect (dialog, "response",
|
|
G_CALLBACK (gimp_dialog_response),
|
|
NULL);
|
|
|
|
#ifdef G_OS_WIN32
|
|
g_signal_connect (GTK_WIDGET (dialog), "map",
|
|
G_CALLBACK (gimp_dialog_set_title_bar_theme),
|
|
NULL);
|
|
#endif
|
|
}
|
|
|
|
static void
|
|
gimp_dialog_constructed (GObject *object)
|
|
{
|
|
GimpDialogPrivate *private = GET_PRIVATE (object);
|
|
|
|
G_OBJECT_CLASS (parent_class)->constructed (object);
|
|
|
|
if (private->help_func)
|
|
gimp_help_connect (GTK_WIDGET (object),
|
|
private->help_func, private->help_id,
|
|
object, NULL);
|
|
|
|
if (show_help_button && private->help_func && private->help_id)
|
|
{
|
|
private->help_button = gtk_dialog_add_button (GTK_DIALOG (object),
|
|
_("_Help"),
|
|
GTK_RESPONSE_HELP);
|
|
}
|
|
|
|
gimp_widget_set_native_handle (GTK_WIDGET (object), &private->window_handle);
|
|
}
|
|
|
|
static void
|
|
gimp_dialog_dispose (GObject *object)
|
|
{
|
|
GdkDisplay *display = NULL;
|
|
|
|
if (g_main_depth () == 0)
|
|
{
|
|
display = gtk_widget_get_display (GTK_WIDGET (object));
|
|
g_object_ref (display);
|
|
}
|
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
|
|
|
if (display)
|
|
{
|
|
gdk_display_flush (display);
|
|
g_object_unref (display);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_dialog_finalize (GObject *object)
|
|
{
|
|
GimpDialogPrivate *private = GET_PRIVATE (object);
|
|
|
|
g_clear_pointer (&private->help_id, g_free);
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gimp_dialog_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GimpDialogPrivate *private = GET_PRIVATE (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_HELP_FUNC:
|
|
private->help_func = g_value_get_pointer (value);
|
|
break;
|
|
|
|
case PROP_HELP_ID:
|
|
g_free (private->help_id);
|
|
private->help_id = g_value_dup_string (value);
|
|
gimp_help_set_help_data (GTK_WIDGET (object), NULL, private->help_id);
|
|
break;
|
|
|
|
case PROP_PARENT:
|
|
{
|
|
GtkWidget *parent = g_value_get_object (value);
|
|
|
|
if (parent)
|
|
{
|
|
if (GTK_IS_WINDOW (parent))
|
|
{
|
|
gtk_window_set_transient_for (GTK_WINDOW (object),
|
|
GTK_WINDOW (parent));
|
|
}
|
|
else
|
|
{
|
|
GtkWidget *toplevel;
|
|
|
|
toplevel = gtk_widget_get_toplevel (parent);
|
|
if (GTK_IS_WINDOW (toplevel))
|
|
{
|
|
gtk_window_set_transient_for (GTK_WINDOW (object),
|
|
GTK_WINDOW (toplevel));
|
|
}
|
|
else
|
|
{
|
|
gtk_window_set_screen (GTK_WINDOW (object),
|
|
gtk_widget_get_screen (parent));
|
|
gtk_window_set_position (GTK_WINDOW (object),
|
|
GTK_WIN_POS_MOUSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_dialog_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GimpDialogPrivate *private = GET_PRIVATE (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_HELP_FUNC:
|
|
g_value_set_pointer (value, private->help_func);
|
|
break;
|
|
|
|
case PROP_HELP_ID:
|
|
g_value_set_string (value, private->help_id);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_dialog_hide (GtkWidget *widget)
|
|
{
|
|
/* set focus to NULL so focus_out callbacks are invoked synchronously */
|
|
gtk_window_set_focus (GTK_WINDOW (widget), NULL);
|
|
|
|
GTK_WIDGET_CLASS (parent_class)->hide (widget);
|
|
}
|
|
|
|
static gboolean
|
|
gimp_dialog_delete_event (GtkWidget *widget,
|
|
GdkEventAny *event)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gimp_dialog_close (GtkDialog *dialog)
|
|
{
|
|
/* Synthesize delete_event to close dialog. */
|
|
|
|
GtkWidget *widget = GTK_WIDGET (dialog);
|
|
|
|
if (gtk_widget_get_window (widget))
|
|
{
|
|
GdkEvent *event = gdk_event_new (GDK_DELETE);
|
|
|
|
event->any.window = g_object_ref (gtk_widget_get_window (widget));
|
|
event->any.send_event = TRUE;
|
|
|
|
gtk_main_do_event (event);
|
|
gdk_event_free (event);
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_dialog_response (GtkDialog *dialog,
|
|
gint response_id)
|
|
{
|
|
GimpDialogPrivate *private = GET_PRIVATE (dialog);
|
|
GtkWidget *widget = gtk_dialog_get_widget_for_response (dialog,
|
|
response_id);
|
|
|
|
if (widget &&
|
|
(! GTK_IS_BUTTON (widget) ||
|
|
gtk_widget_get_focus_on_click (widget)))
|
|
{
|
|
gtk_widget_grab_focus (widget);
|
|
}
|
|
|
|
/* if our own help button was activated, abort "response" and
|
|
* call our help callback.
|
|
*/
|
|
if (response_id == GTK_RESPONSE_HELP &&
|
|
widget == private->help_button)
|
|
{
|
|
g_signal_stop_emission_by_name (dialog, "response");
|
|
|
|
if (private->help_func)
|
|
private->help_func (private->help_id, dialog);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* gimp_dialog_new: (skip)
|
|
* @title: The dialog's title which will be set with
|
|
* gtk_window_set_title().
|
|
* @role: The dialog's @role which will be set with
|
|
* gtk_window_set_role().
|
|
* @parent: (nullable): The @parent widget of this dialog.
|
|
* @flags: The @flags (see the #GtkDialog documentation).
|
|
* @help_func: The function which will be called if the user presses "F1".
|
|
* @help_id: The help_id which will be passed to @help_func.
|
|
* @...: A %NULL-terminated @va_list destribing the
|
|
* action_area buttons.
|
|
*
|
|
* Creates a new @GimpDialog widget.
|
|
*
|
|
* This function simply packs the action_area arguments passed in "..."
|
|
* into a @va_list variable and passes everything to gimp_dialog_new_valist().
|
|
*
|
|
* For a description of the format of the @va_list describing the
|
|
* action_area buttons see gtk_dialog_new_with_buttons().
|
|
*
|
|
* Returns: A #GimpDialog.
|
|
**/
|
|
GtkWidget *
|
|
gimp_dialog_new (const gchar *title,
|
|
const gchar *role,
|
|
GtkWidget *parent,
|
|
GtkDialogFlags flags,
|
|
GimpHelpFunc help_func,
|
|
const gchar *help_id,
|
|
...)
|
|
{
|
|
GtkWidget *dialog;
|
|
va_list args;
|
|
|
|
g_return_val_if_fail (parent == NULL || GTK_IS_WIDGET (parent), NULL);
|
|
g_return_val_if_fail (title != NULL, NULL);
|
|
g_return_val_if_fail (role != NULL, NULL);
|
|
|
|
va_start (args, help_id);
|
|
|
|
dialog = gimp_dialog_new_valist (title, role,
|
|
parent, flags,
|
|
help_func, help_id,
|
|
args);
|
|
|
|
va_end (args);
|
|
|
|
return dialog;
|
|
}
|
|
|
|
/**
|
|
* gimp_dialog_new_valist: (skip)
|
|
* @title: The dialog's title which will be set with
|
|
* gtk_window_set_title().
|
|
* @role: The dialog's @role which will be set with
|
|
* gtk_window_set_role().
|
|
* @parent: The @parent widget of this dialog or %NULL.
|
|
* @flags: The @flags (see the #GtkDialog documentation).
|
|
* @help_func: The function which will be called if the user presses "F1".
|
|
* @help_id: The help_id which will be passed to @help_func.
|
|
* @args: A @va_list destribing the action_area buttons.
|
|
*
|
|
* Creates a new @GimpDialog widget. If a GtkWindow is specified as
|
|
* @parent then the dialog will be made transient for this window.
|
|
*
|
|
* For a description of the format of the @va_list describing the
|
|
* action_area buttons see gtk_dialog_new_with_buttons().
|
|
*
|
|
* Returns: A #GimpDialog.
|
|
**/
|
|
GtkWidget *
|
|
gimp_dialog_new_valist (const gchar *title,
|
|
const gchar *role,
|
|
GtkWidget *parent,
|
|
GtkDialogFlags flags,
|
|
GimpHelpFunc help_func,
|
|
const gchar *help_id,
|
|
va_list args)
|
|
{
|
|
GtkWidget *dialog;
|
|
gboolean use_header_bar;
|
|
|
|
g_return_val_if_fail (title != NULL, NULL);
|
|
g_return_val_if_fail (role != NULL, NULL);
|
|
g_return_val_if_fail (parent == NULL || GTK_IS_WIDGET (parent), NULL);
|
|
|
|
g_object_get (gtk_settings_get_default (),
|
|
"gtk-dialogs-use-header", &use_header_bar,
|
|
NULL);
|
|
|
|
dialog = g_object_new (GIMP_TYPE_DIALOG,
|
|
"title", title,
|
|
"role", role,
|
|
"modal", (flags & GTK_DIALOG_MODAL),
|
|
"help-func", help_func,
|
|
"help-id", help_id,
|
|
"parent", parent,
|
|
"use-header-bar", use_header_bar,
|
|
NULL);
|
|
|
|
if (parent)
|
|
{
|
|
if (flags & GTK_DIALOG_DESTROY_WITH_PARENT)
|
|
g_signal_connect_object (parent, "destroy",
|
|
G_CALLBACK (gimp_dialog_close),
|
|
dialog, G_CONNECT_SWAPPED);
|
|
}
|
|
|
|
gimp_dialog_add_buttons_valist (GIMP_DIALOG (dialog), args);
|
|
|
|
return dialog;
|
|
}
|
|
|
|
/**
|
|
* gimp_dialog_add_button:
|
|
* @dialog: The @dialog to add a button to.
|
|
* @button_text: text of button, or stock ID.
|
|
* @response_id: response ID for the button.
|
|
*
|
|
* This function is essentially the same as gtk_dialog_add_button()
|
|
* except it ensures there is only one help button and automatically
|
|
* sets the RESPONSE_OK widget as the default response.
|
|
*
|
|
* Returns: (type Gtk.Widget) (transfer none): the button widget that was added.
|
|
**/
|
|
GtkWidget *
|
|
gimp_dialog_add_button (GimpDialog *dialog,
|
|
const gchar *button_text,
|
|
gint response_id)
|
|
{
|
|
GtkWidget *button;
|
|
gboolean use_header_bar;
|
|
|
|
/* hide the automatically added help button if another one is added */
|
|
if (response_id == GTK_RESPONSE_HELP)
|
|
{
|
|
GimpDialogPrivate *private = GET_PRIVATE (dialog);
|
|
|
|
if (private->help_button)
|
|
{
|
|
gtk_widget_destroy (private->help_button);
|
|
private->help_button = NULL;
|
|
}
|
|
}
|
|
|
|
button = gtk_dialog_add_button (GTK_DIALOG (dialog), button_text,
|
|
response_id);
|
|
|
|
g_object_get (dialog,
|
|
"use-header-bar", &use_header_bar,
|
|
NULL);
|
|
|
|
if (use_header_bar &&
|
|
(response_id == GTK_RESPONSE_OK ||
|
|
response_id == GTK_RESPONSE_CANCEL ||
|
|
response_id == GTK_RESPONSE_CLOSE))
|
|
{
|
|
GtkWidget *header = gtk_dialog_get_header_bar (GTK_DIALOG (dialog));
|
|
|
|
if (response_id == GTK_RESPONSE_OK)
|
|
gtk_dialog_set_default_response (GTK_DIALOG (dialog),
|
|
GTK_RESPONSE_OK);
|
|
|
|
gtk_container_child_set (GTK_CONTAINER (header), button,
|
|
"position", 0,
|
|
NULL);
|
|
}
|
|
|
|
return button;
|
|
}
|
|
|
|
/**
|
|
* gimp_dialog_add_buttons: (skip)
|
|
* @dialog: The @dialog to add buttons to.
|
|
* @...: button_text-response_id pairs.
|
|
*
|
|
* This function is essentially the same as gtk_dialog_add_buttons()
|
|
* except it calls gimp_dialog_add_button() instead of gtk_dialog_add_button()
|
|
**/
|
|
void
|
|
gimp_dialog_add_buttons (GimpDialog *dialog,
|
|
...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start (args, dialog);
|
|
|
|
gimp_dialog_add_buttons_valist (dialog, args);
|
|
|
|
va_end (args);
|
|
}
|
|
|
|
/**
|
|
* gimp_dialog_add_buttons_valist: (skip)
|
|
* @dialog: The @dialog to add buttons to.
|
|
* @args: The buttons as va_list.
|
|
*
|
|
* This function is essentially the same as gimp_dialog_add_buttons()
|
|
* except it takes a va_list instead of '...'
|
|
**/
|
|
void
|
|
gimp_dialog_add_buttons_valist (GimpDialog *dialog,
|
|
va_list args)
|
|
{
|
|
const gchar *button_text;
|
|
gint response_id;
|
|
|
|
g_return_if_fail (GIMP_IS_DIALOG (dialog));
|
|
|
|
while ((button_text = va_arg (args, const gchar *)))
|
|
{
|
|
response_id = va_arg (args, gint);
|
|
|
|
gimp_dialog_add_button (dialog, button_text, response_id);
|
|
}
|
|
}
|
|
|
|
|
|
typedef struct
|
|
{
|
|
GtkDialog *dialog;
|
|
gint response_id;
|
|
GMainLoop *loop;
|
|
gboolean destroyed;
|
|
} RunInfo;
|
|
|
|
static void
|
|
run_shutdown_loop (RunInfo *ri)
|
|
{
|
|
if (g_main_loop_is_running (ri->loop))
|
|
g_main_loop_quit (ri->loop);
|
|
}
|
|
|
|
static void
|
|
run_unmap_handler (GtkDialog *dialog,
|
|
RunInfo *ri)
|
|
{
|
|
run_shutdown_loop (ri);
|
|
}
|
|
|
|
static void
|
|
run_response_handler (GtkDialog *dialog,
|
|
gint response_id,
|
|
RunInfo *ri)
|
|
{
|
|
ri->response_id = response_id;
|
|
|
|
run_shutdown_loop (ri);
|
|
}
|
|
|
|
static gint
|
|
run_delete_handler (GtkDialog *dialog,
|
|
GdkEventAny *event,
|
|
RunInfo *ri)
|
|
{
|
|
run_shutdown_loop (ri);
|
|
|
|
return TRUE; /* Do not destroy */
|
|
}
|
|
|
|
static void
|
|
run_destroy_handler (GtkDialog *dialog,
|
|
RunInfo *ri)
|
|
{
|
|
/* shutdown_loop will be called by run_unmap_handler */
|
|
|
|
ri->destroyed = TRUE;
|
|
}
|
|
|
|
/**
|
|
* gimp_dialog_run:
|
|
* @dialog: a #GimpDialog
|
|
*
|
|
* This function does exactly the same as gtk_dialog_run() except it
|
|
* does not make the dialog modal while the #GMainLoop is running.
|
|
*
|
|
* Returns: response ID
|
|
**/
|
|
gint
|
|
gimp_dialog_run (GimpDialog *dialog)
|
|
{
|
|
RunInfo ri = { NULL, GTK_RESPONSE_NONE, NULL };
|
|
gulong response_handler;
|
|
gulong unmap_handler;
|
|
gulong destroy_handler;
|
|
gulong delete_handler;
|
|
|
|
g_return_val_if_fail (GIMP_IS_DIALOG (dialog), -1);
|
|
|
|
g_object_ref (dialog);
|
|
|
|
gtk_window_present (GTK_WINDOW (dialog));
|
|
|
|
#ifdef G_OS_WIN32
|
|
gimp_dialog_set_title_bar_theme (GTK_WIDGET (dialog));
|
|
#endif
|
|
|
|
response_handler = g_signal_connect (dialog, "response",
|
|
G_CALLBACK (run_response_handler),
|
|
&ri);
|
|
unmap_handler = g_signal_connect (dialog, "unmap",
|
|
G_CALLBACK (run_unmap_handler),
|
|
&ri);
|
|
delete_handler = g_signal_connect (dialog, "delete-event",
|
|
G_CALLBACK (run_delete_handler),
|
|
&ri);
|
|
destroy_handler = g_signal_connect (dialog, "destroy",
|
|
G_CALLBACK (run_destroy_handler),
|
|
&ri);
|
|
|
|
ri.loop = g_main_loop_new (NULL, FALSE);
|
|
|
|
g_main_loop_run (ri.loop);
|
|
|
|
g_main_loop_unref (ri.loop);
|
|
|
|
ri.loop = NULL;
|
|
ri.destroyed = FALSE;
|
|
|
|
if (!ri.destroyed)
|
|
{
|
|
g_signal_handler_disconnect (dialog, response_handler);
|
|
g_signal_handler_disconnect (dialog, unmap_handler);
|
|
g_signal_handler_disconnect (dialog, delete_handler);
|
|
g_signal_handler_disconnect (dialog, destroy_handler);
|
|
}
|
|
|
|
g_object_unref (dialog);
|
|
|
|
return ri.response_id;
|
|
}
|
|
|
|
/**
|
|
* gimp_dialog_set_alternative_button_order_from_array:
|
|
* @dialog: The #GimpDialog
|
|
* @n_buttons: The size of @order
|
|
* @order: (array length=n_buttons): array of buttons' response ids.
|
|
*
|
|
* Reorder @dialog's buttons if [property@Gtk.Settings:gtk-alternative-button-order]
|
|
* is set to TRUE. This is mostly a wrapper around the GTK function
|
|
* [method@Gtk.Dialog.set_alternative_button_order], except it won't
|
|
* output a deprecation warning.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
void
|
|
gimp_dialog_set_alternative_button_order_from_array (GimpDialog *dialog,
|
|
gint n_buttons,
|
|
gint *order)
|
|
{
|
|
/* since we don't know yet what to do about alternative button order,
|
|
* just hide the warnings for now...
|
|
*/
|
|
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
|
|
gtk_dialog_set_alternative_button_order_from_array (GTK_DIALOG (dialog), n_buttons, order);
|
|
G_GNUC_END_IGNORE_DEPRECATIONS;
|
|
}
|
|
|
|
/**
|
|
* gimp_dialog_get_native_handle:
|
|
* @dialog: The #GimpDialog
|
|
*
|
|
* Returns an opaque data handle representing the window in the currently
|
|
* running platform. You should not try to use this directly. Usually this is to
|
|
* be used in functions such as [func@Gimp.brushes_popup] which will allow the
|
|
* core process to set this [class@Dialog] as parent to the newly created popup.
|
|
*
|
|
* Returns: (transfer none): an opaque [struct@GLib.Bytes] identifying this
|
|
* window.
|
|
*
|
|
* Since: 3.0
|
|
**/
|
|
GBytes *
|
|
gimp_dialog_get_native_handle (GimpDialog *dialog)
|
|
{
|
|
return dialog->priv->window_handle;
|
|
}
|
|
|
|
/**
|
|
* gimp_dialogs_show_help_button: (skip)
|
|
* @show: whether a help button should be added when creating a GimpDialog
|
|
*
|
|
* This function is for internal use only.
|
|
*
|
|
* Since: 2.2
|
|
**/
|
|
void
|
|
gimp_dialogs_show_help_button (gboolean show)
|
|
{
|
|
show_help_button = show ? TRUE : FALSE;
|
|
}
|
|
|
|
#ifdef G_OS_WIN32
|
|
void
|
|
gimp_dialog_set_title_bar_theme (GtkWidget *dialog)
|
|
{
|
|
HWND hwnd;
|
|
gboolean use_dark_mode = FALSE;
|
|
GdkWindow *window = NULL;
|
|
|
|
window = gtk_widget_get_window (GTK_WIDGET (dialog));
|
|
if (window)
|
|
{
|
|
GtkStyleContext *style;
|
|
GdkRGBA *color = NULL;
|
|
|
|
hwnd = (HWND) gdk_win32_window_get_handle (window);
|
|
/* Workaround since we don't have access to GimpGuiConfig.
|
|
* If the background color is below the threshold, then we're
|
|
* likely in dark mode.
|
|
*/
|
|
style = gtk_widget_get_style_context (GTK_WIDGET (dialog));
|
|
gtk_style_context_get (style, gtk_style_context_get_state (style),
|
|
GTK_STYLE_PROPERTY_BACKGROUND_COLOR, &color,
|
|
NULL);
|
|
if (color)
|
|
{
|
|
if (color->red < 0.5 && color->green < 0.5 && color->blue < 0.5)
|
|
use_dark_mode = TRUE;
|
|
|
|
gdk_rgba_free (color);
|
|
}
|
|
|
|
DwmSetWindowAttribute (hwnd, DWMWA_USE_IMMERSIVE_DARK_MODE,
|
|
&use_dark_mode, sizeof (use_dark_mode));
|
|
UpdateWindow (hwnd);
|
|
ShowWindow (hwnd, 5);
|
|
|
|
/* Toggle the window's visibility so the title bar change appears */
|
|
gdk_window_hide (window);
|
|
gdk_window_show (window);
|
|
}
|
|
}
|
|
#endif
|