[gtkmm] Gtk::Application: Try to make this a replacement for Gtk::Main.



commit ecaf1dd3614a10a95b000a1a18a3cac7bf682e74
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Jan 20 09:14:00 2011 +0100

    Gtk::Application: Try to make this a replacement for Gtk::Main.
    
    * gtk/src/application.[hg|ccg]: Add a copy of init_gtkmm_internals() from
    Gtk::Main's main.cc and call it from the constructor, so that
    Gtk::Application can be a replacement for Gtk::Main.
    Add a constructor that takes argc and argv, so we can completely
    initialize GTK+ and gtkmm, because doing it in run() will be too late for
    some code: See bug #639925.
    Add a run() that does not take argc, argv, for when you have supplied them
    to the constructor instead.
    Add a run() that takes a window, like Gtk::Main::run(), so it can return
    when the window closes. However, see bug #639931 about it really responding to
    destruction, not closing.
    We show the window in an activate signal handler, because GTK+ complains if
    we don't have such a handler. See bug #640042.

 ChangeLog               |   18 ++++++++
 gtk/src/application.ccg |  108 +++++++++++++++++++++++++++++++++++++++++++++++
 gtk/src/application.hg  |   88 +++++++++++++++++++++++++++++++++++++-
 3 files changed, 212 insertions(+), 2 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index dcae841..58dd407 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2011-01-20  Murray Cumming  <murrayc murrayc com>
+
+	Gtk::Application: Try to make this a replacement for Gtk::Main.
+
+	* gtk/src/application.[hg|ccg]: Add a copy of init_gtkmm_internals() from 
+	Gtk::Main's main.cc and call it from the constructor, so that 
+	Gtk::Application can be a replacement for Gtk::Main.
+	Add a constructor that takes argc and argv, so we can completely 
+	initialize GTK+ and gtkmm, because doing it in run() will be too late for 
+	some code: See bug #639925.
+	Add a run() that does not take argc, argv, for when you have supplied them 
+	to the constructor instead.
+	Add a run() that takes a window, like Gtk::Main::run(), so it can return 
+	when the window closes. However, see bug #639931 about it really responding to 
+	destruction, not closing.
+	We show the window in an activate signal handler, because GTK+ complains if 
+	we don't have such a handler. See bug #640042.
+
 2011-01-18  Murray Cumming  <murrayc murrayc com>
 
 	Range: Added get/set_round_digits() and property.
diff --git a/gtk/src/application.ccg b/gtk/src/application.ccg
index 00066c3..3ef51ca 100644
--- a/gtk/src/application.ccg
+++ b/gtk/src/application.ccg
@@ -20,9 +20,117 @@
 
 #include <gtk/gtk.h>
 #include <gtkmm/window.h>
+#include <glibmm/init.h>
+#include <giomm/init.h>
+#include <pangomm/wrap_init.h>
+#ifdef GTKMM_ATKMM_ENABLED
+#include <atkmm/wrap_init.h>
+#endif //GTKMM_ATKMM_ENABLED
+#include <gdkmm/wrap_init.h>
+#include <gtkmm/wrap_init.h>
 
 namespace Gtk
 {
 
+static void init_gtkmm_internals()
+{
+  static bool init_done = false;
+
+  if(!init_done)
+  {
+    Glib::init();
+    Gio::init();
+
+    // Populate the map of GTypes to C++ wrap_new() functions.
+    Pango::wrap_init();
+#ifdef GTKMM_ATKMM_ENABLED
+    Atk::wrap_init();
+#endif //GTKMM_ATKMM_ENABLED
+    Gdk::wrap_init();
+    Gtk::wrap_init();
+
+    init_done = true;
+  }
+}
+
+const Glib::Class& Application::custom_class_init()
+{
+  Glib::init();
+  return application_class_.init();
+}
+
+Application::Application(const Glib::ustring& application_id, Gio::ApplicationFlags flags)
+:
+  // Mark this class as non-derived to allow C++ vfuncs to be skipped.
+  Glib::ObjectBase(0),
+  Gio::Application(Glib::ConstructParams(custom_class_init(), "application_id", application_id.c_str(), "flags", GApplicationFlags(flags), static_cast<char*>(0))),
+  m_main_window(0),
+  m_argc(0),
+  m_argv(0)
+{
+}
+
+Application::Application(int argc, char** argv, const Glib::ustring& application_id, Gio::ApplicationFlags flags)
+:
+  // Mark this class as non-derived to allow C++ vfuncs to be skipped.
+  Glib::ObjectBase(0),
+  Gio::Application(Glib::ConstructParams(custom_class_init(), "application_id", application_id.c_str(), "flags", GApplicationFlags(flags), static_cast<char*>(0))),
+  m_main_window(0),
+  m_argc(argc),
+  m_argv(argv)
+{
+  gtk_init(&argc, &argv);
+  init_gtkmm_internals();
+}
+
+void Application::on_activate_showwindow()
+{
+  if(m_main_window)
+    m_main_window->show();
+}
+
+int Application::run(int argc, char** argv)
+{
+  return Gio::Application::run(argc, argv);
+}
+
+
+int Application::run(Gtk::Window& window, int argc, char** argv)
+{
+  add_window(window);
+  
+  //Show the window when the application starts.
+  //We could just call show() now,
+  //but GApplication currently warns if we don't connect to the activate signal,
+  //which seems very C-centric. See https://bugzilla.gnome.org/show_bug.cgi?id=640042
+  m_main_window = &window;
+  signal_activate().connect(
+    sigc::mem_fun(*this, &Application::on_activate_showwindow));
+
+  const int result = Gio::Application::run(argc, argv);
+  init_gtkmm_internals();
+  return result;
+}
+
+int Application::run(Gtk::Window& window)
+{
+  g_assert(m_argc);
+  g_assert(m_argv);
+
+  add_window(window);
+  
+  //Show the window when the application starts.
+  //We could just call show() now,
+  //but GApplication currently warns if we don't connect to the activate signal,
+  //which seems very C-centric. See https://bugzilla.gnome.org/show_bug.cgi?id=640042
+  m_main_window = &window;
+  signal_activate().connect(
+    sigc::mem_fun(*this, &Application::on_activate_showwindow));
+
+  const int result = Gio::Application::run(m_argc, m_argv);
+  init_gtkmm_internals();
+  return result;
+}
+
 
 } // namespace Gtk
diff --git a/gtk/src/application.hg b/gtk/src/application.hg
index b63679b..d662e01 100644
--- a/gtk/src/application.hg
+++ b/gtk/src/application.hg
@@ -37,12 +37,38 @@ protected:
   _CLASS_GOBJECT(Application, GtkApplication, GTK_APPLICATION, Gio::Application, GApplication)
 
 protected:
-#m4 _CONVERSION(`Gio::ApplicationFlags',`GApplicationFlags',`(GApplicationFlags)($3)')
-  _WRAP_CTOR(Application(const Glib::ustring& application_id, Gio::ApplicationFlags flags = Gio::APPLICATION_FLAGS_NONE), gtk_application_new)
 
+  /** Creates a new Application instance.
+   * This constructor calls g_type_init() for you.
+   * You should call run() with your main() function's argc and argv parameters
+   * to initialize gtkmm too.
+   *
+   * @param application_id A valid application id
+   * @param flags The application flags
+   */
+  explicit Application(const Glib::ustring& application_id, Gio::ApplicationFlags flags = Gio::APPLICATION_FLAGS_NONE);
+  _IGNORE(gtk_application_new)
+
+  //This constructor does not correspond to anything in the C API.
+  //We added it so we can choose to always initialize gtkmm as early as possible.
+  //See https://bugzilla.gnome.org/show_bug.cgi?id=639925
+  /** Creates a new Application instance.
+   * This constructor initializes gtkmm for you, so you should call run() 
+   * without specifying the the argc and argv parameters again. 
+   * 
+   * @param argc The parameter received by your main() function.
+   * @param argv The parameter received by your main() function.
+   * @param application_id A valid application id
+   * @param flags The application flags
+   */
+  explicit Application(int argc, char** argv, const Glib::ustring& application_id, Gio::ApplicationFlags flags = Gio::APPLICATION_FLAGS_NONE);
+  
 public:
 
+#m4 _CONVERSION(`Gio::ApplicationFlags',`GApplicationFlags',`(GApplicationFlags)($3)')
   _WRAP_CREATE(const Glib::ustring& application_id, Gio::ApplicationFlags flags = Gio::APPLICATION_FLAGS_NONE)
+  
+  _WRAP_CREATE(int argc, char** argv, const Glib::ustring& application_id, Gio::ApplicationFlags flags = Gio::APPLICATION_FLAGS_NONE)
 
 #m4 _CONVERSION(`GList*',`Glib::ListHandle<Window*>',`$2($3, Glib::OWNERSHIP_NONE)')
   _WRAP_METHOD(Glib::ListHandle<Window*> get_windows(), gtk_application_get_windows)
@@ -52,6 +78,64 @@ public:
 
   _WRAP_METHOD(void add_window(Window& window), gtk_application_add_window)
   _WRAP_METHOD(void remove_window(Window& window), gtk_application_remove_window)
+
+  /** Starts the application.
+   * 
+   * The default implementation of this virtual function will simply run
+   * a main loop.
+   * 
+   * It is an error to call this function if @a application is a proxy for
+   * a remote application.
+   * 
+   * @newin{2,28}
+   */
+  int run(int argc, char** argv);
+  
+  /** Starts the application.
+   * 
+   * The default implementation of this virtual function will simply run
+   * a main loop.
+   * 
+   * It is an error to call this function if @a application is a proxy for
+   * a remote application.
+   *
+   * @param window The window to show. This method will return when the window is hidden.
+   * 
+   * @newin{2,28}
+   */
+  int run(Gtk::Window& window, int argc, char** argv);
+
+  /** Starts the application.
+   * 
+   * The default implementation of this virtual function will simply run
+   * a main loop.
+   * 
+   * It is an error to call this function if @a application is a proxy for
+   * a remote application.
+   *
+   * @param window The window to show. This method will return when the window is hidden.
+   * 
+   * @newin{2,28}
+   */
+  int run(Gtk::Window& window);
+  
+private:
+  /** This is just a way to call Glib::init() (which calls g_type_init()) before
+   * calling application_class_.init(), so that 
+   * gtk_application_get_type() will always succeed.
+   * See https://bugzilla.gnome.org/show_bug.cgi?id=639925
+   */
+  const Glib::Class& custom_class_init();
+  
+  void on_activate_showwindow();
+  
+  ///We show the window in the activate signal handler.
+  Gtk::Window* m_main_window;
+  
+  //We need these to call g_application_run(), 
+  //even if we have already called gtk_init().
+  int m_argc;
+  char** m_argv;
 };
 
 } // namespace Gtk



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