Warning: All the online documentation I could find is for gtkmm-4. If you are stuck using gtkmm-3.0 for Ubuntu, download your own docs from the repository (see below). I've included links to gtkmm-4 documentation in the hopes that they are helpful; use at your own risk.
Here is a working solution for gtkmm-3.0. Compile with:
g++ helloworld.cc -o main `pkg-config --cflags --libs gtkmm-3.0`
Code:
// In file helloworld.cc
// sigc::mem_fun is the important part:
// it lets you turn a member function into a static one (or something).
// I don't really get it.
// I got most of the code here from https://www.gtk.org/docs/language-bindings/cpp
#include <iostream>
#include <sigc++/sigc++.h> // Unnecessary, because the gtkmm modules also include mem_fun.
#include <glibmm/refptr.h> // The wrapper object that Application::create returns.
#include <gtkmm/application.h> // C++ wrapper for C's gtk_main.
#include <gtkmm/button.h>
#include <gtkmm/window.h>
class HelloWorld : public Gtk::Window
{
public:
HelloWorld(Glib::RefPtr<Gtk::Application>);
protected:
void on_button_clicked();
Gtk::Button m_button;
Glib::RefPtr<Gtk::Application> app;
};
// Constructor for window class. app should be a pointer to the Application instance you made in main.
HelloWorld::HelloWorld(Glib::RefPtr<Gtk::Application> app)
: m_button("Quit this program") // Sets button label. I have no idea what this syntax is. C++ be whack, yo
{
this->app = app;
// mem_fun does most of the magic. How does it work? idk lol
m_button.signal_clicked().connect(sigc::mem_fun(*this,
&HelloWorld::on_button_clicked));
add(m_button);
m_button.show();
}
void HelloWorld::on_button_clicked()
{
std::cout << "Exiting the program now." << std::endl;
this->app->quit();
std::cout << "Note: Program doesn't actually end until this function finishes." << std::endl;
}
int main (int argc, char *argv[])
{
Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example");
HelloWorld helloworld(app);
return app->run(helloworld);
}
My thoughts: I don't really get it?
Gtk::Button.signal_clicked() (reference) returns a Glib::SignalProxy<void()>. SignalProxy (reference) has template <R(T...)>, which I think describes the kind of functions that can be connected--in this case, with a return type void and an empty list () of arguments. SignalProxy.connect() returns something I'll ignore, and accepts either a SlotType& or a SlotType&& (I have no idea what the difference is) where SlotType is sigc::slot<R(T...)>, or in this case sigc::slot<void()>.
sigc::slot<R(T...)> (reference) seems pretty fundamental. It looks like it's just a wrapper that holds a function (presumably, so SignalProxy can store it to be called later when the button is clicked). Up until now, it all makes sense.
The notes on sigc::mem_fun (reference) say that it returns a sigc::mem_functor, which sounds reasonable but mem_functor does not seem to fulfill what SignalProxy.connect() wants: sigc::slot and sigc::mem_functor do not inherit from each other. Baffling. I guess there's some kind of undocumented type coercion going on here? Maybe? The other lead is that mem_fun apparently returns an object of type decltype(auto)? Which I tried reading documentation on, and then they started talking about lvalues and unparenthesized id-expressions, and that's when my eyes glazed over. Looking at the old documentation, there used to be like 70 overloaded versions of mem_fun to do what one version can do now, so I guess decltype is doing its job. But the point is, that's where I gave up.
decltype(auto) and mem_functors are C++ deep-magic. mem_fun does the thing SignalProxy.connect() needs, and that's all I know.
References:
gtkmm-4.0 documentation
glibmm documentation
sigc++ documentation
gdk documentation in c << gtkmm refers to stuff like "GdkEventKey" and enumerations from the header <gdk/gdkkeysyms.h>. I couldn't find a c++ reference for this, or anything like "gdkmm". I think maybe gtkmm just uses the C structs for events directly?
Installing documentation: I'm on Ubuntu, 20.04.3 LTS. You can install html documentation for gtk 3.0 from the repository. Do sudo apt install libgtkmm-3.0-doc libglibmm-2.4-doc libsigc++-2.0-doc. To find out where the index file is for, for example, gtkmm, do dpkg -L libgtkmm-3.0-doc | grep index. sigc++ has multiple index files, two of which are traps. I could not figure out where the documentation for GDK is, possibly because there isn't any in the repository. Use the online stuff instead.