/* Copyright (C) 2011 and 2013 Chris Vine

The library comprised in this file or of which this file is part is
distributed by Chris Vine under the GNU Lesser General Public
License as follows:

   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.1 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, version 2.1, for more details.

   You should have received a copy of the GNU Lesser General Public
   License, version 2.1, along with this library (see the file LGPL.TXT
   which came with this source code package in the c++-gtk-utils
   sub-directory); if not, write to the Free Software Foundation, Inc.,
   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

*/

#ifndef CGU_APPLICATION_H
#define CGU_APPLICATION_H

#include <list>
#include <exception>
#include <utility>

#include <c++-gtk-utils/cgu_config.h>

#ifdef CGU_USE_GTK
#include <gtk/gtk.h>
#endif

#include <gio/gio.h>

#include <c++-gtk-utils/gobj_handle.h>
#include <c++-gtk-utils/window.h>
#include <c++-gtk-utils/emitter.h>

namespace Cgu {

#if defined(DOXYGEN_PARSING) || defined(CGU_USE_GTK)
#if defined(DOXYGEN_PARSING) || GTK_CHECK_VERSION(2,99,0)

/** 
 * @class Cgu::ApplicationNameError application.h c++-gtk-utils/application.h
 * @brief This class is thrown when the program id name passed to the
 * constructor of Cgu::Application is invalid.
 */
struct ApplicationNameError: public std::exception {
  virtual const char* what() const throw() {return "ApplicationNameError\n";}
};

/** 
 * @class Cgu::Application application.h c++-gtk-utils/application.h
 * @brief This is a class for constructing and managing GtkApplication
 * objects.
 *
 * @details It is available since version 2.0.0-rc2.  It is only
 * compiled in with a GTK-3 or GTK-4 installation, and if the library
 * is not configured with the \--without-gtk option.
 *
 * In typical usage, a Cgu::Application object is created in main(),
 * and then a callback is attached to the 'activate', 'command_line'
 * or 'open' emitter, depending on the flag passed to the Application
 * object's constructor.  The run() method of the Application object
 * is then called, and a window deriving from Cgu::WinBase is
 * constructed in the callback and added to the Application object or,
 * if the program is a single instance program with only one main
 * window and an instance is already running, a function is called to
 * present that window.
 *
 * Here is a brief explanation of how the flag options passed to the
 * Cgu::Application object (and so to the underlying GApplication
 * object) work:
 *
 * @par
 * (a) If a Cgu::Application object is constructed with the
 * G_APPLICATION_FLAGS_NONE flag set, then calling the
 * Cgu::Application::run() method (which hands off to
 * g_application_run()) will cause the 'activate' emitter to emit.  No
 * command line parameter should be passed to the run method (argc
 * should be 0 or 1), otherwise GtkApplication will cause the start-up
 * to abort, except that from glib >=2.40 and gtk >=3.12 recognised
 * gtk command line options can be passed in for stripping out and
 * consumption by gtk.  g_application_run(), and so
 * Cgu::Application::run(), can be called with argc and argv set to 0
 * where such aborting must be avoided.
 * @par
 * (b) If a Cgu::Application object is constructed with the
 * G_APPLICATION_HANDLES_OPEN flag set, then calling the
 * Cgu::Application::run() method will cause the 'activate' emitter to
 * emit if no command line parameters were provided when the program
 * was started, or cause the 'open' emitter to emit if parameters are
 * passed.  Such parameters will be construed as files/uris, and will
 * be passed to the 'open' emitter by array of GFile*'s.
 * @par
 * (c) If a Cgu::Application object is constructed with the
 * G_APPLICATION_HANDLES_COMMAND_LINE flag set, then calling the
 * Cgu::Application::run() method will cause the 'command_line'
 * emitter to emit.  All the command line parameters not handled
 * locally in the new instance will be passed on, and they can be
 * obtained via the GApplicationCommandLine argument of the
 * 'command_line' emitter.
 *
 * Prior to glib-2.40/gtk-3.12 g_application_run() (and so
 * Cgu::Application::run()) does not consume any recognised glib/gtk
 * options such as \--display.  Such options can be stripped out (and
 * acted on by gtk) by calling gtk_init() before constructing the
 * Cgu::Application object (but gtk_init() does not need to be called
 * for any other purpose), or by using the GOptionGroup/GOptionEntry
 * interface.
 *
 * There is no emitter provided for GApplication's 'shutdown' and
 * 'handle-local-options' signals ('handle-local-options' is provided
 * from glib-2.40 onwards).  There is only very rarely a need to use
 * the 'shutdown' signal in C++ code, which should not normally keep
 * naked resources (the question whether clean-up on shutdown is
 * needed is usually not just answered by whether we are in the first
 * instance of the program to start, but whether particular state has
 * accumulated in consequence of the program running, which is a
 * question best answered by the object(s) managing the state, say on
 * destruction on stack unwinding); but where the 'shutdown' signal is
 * useful, GApplication's C level API is available via
 * Cgu::Application::get_g_app().  If using 'handle-local-options' you
 * will normally have hooked into local option handling using
 * g_application_add_main_option_entries() or
 * g_application_add_option_group().  In that case the option
 * handling, including connecting where relevent to
 * 'handle-local-options', is also best done at GApplication's C level
 * by obtaining the GApplication object with
 * Cgu::Application::get_g_app().
 *
 * There is little in this class that cannot also be done using the
 * @ref prog_presenterAnchor "Cgu::prog_present" interface, which has
 * the advantage of being more portable (@ref prog_presenterAnchor
 * "Cgu::prog_present" does not depend on GTK-3 or GTK-4), but this
 * class is more convenient to use where a program requires multiple
 * main application windows which can be independently opened and any
 * of which are to keep the program alive until the last one is
 * closed, or if an application menu is to be provided for, say, the
 * gnome shell.
 *
 * Cgu::Application objects are not singletons.  It is possible to
 * drop an Application object out of scope or destroy it in some other
 * way after closing or removing all its windows, then construct
 * another with a different flag and then call run() on the second one
 * (although it would be a curious application that wanted to do so).
 * It is also possible, but even more off-the-wall, to have two
 * Application objects in existence in the same process at the same
 * time provided different dbus identifiers are supplied to the
 * constructor for each, although run() may only be called on one of
 * them at any one time.  However, this is something of a curiosity:
 * in nearly all cases an application will only have one
 * Cgu::Application object, since the main purpose of Cgu::Application
 * is to facilitate single instance programs.
 *
 * Cgu::WinBase objects, and so Cgu::Application, can be used with
 * widget heirarchies or top level windows created using GtkBuilder.
 * See @ref GtkBuilder for particulars about that.
 *
 * Here is a compilable example, demonstrating the use of the
 * GApplicationFlags options.  It uses a GtkApplicationWindow object,
 * as provided by GTK >= 3.4, so that it can provide an application
 * menu for, say, the gnome shell.  For earlier versions of GTK-3, the
 * Message class can be constructed from a standard GtkWindow object,
 * and the application and window menu code in the startup() callback
 * can be omitted.
 *
 * @code
 *   #include <iostream>
 *   #include <ostream>
 *   #include <string>
 *   #include <list>
 *
 *   #include <gtk/gtk.h>
 *
 *   #include <c++-gtk-utils/callback.h>
 *   #include <c++-gtk-utils/application.h>
 *   #include <c++-gtk-utils/window.h>
 *   #include <c++-gtk-utils/shared_handle.h>
 *   #include <c++-gtk-utils/gobj_handle.h>
 *
 *   // SETUP HERE: uncomment the flag to be tested:
 *
 *   //const GApplicationFlags app_flag = G_APPLICATION_FLAGS_NONE;
 *   const GApplicationFlags app_flag = G_APPLICATION_HANDLES_OPEN;
 *   //const GApplicationFlags app_flag = G_APPLICATION_HANDLES_COMMAND_LINE;
 *
 *   using namespace Cgu;
 *
 *   // *** Demonstration Message class ***
 *
 *   extern "C" void message_button_clicked(GtkWidget*, void*);
 *
 *   class Message: public Cgu::WinBase {
 *   public:
 *     friend void message_button_clicked(GtkWidget*, void*);
 *     Message(const char* text, GApplication* app);
 *   };
 *
 *   // *** for Message menu actions ***
 *
 *   namespace {
 *   extern "C" {
 *   void win_beep(GSimpleAction*, GVariant*, void*) {
 *     gdk_beep();
 *   }
 *
 *   GActionEntry win_entries[] = {
 *     { "beep", win_beep, NULL, NULL, NULL },
 *   };
 *   } // extern "C"
 *   } // unnamed namespace
 *
 *   // *** Message callbacks ***
 *
 *   void message_button_clicked(GtkWidget* w, void*) {
 *     std::cout << "Clicked" << std::endl;
 *   }
 *
 *   // *** Message implementation ***
 *
 *   Message::Message(const char* text, GApplication* app):
 *       WinBase{"Message", 0, false, 0,
 *               GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(app)))} {
 *     g_action_map_add_action_entries(G_ACTION_MAP(get_win()),
 *                                     win_entries,
 *                                     G_N_ELEMENTS(win_entries),
 *                                     static_cast<void*>(0));
 *     GtkWidget* box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
 *     gtk_box_set_homogeneous(GTK_BOX(box), false);
 *     gtk_container_add(GTK_CONTAINER(get_win()), box);
 *     GtkWidget* label = gtk_label_new(text);
 *     gtk_box_pack_start(GTK_BOX(box), label,
 *                        true, false, 0);
 *     GtkWidget* button_box = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
 *     gtk_box_pack_start(GTK_BOX(box), button_box,
 *                        false, false, 0);
 *     GtkWidget* button = gtk_button_new_from_stock(GTK_STOCK_OK);
 *     gtk_container_add(GTK_CONTAINER(button_box), button);
 *     g_signal_connect(G_OBJECT(button), "clicked",
 *                      G_CALLBACK(message_button_clicked), 0);
 *     gtk_widget_set_can_default(button, true);
 *   }
 *
 *   namespace {
 *
 *   // *** for application actions ***
 *
 *   extern "C" {
 *   void app_beep(GSimpleAction*, GVariant*, void*) {
 *     gdk_beep();
 *   }
 *
 *   void app_quit(GSimpleAction*, GVariant*, void* data) {
 *     Cgu::Application* app = static_cast<Cgu::Application*>(data);
 *     std::list<Cgu::WinBase*> wins = app->get_windows();
 *     for (auto iter = wins.begin(); iter != wins.end(); ++iter) {
 *       delete *iter;  // this will also remove the Message object from
 *                      // the Cgu::Application object
 *     }
 *   }
 *
 *   GActionEntry app_entries[] = {
 *     { "beep", app_beep, NULL, NULL, NULL },
 *     { "quit", app_quit, NULL, NULL, NULL },
 *   };
 *   } // extern "C"
 *
 *   // *** application callbacks ***
 *
 *   void startup(Cgu::Application* app) {
 *     std::cout << "startup() called" << std::endl;
 *
 *     g_action_map_add_action_entries(G_ACTION_MAP(app->get_g_app()),
 *                                     app_entries,
 *                                     G_N_ELEMENTS(app_entries),
 *                                     app);
 *     Cgu::GobjHandle<GMenu> app_menu{g_menu_new()};
 *     g_menu_append(app_menu, "Beep", "app.beep");
 *     g_menu_append(app_menu, "_Quit", "app.quit");
 *     gtk_application_set_app_menu(GTK_APPLICATION(app->get_g_app()),
 *                                  G_MENU_MODEL(app_menu.get()));
 *
 *     Cgu::GobjHandle<GMenu> win_menu{g_menu_new()};
 *     Cgu::GobjHandle<GMenu> sub_menu{g_menu_new()};
 *     g_menu_append_submenu(win_menu, "Menu1", G_MENU_MODEL(sub_menu.get()));
 *     g_menu_append(sub_menu, "More beep", "win.beep"); // see Message::Message() for actions
 *     gtk_application_set_menubar(GTK_APPLICATION(app->get_g_app()),
 *                                 G_MENU_MODEL(win_menu.get()));
 *   }
 *
 *   void activate(Cgu::Application* app) {
 *     std::cout << "activate() called" << std::endl;
 *
 *     // probably if no arguments are passed, only one window is wanted,
 *     // which is now to present itself if it already exists: comment this
 *     // 'if' block out if a new window is to be added on each occasion
 *     // the program is started
 *     if (app->get_win_count() > 0) {
 *       gtk_window_present(app->get_windows().front()->get_win());
 *       return;
 *     }
 *     WinBase* dialog = new Message("This is a message", app->get_g_app());
 *     app->add(dialog);
 *     dialog->show_all();
 *   }
 *
 *   void command_line(Cgu::Application* app, GApplicationCommandLine* cl, gint&) {
 *     std::cout << "command_line() called" << std::endl;
 *
 *     // probably if the G_APPLICATION_HANDLES_COMMAND_LINE flag is set,
 *     // only one window is wanted, which is now to present itself if it
 *     // already exists: comment this 'if' block out if a new window is to
 *     // be added on each occasion the program is started
 *     if (app->get_win_count() > 0) {
 *       gtk_window_present(app->get_windows().front()->get_win());
 *       return;
 *     }
 *     std::string text("Command line options are:\n");
 *     int argc = 0;
 *     gchar** argv = g_application_command_line_get_arguments(cl, &argc);
 *     for (int count = 0; count < argc; ++count) {
 *       try {
 *         text += argv[count];
 *         text += '\n';
 *       }
 *       catch (...) {
 *         g_strfreev(argv);
 *         throw; // exceptions will be consumed by the callback handler and
 *                // a g_critical warning issued, but let's not leak memory
 *       }
 *     }
 *     g_strfreev(argv);
 *     WinBase* dialog = new Message(text.c_str(), app->get_g_app());
 *     app->add(dialog);
 *     dialog->show_all();
 *   }
 *
 *   void open(Cgu::Application* app, std::pair<GFile**, gint> files, gchar*) {
 *     std::cout << "open() called" << std::endl;
 *
 *     // probably if the G_APPLICATION_HANDLES_OPEN flag is set and an
 *     // argument is passed, the adding of a new window is wanted on each
 *     // occasion the program is started
 *     std::string text("Files are:\n");
 *     for (int count = 0; count < files.second; ++count) {
 *       GcharScopedHandle uri(g_file_get_uri(files.first[count]));
 *       text += uri;
 *       text += '\n';
 *     }
 *     WinBase* dialog = new Message(text.c_str(), app->get_g_app());
 *     app->add(dialog);
 *     dialog->show_all();
 *   }
 *
 *   } // unnamed namespace
 *
 *   // *** main() ***
 *
 *   int main(int argc, char* argv[]) {
 *
 *     // gtk_init() is only relevant for the purposes of stripping out
 *     // and acting on glib/gtk recognised options, either where
 *     // glib < 2.40 and gtk < 3.12 are used or where you want to pass
 *     // no arguments to Cgu::Application::run() when
 *     // G_APPLICATION_FLAGS_NONE is set in order to ensure that the
 *     // program does not abort with unrecognised options -
 *     // gtk_application_new() (and so the Cgu::Application constructor)
 *     // will call g_type_init() if the type system needs initialization
 *     gtk_init(&argc, &argv);
 *
 *     Application app{"my_prog", app_flag};
 *     app.startup.connect(Callback::make(startup));
 *     app.activate.connect(Callback::make(activate));
 *     app.command_line.connect(Callback::make(command_line));
 *     app.open.connect(Callback::make(open));
 *     if (app_flag == G_APPLICATION_FLAGS_NONE)
 *       return app.run(0, 0);
 *     else
 *       return app.run(argc, argv);
 *   }
 * @endcode
 *
 * One thing to note about this example is that the callbacks
 * connected to the Cgu::Application object execute in the first
 * instance of the program to be started (the instance in which
 * Cgu::Application::run() blocks).  If the program is then restarted,
 * Cgu::Application::run() returns in the new program instance as soon
 * as it has invoked the existing instance via dbus, following which
 * the new program instance exits, so immediately disposing of the
 * Cgu::Application object and callbacks which were constructed on the
 * restart.  This is a feature of GApplication/GtkApplication: given
 * the overhead of starting a new process, and that restarting a
 * single-instance program is in any event an exceptional event, any
 * additional overhead created by constructing and then destroying the
 * Cgu::Application object and callbacks in the new instance is
 * trivial.  (As mentioned above, from glib-2.40 the
 * 'handle-local-options' signal can be used to hook into the
 * GApplication object constructed in the new program instance, but
 * this is intended to assist option parsing in the new instance.)
 */

class Application {

  std::list<WinBase*> win_list;
  GobjHandle<GtkApplication> app;

  void* reserved; // for future use
public:

  typedef std::list<WinBase*>::size_type size_type;

/**
 * This class cannot be copied.  The copy constructor is deleted.
 */
  Application(const Application&) = delete;

/**
 * This class cannot be copied.  The assignment operator is deleted.
 */
  Application& operator=(const Application&) = delete;

/**
 * This SafeEmitterArg object emits (and so executes any connected
 * callback) when the underlying GApplication object emits its
 * @a activate signal.  The argument passed to the emitter's
 * callback(s) is a pointer to the Cgu::Application object.
 * @note When the callback executes, thread cancellation is blocked,
 * and any exceptions are consumed with a g_critical message issued.
 * The callback will always execute in the main GUI thread when
 * executed in response to the run() method.  Because a SafeEmitterArg
 * object is used, the emitter object itself is thread safe.
 *
 * Since 2.0.0-rc2
 */
  Cgu::SafeEmitterArg<Cgu::Application*> activate;

/**
 * This SafeEmitterArg object emits (and so executes any connected
 * callback) when the underlying GApplication object emits its @a
 * startup signal (which, unless the G_APPLICATION_NON_UNIQUE flag has
 * been set in the Cgu::Application object's constructor, it will
 * normally do once, on the first occasion that run() is called). The
 * argument passed to the emitter's callback(s) is a pointer to the
 * Cgu::Application object.  This signal can be used to set up a
 * desktop application menu, or a menu bar for WinBase objects
 * constructed from a GtkApplicationWindow object.
 * @note When the callback executes, thread cancellation is blocked,
 * and any exceptions are consumed with a g_critical message issued.
 * The callback will always execute in the main GUI thread when
 * executed in response to the run() method.  Because a SafeEmitterArg
 * object is used, the emitter object itself is thread safe.
 *
 * Since 2.0.0-rc2
 */
  Cgu::SafeEmitterArg<Cgu::Application*> startup;

/**
 * This SafeEmitterArg object emits (and so executes any connected
 * callback) when the underlying GApplication object emits its
 * @a command-line signal.  The second argument passed to the
 * emitter's callback(s) is the one passed by that signal, that is to
 * say the arguments are:
 *
 * first: a pointer to the Cgu::Application object.
 *
 * second: a pointer to a GApplicationCommandLine object representing
 * the passed command line (this is owned by gio and should not be
 * unref'ed unless it has previously been explicitly ref'ed to keep
 * the GApplicationCommandLine object alive even after the connected
 * callback has returned).
 *
 * third: a gint& reference to which the value to be returned to the
 * GApplication's command-line signal can be passed: if no value is
 * assigned to it or no callback has been attached to the signal, 0
 * will be returned, except that if an exception from a callback is
 * consumed, -1 will be returned.  If more than one callback is
 * attached to the signal and no exception is consumed, the last one
 * to assign a value will be have its value returned.
 *
 * @note When the callback executes, thread cancellation is blocked,
 * and any exceptions are consumed with a g_critical message issued
 * and a return value of -1 set.  The callback will always execute in
 * the main GUI thread when executed in response to the run() method.
 * Because a SafeEmitterArg object is used, the emitter object itself
 * is thread safe.
 *
 * Since 2.0.0-rc2
 */
  Cgu::SafeEmitterArg<Cgu::Application*, GApplicationCommandLine*, gint&> command_line;

/**
 * This SafeEmitterArg object emits (and so executes any connected
 * callback) when the underlying GApplication object emits its @a open
 * signal.  The second and third arguments passed to the emitter's
 * callback(s) are those passed by that signal, that is to say the
 * arguments are:
 *
 * first: a pointer to the Cgu::Application object.
 *
 * second: a std::pair object where the first member is an array of
 * GFile*'s representing the files/uris passed as arguments, and the
 * second member is the length of that array (the array is owned by
 * gio and should not be freed).
 *
 * third: a gchar* argument comprising the text of the "hint" (this is
 * owned by gio and should not be freed).
 *
 * @note When the callback executes, thread cancellation is blocked,
 * and any exceptions are consumed with a g_critical message issued.
 * The callback will always execute in the main GUI thread when
 * executed in response to the run() method.  Because a SafeEmitterArg
 * object is used, the emitter object itself is thread safe.
 *
 * Since 2.0.0-rc2
 */
  Cgu::SafeEmitterArg<Cgu::Application*, std::pair<GFile**, gint>, gchar*> open;

/**
 * Add a Cgu::WinBase object to the Cgu::Application object, and so
 * also add its managed GtkWindow object to the GtkApplication object.
 * Any Cgu::WinBase object passed to this method should not normally
 * be modal and must have been constructed on free store with the new
 * expression.  It is passed by pointer because it will be self-owning
 * (its lifetime would normally be determined by user action, not by
 * the program), although if it is removed from this Cgu::Application
 * object with remove(), the delete expression can (and normally
 * should) be called on it.  If a delete event occurs on the WinBase
 * object so that the WinBase object destroys itself (say, by the user
 * clicking on the window's close/delete button), or it destroys
 * itself in some other way (say, by calling the WinBase::close()
 * method), it will automatically be removed from this Application
 * object without further action being necessary.  The WinBase::exec()
 * method should never be called on a WinBase object which has been
 * added to an Application object.  The Cgu::Application class, and
 * thus this method, does not employ mutexes to make it thread safe,
 * as there should never be a reason to call Cgu::Application methods
 * in other than the main GUI thread.
 * @param win The Cgu::WinBase object to be added.
 * @exception std::bad_alloc This method might throw std::bad_alloc if
 * memory is exhausted and the system throws in that case, in which
 * case the WinBase object passed in will not be added.  If such an
 * exception is thrown and program recovery is to be attempted (which
 * is usually a waste of time as glib/gtk will terminate the program
 * if unable to obtain memory from the operating system), it would be
 * best to delete the Cgu::WinBase object passed in and start again.
 * An alternative is to show the window to the user for the user to
 * dispose of (windows passed to this method are self-owning); but if
 * that is done note that if the contained GtkWindow object is a
 * GtkApplicationWindow object, then it will already be associated
 * with a GtkApplication object when constructed, so it would usually
 * be best also to call gtk_application_remove_window() on it via
 * Cgu::Application::get_g_app() and Cgu::WinBase::get_win() before or
 * after it is shown so the Cgu::Application and GtkApplication
 * objects remain in sync.
 * @note As well as this method only being called in the main GUI
 * thread, if the program by which it is called calls GTK directly in
 * more than one thread and thus employs
 * gdk_threads_enter()/gdk_threads_leave() (rather than, say,
 * Cgu::Notifier or Cgu::Callback::post()), it must be surrounded by
 * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
 * a GTK signal handler. (The best approach however is for a program
 * only to address GTK/GDK in the main program thread, for which
 * purpose this library provides various functions and classes for
 * inter-thread communication, such as Cgu::Notifier and
 * Cgu::Callback::post(): see @ref Threading for particulars about
 * GTK thread safety.)
 *
 * Since 2.0.0-rc2
 */
  void add(Cgu::WinBase* win);

/**
 * Remove a Cgu::WinBase object from the Cgu::Application object, and
 * so also remove its managed GtkWindow object from the GtkApplication
 * object.  This method will not throw assuming that merely iterating
 * through a list does not throw (as it would not on any sane
 * implementation).  The Cgu::Application class, and thus this method,
 * does not employ mutexes to make it thread safe, as there should
 * never be a reason to call Cgu::Application methods in other than
 * the main GUI thread.  Calling this method does not destroy the
 * WinBase object.
 * @param win The Cgu::WinBase object to be removed.
 * @return true if the Cgu::WinBase object was found in the
 * Cgu::Application object and so removed, otherwise false.
 * @note As well as this method only being called in the main GUI
 * thread, if the program by which it is called calls GTK directly in
 * more than one thread and thus employs
 * gdk_threads_enter()/gdk_threads_leave() (rather than, say,
 * Cgu::Notifier or Cgu::Callback::post()), it must be surrounded by
 * gdk_threads_enter()/gdk_threads_leave() if called otherwise than in
 * a GTK signal handler. (The best approach however is for a program
 * only to address GTK/GDK in the main program thread, for which
 * purpose this library provides various functions and classes for
 * inter-thread communication, such as Cgu::Notifier and
 * Cgu::Callback::post(): see @ref Threading for particulars about
 * GTK thread safety.)
 *
 * Since 2.0.0-rc2
 */
  bool remove(Cgu::WinBase* win);

/** 
 * Calls g_application_run() in respect of the underlying
 * GtkApplication object, so invoking some of the Cgu::Application
 * class's emitters (normally in the first instance of the program to
 * be started): the exact behaviour depends on the GApplication flags
 * passed to the constructor and is explained in the introductory
 * remarks above.  This method is thread safe (although that is
 * irrelevant to its purpose) and will not throw.  In addition, if a
 * callback connected to an emitter throws, the exception is consumed
 * and a g_critical warning issued.  This function blocks until the
 * last WinBase object associated with this Application object is
 * destroyed or removed.
 * @param argc The argc from main() or 0.
 * @param argv The argv from main() or 0.
 * @return The exit status from g_application_run().
 *
 * Since 2.0.0-rc2
 */
  int run(int argc, char** argv) {
    return g_application_run((GApplication*)app.get(), argc, argv);
  }

/**
 * Get the underlying GApplication object (note, not the
 * GtkApplication object, although the GApplication object can be cast
 * to GtkApplication), so allowing any of gio's g_application_*()
 * functions to be applied to it.  In normal usage it will not be
 * necessary to call this method.  This method is thread safe and will
 * not throw.
 * @return The underlying GApplication object.
 *
 * Since 2.0.0-rc2
 */
  GApplication* get_g_app() const {return (GApplication*)app.get();}

/**
 * Get the list of Cgu::WinBase objects associated with the
 * application.  The Cgu::Application class, and thus this method,
 * does not employ mutexes to make it thread safe, as there should
 * never be a reason to call Cgu::Application methods in other than
 * the main GUI thread.
 * @return A list of the top level Cgu::WinBase objects associated
 * with the application, which will appear in the order in which they
 * were added.  If you need to access these, you will probably want to
 * do a dynamic_cast or static_cast to the child type.
 * @exception std::bad_alloc This method might throw std::bad_alloc if
 * memory is exhausted and the system throws in that case.
 *
 * Since 2.0.0-rc2
 */
  std::list<Cgu::WinBase*> get_windows() const {return win_list;}

/**
 * Gets the current count of Cgu::WinBase objects associated with this
 * Cgu::Application object.  When it reaches 0, the application will
 * normally end (but this can be prevented by calling
 * g_application_hold()/g_application_release() on the GApplication
 * object returned by get_g_app()).  This method can be used in the
 * callback of one of this class's emitters to determine whether this
 * is the first instance of a program to be started (assuming the
 * first instance calls add() to bring up a window), because in that
 * case it will return 0 until add() is called.  Calling
 * get_windows().size() will give the same result, but using this
 * method is more efficient as it will avoid a copy of the list of
 * windows.  This method will not throw assuming that calling
 * std::list::size() does not throw (as it would not on any sane
 * implementation).  The Cgu::Application class, and thus this method,
 * does not employ mutexes to make it thread safe, as there should
 * never be a reason to call Cgu::Application methods in other than
 * the main GUI thread.
 * @return The number of Cgu::WinBase objects currently associated
 * with this Cgu::Application object.
 *
 * Since 2.0.0-rc2
 */
  size_type get_win_count() const {return win_list.size();}

/**
 * This constructor will, via gtk_application_new(), cause
 * g_type_init() to be called.  If any GTK functions are to be called
 * before an Application object is constructed, g_type_init() (or
 * gtk_init()) must be called explicitly.
 * @param prog_name An identifier name.  This can comprise any valid
 * ASCII characters "[A-Z][a-z][0-9]_-", although it is usually best
 * to pass the program name.  Unlike with gtk_application_new(), it
 * does not need to comprise a full dbus bus name: this method will
 * construct its own valid dbus bus name from prog_name in the org.cgu
 * domain.
 * @param flags The GApplicationFlags to be passed to the
 * Cgu::Application object.  This class does not contain its own
 * sub-class of GApplication to customize this, but adopts the
 * behaviour of GtkApplication.  That behaviour is explained in the
 * introductory remarks.
 * @exception Cgu::ApplicationNameError This exception will be thrown
 * if the prog_name parameter does not meet the requirements referred
 * to above.
 * @exception std::bad_alloc This method might throw std::bad_alloc if
 * memory is exhausted and the system throws in that case.
 *
 * Since 2.0.0-rc2
 */
  Application(const char* prog_name, GApplicationFlags flags);

/**
 * From version 2.0.0-rc3, as a safety feature the destructor removes
 * any remaining WinBase objects associated with this Application
 * object (this would only be relevant if the user constructs the
 * Application object on free store, and then deletes it while the
 * run() method is still blocking for the purpose of constructing a
 * different Application object, but does not call the remove() method
 * on all associated WinBase objects before doing so: constructing an
 * Application object on free store in this way would be highly
 * unusual however).
 *
 * Since 2.0.0-rc3
 */
  ~Application() {while (!win_list.empty()) remove(win_list.front());}

/* Only has effect if --with-glib-memory-slices-compat or
 * --with-glib-memory-slices-no-compat option picked */
  CGU_GLIB_MEMORY_SLICES_FUNCS
};

#endif // GTK_CHECK_VERSION
#endif // CGU_USE_GTK

} // namespace Cgu

#endif // CGU_APPLICATION_H
