Skip to content

GTK Development

MATE uses GTK 3. GTK builds on top of GObject and GLib — make sure you have read C, GLib & GObject first.

Widget hierarchy

Every visible element is a GtkWidget. Widgets are arranged in a tree: container widgets (boxes, grids, notebooks) hold child widgets. The root of the tree is always a GtkWindow (or a subclass like GtkApplicationWindow).

GtkWindow
  └─ GtkBox (vertical)
       ├─ GtkMenuBar
       ├─ GtkScrolledWindow
       │    └─ GtkTreeView
       └─ GtkStatusBar

Building UI with GtkBuilder

Rather than constructing widgets in C, MATE components often define their UI in .ui XML files processed by GtkBuilder:

<!-- my-window.ui -->
<interface>
  <object class="GtkWindow" id="main_window">
    <property name="title">My App</property>
    <child>
      <object class="GtkButton" id="ok_button">
        <property name="label">OK</property>
        <signal name="clicked" handler="on_ok_clicked"/>
      </object>
    </child>
  </object>
</interface>

Load it in C:

GtkBuilder *builder = gtk_builder_new_from_file ("my-window.ui");
GtkWidget  *window  = GTK_WIDGET (gtk_builder_get_object (builder, "main_window"));
gtk_builder_connect_signals (builder, NULL);
g_object_unref (builder);

Use Glade to edit .ui files visually.

Signals and callbacks

GTK signals follow the same GObject mechanism. The callback signature must match the signal:

static void
on_button_clicked (GtkButton *button, gpointer user_data)
{
    MyWindow *win = MY_WINDOW (user_data);
    /* ... */
}

g_signal_connect (button, "clicked", G_CALLBACK (on_button_clicked), win);

A common pattern to avoid signal feedback loops:

g_signal_handlers_block_by_func (widget, handler, data);
gtk_toggle_button_set_active (...);
g_signal_handlers_unblock_by_func (widget, handler, data);

GtkAction and menus

Most existing MATE components use the older GtkUIManager + GtkActionGroup menu system. New code should prefer GAction + GMenu:

/* GAction (modern) */
GSimpleAction *action = g_simple_action_new ("quit", NULL);
g_signal_connect (action, "activate", G_CALLBACK (quit_cb), app);
g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (action));

Menu XML for GMenu:

<menu id="app-menu">
  <section>
    <item>
      <attribute name="label">Quit</attribute>
      <attribute name="action">app.quit</attribute>
    </item>
  </section>
</menu>

CSS theming

GTK 3 uses CSS for theming. You can apply custom CSS in code — useful when experimenting with widget appearance:

GtkCssProvider *provider = gtk_css_provider_new ();
gtk_css_provider_load_from_data (provider,
    "button { background: red; }", -1, NULL);
gtk_style_context_add_provider_for_screen (
    gdk_screen_get_default (),
    GTK_STYLE_PROVIDER (provider),
    GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);

To inspect and live-edit CSS on a running app, use the GTK Inspector.

Useful patterns

Idle callbacks — run code after the current event is processed:

g_idle_add ((GSourceFunc) my_idle_func, data);

Timeouts:

g_timeout_add (500, (GSourceFunc) my_timeout_cb, data);  /* ms */

Accessing the display:

GdkDisplay *display = gdk_display_get_default ();
GdkScreen  *screen  = gdk_display_get_default_screen (display);

Further reading

Last updated on • mbkma