[gtkmm] Add back Gtk::Application so we can finish it.



commit 52ee48c3abd05130755c5fbc78a4bb39e22a0c71
Author: Murray Cumming <murrayc murrayc com>
Date:   Wed Aug 3 09:20:54 2011 +0200

    Add back Gtk::Application so we can finish it.

 gtk/gtkmm.h                  |    1 +
 gtk/src/appchooserdialog.ccg |    4 +-
 gtk/src/application.ccg      |  172 ++++++++++++++++++++++++++++++++++++++++
 gtk/src/application.hg       |  179 ++++++++++++++++++++++++++++++++++++++++++
 gtk/src/filelist.am          |    1 +
 gtk/src/window.ccg           |    5 +
 gtk/src/window.hg            |   12 +++
 7 files changed, 372 insertions(+), 2 deletions(-)
---
diff --git a/gtk/gtkmm.h b/gtk/gtkmm.h
index d9f1019..fb38358 100644
--- a/gtk/gtkmm.h
+++ b/gtk/gtkmm.h
@@ -101,6 +101,7 @@ extern const int gtkmm_micro_version;
 #include <gtkmm/appchooserbutton.h>
 #include <gtkmm/appchooserdialog.h>
 #include <gtkmm/appchooserwidget.h>
+#include <gtkmm/application.h>
 #include <gtkmm/arrow.h>
 #include <gtkmm/aspectframe.h>
 #include <gtkmm/assistant.h>
diff --git a/gtk/src/appchooserdialog.ccg b/gtk/src/appchooserdialog.ccg
index 58a2fd4..7832b4d 100644
--- a/gtk/src/appchooserdialog.ccg
+++ b/gtk/src/appchooserdialog.ccg
@@ -16,7 +16,6 @@
  */
 
 #include <gtk/gtk.h>
-#include <giomm/file.h>
 
 namespace Gtk
 {
@@ -46,5 +45,6 @@ AppChooserDialog::AppChooserDialog(const Glib::RefPtr<Gio::File>& file, Gtk::Win
 {
   set_transient_for(parent);
 }
-
+  
 } // namespace Gtk
+
diff --git a/gtk/src/application.ccg b/gtk/src/application.ccg
new file mode 100644
index 0000000..7ae968c
--- /dev/null
+++ b/gtk/src/application.ccg
@@ -0,0 +1,172 @@
+// -*- c++ -*-
+/* $Id: action.ccg,v 1.11 2006/05/10 20:59:27 murrayc Exp $ */
+
+/* Copyright 2003 The gtkmm Development Team
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <glibmm/vectorutils.h>
+
+#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();
+  
+  m_main_window = 0; //We don't need to remember this anymore.
+}
+
+void Application::on_window_hide(Window* window)
+{
+  //Tell GtkApplication to forget the window.
+  //This can cause run() to return, if it is the last window.
+  //Otherwise, GtkApplication waits for the window to be _destroyed_,
+  //which is just not something that it should care about:
+  //See https://bugzilla.gnome.org/show_bug.cgi?id=639931
+  if(window && window->get_application()) //We check that it's still in an application anyway.
+    remove_window(*window);
+}
+
+void Application::add_window(Window& window)
+{
+  //Respond to window hiding, not destruction:
+  //See https://bugzilla.gnome.org/show_bug.cgi?id=639931
+  window.signal_hide().connect(
+    sigc::bind(
+      sigc::mem_fun(*this, &Application::on_window_hide),
+      &window));
+    
+  gtk_application_add_window(gobj(), (window).gobj()); 
+}
+
+int Application::run(int argc, char** argv)
+{
+  return Gio::Application::run(argc, argv);
+}
+
+int Application::run(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(); //TODO: This is too late. We want to do this as soon as possible, but it can't be done before gtk_init(argc, argv).
+  return result;
+}
+
+int Application::run(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();  //TODO: This is too late. We want to do this as soon as possible, but it can't be done before gtk_init(argc, argv).
+  return result;
+}
+
+int Application::run()
+{
+  g_assert(m_argc);
+  g_assert(m_argv);
+
+  const int result = Gio::Application::run(m_argc, m_argv);
+  init_gtkmm_internals();  //TODO: This is too late. We want to do this as soon as possible, but it can't be done before gtk_init(argc, argv).
+  return result;
+}
+
+
+} // namespace Gtk
diff --git a/gtk/src/application.hg b/gtk/src/application.hg
new file mode 100644
index 0000000..1b538e0
--- /dev/null
+++ b/gtk/src/application.hg
@@ -0,0 +1,179 @@
+/* Copyright (C) 2003 The gtkmm Development Team
+ *
+ * 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 for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+_CONFIGINCLUDE(gtkmmconfig.h)
+
+#include <vector>
+
+#include <giomm/application.h>
+#include <gtkmm/actiongroup.h>
+
+_DEFS(gtkmm,gtk)
+_PINCLUDE(giomm/private/application_p.h)
+
+namespace Gtk
+{
+
+class Window;
+
+/** TODO
+ */
+class Application
+  : public Gio::Application
+{
+protected:
+  _CLASS_GOBJECT(Application, GtkApplication, GTK_APPLICATION, Gio::Application, GApplication)
+
+protected:
+
+  /** 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*',`std::vector<Window*>',`Glib::ListHandler<Window*>::list_to_vector($3, Glib::OWNERSHIP_NONE)')
+  _WRAP_METHOD(std::vector<Window*> get_windows(), gtk_application_get_windows)
+
+#m4 _CONVERSION(`GList*',`std::vector<const Window*>',`Glib::ListHandler<const Window*>::list_to_vector($3, Glib::OWNERSHIP_NONE)')
+  _WRAP_METHOD(std::vector<const Window*> get_windows() const, gtk_application_get_windows)
+
+  /** Adds a window to the Gtk::Application.
+   * 
+   * If all the windows managed by Gtk::Application are closed, the
+   * Gtk::Application will call quit(), and quit
+   * the application.
+   * 
+   * If your application uses only a single toplevel window, you can
+   * use get_window(). If you are using a sub-class
+   * of Gtk::Application you should call create_window()
+   * to let the Gtk::Application instance create a Gtk::Window and add
+   * it to the list of toplevels of the application. You should call
+   * this function only to add Gtk::Window<!-- -->s that you created
+   * directly using new Gtk::Window.
+   * 
+   * @newin{3,0}
+   * @param window A toplevel window to add to the application.
+   */
+  void add_window(Window& window);
+  _IGNORE(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{3,0}
+   */
+  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{3,0}
+   */
+  int run(Window& window, int argc, char** argv);
+
+  //TODO: If argc and argv are necessary at all, document the need to call that constructor first.
+  //See https://bugzilla.gnome.org/show_bug.cgi?id=639925#c4
+  /** 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{3,0}
+   */
+  int run(Window& window);
+
+  //TODO: If argc and argv are necessary at all, document the need to call that constructor first.
+  //See https://bugzilla.gnome.org/show_bug.cgi?id=639925#c4
+  /** 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{3,0}
+   */
+  int run();
+  
+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();
+  void on_window_hide(Window*);
+  
+  ///We show the window in the activate signal handler.
+  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
diff --git a/gtk/src/filelist.am b/gtk/src/filelist.am
index dde0343..73ec97c 100644
--- a/gtk/src/filelist.am
+++ b/gtk/src/filelist.am
@@ -26,6 +26,7 @@ gtkmm_files_any_hg =		\
 	appchooserbutton.hg \
 	appchooserdialog.hg \
 	appchooserwidget.hg \
+	application.hg \
 	arrow.hg		\
 	aspectframe.hg		\
 	assistant.hg		\
diff --git a/gtk/src/window.ccg b/gtk/src/window.ccg
index b56d643..1628143 100644
--- a/gtk/src/window.ccg
+++ b/gtk/src/window.ccg
@@ -198,4 +198,9 @@ void Window::unset_transient_for()
   gtk_window_set_transient_for(gobj(), 0 /* See GTK+ docs */);
 }
 
+void Window::unset_application()
+{
+  gtk_window_set_application(gobj(), 0 /* See GTK+ docs */);
+}
+
 } // namespace Gtk
diff --git a/gtk/src/window.hg b/gtk/src/window.hg
index d28725b..33a5d08 100644
--- a/gtk/src/window.hg
+++ b/gtk/src/window.hg
@@ -23,6 +23,7 @@
 
 #include <glibmm/object.h>
 #include <gtkmm/bin.h>
+#include <gtkmm/application.h>
 
 _DEFS(gtkmm,gtk)
 _PINCLUDE(gtkmm/private/bin_p.h)
@@ -96,6 +97,7 @@ public:
   _WRAP_PROPERTY("accept-focus", bool)
   _WRAP_PROPERTY("focus-on-map", bool)
   _WRAP_PROPERTY("deletable", bool)
+  _WRAP_PROPERTY("application", Glib::RefPtr<Application>)
 
   _WRAP_SIGNAL(void set_focus(Widget* focus), "set_focus")
 
@@ -323,6 +325,16 @@ dnl
   _WRAP_METHOD(void reshow_with_initial_size(),
                gtk_window_reshow_with_initial_size)
 
+  _WRAP_METHOD(Glib::RefPtr<Application> get_application(), gtk_window_get_application, refreturn)
+  _WRAP_METHOD(Glib::RefPtr<const Application> get_application() const, gtk_window_get_application, refreturn)
+  
+  _WRAP_METHOD(void set_application(const Glib::RefPtr<Application>& application), gtk_window_set_application)
+  
+  /** Unsets the Application associated with the window.
+   * This could cause the application to exit if it is the application's last window.
+   */
+  void unset_application();
+                                                 
   _WRAP_METHOD(void set_has_resize_grip(bool setting = true), gtk_window_set_has_resize_grip)
   _WRAP_METHOD(bool get_has_resize_grip() const, gtk_window_get_has_resize_grip)
 



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