[gtk+/wip/native-file-chooser: 3/7] Add GtkNativeDialog base class



commit 903f18ef87564315b36f698d0ebbc84c281e3db3
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Oct 29 14:59:48 2015 +0100

    Add GtkNativeDialog base class
    
    This is a base class that essentially mirrors GtkDialog, but
    it is not a GtkWindow, as the actual implemetation will be using
    native code.
    
    The base class has show and hide vfuncs, as well as a helper function
    to run the dialog in a modal fashion.
    
    This will be later used by the native file chooser dialog.

 docs/reference/gtk/gtk-docs.sgml     |    1 +
 docs/reference/gtk/gtk3-sections.txt |   21 ++
 gtk/Makefile.am                      |    3 +
 gtk/gtk.h                            |    1 +
 gtk/gtknativedialog.c                |  635 ++++++++++++++++++++++++++++++++++
 gtk/gtknativedialog.h                |   79 +++++
 gtk/gtknativedialogprivate.h         |   31 ++
 7 files changed, 771 insertions(+), 0 deletions(-)
---
diff --git a/docs/reference/gtk/gtk-docs.sgml b/docs/reference/gtk/gtk-docs.sgml
index d095c2f..f7776a2 100644
--- a/docs/reference/gtk/gtk-docs.sgml
+++ b/docs/reference/gtk/gtk-docs.sgml
@@ -203,6 +203,7 @@
       <xi:include href="xml/gtkcolorchooserdialog.xml" />
       <xi:include href="xml/gtkfilechooser.xml" />
       <xi:include href="xml/gtkfilechooserbutton.xml" />
+      <xi:include href="xml/gtknativedialog.xml" />
       <xi:include href="xml/gtkfilechooserdialog.xml" />
       <xi:include href="xml/gtkfilechooserwidget.xml" />
       <xi:include href="xml/gtkfilefilter.xml" />
diff --git a/docs/reference/gtk/gtk3-sections.txt b/docs/reference/gtk/gtk3-sections.txt
index b352d13..4301012 100644
--- a/docs/reference/gtk/gtk3-sections.txt
+++ b/docs/reference/gtk/gtk3-sections.txt
@@ -2494,6 +2494,27 @@ gtk_misc_get_type
 </SECTION>
 
 <SECTION>
+<FILE>gtknativedialog</FILE>
+<TITLE>GtkNativeDialog</TITLE>
+GTK_TYPE_NATIVE_DIALOG
+GtkNativeDialogClass
+gtk_native_dialog_show
+gtk_native_dialog_hide
+gtk_native_dialog_get_visible
+gtk_native_dialog_set_modal
+gtk_native_dialog_get_modal
+gtk_native_dialog_set_title
+gtk_native_dialog_get_title
+gtk_native_dialog_set_transient_for
+gtk_native_dialog_get_transient_for
+gtk_native_dialog_run
+<SUBSECTION Standard>
+GtkNativeDialog
+<SUBSECTION Private>
+gtk_native_dialog_get_type
+</SECTION>
+
+<SECTION>
 <FILE>gtknotebook</FILE>
 <TITLE>GtkNotebook</TITLE>
 GtkNotebook
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 02a3092..a6a41b0 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -229,6 +229,7 @@ gtk_public_h_sources =              \
        gtkmodelbutton.h        \
        gtkmodules.h            \
        gtkmountoperation.h     \
+       gtknativedialog.h       \
        gtknotebook.h           \
        gtkoffscreenwindow.h    \
        gtkorientable.h         \
@@ -481,6 +482,7 @@ gtk_private_h_sources =             \
        gtkmodifierstyle.h      \
        gtkmodulesprivate.h     \
        gtkmountoperationprivate.h \
+       gtknativedialogprivate.h \
        gtkorientableprivate.h  \
        gtkpango.h              \
        gtkpathbar.h            \
@@ -760,6 +762,7 @@ gtk_base_c_sources =                \
        gtkmodifierstyle.c      \
        gtkmodules.c            \
        gtkmountoperation.c     \
+       gtknativedialog.c       \
        gtknotebook.c           \
        gtkoffscreenwindow.c    \
        gtkorientable.c         \
diff --git a/gtk/gtk.h b/gtk/gtk.h
index ae556d4..dc57f42 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -144,6 +144,7 @@
 #include <gtk/gtkmodelbutton.h>
 #include <gtk/gtkmodules.h>
 #include <gtk/gtkmountoperation.h>
+#include <gtk/gtknativedialog.h>
 #include <gtk/gtknotebook.h>
 #include <gtk/gtkoffscreenwindow.h>
 #include <gtk/gtkorientable.h>
diff --git a/gtk/gtknativedialog.c b/gtk/gtknativedialog.c
new file mode 100644
index 0000000..0532362
--- /dev/null
+++ b/gtk/gtknativedialog.c
@@ -0,0 +1,635 @@
+/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
+/* GTK - The GIMP Toolkit
+ * gtkfilechoosernative.c: Native File selector dialog
+ * Copyright (C) 2015, Red Hat, Inc.
+ *
+ * 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 2 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
+ * Lesser 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "gtknativedialogprivate.h"
+
+#include "gtkprivate.h"
+#include "gtkfilechooserdialog.h"
+#include "gtkfilechooserprivate.h"
+#include "gtkfilechooserwidget.h"
+#include "gtkfilechooserwidgetprivate.h"
+#include "gtkfilechooserutils.h"
+#include "gtkfilechooserembed.h"
+#include "gtkfilesystem.h"
+#include "gtksizerequest.h"
+#include "gtktypebuiltins.h"
+#include "gtkintl.h"
+#include "gtksettings.h"
+#include "gtktogglebutton.h"
+#include "gtkstylecontext.h"
+#include "gtkheaderbar.h"
+#include "gtklabel.h"
+#include "gtkfilechooserentry.h"
+
+/**
+ * SECTION:gtknativedialog
+ * @Short_description: Integrate with native dialogs
+ * @Title: GtkNativeDialog
+ * @See_also: #GtkFileChooserNative, #GtkDialog
+ *
+ * Native dialogs are platform dialogs that don't use #GtkDialog or
+ * #GtkWindow. They are used in order to integrate better with a
+ * platform, by looking the same as other native applications and
+ * supporting platform specific features.
+ *
+ * The #GtkDialog functions cannot be used on such objects, but we
+ * need a similar API in order to drive them. The #GtkNativeDialog
+ * object is an API that allows you to do this. It allows you to set
+ * various common properties on the dialog, as well as show and hide
+ * it and get a #GtkNativeDialog::response signal when the user finished
+ * with the dialog.
+ *
+ * There is also a gtk_native_dialog_run() helper that makes it easy
+ * to run any native dialog in a modal way with a recursive mainloop,
+ * similar to gtk_dialog_run().
+ */
+
+typedef struct _GtkNativeDialogPrivate GtkNativeDialogPrivate;
+
+struct _GtkNativeDialogPrivate
+{
+  GtkWindow *transient_for;
+  char *title;
+
+  guint visible : 1;
+  guint modal : 1;
+
+  /* Run state */
+  gint run_response_id;
+  GMainLoop *run_loop; /* Non-NULL when in run */
+};
+
+enum {
+  PROP_0,
+  PROP_TITLE,
+  PROP_VISIBLE,
+  PROP_MODAL,
+  PROP_TRANSIENT_FOR,
+
+  LAST_ARG,
+};
+
+enum {
+  RESPONSE,
+
+  LAST_SIGNAL
+};
+
+static GParamSpec *native_props[LAST_ARG] = { NULL, };
+static guint native_signals[LAST_SIGNAL];
+
+G_DEFINE_TYPE_WITH_CODE (GtkNativeDialog, gtk_native_dialog, G_TYPE_OBJECT,
+                         G_ADD_PRIVATE (GtkNativeDialog))
+
+static void
+gtk_native_dialog_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+
+{
+  GtkNativeDialog *self = GTK_NATIVE_DIALOG (object);
+
+  switch (prop_id)
+    {
+    case PROP_TITLE:
+      gtk_native_dialog_set_title (self, g_value_get_string (value));
+      break;
+
+    case PROP_MODAL:
+      gtk_native_dialog_set_modal (self, g_value_get_boolean (value));
+      break;
+
+    case PROP_VISIBLE:
+      if (g_value_get_boolean (value))
+        gtk_native_dialog_show (self);
+      else
+        gtk_native_dialog_hide (self);
+      break;
+
+    case PROP_TRANSIENT_FOR:
+      gtk_native_dialog_set_transient_for (self, g_value_get_object (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_native_dialog_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  GtkNativeDialog *self = GTK_NATIVE_DIALOG (object);
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+
+  switch (prop_id)
+    {
+    case PROP_TITLE:
+      g_value_set_string (value, priv->title);
+      break;
+
+    case PROP_MODAL:
+      g_value_set_boolean (value, priv->modal);
+      break;
+
+    case PROP_VISIBLE:
+      g_value_set_boolean (value, priv->visible);
+      break;
+
+    case PROP_TRANSIENT_FOR:
+      g_value_set_object (value, priv->transient_for);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gtk_native_dialog_dispose (GObject *object)
+{
+  GtkNativeDialog *self = GTK_NATIVE_DIALOG (object);
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+
+  if (priv->visible)
+    gtk_native_dialog_hide (self);
+
+  G_OBJECT_CLASS (gtk_native_dialog_parent_class)->dispose (object);
+}
+
+static void
+gtk_native_dialog_finalize (GObject *object)
+{
+  GtkNativeDialog *self = GTK_NATIVE_DIALOG (object);
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+
+  g_clear_pointer (&priv->title, g_free);
+  g_clear_object (&priv->transient_for);
+
+  G_OBJECT_CLASS (gtk_native_dialog_parent_class)->finalize (object);
+}
+
+static void
+gtk_native_dialog_class_init (GtkNativeDialogClass *class)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (class);
+
+  gobject_class->set_property = gtk_native_dialog_set_property;
+  gobject_class->get_property = gtk_native_dialog_get_property;
+  gobject_class->finalize = gtk_native_dialog_finalize;
+  gobject_class->dispose = gtk_native_dialog_dispose;
+
+  /**
+   * GtkNativeDialog:title:
+   *
+   * The title of the dialog window
+   *
+   * Since: 3.20
+   */
+  native_props[PROP_TITLE] =
+    g_param_spec_string ("title",
+                         P_("Dialog Title"),
+                         P_("The title of the file chooser dialog"),
+                         NULL,
+                         GTK_PARAM_READWRITE);
+
+  /**
+   * GtkNativeDialog:modal:
+   *
+   * Whether the window should be modal with respect to its transient parent.
+   *
+   * Since: 3.20
+   */
+  native_props[PROP_MODAL] =
+    g_param_spec_boolean ("modal",
+                          P_("Modal"),
+                          P_("If TRUE, the dialog is modal (other windows are not usable while this one is 
up)"),
+                          FALSE,
+                          GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  /**
+   * GtkNativeDialog:visible:
+   *
+   * Whether the window is currenlty visible.
+   *
+   * Since: 3.20
+   */
+  native_props[PROP_VISIBLE] =
+    g_param_spec_boolean ("visible",
+                          P_("Visible"),
+                          P_("Whether the dialog is currently visible"),
+                          FALSE,
+                          GTK_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY);
+
+  /**
+   * GtkNativeDialog:transient-for:
+   *
+   * The transient parent of the dialog, or %NULL for none.
+   *
+   * Since: 3.20
+   */
+  native_props[PROP_TRANSIENT_FOR] =
+    g_param_spec_object ("transient-for",
+                         P_("Transient for Window"),
+                         P_("The transient parent of the dialog"),
+                         GTK_TYPE_WINDOW,
+                         GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_EXPLICIT_NOTIFY);
+
+  g_object_class_install_properties (gobject_class, LAST_ARG, native_props);
+
+  /**
+   * GtkNativeDialog::response:
+   * @self: the object on which the signal is emitted
+   * @response_id: the response ID
+   *
+   * Emitted when the user responds to the dialog.
+   *
+   * When this is called the dialog has been hidden.
+   *
+   * If you call gtk_native_dialog_hide() before the user responds to
+   * the dialog this signal will not be emitted.
+   *
+   * Since: 3.20
+   */
+  native_signals[RESPONSE] =
+    g_signal_new (I_("response"),
+                  G_OBJECT_CLASS_TYPE (class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GtkNativeDialogClass, response),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__INT,
+                  G_TYPE_NONE, 1,
+                  G_TYPE_INT);
+}
+
+static void
+gtk_native_dialog_init (GtkNativeDialog *self)
+{
+}
+
+/**
+ * gtk_native_dialog_show:
+ * @self: a #GtkNativeDialog
+ *
+ * Shows the dialog on the display, allowing the user to interact with
+ * it. When the user accepts the state of the dialog the dialog will
+ * be automatically hidden and the #GtkNativeDialog::response signal
+ * will be emitted.
+ *
+ * Multiple calls while the dialog is visible will be ignored.
+ *
+ * Since: 3.20
+ **/
+void
+gtk_native_dialog_show (GtkNativeDialog *self)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+  GtkNativeDialogClass *klass;
+
+  g_return_if_fail (GTK_IS_NATIVE_DIALOG (self));
+
+  if (priv->visible)
+    return;
+
+  klass = GTK_NATIVE_DIALOG_GET_CLASS (self);
+
+  g_return_if_fail (klass->show != NULL);
+
+  klass->show (self);
+
+  priv->visible = TRUE;
+  g_object_notify_by_pspec (G_OBJECT (self), native_props[PROP_VISIBLE]);
+}
+
+/**
+ * gtk_native_dialog_hide:
+ * @self: a #GtkNativeDialog
+ *
+ * Hides the dialog if it is visilbe, aborting any interaction. Once this
+ * is called the  #GtkNativeDialog::response signal will not be emitted
+ * until after the next call to gtk_native_dialog_show().
+ *
+ * If the dialog is not visible this does nothing.
+ *
+ * Since: 3.20
+ **/
+void
+gtk_native_dialog_hide (GtkNativeDialog *self)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+  GtkNativeDialogClass *klass;
+
+  g_return_if_fail (GTK_IS_NATIVE_DIALOG (self));
+
+  if (!priv->visible)
+    return;
+
+  priv->visible = FALSE;
+
+  klass = GTK_NATIVE_DIALOG_GET_CLASS (self);
+
+  g_return_if_fail (klass->hide != NULL);
+
+  klass->hide (self);
+
+  if (priv->run_loop && g_main_loop_is_running (priv->run_loop))
+    g_main_loop_quit (priv->run_loop);
+
+  g_object_notify_by_pspec (G_OBJECT (self), native_props[PROP_VISIBLE]);
+}
+
+void
+_gtk_native_dialog_emit_response (GtkNativeDialog *self,
+                                  int response_id)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+  priv->visible = FALSE;
+  g_object_notify_by_pspec (G_OBJECT (self), native_props[PROP_VISIBLE]);
+
+  g_signal_emit (self, native_signals[RESPONSE], 0, response_id);
+}
+
+/**
+ * gtk_native_dialog_get_visible:
+ * @self: a #GtkNativeDialog
+ *
+ * Determines whether the dialog is visible.
+ *
+ * Returns: %TRUE if the dialog is visible
+ *
+ * Since: 3.20
+ **/
+gboolean
+gtk_native_dialog_get_visible (GtkNativeDialog *self)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+
+  g_return_val_if_fail (GTK_IS_NATIVE_DIALOG (self), FALSE);
+
+  return priv->visible;
+}
+
+/**
+ * gtk_native_dialog_set_modal:
+ * @self: a #GtkNativeDialog
+ * @modal: whether the window is modal
+ *
+ * Sets a dialog modal or non-modal. Modal dialogs prevent interaction
+ * with other windows in the same application. To keep modal dialogs
+ * on top of main application windows, use
+ * gtk_native_dialog_set_transient_for() to make the dialog transient for the
+ * parent; most [window managers][gtk-X11-arch]
+ * will then disallow lowering the dialog below the parent.
+ *
+ * Since: 3.20
+ **/
+void
+gtk_native_dialog_set_modal (GtkNativeDialog *self,
+                             gboolean modal)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+
+  g_return_if_fail (GTK_IS_NATIVE_DIALOG (self));
+
+  modal = modal != FALSE;
+
+  if (priv->modal == modal)
+    return;
+
+  priv->modal = modal;
+  g_object_notify_by_pspec (G_OBJECT (self), native_props[PROP_MODAL]);
+}
+
+/**
+ * gtk_native_dialog_get_modal:
+ * @self: a #GtkNativeDialog
+ *
+ * Returns whether the dialog is modal. See gtk_native_dialog_set_modal().
+ *
+ * Returns: %TRUE if the dialog is set to be modal
+ *
+ * Since: 3.20
+ **/
+gboolean
+gtk_native_dialog_get_modal (GtkNativeDialog *self)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+
+  g_return_val_if_fail (GTK_IS_NATIVE_DIALOG (self), FALSE);
+
+  return priv->modal;
+}
+
+/**
+ * gtk_native_dialog_set_title:
+ * @self: a #GtkNativeDialog
+ * @title: title of the dialog
+ *
+ * Sets the title of the #GtkNativeDialog.
+ *
+ * Since: 3.20
+ **/
+void
+gtk_native_dialog_set_title (GtkNativeDialog *self,
+                                   const char *title)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+
+  g_return_if_fail (GTK_IS_NATIVE_DIALOG (self));
+
+  g_free (priv->title);
+  priv->title = g_strdup (title);
+
+  g_object_notify_by_pspec (G_OBJECT (self), native_props[PROP_TITLE]);
+}
+
+/**
+ * gtk_native_dialog_get_title:
+ * @self: a #GtkNativeDialog
+ *
+ * Gets the title of the #GtkNativeDialog.
+ *
+ * Returns: the title of the dialog, or %NULL if none has
+ *    been set explicitly. The returned string is owned by the widget
+ *    and must not be modified or freed.
+ *
+ * Since: 3.20
+ **/
+const char *
+gtk_native_dialog_get_title (GtkNativeDialog *self)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+
+  g_return_val_if_fail (GTK_IS_NATIVE_DIALOG (self), NULL);
+
+  return priv->title;
+}
+
+/**
+ * gtk_native_dialog_set_transient_for:
+ * @self: a #GtkNativeDialog
+ * @parent: (allow-none): parent window, or %NULL
+ *
+ * Dialog windows should be set transient for the main application
+ * window they were spawned from. This allows
+ * [window managers][gtk-X11-arch] to e.g. keep the
+ * dialog on top of the main window, or center the dialog over the
+ * main window.
+ *
+ * Passing %NULL for @parent unsets the current transient window.
+ *
+ * Since: 3.20
+ */
+void
+gtk_native_dialog_set_transient_for (GtkNativeDialog *self,
+                                     GtkWindow *parent)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+
+  g_return_if_fail (GTK_IS_NATIVE_DIALOG (self));
+
+  if (g_set_object (&priv->transient_for, parent))
+    g_object_notify_by_pspec (G_OBJECT (self), native_props[PROP_TRANSIENT_FOR]);
+}
+
+/**
+ * gtk_native_dialog_get_transient_for:
+ * @self: a #GtkNativeDialog
+ *
+ * Fetches the transient parent for this window. See
+ * gtk_native_dialog_set_transient_for().
+ *
+ * Returns: (transfer none): the transient parent for this window, or %NULL
+ *    if no transient parent has been set.
+ *
+ * Since: 3.20
+ **/
+GtkWindow *
+gtk_native_dialog_get_transient_for (GtkNativeDialog *self)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+
+  g_return_val_if_fail (GTK_IS_NATIVE_DIALOG (self), NULL);
+
+  return priv->transient_for;
+}
+
+static void
+run_response_cb (GtkNativeDialog *self,
+                 gint response_id,
+                 gpointer data)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+
+  priv->run_response_id = response_id;
+  if (priv->run_loop && g_main_loop_is_running (priv->run_loop))
+    g_main_loop_quit (priv->run_loop);
+}
+
+/**
+ * gtk_native_dialog_run:
+ * @self: a #GtkNativeDialog
+ *
+ * Blocks in a recursive main loop until @self emits the
+ * #GtkNativeDialog::response signal. It then returns the response ID
+ * from the ::response signal emission.
+ *
+ * Before entering the recursive main loop, gtk_native_dialog_run()
+ * calls gtk_native_dialog_show() on the dialog for you.
+ *
+ * After gtk_native_dialog_run() returns, then dialog will be hidden.
+ *
+ * Typical usage of this function might be:
+ * |[<!-- language="C" -->
+ *   gint result = gtk_native_dialog_run (GTK_NATIVE_DIALOG (dialog));
+ *   switch (result)
+ *     {
+ *       case GTK_RESPONSE_ACCEPT:
+ *          do_application_specific_something ();
+ *          break;
+ *       default:
+ *          do_nothing_since_dialog_was_cancelled ();
+ *          break;
+ *     }
+ *   g_object_unref (dialog);
+ * ]|
+ *
+ * Note that even though the recursive main loop gives the effect of a
+ * modal dialog (it prevents the user from interacting with other
+ * windows in the same window group while the dialog is run), callbacks
+ * such as timeouts, IO channel watches, DND drops, etc, will
+ * be triggered during a gtk_nautilus_dialog_run() call.
+ *
+ * Returns: response ID
+ *
+ * Since: 3.20
+ **/
+gint
+gtk_native_dialog_run (GtkNativeDialog *self)
+{
+  GtkNativeDialogPrivate *priv = gtk_native_dialog_get_instance_private (self);
+  gboolean was_modal;
+  guint response_handler;
+
+  g_return_val_if_fail (GTK_IS_NATIVE_DIALOG (self), -1);
+  g_return_val_if_fail (!priv->visible, -1);
+  g_return_val_if_fail (priv->run_loop == NULL, -1);
+
+  if (priv->visible || priv->run_loop != NULL)
+    return -1;
+
+  g_object_ref (self);
+
+  priv->run_response_id = GTK_RESPONSE_NONE;
+  priv->run_loop = g_main_loop_new (NULL, FALSE);
+
+  was_modal = priv->modal;
+  gtk_native_dialog_set_modal (self, FALSE);
+
+  response_handler =
+    g_signal_connect (self,
+                      "response",
+                      G_CALLBACK (run_response_cb),
+                      NULL);
+
+  gtk_native_dialog_show (self);
+
+  gdk_threads_leave ();
+  g_main_loop_run (priv->run_loop);
+  gdk_threads_enter ();
+
+  g_signal_handler_disconnect (self, response_handler);
+
+  g_main_loop_unref (priv->run_loop);
+  priv->run_loop = NULL;
+
+  if (!was_modal)
+    gtk_native_dialog_set_modal (self, FALSE);
+
+  g_object_unref (self);
+
+  return priv->run_response_id;
+}
diff --git a/gtk/gtknativedialog.h b/gtk/gtknativedialog.h
new file mode 100644
index 0000000..8d5bd60
--- /dev/null
+++ b/gtk/gtknativedialog.h
@@ -0,0 +1,79 @@
+/* GTK - The GIMP Toolkit
+ * gtknativedialog.h: Native dialog
+ * Copyright (C) 2015, Red Hat, Inc.
+ *
+ * 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 2 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
+ * Lesser 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_NATIVE_DIALOG_H__
+#define __GTK_NATIVE_DIALOG_H__
+
+#if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
+#error "Only <gtk/gtk.h> can be included directly."
+#endif
+
+#include <gtk/gtkwindow.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_NATIVE_DIALOG             (gtk_native_dialog_get_type ())
+
+GDK_AVAILABLE_IN_3_20
+G_DECLARE_DERIVABLE_TYPE (GtkNativeDialog, gtk_native_dialog, GTK, NATIVE_DIALOG, GObject)
+
+struct _GtkNativeDialogClass
+{
+  GObjectClass parent_class;
+
+  void (* response) (GtkNativeDialog *self, gint response_id);
+
+  /* <private> */
+  void (* show) (GtkNativeDialog *self);
+  void (* hide) (GtkNativeDialog *self);
+
+  /* Padding for future expansion */
+  void (*_gtk_reserved1) (void);
+  void (*_gtk_reserved2) (void);
+  void (*_gtk_reserved3) (void);
+  void (*_gtk_reserved4) (void);
+};
+
+GDK_AVAILABLE_IN_3_20
+void                  gtk_native_dialog_show (GtkNativeDialog *self);
+GDK_AVAILABLE_IN_3_20
+void                  gtk_native_dialog_hide (GtkNativeDialog *self);
+GDK_AVAILABLE_IN_3_20
+gboolean              gtk_native_dialog_get_visible (GtkNativeDialog *self);
+GDK_AVAILABLE_IN_3_20
+void                  gtk_native_dialog_set_modal (GtkNativeDialog *self,
+                                                   gboolean modal);
+GDK_AVAILABLE_IN_3_20
+gboolean              gtk_native_dialog_get_modal (GtkNativeDialog *self);
+GDK_AVAILABLE_IN_3_20
+void                  gtk_native_dialog_set_title (GtkNativeDialog *self,
+                                                   const char *title);
+GDK_AVAILABLE_IN_3_20
+const char *          gtk_native_dialog_get_title (GtkNativeDialog *self);
+GDK_AVAILABLE_IN_3_20
+void                  gtk_native_dialog_set_transient_for (GtkNativeDialog *self,
+                                                           GtkWindow *parent);
+GDK_AVAILABLE_IN_3_20
+GtkWindow *           gtk_native_dialog_get_transient_for (GtkNativeDialog *self);
+
+GDK_AVAILABLE_IN_3_20
+gint                  gtk_native_dialog_run (GtkNativeDialog *self);
+
+G_END_DECLS
+
+#endif /* __GTK_NATIVE_DIALOG_H__ */
diff --git a/gtk/gtknativedialogprivate.h b/gtk/gtknativedialogprivate.h
new file mode 100644
index 0000000..8f7013a
--- /dev/null
+++ b/gtk/gtknativedialogprivate.h
@@ -0,0 +1,31 @@
+/* GTK - The GIMP Toolkit
+ * gtknativedialogprivate.h: Native dialog
+ * Copyright (C) 2015, Red Hat, Inc.
+ *
+ * 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 2 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
+ * Lesser 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GTK_NATIVE_DIALOG_PRIVATE_H__
+#define __GTK_NATIVE_DIALOG_PRIVATE_H__
+
+#include <gtk/gtknativedialog.h>
+
+G_BEGIN_DECLS
+
+void _gtk_native_dialog_emit_response (GtkNativeDialog *self,
+                                       int              response_id);
+
+G_END_DECLS
+
+#endif /* __GTK_NATIVE_DIALOG_PRIVATE_H__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]