Search code examples
c++gtk3differencegtkmmgtkmm3

What is the difference between Gtk::Main and Gtk::Application::create?


Both create Gtk windows but I can't really understand what is going behind the scenes. I tried binding a signal to a button to quit the window but the program got a SIGSEGV when using Gtk::Application::create. When I changed the program to follow Gtk::Main conventions. Everything Worked fine.

Gtk::Application::create program(fails to work):

auto app = Gtk::Application::create(argc, argv);
Gtk::Button *button = new Gtk::Button("Quit");
button->signal_clicked().connect(sigc::ptr_fun(Gtk::Main::quit));
Gtk::Window window;
window.set_default_size(200, 200);
window.add(*button);
button->show();
return app->run(window);

Gtk::Main program(works):

auto app = Gtk::Main(argc, argv);
Gtk::Button *button = new Gtk::Button("Quit");
button->signal_clicked().connect(sigc::ptr_fun(app.quit));
Gtk::Window window;
window.set_default_size(200, 200);
window.add(*button);
button->show();
app.run(window);
return 0;

Solution

  • Why doesn't it work

    The first code gets SIGSEGV because you are calling static Gtk::Main::quit when using Gtk::Application.

    You could probably use sigc::mem_fun to call Gio::Application::quit inherited in Gtk::Application but that's not a good idea when using Gtk::Application::run(Gtk::Window&):

    If you call Gio::Application::quit() while a window is connected to the application, and then return from main() without removing the window from the application, the application's destructor will not be called.

    And to be honest I don't know how, because Glib::RefPtr returned by Gtk::Application::create() doesn't have a way to get the object:

    Unlike most other smart pointers, RefPtr doesn't support dereferencing through * object_ptr.

    Close the window instead

    From Gtk::Application::add_window(Gtk::Window&):

    If all the windows managed by Gtk::Application are closed (hidden) or removed from the application then the call to run() will return.

    #include <gtkmm.h>
    
    int main()
    {
        auto app = Gtk::Application::create();
        Gtk::Button *button = new Gtk::Button("Quit");
        Gtk::Window window;
        button->signal_clicked().connect(sigc::mem_fun(&window, &Gtk::Window::close));
    
        window.set_default_size(200, 200);
        window.add(*button);
        window.show_all(); //for some widgets (I don't remember which) show() is not enough
        return app->run(window);
    }