Explorar el Código

m2-GTK4 v1.0.0: GNU Modula-2 bindings for GTK4 (+ libadwaita)

Hand-written DEFINITION MODULE FOR "C" bindings for GLib, GObject, Gio
and GTK4, plus curated libadwaita modules, pure-M2 helpers, tests,
examples and a GIR-based binding generator.

- src/     82 FOR "C" bindings: GLib/GObject/Gio, GTK core, widgets,
           inputs, containers, actions/menus, dialogs, model views,
           GError/GioError, and 19 curated Adw* modules
- lib/     GtkUtils (strings, Connect, SetAccel, ownership/GError) and
           GtkClosures (per-connection signal contexts)
- tests/   16 gm2 tests + run_tests.sh (private GSettings schema)
- examples/ 11 runnable GTK4 / libadwaita programs
- tools/   gir2def.py (GIR -> .def), gir_verify.py (symbol check),
           run_gir_check.sh; make gir / gir-check / gir-verify

Built in the ISO dialect (-fiso). `make && ./tests/run_tests.sh` is all
green (16 passed); `make gir-verify` reports 0 unexpected across Gtk,
GLib, Gio and Adw (8602 identifiers).
Eric Streit hace 3 días
commit
0418ccb46e
Se han modificado 100 ficheros con 7294 adiciones y 0 borrados
  1. 7 0
      .gitignore
  2. 82 0
      Makefile
  3. 421 0
      README.md
  4. 124 0
      examples/actions.mod
  5. 168 0
      examples/adw.mod
  6. 104 0
      examples/containers.mod
  7. 77 0
      examples/counter.mod
  8. 161 0
      examples/editor.mod
  9. 106 0
      examples/files.mod
  10. 119 0
      examples/headerbar.mod
  11. 50 0
      examples/hello.mod
  12. 149 0
      examples/inputs.mod
  13. 126 0
      examples/layouts.mod
  14. 202 0
      examples/views.mod
  15. 68 0
      lib/GtkClosures.def
  16. 114 0
      lib/GtkClosures.mod
  17. 59 0
      lib/GtkUtils.def
  18. 129 0
      lib/GtkUtils.mod
  19. 148 0
      src/AdwAboutWindow.def
  20. 82 0
      src/AdwActionRow.def
  21. 27 0
      src/AdwApplication.def
  22. 34 0
      src/AdwApplicationWindow.def
  23. 52 0
      src/AdwBanner.def
  24. 44 0
      src/AdwClamp.def
  25. 58 0
      src/AdwComboRow.def
  26. 68 0
      src/AdwEntryRow.def
  27. 100 0
      src/AdwExpanderRow.def
  28. 82 0
      src/AdwHeaderBar.def
  29. 149 0
      src/AdwMessageDialog.def
  30. 70 0
      src/AdwPreferencesGroup.def
  31. 87 0
      src/AdwPreferencesPage.def
  32. 47 0
      src/AdwPreferencesRow.def
  33. 52 0
      src/AdwStatusPage.def
  34. 30 0
      src/AdwSwitchRow.def
  35. 73 0
      src/AdwToast.def
  36. 38 0
      src/AdwToastOverlay.def
  37. 68 0
      src/AdwToolbarView.def
  38. 42 0
      src/GAction.def
  39. 38 0
      src/GActionMap.def
  40. 50 0
      src/GError.def
  41. 48 0
      src/GFile.def
  42. 134 0
      src/GLib.def
  43. 28 0
      src/GListModel.def
  44. 47 0
      src/GListStore.def
  45. 87 0
      src/GMenu.def
  46. 24 0
      src/GMenuModel.def
  47. 94 0
      src/GObject.def
  48. 72 0
      src/GSettings.def
  49. 44 0
      src/GSettingsSchema.def
  50. 49 0
      src/GSimpleAction.def
  51. 55 0
      src/GVariant.def
  52. 57 0
      src/Gio.def
  53. 37 0
      src/GioError.def
  54. 40 0
      src/Gtk.def
  55. 57 0
      src/GtkApplication.def
  56. 38 0
      src/GtkApplicationWindow.def
  57. 42 0
      src/GtkBox.def
  58. 39 0
      src/GtkButton.def
  59. 58 0
      src/GtkCheckButton.def
  60. 63 0
      src/GtkColumnView.def
  61. 43 0
      src/GtkColumnViewCell.def
  62. 78 0
      src/GtkColumnViewColumn.def
  63. 57 0
      src/GtkDropDown.def
  64. 62 0
      src/GtkEditable.def
  65. 70 0
      src/GtkEntry.def
  66. 58 0
      src/GtkEnums.def
  67. 62 0
      src/GtkExpander.def
  68. 99 0
      src/GtkFileDialog.def
  69. 51 0
      src/GtkFrame.def
  70. 77 0
      src/GtkGrid.def
  71. 65 0
      src/GtkGridView.def
  72. 70 0
      src/GtkHeaderBar.def
  73. 39 0
      src/GtkLabel.def
  74. 118 0
      src/GtkListBox.def
  75. 48 0
      src/GtkListItem.def
  76. 66 0
      src/GtkListView.def
  77. 56 0
      src/GtkMenuButton.def
  78. 31 0
      src/GtkNoSelection.def
  79. 83 0
      src/GtkNotebook.def
  80. 60 0
      src/GtkOverlay.def
  81. 61 0
      src/GtkPaned.def
  82. 36 0
      src/GtkPopoverMenuBar.def
  83. 35 0
      src/GtkRange.def
  84. 55 0
      src/GtkScale.def
  85. 87 0
      src/GtkScrolledWindow.def
  86. 45 0
      src/GtkSearchEntry.def
  87. 45 0
      src/GtkSelectionModel.def
  88. 28 0
      src/GtkSignalListItemFactory.def
  89. 63 0
      src/GtkSingleSelection.def
  90. 105 0
      src/GtkSpinButton.def
  91. 109 0
      src/GtkStack.def
  92. 33 0
      src/GtkStackSwitcher.def
  93. 36 0
      src/GtkStringList.def
  94. 31 0
      src/GtkStringObject.def
  95. 42 0
      src/GtkSwitch.def
  96. 89 0
      src/GtkTextBuffer.def
  97. 27 0
      src/GtkTextIter.def
  98. 100 0
      src/GtkTextView.def
  99. 82 0
      src/GtkWidget.def
  100. 74 0
      src/GtkWindow.def

+ 7 - 0
.gitignore

@@ -0,0 +1,7 @@
+build/
+gen/
+*.o
+*.s
+*.a
+*~
+__pycache__/

+ 82 - 0
Makefile

@@ -0,0 +1,82 @@
+# m2-GTK4 - GNU Modula-2 bindings for GTK4
+GM2      ?= gm2
+GTKCFG   := $(shell pkg-config --cflags gtk4 2>/dev/null)
+GTKLIBS  := $(shell pkg-config --libs gtk4 2>/dev/null || echo -lgtk-4)
+# libadwaita is optional; added to the flags when present.
+ADWLIBS  := $(shell pkg-config --libs libadwaita-1 2>/dev/null)
+GTKCFG   += $(shell pkg-config --cflags libadwaita-1 2>/dev/null)
+GTKLIBS  += $(ADWLIBS)
+GM2FLAGS ?= -fiso
+GIR      ?= Gtk-4.0
+GIR_DIR  ?= /usr/share/gir-1.0
+
+SRC_DIR := src
+LIB_DIR := lib
+BLD     := build
+OBJDIR  := $(BLD)/objs
+OBJS    := $(OBJDIR)/GtkUtils.o $(OBJDIR)/GtkClosures.o
+
+INCLUDES := -I$(SRC_DIR) -I$(LIB_DIR)
+
+TESTS    := test_glib test_version test_widgets test_inputs test_inputs2 test_containers test_containers2 test_actions test_closure test_headerbar test_gio test_gerror test_filedialog test_views test_application
+EXAMPLES := hello counter inputs containers actions headerbar editor layouts files views
+
+# Include the libadwaita test/example only when libadwaita is installed.
+ifneq ($(ADWLIBS),)
+TESTS    += test_adw
+EXAMPLES += adw
+endif
+
+.PHONY: all tests examples check clean gir gir-check gir-verify
+
+all: tests examples
+
+$(OBJDIR):
+	mkdir -p $(OBJDIR)
+
+$(BLD)/tests:
+	mkdir -p $(BLD)/tests
+
+$(BLD)/examples:
+	mkdir -p $(BLD)/examples
+
+# The FOR "C" .def modules carry no code; only the pure-M2 helpers are
+# compiled to object files and linked into every program.
+$(OBJDIR)/GtkUtils.o: $(LIB_DIR)/GtkUtils.mod $(LIB_DIR)/GtkUtils.def | $(OBJDIR)
+	$(GM2) $(INCLUDES) $(GM2FLAGS) -c $< -o $@
+
+$(OBJDIR)/GtkClosures.o: $(LIB_DIR)/GtkClosures.mod $(LIB_DIR)/GtkClosures.def | $(OBJDIR)
+	$(GM2) $(INCLUDES) $(GM2FLAGS) -c $< -o $@
+
+tests: $(BLD)/tests $(OBJS) $(addprefix $(BLD)/tests/,$(TESTS))
+
+$(BLD)/tests/%: tests/%.mod $(OBJS) | $(BLD)/tests
+	$(GM2) $(INCLUDES) $(GM2FLAGS) $(GTKCFG) $< $(OBJS) -o $@ $(GTKLIBS)
+
+examples: $(BLD)/examples $(OBJS) $(addprefix $(BLD)/examples/,$(EXAMPLES))
+
+$(BLD)/examples/%: examples/%.mod $(OBJS) | $(BLD)/examples
+	$(GM2) $(INCLUDES) $(GM2FLAGS) $(GTKCFG) $< $(OBJS) -o $@ $(GTKLIBS)
+
+check: tests
+	./tests/run_tests.sh
+
+# Optional GIR -> .def generator (broad, auto-generated coverage).
+#   make gir                       # Gtk-4.0 -> gen/
+#   make gir GIR=Gio-2.0           # another namespace
+gir:
+	python3 tools/gir2def.py $(GIR) --gir-dir $(GIR_DIR) -o gen
+
+# Generate and compile/link-check a sample of the output.
+gir-check:
+	./tools/run_gir_check.sh
+
+# Check that every generated identifier exists in the installed library.
+GIR_VERIFY ?= Gtk-4.0 GLib-2.0 Gio-2.0 Adw-1
+gir-verify:
+	set -e; for ns in $(GIR_VERIFY); do \
+	    python3 tools/gir_verify.py $$ns --gir-dir $(GIR_DIR); \
+	done
+
+clean:
+	rm -rf $(BLD) gen

+ 421 - 0
README.md

@@ -0,0 +1,421 @@
+# m2-GTK4 — GTK4 bindings for GNU Modula-2
+
+Thin `DEFINITION MODULE FOR "C"` bindings of **GTK 4** for `gm2`
+(GCC 16 / GNU Modula-2), plus a small pure-Modula-2 helper layer.
+
+The first slice covers the canonical GTK4 application shape
+(`GtkApplication` + `GtkWindow` + `GtkLabel` / `GtkButton` / `GtkBox`),
+a working `"activate"` / `"clicked"` signal path, and the GLib/GObject
+runtime underneath it.  The second slice adds the common input widgets:
+`GtkEntry`/`GtkEditable`, `GtkCheckButton`, `GtkSwitch`, `GtkScale`
+(`GtkRange`), plus a shared `GtkEnums` module.  The third slice adds the
+layout containers: `GtkGrid`, `GtkStack` + `GtkStackSwitcher`,
+`GtkNotebook`, `GtkScrolledWindow`.  The fourth slice adds actions,
+menus and accelerators: GIO's `GAction` / `GActionMap` /
+`GSimpleAction`, `GMenu` / `GMenuModel` / `GVariant`, plus
+`GtkApplicationWindow` and `GtkPopoverMenuBar`.  The fifth slice switches
+the project to the ISO dialect (`-fiso`) and adds per-connection signal
+closures (`GtkClosures`) and window chrome (`GtkHeaderBar`,
+`GtkMenuButton`, `gtk_window_set_titlebar`).  The sixth slice adds more
+inputs: `GtkSpinButton`, `GtkSearchEntry`, `GtkDropDown` (with
+`GtkStringList` / `GListModel`) and `GtkTextView` + `GtkTextBuffer`.
+The seventh slice adds more containers: `GtkFrame`, `GtkExpander`,
+`GtkPaned`, `GtkOverlay`, `GtkListBox` (+ `GtkListBoxRow`).  The eighth
+slice adds GIO extras: `GListStore` (+ `GtkStringObject`), `GFile`,
+`GtkFileDialog` and `GSettings` (+ `GSettingsSchema`).  The ninth slice
+adds model-backed views: `GtkListView`, `GtkGridView`, `GtkColumnView`
+(+ `GtkColumnViewColumn` / `GtkColumnViewCell`), the selection models
+`GtkSingleSelection` / `GtkNoSelection`, and the
+`GtkSignalListItemFactory` / `GtkListItem` pair.  A
+[`tools/gir2def.py`](#generator-broad-coverage) generator additionally
+emits broad `.def` coverage from GObject-Introspection `.gir` XML.
+A tenth slice adds **libadwaita** (AdwApplication, header/toolbar,
+preferences rows, toast, about/message dialogs) and **GError** handling
+plus an ownership helper layer.
+
+Verified with gm2 16.0.1 (experimental) and GTK 4.18.6 on Linux.
+
+## Status
+
+| Module | C header | Contents |
+|---|---|---|
+| `GLib` | `<glib.h>` | base C types, `GMainLoop`, timeouts/idle sources, memory, strings, clock |
+| `GObject` | `<glib-object.h>` | `ref`/`unref`, `GType`, `g_object_new`, `g_signal_connect_data`, handler disconnect, properties |
+| `Gio` | `<gio/gapplication.h>` | `GApplication` flags, `run`/`quit`/`hold`/`release` |
+| `Gtk` | `<gtk/gtk.h>` | `gtk_init`, library version helpers |
+| `GtkApplication` | `<gtk/gtkapplication.h>` | create/add/remove windows |
+| `GtkWidget` | `<gtk/gtkwidget.h>` | visibility, sensitivity, margins, expand, align, size |
+| `GtkWindow` | `<gtk/gtkwindow.h>` | create, title, size, child, present/close/destroy |
+| `GtkBox` | `<gtk/gtkbox.h>` | orientation, append/prepend/remove, spacing |
+| `GtkLabel` | `<gtk/gtklabel.h>` | text, markup |
+| `GtkButton` | `<gtk/gtkbutton.h>` | label buttons |
+| `GtkEnums` | `<gtk/gtkenums.h>` | orientation, alignment, position constants |
+| `GtkEditable` | `<gtk/gtkeditable.h>` | text get/set, editable, alignment, selection |
+| `GtkEntry` | `<gtk/gtkentry.h>` | placeholder, max length, visibility, progress |
+| `GtkCheckButton` | `<gtk/gtkcheckbutton.h>` | active, label, inconsistent |
+| `GtkSwitch` | `<gtk/gtkswitch.h>` | active / state |
+| `GtkRange` | `<gtk/gtkrange.h>` | numeric value (base of GtkScale) |
+| `GtkScale` | `<gtk/gtkscale.h>` | slider, digits, value position |
+| `GtkGrid` | `<gtk/gtkgrid.h>` | cell attach, spacing, homogeneous |
+| `GtkStack` | `<gtk/gtkstack.h>` | named/titled pages, visible child, transitions |
+| `GtkStackSwitcher` | `<gtk/gtkstackswitcher.h>` | button row that drives a stack |
+| `GtkNotebook` | `<gtk/gtknotebook.h>` | tabbed pages |
+| `GtkScrolledWindow` | `<gtk/gtkscrolledwindow.h>` | scrollable viewport, policy |
+| `GtkApplicationWindow` | `<gtk/gtkapplicationwindow.h>` | app window, window-scoped actions, show-menubar |
+| `GtkPopoverMenuBar` | `<gtk/gtkpopovermenubar.h>` | in-window menu bar from a model |
+| `GtkHeaderBar` | `<gtk/gtkheaderbar.h>` | title widget, pack start/end, title buttons, decoration layout |
+| `GtkMenuButton` | `<gtk/gtkmenubutton.h>` | button that pops up a menu model |
+| `GAction` | `<gio/gaction.h>` | activate, name, enabled, state |
+| `GActionMap` | `<gio/gactionmap.h>` | add / lookup / remove named actions |
+| `GSimpleAction` | `<gio/gsimpleaction.h>` | parameterless and stateful actions |
+| `GMenu` | `<gio/gmenu.h>` | GMenu + GMenuItem builder |
+| `GMenuModel` | `<gio/gmenumodel.h>` | model item count |
+| `GVariant` | `<glib/gvariant.h>` | boolean / string / int32 values |
+| `GtkSpinButton` | `<gtk/gtkspinbutton.h>` | numeric entry, range/increments/digits/wrap |
+| `GtkSearchEntry` | `<gtk/gtksearchentry.h>` | search-styled entry, placeholder |
+| `GListModel` | `<gio/glistmodel.h>` | indexed model interface |
+| `GtkStringList` | `<gtk/gtkstringlist.h>` | simple string model |
+| `GtkDropDown` | `<gtk/gtkdropdown.h>` | choose one item from a model |
+| `GtkTextIter` | `<gtk/gtktextiter.h>` | opaque 80-byte iterator (by address) |
+| `GtkTextBuffer` | `<gtk/gtktextbuffer.h>` | text model for a text view |
+| `GtkTextView` | `<gtk/gtktextview.h>` | multi-line text widget |
+| `GtkFrame` | `<gtk/gtkframe.h>` | labelled border around one child |
+| `GtkExpander` | `<gtk/gtkexpander.h>` | collapsible section |
+| `GtkPaned` | `<gtk/gtkpaned.h>` | two panes with a draggable divider |
+| `GtkOverlay` | `<gtk/gtkoverlay.h>` | stack overlays on a main child |
+| `GtkListBox` | `<gtk/gtklistbox.h>` | vertical row list + `GtkListBoxRow` |
+| `GListStore` | `<gio/gliststore.h>` | in-memory list model |
+| `GtkStringObject` | `<gtk/gtkstringobject.h>` | GObject string wrapper (item type) |
+| `GtkSignalListItemFactory` | `<gtk/gtksignallistitemfactory.h>` | setup/bind/teardown item factory |
+| `GtkListItem` | `<gtk/gtklistitem.h>` | per-row object passed to a factory |
+| `GtkSelectionModel` | `<gtk/gtkselectionmodel.h>` | selection interface for a view |
+| `GtkSingleSelection` | `<gtk/gtksingleselection.h>` | zero/one selected item |
+| `GtkNoSelection` | `<gtk/gtknoselection.h>` | display-only (no selection) |
+| `GtkListView` | `<gtk/gtklistview.h>` | model-driven list |
+| `GtkGridView` | `<gtk/gtkgridview.h>` | model-driven wrapping grid |
+| `GtkColumnView` | `<gtk/gtkcolumnview.h>` | model-driven multi-column table |
+| `GtkColumnViewColumn` | `<gtk/gtkcolumnviewcolumn.h>` | one column |
+| `GtkColumnViewCell` | `<gtk/gtkcolumnviewcell.h>` | column cell (`GtkListItem` subclass) |
+| `GFile` | `<gio/gfile.h>` | path/URI file handle |
+| `GtkFileDialog` | `<gtk/gtkfiledialog.h>` | async native open/save/folder dialog |
+| `GSettings` | `<gio/gsettings.h>` | typed schema keys |
+| `GSettingsSchema` | `<gio/gsettingsschema.h>` | schema lookup / key check |
+| `GError` | `<glib/gerror.h>` | error value (message/domain/code) |
+| `GioError` | `<gio/gioerror.h>` | GIO error domain and codes |
+| `AdwApplication` | `<libadwaita-1/adw-application.h>` | Adwaita application |
+| `AdwApplicationWindow` | `<libadwaita-1/adw-application-window.h>` | Adwaita window |
+| `AdwHeaderBar` | `<libadwaita-1/adw-header-bar.h>` | header bar |
+| `AdwToolbarView` | `<libadwaita-1/adw-toolbar-view.h>` | top/bottom bars + content |
+| `AdwPreferencesPage` | `<libadwaita-1/adw-preferences-page.h>` | page of groups |
+| `AdwPreferencesGroup` | `<libadwaita-1/adw-preferences-group.h>` | titled group of rows |
+| `AdwPreferencesRow` | `<libadwaita-1/adw-preferences-row.h>` | base row (title) |
+| `AdwActionRow` | `<libadwaita-1/adw-action-row.h>` | row with subtitle/prefix/suffix |
+| `AdwSwitchRow` | `<libadwaita-1/adw-switch-row.h>` | row with a switch |
+| `AdwEntryRow` | `<libadwaita-1/adw-entry-row.h>` | row with an entry |
+| `AdwComboRow` | `<libadwaita-1/adw-combo-row.h>` | row with a drop-down |
+| `AdwExpanderRow` | `<libadwaita-1/adw-expander-row.h>` | row that expands |
+| `AdwStatusPage` | `<libadwaita-1/adw-status-page.h>` | placeholder page |
+| `AdwToast` | `<libadwaita-1/adw-toast.h>` | transient notification |
+| `AdwToastOverlay` | `<libadwaita-1/adw-toast-overlay.h>` | toast host |
+| `AdwBanner` | `<libadwaita-1/adw-banner.h>` | dismissible info bar |
+| `AdwClamp` | `<libadwaita-1/adw-clamp.h>` | max-size centred container |
+| `AdwAboutWindow` | `<libadwaita-1/adw-about-window.h>` | about dialog |
+| `AdwMessageDialog` | `<libadwaita-1/adw-message-dialog.h>` | message / confirm dialog |
+| `GtkUtils` (`lib/`) | — | `CStrToM2`, `StrAppend`, `IntToStr`, `Connect`, `SetAccel`, `Unref`, `Free`, `ErrorMessage`, `ClearError` |
+| `GtkClosures` (`lib/`) | — | per-connection signal contexts (`Connect2`/`Connect3`, owned variants) |
+
+## Layout
+
+```text
+m2-GTK4/
+  src/        FOR "C" .def bindings (one per GTK/GIO object)
+  lib/        pure-M2 helpers built on the bindings (GtkUtils, GtkClosures)
+  tests/      gm2 smoke tests + run_tests.sh (+ a private GSettings schema)
+  examples/   runnable GTK4 programs (hello, counter, ...)
+  tools/      gir2def.py (GIR -> .def generator) + run_gir_check.sh
+  gen/        generator output (git-ignored)
+  build/      generated binaries (git-ignored)
+```
+
+## Prerequisites
+
+- `gm2` (tested: 16.0.1 experimental, `~/bin/Modula2/Gm2/bin/gm2`)
+- GTK4 dev files (`pkg-config --cflags --libs gtk4`, tested: 4.18.6)
+- libadwaita dev files (`pkg-config --cflags --libs libadwaita-1`, tested:
+  1.7.6) — optional; enables the `Adw*` modules, `test_adw` and the
+  `adw` example. The build detects them automatically.
+
+The build uses the **ISO dialect** (`-fiso`). That is required for
+`SYSTEM.CAST` and for `NEW`/`DISPOSE` (which need `ALLOCATE`/`DEALLOCATE`
+from the ISO `Storage` module), both used by `GtkClosures`. `make`
+passes `-fiso` by default.
+
+```sh
+export PATH=$HOME/bin/Modula2/Gm2/bin:$PATH
+```
+
+## Build & test
+
+```sh
+make            # tests + examples -> build/
+./tests/run_tests.sh
+./build/examples/hello
+./build/examples/counter
+./build/examples/inputs
+./build/examples/containers
+./build/examples/actions
+./build/examples/headerbar
+./build/examples/editor
+./build/examples/layouts
+./build/examples/files
+./build/examples/views
+./build/examples/adw
+```
+
+`make check` is `make tests` + the runner script. The GUI tests are
+skipped automatically when neither `DISPLAY` nor `WAYLAND_DISPLAY` is
+set. The runner also compiles `tests/schemas/*.gschema.xml` into
+`build/schemas` and points `GSETTINGS_SCHEMA_DIR` at it, so `test_gio`
+can exercise `GSettings` without touching real user settings.
+
+## Generator (broad coverage)
+
+The hand-written modules in `src/` are the idiomatic API. For breadth,
+`tools/gir2def.py` generates `FOR "C"` `.def` files directly from
+GObject-Introspection `.gir` XML:
+
+```sh
+make gir                # Gtk-4.0 -> gen/   (301 modules, ~3.7k procedures)
+make gir GIR=Gio-2.0    # any namespace
+make gir-check          # generate + compile/link a sample
+```
+
+It emits one module per class/interface/record (named `<Namespace><Name>`,
+e.g. `GtkButton`), namespace functions in `<Namespace>Functions.def`, and
+enums/bitfields in `<Namespace>Enums.def`. Procedure names are the exact
+GIR `c:identifier`, so the output links straight against the C library.
+All 633 generated modules across Gtk/GLib/Gio/Adw parse under `gm2 -fiso`.
+
+`make gir-verify` closes the loop by checking that every generated
+identifier actually exists as an exported symbol in the installed
+library (via `nm`); it reports 0 unexpected across Gtk, GLib, Gio and
+Adw (a short allowlist covers macros/deprecated no-ops).
+
+See `tools/README.md` for the type mapping and the known limits (value
+structs are opaque, signals/properties are not generated, variadics and
+`GError**` are dropped). Output goes to `gen/` and is meant to be
+cherry-picked, not to replace `src/`.
+
+## Usage
+
+```modula2
+MODULE hello ;
+
+FROM Gio IMPORT g_application_run;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkWindow IMPORT gtk_application_window_new, gtk_window_set_title,
+   gtk_window_set_default_size, gtk_window_set_child, gtk_window_present;
+FROM GtkLabel IMPORT gtk_label_new;
+FROM GtkUtils IMPORT Connect;
+FROM SYSTEM IMPORT ADDRESS, ADR;
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR window, label: ADDRESS;
+BEGIN
+   window := gtk_application_window_new(application);
+   gtk_window_set_title(window, "Hello");
+   gtk_window_set_default_size(window, 360, 120);
+   label := gtk_label_new("Hello, GNU Modula-2 + GTK4!");
+   gtk_window_set_child(window, label);
+   gtk_window_present(window)
+END OnActivate;
+
+VAR app: ADDRESS;
+BEGIN
+   app := gtk_application_new("org.example.Hello", 0);
+   Connect(app, "activate", ADR(OnActivate), NIL);
+   g_application_run(app, 0, NIL)
+END hello.
+```
+
+Compile a program against the bindings:
+
+```sh
+gm2 -fiso -Isrc -Ilib myprog.mod build/objs/GtkUtils.o \
+    build/objs/GtkClosures.o -o myprog \
+    $(pkg-config --cflags --libs gtk4)
+```
+
+## How it was built, step by step
+
+**Step 0 — feasibility spike.** Before writing anything, the riskiest
+interop points were proved against the real library: creating a GTK4
+window from Modula-2, running the GLib main loop, and invoking a
+Modula-2 procedure from C as a `GSourceFunc`. This fixed the design.
+
+**Step 1 — discover the GNU Modula-2 ↔ C rules.** See the next section.
+These rules decide every line of a binding `.def`.
+
+**Step 2 — GLib and GObject.** Everything else sits on the base types,
+the main loop and the signal machinery, so these came first.
+
+**Step 3 — application and window.** `GtkApplication` + `GApplication`
+drive the loop; `GtkWindow` gives something to show. Using
+`gtk_application_window_new(app)` (not `gtk_window_new()`) is what
+keeps the application alive while the window is open.
+
+**Step 4 — widgets and layout.** `GtkBox`, `GtkLabel`, `GtkButton`, and
+the per-widget `GtkWidget` layout helpers.
+
+**Step 5 — helpers and signal ergonomics.** `GtkUtils.Connect` wraps the
+`g_signal_connect` macro (which has no C symbol) by calling the real
+`g_signal_connect_data`; `CStrToM2` and `IntToStr` handle the
+string/number conversions GTK code always needs.
+
+**Step 6 — tests and examples.** A headless GLib loop test, a
+version/link test, a widget + signal round-trip test, and an
+application test; plus `hello` and `counter` examples.
+
+**Step 7 — input widgets.** `GtkEnums` was extracted as the shared home
+for enum constants, then `GtkEditable`/`GtkEntry`,
+`GtkCheckButton`, `GtkSwitch`, `GtkRange`/`GtkScale` were added,
+with a `test_inputs` round-trip test and the `inputs` example. This
+step also pinned down the real-number mapping (`REAL` = C `double`).
+
+**Step 8 — layout containers.** `GtkGrid`, `GtkStack` +
+`GtkStackSwitcher`, `GtkNotebook` and `GtkScrolledWindow`, with a
+`test_containers` test and the `containers` example (a notebook whose
+pages are a grid, a switcher-driven stack, and a scrolled list).
+
+**Step 9 — actions, menus, accelerators.** GIO's action/menu stack
+(`GAction`, `GActionMap`, `GSimpleAction`, `GMenu`, `GMenuModel`,
+`GVariant`), `GtkApplicationWindow`, and `GtkPopoverMenuBar`, wired
+together in the `actions` example (menu bar + app/win actions +
+Ctrl+N/Q/B accelerators via `GtkUtils.SetAccel`) and checked by
+`test_actions`.
+
+**Step 10 — ISO dialect and per-connection closures.** The project was
+switched to `-fiso`, which provides `SYSTEM.CAST` and intrinsic
+`NEW`/`DISPOSE` (with `Storage`'s `ALLOCATE`/`DEALLOCATE`). That made
+the `GtkClosures` module possible: each signal connection gets its own
+heap context holding the handler and payload, a trampoline forwards the
+call, and a GClosure destroy notify frees the context - and optionally
+the payload - on disconnect or finalize. Covered by `test_closure`.
+
+**Step 11 — header bar and window controls.** `GtkHeaderBar`,
+`GtkMenuButton`, and `gtk_window_set_titlebar()` were added, then
+combined in the `headerbar` example (title widget, a connected "New"
+button packed start, a menu button packed end) and checked by
+`test_headerbar`.
+
+**Step 12 — more inputs.** `GtkSpinButton`, `GtkSearchEntry`,
+`GtkStringList` + `GListModel`, `GtkDropDown`, and `GtkTextView` +
+`GtkTextBuffer` with an opaque 80-byte `GtkTextIter` marshalled by
+address. Checked by `test_inputs2` and shown in the `editor` example
+(search entry, text view, wrap-mode drop-down, padding spin button).
+
+**Step 13 — more containers.** `GtkFrame`, `GtkExpander`, `GtkPaned`,
+`GtkOverlay`, and `GtkListBox` + `GtkListBoxRow` (with
+`GtkSelectionMode` in `GtkEnums`). Checked by `test_containers2` and
+shown in the `layouts` example (a paned split, frame/expander on the
+left, overlay + list box on the right, `row-activated` via
+`GtkClosures.Connect3`).
+
+**Step 14 — GIO extras.** `GListStore` + `GtkStringObject` (a concrete
+list model), `GFile`, the asynchronous `GtkFileDialog`, and `GSettings`
++ `GSettingsSchema`. Checked by `test_gio` (headless) and
+`test_filedialog`; shown in the `files` example (button -> native open
+dialog -> `open_finish` -> `GFile` basename). The GSettings test uses a
+private schema compiled by the runner.
+
+**Step 15 — model-backed views.** `GtkSignalListItemFactory` +
+`GtkListItem`, the selection models `GtkSingleSelection` /
+`GtkNoSelection`, and the views `GtkListView`, `GtkGridView`,
+`GtkColumnView` (+ `GtkColumnViewColumn`, `GtkColumnViewCell`). Checked
+by `test_views`, which presents a window and asserts (from the main
+loop) that the factory "setup"/"bind" callbacks ran, and shown in the
+`views` example (one store feeding list, grid and column views).
+
+**Step 16 — generator verification.** `tools/gir_verify.py` collects every
+`c:identifier` that `gir2def.py` would emit and checks it against the
+exported symbols of the libraries `pkg-config` links for the namespace
+(symbol-version suffixes stripped). `make gir-verify` reports 0
+unexpected across Gtk/GLib/Gio/Adw, with a small allowlist for GIR-listed
+macros and per-module ABI functions. `tools/run_gir_check.sh` also
+bulk-parses every generated module.
+
+**Step 17 — libadwaita.** Curated `Adw*` modules (application, window,
+header bar, toolbar view, preferences page/group and the action/switch/
+entry/combo/expander rows, status page, toast/overlay, banner, clamp,
+about and message dialogs), checked by `test_adw` and shown in the `adw`
+example. libadwaita is optional in the build.
+
+**Step 18 — GError and ownership.** `GError` (with its public struct
+layout) and `GioError` (domain + codes), plus `GtkUtils.Unref`/`Free`/
+`ErrorMessage`/`ClearError` and a documented ownership discipline.
+Checked by `test_gerror` (a real `GIO_ERROR_NOT_FOUND` from
+`g_file_delete`).
+
+## GNU Modula-2 interop rules learned
+
+1. Declare the module `DEFINITION MODULE FOR "C" Name ;` and list every
+   export in `EXPORT UNQUALIFIED`. Without `EXPORT UNQUALIFIED` the
+   compiler prefixes symbols with `Module_`, and the link fails.
+2. Formal parameters in a **procedure type** must be unnamed:
+   `GSourceFunc = PROCEDURE (ADDRESS) : INTEGER;` (named parameters are
+   a syntax error in gm2's default dialect).
+3. A function result that callers may ignore is declared `: [ T ]`
+   (e.g. `PROCEDURE g_timeout_add (...) : [ guint ];`). Without the
+   brackets, ignoring the result is a hard error. This also works in
+   ordinary modules — `GtkUtils.Connect` uses it.
+4. `ARRAY OF CHAR` maps onto `char *`, so string literals and `CHAR`
+   arrays can be passed straight to `const char *` parameters.
+5. `VAR` record/string parameters map onto `T *`; opaque handles
+   (`GObject *`, `GtkWidget *`, ...) travel as `ADDRESS` (use `NIL` to
+   test for `NULL`).
+6. `BOOLEAN` is not `gboolean`: pass `INTEGER` with `GLib.gTrue` /
+   `GLib.gFalse`, or use `INTEGER` directly.
+7. A top-level Modula-2 procedure is a plain C function pointer; pass
+   it directly to a callback-typed parameter, or use `ADR(proc)` where
+   the binding takes an `ADDRESS`/`GCallback`.
+8. **Real numbers:** gm2 `REAL` is 8 bytes and matches C `double`;
+   gm2 `SHORTREAL` is 4 bytes and matches C `float`; gm2 `LONGREAL` is
+   16 bytes and matches nothing in GTK. Use `REAL` for `gdouble` /
+   `double` (e.g. `GtkRange` values, `GtkScale` ranges).
+9. Beware `*)` and `(*` inside comments — they close/open a comment
+   early. Write `void ptr`, not `void *`, in prose.
+10. gm2 has no pointer arithmetic and its `T(x)` cast requires equal
+    sizes; `CStrToM2` therefore copies with libc `strncpy` instead of
+    walking a `char *`.
+11. `GVariant` values from `g_variant_new_*` are *floating*: ownership
+    transfers to the callee (e.g. `g_simple_action_new_stateful`).
+    Values returned by `g_action_get_state()` / `g_variant_get_*` own a
+    reference and must be released with `g_variant_unref()`.
+12. **ISO dialect.** Compiled with `-fiso`: `CAST(T, expr)` (ISO
+    `SYSTEM`) and `NEW`/`DISPOSE` (with `Storage`'s
+    `ALLOCATE`/`DEALLOCATE`) are available there but not in PIM.
+13. When a parameter is typed as a **procedure type**, pass the procedure
+    directly (`Connect2(b, "clicked", OnClick, ...)`), not `ADR(OnClick)`
+    — gm2 type-checks it. Use `ADR(proc)` only where the parameter is a
+    plain `ADDRESS` / `GCallback`.
+14. A large opaque C struct that is always passed by address (e.g.
+    `GtkTextIter`) can be modelled as a record of `ADDRESS` words sized
+    to `sizeof` it: that gives the right size *and* 64-bit alignment.
+    `GtkTextIter` is 80 bytes, hence `ARRAY [0..9] OF ADDRESS`.
+
+## Roadmap
+
+The original roadmap is complete: GLib/GObject core, widgets, inputs,
+containers, actions/menus/accelerators, header bars, GIO extras,
+model-backed views, and the GIR generator are all in.  On top of that:
+generator verification (`make gir-verify`), curated **libadwaita**, and
+**GError** + ownership helpers.
+
+Possible next steps:
+
+1. Hand-curate more of the generated surface (signals, properties,
+   value-struct records, `GtkCssProvider` styling).
+2. Turn the generator's `ADDRESS` placeholders into cross-module type
+   aliases and `[ ]`/`VAR` refinements using the GIR annotations.
+3. Grow the test suite around the newly generated modules.
+4. Prune/promote useful `gen/` output into `src/` as it proves out.

+ 124 - 0
examples/actions.mod

@@ -0,0 +1,124 @@
+MODULE actions ;
+
+(*
+   m2-GTK4 example - application actions, a menu bar and accelerators.
+
+   A GtkApplicationWindow with an in-window GtkPopoverMenuBar built
+   from a GMenu:
+     File > New   (app.new,  Ctrl+N)
+     File > Quit  (app.quit, Ctrl+Q)
+     View > Bold  (win.bold, Ctrl+B, a stateful toggle)
+
+   "app." actions live on the GtkApplication; "win." actions live on the
+   GtkApplicationWindow (which implements GActionMap).  Each handler
+   updates a status label.
+
+   Build:  make examples
+   Run:    ./build/examples/actions
+*)
+
+FROM Gio IMPORT g_application_run, g_application_quit;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkApplicationWindow IMPORT gtk_application_window_new;
+FROM GtkWindow IMPORT gtk_window_set_title, gtk_window_set_default_size,
+   gtk_window_set_child, gtk_window_present;
+FROM GtkBox IMPORT gtk_box_new, gtk_box_append;
+FROM GtkEnums IMPORT GtkVertical;
+FROM GtkLabel IMPORT gtk_label_new, gtk_label_set_text;
+FROM GtkPopoverMenuBar IMPORT gtk_popover_menu_bar_new_from_model;
+FROM GSimpleAction IMPORT g_simple_action_new, g_simple_action_new_stateful;
+FROM GActionMap IMPORT g_action_map_add_action;
+FROM GMenu IMPORT g_menu_new, g_menu_append, g_menu_append_submenu;
+FROM GVariant IMPORT g_variant_new_boolean, g_variant_get_boolean;
+FROM GtkUtils IMPORT Connect, SetAccel;
+FROM SYSTEM IMPORT ADDRESS, ADR;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.Actions";
+
+VAR
+   app, status: ADDRESS;
+
+PROCEDURE OnQuit (action: ADDRESS; param: ADDRESS; data: ADDRESS);
+BEGIN
+   g_application_quit(app)
+END OnQuit;
+
+PROCEDURE OnNew (action: ADDRESS; param: ADDRESS; data: ADDRESS);
+BEGIN
+   gtk_label_set_text(status, "New selected")
+END OnNew;
+
+(* void change_state(GSimpleAction *action, GVariant *value, gpointer data) *)
+PROCEDURE OnBold (action: ADDRESS; param: ADDRESS; data: ADDRESS);
+BEGIN
+   IF g_variant_get_boolean(param) # 0 THEN
+      gtk_label_set_text(status, "Bold on")
+   ELSE
+      gtk_label_set_text(status, "Bold off")
+   END
+END OnBold;
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   window, box, bar, fileMenu, viewMenu, menubar, action: ADDRESS;
+BEGIN
+   (* app-scoped actions: new, quit *)
+   action := g_simple_action_new("new", NIL);
+   Connect(action, "activate", ADR(OnNew), NIL);
+   g_action_map_add_action(application, action);
+
+   action := g_simple_action_new("quit", NIL);
+   Connect(action, "activate", ADR(OnQuit), NIL);
+   g_action_map_add_action(application, action);
+
+   window := gtk_application_window_new(application);
+
+   (* window-scoped stateful action: bold *)
+   action := g_simple_action_new_stateful("bold", NIL,
+                                          g_variant_new_boolean(0));
+   Connect(action, "change-state", ADR(OnBold), NIL);
+   g_action_map_add_action(window, action);
+
+   (* menu model *)
+   fileMenu := g_menu_new();
+   g_menu_append(fileMenu, "New", "app.new");
+   g_menu_append(fileMenu, "Quit", "app.quit");
+
+   viewMenu := g_menu_new();
+   g_menu_append(viewMenu, "Bold", "win.bold");
+
+   menubar := g_menu_new();
+   g_menu_append_submenu(menubar, "File", fileMenu);
+   g_menu_append_submenu(menubar, "View", viewMenu);
+
+   bar := gtk_popover_menu_bar_new_from_model(menubar);
+   status := gtk_label_new("Ready");
+
+   box := gtk_box_new(GtkVertical, 8);
+   gtk_box_append(box, bar);
+   gtk_box_append(box, status);
+
+   (* accelerators *)
+   SetAccel(application, "app.new", "<primary>n");
+   SetAccel(application, "app.quit", "<primary>q");
+   SetAccel(application, "win.bold", "<primary>b");
+
+   gtk_window_set_title(window, "m2-GTK4 Actions");
+   gtk_window_set_default_size(window, 420, 220);
+   gtk_window_set_child(window, box);
+   gtk_window_present(window)
+END OnActivate;
+
+VAR
+   rc: INTEGER;
+BEGIN
+   app := gtk_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("gtk_application_new failed\n");
+      HALT(1)
+   END;
+   Connect(app, "activate", ADR(OnActivate), NIL);
+   rc := g_application_run(app, 0, NIL)
+END actions.

+ 168 - 0
examples/adw.mod

@@ -0,0 +1,168 @@
+MODULE adw ;
+
+(*
+   m2-GTK4 example - a libadwaita preferences application.
+
+   AdwApplicationWindow > AdwToastOverlay > AdwToolbarView
+     top bar - AdwHeaderBar (title + "About" button, packed end)
+     content - AdwPreferencesPage >
+                 AdwPreferencesGroup >
+                   AdwActionRow (activatable -> toast)
+                   AdwSwitchRow
+                   AdwEntryRow
+                   AdwComboRow
+                   AdwExpanderRow (with a switch row inside)
+
+   Build:  make examples
+   Run:    ./build/examples/adw
+*)
+
+FROM Gio IMPORT g_application_run;
+FROM AdwApplication IMPORT adw_application_new;
+FROM AdwApplicationWindow IMPORT adw_application_window_new,
+   adw_application_window_set_content;
+FROM AdwHeaderBar IMPORT adw_header_bar_new, adw_header_bar_pack_end,
+   adw_header_bar_set_title_widget;
+FROM AdwToolbarView IMPORT adw_toolbar_view_new, adw_toolbar_view_add_top_bar,
+   adw_toolbar_view_set_content;
+FROM AdwPreferencesPage IMPORT adw_preferences_page_new,
+   adw_preferences_page_add, adw_preferences_page_set_title;
+FROM AdwPreferencesGroup IMPORT adw_preferences_group_new,
+   adw_preferences_group_add, adw_preferences_group_set_title,
+   adw_preferences_group_set_description;
+FROM AdwPreferencesRow IMPORT adw_preferences_row_set_title;
+FROM AdwActionRow IMPORT adw_action_row_new, adw_action_row_set_subtitle,
+   adw_action_row_set_icon_name;
+FROM AdwSwitchRow IMPORT adw_switch_row_new;
+FROM AdwEntryRow IMPORT adw_entry_row_new;
+FROM AdwComboRow IMPORT adw_combo_row_new, adw_combo_row_set_model,
+   adw_combo_row_set_selected;
+FROM AdwExpanderRow IMPORT adw_expander_row_new, adw_expander_row_add_row;
+FROM AdwToast IMPORT adw_toast_new, adw_toast_set_timeout;
+FROM AdwToastOverlay IMPORT adw_toast_overlay_new,
+   adw_toast_overlay_add_toast, adw_toast_overlay_set_child;
+FROM AdwAboutWindow IMPORT adw_about_window_new,
+   adw_about_window_set_application_name,
+   adw_about_window_set_application_icon, adw_about_window_set_version,
+   adw_about_window_set_developer_name, adw_about_window_set_comments,
+   adw_about_window_set_website;
+FROM GtkWindow IMPORT gtk_window_present;
+FROM GtkButton IMPORT gtk_button_new_with_label;
+FROM GtkLabel IMPORT gtk_label_new;
+FROM GtkStringList IMPORT gtk_string_list_new, gtk_string_list_append;
+FROM GtkClosures IMPORT Connect2;
+FROM SYSTEM IMPORT ADDRESS;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.Adw";
+
+VAR
+   overlay: ADDRESS;
+
+PROCEDURE ShowToast (text: ARRAY OF CHAR);
+VAR
+   toast: ADDRESS;
+BEGIN
+   toast := adw_toast_new(text);
+   adw_toast_set_timeout(toast, 2);
+   adw_toast_overlay_add_toast(overlay, toast)
+END ShowToast;
+
+(* void activated(AdwActionRow *row, gpointer data) *)
+PROCEDURE OnRowActivated (row: ADDRESS; data: ADDRESS);
+BEGIN
+   ShowToast("Row activated")
+END OnRowActivated;
+
+PROCEDURE OnAbout (button: ADDRESS; data: ADDRESS);
+VAR
+   about: ADDRESS;
+BEGIN
+   about := adw_about_window_new();
+   adw_about_window_set_application_name(about, "m2-GTK4");
+   adw_about_window_set_application_icon(about, "application-x-executable");
+   adw_about_window_set_version(about, "0.1");
+   adw_about_window_set_developer_name(about, "m2-GTK4");
+   adw_about_window_set_comments(about, "libadwaita bindings for GNU Modula-2");
+   adw_about_window_set_website(about, "https://example.org");
+   gtk_window_present(about)
+END OnAbout;
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   window, toolbar, header, aboutButton, page, group, row, sw, er, combo,
+   list, expander, inner: ADDRESS;
+BEGIN
+   window := adw_application_window_new(application);
+
+   aboutButton := gtk_button_new_with_label("About");
+   Connect2(aboutButton, "clicked", OnAbout, NIL);
+
+   header := adw_header_bar_new();
+   adw_header_bar_set_title_widget(header, gtk_label_new("Preferences"));
+   adw_header_bar_pack_end(header, aboutButton);
+
+   toolbar := adw_toolbar_view_new();
+   adw_toolbar_view_add_top_bar(toolbar, header);
+
+   page := adw_preferences_page_new();
+   adw_preferences_page_set_title(page, "Settings");
+
+   group := adw_preferences_group_new();
+   adw_preferences_group_set_title(group, "General");
+   adw_preferences_group_set_description(group, "Example Adwaita rows");
+
+   row := adw_action_row_new();
+   adw_preferences_row_set_title(row, "Appearance");
+   adw_action_row_set_subtitle(row, "Tap to show a toast");
+   adw_action_row_set_icon_name(row, "applications-graphics");
+   Connect2(row, "activated", OnRowActivated, NIL);
+   adw_preferences_group_add(group, row);
+
+   sw := adw_switch_row_new();
+   adw_preferences_row_set_title(sw, "Enable notifications");
+   adw_preferences_group_add(group, sw);
+
+   er := adw_entry_row_new();
+   adw_preferences_row_set_title(er, "Name");
+   adw_preferences_group_add(group, er);
+
+   list := gtk_string_list_new(NIL);
+   gtk_string_list_append(list, "System");
+   gtk_string_list_append(list, "Light");
+   gtk_string_list_append(list, "Dark");
+   combo := adw_combo_row_new();
+   adw_preferences_row_set_title(combo, "Theme");
+   adw_combo_row_set_model(combo, list);
+   adw_combo_row_set_selected(combo, 0);
+   adw_preferences_group_add(group, combo);
+
+   expander := adw_expander_row_new();
+   adw_preferences_row_set_title(expander, "Advanced");
+   inner := adw_switch_row_new();
+   adw_preferences_row_set_title(inner, "Developer mode");
+   adw_expander_row_add_row(expander, inner);
+   adw_preferences_group_add(group, expander);
+
+   adw_preferences_page_add(page, group);
+   adw_toolbar_view_set_content(toolbar, page);
+
+   overlay := adw_toast_overlay_new();
+   adw_toast_overlay_set_child(overlay, toolbar);
+   adw_application_window_set_content(window, overlay);
+
+   gtk_window_present(window)
+END OnActivate;
+
+VAR
+   app: ADDRESS;
+BEGIN
+   app := adw_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("adw_application_new failed\n");
+      HALT(1)
+   END;
+   Connect2(app, "activate", OnActivate, NIL);
+   g_application_run(app, 0, NIL)
+END adw.

+ 104 - 0
examples/containers.mod

@@ -0,0 +1,104 @@
+MODULE containers ;
+
+(*
+   m2-GTK4 example - the layout containers together.
+
+   A GtkNotebook with three pages:
+     1. "Grid"   - a GtkGrid of buttons
+     2. "Stack"  - a GtkStackSwitcher driving a GtkStack
+     3. "Scroll" - a GtkScrolledWindow around a tall box
+
+   Build:  make examples
+   Run:    ./build/examples/containers
+*)
+
+FROM Gio IMPORT g_application_run;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkWindow IMPORT gtk_application_window_new, gtk_window_set_title,
+   gtk_window_set_default_size, gtk_window_set_child, gtk_window_present;
+FROM GtkBox IMPORT gtk_box_new, gtk_box_append;
+FROM GtkEnums IMPORT GtkVertical, GtkPosTop;
+FROM GtkLabel IMPORT gtk_label_new;
+FROM GtkButton IMPORT gtk_button_new_with_label;
+FROM GtkGrid IMPORT gtk_grid_new, gtk_grid_attach,
+   gtk_grid_set_row_spacing, gtk_grid_set_column_spacing;
+FROM GtkStack IMPORT gtk_stack_new, gtk_stack_add_titled,
+   gtk_stack_set_transition_type, GtkStackTransitionSlideLeft;
+FROM GtkStackSwitcher IMPORT gtk_stack_switcher_new,
+   gtk_stack_switcher_set_stack;
+FROM GtkNotebook IMPORT gtk_notebook_new, gtk_notebook_append_page,
+   gtk_notebook_set_tab_pos;
+FROM GtkScrolledWindow IMPORT gtk_scrolled_window_new,
+   gtk_scrolled_window_set_child, gtk_scrolled_window_set_policy,
+   gtk_scrolled_window_set_min_content_height,
+   GtkPolicyNever, GtkPolicyAutomatic;
+FROM GtkUtils IMPORT Connect, IntToStr;
+FROM SYSTEM IMPORT ADDRESS, ADR;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.Containers";
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   window, notebook, grid, stack, switcher, sw, box: ADDRESS;
+   text: ARRAY [0..15] OF CHAR;
+   i: INTEGER;
+BEGIN
+   notebook := gtk_notebook_new();
+   gtk_notebook_set_tab_pos(notebook, GtkPosTop);
+
+   (* page 1: a 3x2 grid of buttons *)
+   grid := gtk_grid_new();
+   gtk_grid_set_row_spacing(grid, 6);
+   gtk_grid_set_column_spacing(grid, 6);
+   FOR i := 0 TO 5 DO
+      IntToStr(i + 1, text);
+      gtk_grid_attach(grid, gtk_button_new_with_label(text),
+                      i MOD 3, i DIV 3, 1, 1)
+   END;
+   gtk_notebook_append_page(notebook, grid, gtk_label_new("Grid"));
+
+   (* page 2: a stack with a switcher *)
+   stack := gtk_stack_new();
+   gtk_stack_set_transition_type(stack, GtkStackTransitionSlideLeft);
+   gtk_stack_add_titled(stack, gtk_label_new("First page"), "first", "First");
+   gtk_stack_add_titled(stack, gtk_label_new("Second page"), "second", "Second");
+   gtk_stack_add_titled(stack, gtk_label_new("Third page"), "third", "Third");
+   switcher := gtk_stack_switcher_new();
+   gtk_stack_switcher_set_stack(switcher, stack);
+   box := gtk_box_new(GtkVertical, 8);
+   gtk_box_append(box, switcher);
+   gtk_box_append(box, stack);
+   gtk_notebook_append_page(notebook, box, gtk_label_new("Stack"));
+
+   (* page 3: a scrolled window around a tall box *)
+   box := gtk_box_new(GtkVertical, 2);
+   FOR i := 1 TO 40 DO
+      IntToStr(i, text);
+      gtk_box_append(box, gtk_label_new(text))
+   END;
+   sw := gtk_scrolled_window_new();
+   gtk_scrolled_window_set_policy(sw, GtkPolicyNever, GtkPolicyAutomatic);
+   gtk_scrolled_window_set_min_content_height(sw, 160);
+   gtk_scrolled_window_set_child(sw, box);
+   gtk_notebook_append_page(notebook, sw, gtk_label_new("Scroll"));
+
+   window := gtk_application_window_new(application);
+   gtk_window_set_title(window, "m2-GTK4 Containers");
+   gtk_window_set_default_size(window, 480, 320);
+   gtk_window_set_child(window, notebook);
+   gtk_window_present(window)
+END OnActivate;
+
+VAR
+   app: ADDRESS;
+BEGIN
+   app := gtk_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("gtk_application_new failed\n");
+      HALT(1)
+   END;
+   Connect(app, "activate", ADR(OnActivate), NIL);
+   g_application_run(app, 0, NIL)
+END containers.

+ 77 - 0
examples/counter.mod

@@ -0,0 +1,77 @@
+MODULE counter ;
+
+(*
+   m2-GTK4 example - a button that updates a label.
+
+   Demonstrates the widget/layout set (GtkWindow > GtkBox > label &
+   button) and a "clicked" signal handler that mutates Modula-2 state.
+
+   Build:  make examples
+   Run:    ./build/examples/counter
+*)
+
+FROM Gio IMPORT g_application_run;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkWindow IMPORT gtk_application_window_new, gtk_window_set_title,
+   gtk_window_set_default_size, gtk_window_set_child, gtk_window_present;
+FROM GtkBox IMPORT gtk_box_new, gtk_box_append, gtk_box_set_spacing;
+FROM GtkEnums IMPORT GtkVertical;
+FROM GtkLabel IMPORT gtk_label_new, gtk_label_set_text;
+FROM GtkButton IMPORT gtk_button_new_with_label;
+FROM GtkUtils IMPORT IntToStr, Connect;
+FROM SYSTEM IMPORT ADDRESS, ADR;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.Counter";
+
+VAR
+   label: ADDRESS;
+   count: INTEGER;
+
+(* void clicked(GtkButton *button, gpointer user_data) *)
+PROCEDURE OnClicked (button: ADDRESS; data: ADDRESS);
+VAR
+   text: ARRAY [0..31] OF CHAR;
+BEGIN
+   INC(count);
+   IntToStr(count, text);
+   gtk_label_set_text(label, text)
+END OnClicked;
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   window, box, button: ADDRESS;
+   text: ARRAY [0..31] OF CHAR;
+BEGIN
+   window := gtk_application_window_new(application);
+   gtk_window_set_title(window, "m2-GTK4 Counter");
+   gtk_window_set_default_size(window, 320, 180);
+
+   box := gtk_box_new(GtkVertical, 12);
+   gtk_box_set_spacing(box, 12);
+
+   count := 0;
+   IntToStr(count, text);
+   label := gtk_label_new(text);
+   gtk_box_append(box, label);
+
+   button := gtk_button_new_with_label("Click me");
+   Connect(button, "clicked", ADR(OnClicked), NIL);
+   gtk_box_append(box, button);
+
+   gtk_window_set_child(window, box);
+   gtk_window_present(window)
+END OnActivate;
+
+VAR
+   app: ADDRESS;
+BEGIN
+   app := gtk_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("gtk_application_new failed\n");
+      HALT(1)
+   END;
+   Connect(app, "activate", ADR(OnActivate), NIL);
+   g_application_run(app, 0, NIL)
+END counter.

+ 161 - 0
examples/editor.mod

@@ -0,0 +1,161 @@
+MODULE editor ;
+
+(*
+   m2-GTK4 example - a small editor built from the second input batch.
+
+   A GtkSearchEntry, a GtkTextView (in a GtkScrolledWindow) backed by a
+   GtkTextBuffer, a GtkDropDown that selects the wrap mode, and a
+   GtkSpinButton that sets the text padding.  The signals use the
+   GtkClosures helper (2- and 3-argument forms).
+
+   Build:  make examples
+   Run:    ./build/examples/editor
+*)
+
+FROM Gio IMPORT g_application_run;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkApplicationWindow IMPORT gtk_application_window_new;
+FROM GtkWindow IMPORT gtk_window_set_title, gtk_window_set_default_size,
+   gtk_window_set_child, gtk_window_present;
+FROM GtkBox IMPORT gtk_box_new, gtk_box_append, gtk_box_set_spacing;
+FROM GtkEnums IMPORT GtkVertical, GtkHorizontal, GtkWrapWord;
+FROM GtkLabel IMPORT gtk_label_new, gtk_label_set_text;
+FROM GtkWidget IMPORT gtk_widget_set_margin_top,
+   gtk_widget_set_margin_bottom, gtk_widget_set_margin_start,
+   gtk_widget_set_margin_end, gtk_widget_set_vexpand;
+FROM GtkSearchEntry IMPORT gtk_search_entry_new,
+   gtk_search_entry_set_placeholder_text;
+FROM GtkEditable IMPORT gtk_editable_get_text;
+FROM GtkScrolledWindow IMPORT gtk_scrolled_window_new,
+   gtk_scrolled_window_set_child, gtk_scrolled_window_set_policy,
+   GtkPolicyNever, GtkPolicyAutomatic;
+FROM GtkTextView IMPORT gtk_text_view_new, gtk_text_view_get_buffer,
+   gtk_text_view_set_wrap_mode, gtk_text_view_set_monospace,
+   gtk_text_view_set_left_margin, gtk_text_view_set_right_margin;
+FROM GtkTextBuffer IMPORT gtk_text_buffer_set_text;
+FROM GtkStringList IMPORT gtk_string_list_new, gtk_string_list_append;
+FROM GtkDropDown IMPORT gtk_drop_down_new, gtk_drop_down_get_selected,
+   gtk_drop_down_set_selected;
+FROM GtkSpinButton IMPORT gtk_spin_button_new_with_range,
+   gtk_spin_button_get_value, gtk_spin_button_set_value;
+FROM GtkClosures IMPORT Connect2, Connect3;
+FROM GtkUtils IMPORT CStrToM2, StrAppend;
+FROM SYSTEM IMPORT ADDRESS, ADR;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.Editor";
+
+VAR
+   view, status: ADDRESS;
+
+PROCEDURE OnSearch (entry: ADDRESS; user: ADDRESS);
+VAR
+   text: ARRAY [0..63] OF CHAR;
+   line: ARRAY [0..95] OF CHAR;
+BEGIN
+   line[0] := 0C;
+   StrAppend(line, "search: ");
+   CStrToM2(gtk_editable_get_text(entry), text);
+   IF text[0] = 0C THEN
+      StrAppend(line, "(none)")
+   ELSE
+      StrAppend(line, text)
+   END;
+   gtk_label_set_text(status, line)
+END OnSearch;
+
+(* 3-argument form: "notify::selected" carries the GParamSpec *)
+PROCEDURE OnWrap (dd: ADDRESS; pspec: ADDRESS; user: ADDRESS);
+BEGIN
+   gtk_text_view_set_wrap_mode(view, gtk_drop_down_get_selected(dd))
+END OnWrap;
+
+PROCEDURE OnPad (spin: ADDRESS; user: ADDRESS);
+VAR
+   margin: INTEGER;
+BEGIN
+   margin := TRUNC(gtk_spin_button_get_value(spin));
+   gtk_text_view_set_left_margin(view, margin);
+   gtk_text_view_set_right_margin(view, margin)
+END OnPad;
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   window, box, search, scroller, bottom, wrapLabel, padLabel,
+   dd, list, spin, buffer: ADDRESS;
+BEGIN
+   status := gtk_label_new("Type in the box or search");
+
+   (* text view inside a scrolled window *)
+   view := gtk_text_view_new();
+   gtk_text_view_set_monospace(view, 1);
+   buffer := gtk_text_view_get_buffer(view);
+   gtk_text_buffer_set_text(buffer, "Edit me!", -1);
+   gtk_text_view_set_left_margin(view, 6);
+   gtk_text_view_set_right_margin(view, 6);
+
+   scroller := gtk_scrolled_window_new();
+   gtk_scrolled_window_set_policy(scroller, GtkPolicyNever,
+                                  GtkPolicyAutomatic);
+   gtk_scrolled_window_set_child(scroller, view);
+   gtk_widget_set_vexpand(scroller, 1);
+
+   (* search entry *)
+   search := gtk_search_entry_new();
+   gtk_search_entry_set_placeholder_text(search, "search the text");
+   Connect2(search, "search-changed", OnSearch, NIL);
+
+   (* wrap-mode drop-down *)
+   list := gtk_string_list_new(NIL);
+   gtk_string_list_append(list, "No wrap");
+   gtk_string_list_append(list, "Wrap chars");
+   gtk_string_list_append(list, "Wrap words");
+   gtk_string_list_append(list, "Wrap words/chars");
+   dd := gtk_drop_down_new(list, NIL);
+   gtk_drop_down_set_selected(dd, 2);
+   gtk_text_view_set_wrap_mode(view, GtkWrapWord);
+   Connect3(dd, "notify::selected", OnWrap, NIL);
+
+   (* padding spin button *)
+   spin := gtk_spin_button_new_with_range(0.0, 40.0, 1.0);
+   gtk_spin_button_set_value(spin, 6.0);
+   Connect2(spin, "value-changed", OnPad, NIL);
+
+   wrapLabel := gtk_label_new("Wrap:");
+   padLabel := gtk_label_new("Padding:");
+   bottom := gtk_box_new(GtkHorizontal, 8);
+   gtk_box_append(bottom, wrapLabel);
+   gtk_box_append(bottom, dd);
+   gtk_box_append(bottom, padLabel);
+   gtk_box_append(bottom, spin);
+
+   box := gtk_box_new(GtkVertical, 8);
+   gtk_box_set_spacing(box, 8);
+   gtk_widget_set_margin_top(box, 12);
+   gtk_widget_set_margin_bottom(box, 12);
+   gtk_widget_set_margin_start(box, 12);
+   gtk_widget_set_margin_end(box, 12);
+   gtk_box_append(box, search);
+   gtk_box_append(box, scroller);
+   gtk_box_append(box, bottom);
+   gtk_box_append(box, status);
+
+   window := gtk_application_window_new(application);
+   gtk_window_set_title(window, "m2-GTK4 Editor");
+   gtk_window_set_default_size(window, 520, 360);
+   gtk_window_set_child(window, box);
+   gtk_window_present(window)
+END OnActivate;
+
+VAR
+   app: ADDRESS;
+BEGIN
+   app := gtk_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("gtk_application_new failed\n");
+      HALT(1)
+   END;
+   Connect2(app, "activate", OnActivate, NIL);
+   g_application_run(app, 0, NIL)
+END editor.

+ 106 - 0
examples/files.mod

@@ -0,0 +1,106 @@
+MODULE files ;
+
+(*
+   m2-GTK4 example - the native GTK4 file dialog.
+
+   A button opens a GtkFileDialog; the asynchronous callback receives
+   the result and calls gtk_file_dialog_open_finish() to get a GFile,
+   whose basename is shown in a label.
+
+   Build:  make examples
+   Run:    ./build/examples/files
+*)
+
+FROM Gio IMPORT g_application_run;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkApplicationWindow IMPORT gtk_application_window_new;
+FROM GtkWindow IMPORT gtk_window_set_title, gtk_window_set_default_size,
+   gtk_window_set_child, gtk_window_present;
+FROM GtkBox IMPORT gtk_box_new, gtk_box_append, gtk_box_set_spacing;
+FROM GtkEnums IMPORT GtkVertical;
+FROM GtkLabel IMPORT gtk_label_new, gtk_label_set_text;
+FROM GtkButton IMPORT gtk_button_new_with_label;
+FROM GtkWidget IMPORT gtk_widget_set_margin_top,
+   gtk_widget_set_margin_bottom, gtk_widget_set_margin_start,
+   gtk_widget_set_margin_end;
+FROM GtkFileDialog IMPORT gtk_file_dialog_new, gtk_file_dialog_open,
+   gtk_file_dialog_open_finish, gtk_file_dialog_set_title;
+FROM GFile IMPORT g_file_get_basename;
+FROM GObject IMPORT g_object_unref;
+FROM GLib IMPORT g_free;
+FROM GtkClosures IMPORT Connect2;
+FROM GtkUtils IMPORT CStrToM2, StrAppend;
+FROM SYSTEM IMPORT ADDRESS, ADR;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.Files";
+
+VAR
+   dialog, window, status: ADDRESS;
+
+PROCEDURE OnOpenClicked (button: ADDRESS; user: ADDRESS);
+BEGIN
+   gtk_file_dialog_open(dialog, window, NIL, ADR(OnOpenFinished), NIL)
+END OnOpenClicked;
+
+(* void finished(GObject *source, GAsyncResult *result, gpointer user_data) *)
+PROCEDURE OnOpenFinished (source: ADDRESS; result: ADDRESS; user: ADDRESS);
+VAR
+   file, name: ADDRESS;
+   buf: ARRAY [0..255] OF CHAR;
+   line: ARRAY [0..287] OF CHAR;
+BEGIN
+   file := gtk_file_dialog_open_finish(dialog, result, NIL);
+   IF file = NIL THEN
+      gtk_label_set_text(status, "No file selected")
+   ELSE
+      name := g_file_get_basename(file);
+      CStrToM2(name, buf);
+      g_free(name);
+      line[0] := 0C;
+      StrAppend(line, "Opened: ");
+      StrAppend(line, buf);
+      gtk_label_set_text(status, line);
+      g_object_unref(file)
+   END
+END OnOpenFinished;
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   box, button: ADDRESS;
+BEGIN
+   dialog := gtk_file_dialog_new();
+   gtk_file_dialog_set_title(dialog, "Open a file");
+
+   status := gtk_label_new("No file selected");
+   button := gtk_button_new_with_label("Open file...");
+   Connect2(button, "clicked", OnOpenClicked, NIL);
+
+   box := gtk_box_new(GtkVertical, 10);
+   gtk_box_set_spacing(box, 10);
+   gtk_widget_set_margin_top(box, 14);
+   gtk_widget_set_margin_bottom(box, 14);
+   gtk_widget_set_margin_start(box, 14);
+   gtk_widget_set_margin_end(box, 14);
+   gtk_box_append(box, button);
+   gtk_box_append(box, status);
+
+   window := gtk_application_window_new(application);
+   gtk_window_set_title(window, "m2-GTK4 Files");
+   gtk_window_set_default_size(window, 420, 160);
+   gtk_window_set_child(window, box);
+   gtk_window_present(window)
+END OnActivate;
+
+VAR
+   app: ADDRESS;
+BEGIN
+   app := gtk_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("gtk_application_new failed\n");
+      HALT(1)
+   END;
+   Connect2(app, "activate", OnActivate, NIL);
+   g_application_run(app, 0, NIL)
+END files.

+ 119 - 0
examples/headerbar.mod

@@ -0,0 +1,119 @@
+MODULE headerbar ;
+
+(*
+   m2-GTK4 example - a header bar with window controls.
+
+   A GtkApplicationWindow whose titlebar is a GtkHeaderBar:
+     title widget      - a label
+     packed start      - a "New" button (connected with GtkClosures.Connect2)
+     packed end        - a GtkMenuButton with an application menu
+                         (Bold toggle, Quit)
+   plus the Ctrl+N / Ctrl+B / Ctrl+Q accelerators.
+
+   Build:  make examples
+   Run:    ./build/examples/headerbar
+*)
+
+FROM Gio IMPORT g_application_run, g_application_quit;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkApplicationWindow IMPORT gtk_application_window_new;
+FROM GtkWindow IMPORT gtk_window_set_title, gtk_window_set_default_size,
+   gtk_window_set_titlebar, gtk_window_set_child, gtk_window_present;
+FROM GtkHeaderBar IMPORT gtk_header_bar_new, gtk_header_bar_set_title_widget,
+   gtk_header_bar_pack_start, gtk_header_bar_pack_end;
+FROM GtkMenuButton IMPORT gtk_menu_button_new,
+   gtk_menu_button_set_menu_model, gtk_menu_button_set_icon_name;
+FROM GtkLabel IMPORT gtk_label_new, gtk_label_set_text;
+FROM GtkButton IMPORT gtk_button_new_with_label;
+FROM GSimpleAction IMPORT g_simple_action_new, g_simple_action_new_stateful;
+FROM GActionMap IMPORT g_action_map_add_action;
+FROM GMenu IMPORT g_menu_new, g_menu_append;
+FROM GVariant IMPORT g_variant_new_boolean, g_variant_get_boolean;
+FROM GtkUtils IMPORT Connect, SetAccel;
+FROM GtkClosures IMPORT Connect2;
+FROM SYSTEM IMPORT ADDRESS, ADR;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.HeaderBar";
+
+VAR
+   app, status: ADDRESS;
+
+PROCEDURE OnQuit (action: ADDRESS; param: ADDRESS; data: ADDRESS);
+BEGIN
+   g_application_quit(app)
+END OnQuit;
+
+(* GtkClosures.Handler2: void handler(instance, user_data) *)
+PROCEDURE OnNew (instance: ADDRESS; user: ADDRESS);
+BEGIN
+   gtk_label_set_text(status, "New selected")
+END OnNew;
+
+PROCEDURE OnBold (action: ADDRESS; param: ADDRESS; data: ADDRESS);
+BEGIN
+   IF g_variant_get_boolean(param) # 0 THEN
+      gtk_label_set_text(status, "Bold on")
+   ELSE
+      gtk_label_set_text(status, "Bold off")
+   END
+END OnBold;
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   window, header, newButton, menuButton, menu, action, title: ADDRESS;
+BEGIN
+   (* app-scoped action: quit *)
+   action := g_simple_action_new("quit", NIL);
+   Connect(action, "activate", ADR(OnQuit), NIL);
+   g_action_map_add_action(application, action);
+
+   window := gtk_application_window_new(application);
+
+   (* window-scoped stateful action: bold *)
+   action := g_simple_action_new_stateful("bold", NIL,
+                                          g_variant_new_boolean(0));
+   Connect(action, "change-state", ADR(OnBold), NIL);
+   g_action_map_add_action(window, action);
+
+   (* header bar: title, start button, end-packed menu button *)
+   title := gtk_label_new("m2-GTK4 Header Bar");
+   header := gtk_header_bar_new();
+   gtk_header_bar_set_title_widget(header, title);
+
+   newButton := gtk_button_new_with_label("New");
+   Connect2(newButton, "clicked", OnNew, NIL);
+   gtk_header_bar_pack_start(header, newButton);
+
+   menu := g_menu_new();
+   g_menu_append(menu, "Bold", "win.bold");
+   g_menu_append(menu, "Quit", "app.quit");
+   menuButton := gtk_menu_button_new();
+   gtk_menu_button_set_icon_name(menuButton, "open-menu-symbolic");
+   gtk_menu_button_set_menu_model(menuButton, menu);
+   gtk_header_bar_pack_end(header, menuButton);
+
+   status := gtk_label_new("Ready");
+
+   SetAccel(application, "app.quit", "<primary>q");
+   SetAccel(application, "win.bold", "<primary>b");
+
+   gtk_window_set_title(window, "m2-GTK4 Header Bar");
+   gtk_window_set_default_size(window, 420, 220);
+   gtk_window_set_titlebar(window, header);
+   gtk_window_set_child(window, status);
+   gtk_window_present(window)
+END OnActivate;
+
+VAR
+   rc: INTEGER;
+BEGIN
+   app := gtk_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("gtk_application_new failed\n");
+      HALT(1)
+   END;
+   Connect(app, "activate", ADR(OnActivate), NIL);
+   rc := g_application_run(app, 0, NIL)
+END headerbar.

+ 50 - 0
examples/hello.mod

@@ -0,0 +1,50 @@
+MODULE hello ;
+
+(*
+   m2-GTK4 example - the canonical GTK4 "Hello, world".
+
+   A GtkApplication is created, its "activate" signal opens a window
+   with a label, and g_application_run() drives the main loop until the
+   window is closed.
+
+   Build:  make examples
+   Run:    ./build/examples/hello
+*)
+
+FROM Gio IMPORT g_application_run;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkWindow IMPORT gtk_application_window_new, gtk_window_set_title,
+   gtk_window_set_default_size, gtk_window_set_child, gtk_window_present;
+FROM GtkLabel IMPORT gtk_label_new;
+FROM GtkUtils IMPORT Connect;
+FROM SYSTEM IMPORT ADDRESS, ADR;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.Hello";
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   window, label: ADDRESS;
+BEGIN
+   window := gtk_application_window_new(application);
+   gtk_window_set_title(window, "m2-GTK4 Hello");
+   gtk_window_set_default_size(window, 360, 120);
+
+   label := gtk_label_new("Hello, GNU Modula-2 + GTK4!");
+   gtk_window_set_child(window, label);
+
+   gtk_window_present(window)
+END OnActivate;
+
+VAR
+   app: ADDRESS;
+BEGIN
+   app := gtk_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("gtk_application_new failed\n");
+      HALT(1)
+   END;
+   Connect(app, "activate", ADR(OnActivate), NIL);
+   g_application_run(app, 0, NIL)
+END hello.

+ 149 - 0
examples/inputs.mod

@@ -0,0 +1,149 @@
+MODULE inputs ;
+
+(*
+   m2-GTK4 example - a small form built from the input widgets.
+
+   GtkEntry + GtkCheckButton + GtkSwitch + GtkScale, with signal
+   handlers that rebuild a status label on every change.  Demonstrates
+   Connect(), CStrToM2(), StrAppend() and IntToStr() together.
+
+   Build:  make examples
+   Run:    ./build/examples/inputs
+*)
+
+FROM Gio IMPORT g_application_run;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkWindow IMPORT gtk_application_window_new, gtk_window_set_title,
+   gtk_window_set_default_size, gtk_window_set_child, gtk_window_present;
+FROM GtkBox IMPORT gtk_box_new, gtk_box_append, gtk_box_set_spacing;
+FROM GtkEnums IMPORT GtkVertical, GtkHorizontal;
+FROM GtkWidget IMPORT gtk_widget_set_margin_top, gtk_widget_set_margin_bottom,
+   gtk_widget_set_margin_start, gtk_widget_set_margin_end;
+FROM GtkLabel IMPORT gtk_label_new, gtk_label_set_text;
+FROM GtkEntry IMPORT gtk_entry_new, gtk_entry_set_placeholder_text;
+FROM GtkEditable IMPORT gtk_editable_get_text;
+FROM GtkCheckButton IMPORT gtk_check_button_new_with_label,
+   gtk_check_button_get_active;
+FROM GtkSwitch IMPORT gtk_switch_new, gtk_switch_get_active;
+FROM GtkScale IMPORT gtk_scale_new_with_range, gtk_scale_set_digits;
+FROM GtkRange IMPORT gtk_range_get_value;
+FROM GtkUtils IMPORT Connect, CStrToM2, StrAppend, IntToStr;
+FROM SYSTEM IMPORT ADDRESS, ADR;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.Inputs";
+
+VAR
+   entry, check, sw, scale, status: ADDRESS;
+
+PROCEDURE UpdateStatus;
+VAR
+   name: ARRAY [0..63] OF CHAR;
+   value: ARRAY [0..31] OF CHAR;
+   line: ARRAY [0..191] OF CHAR;
+BEGIN
+   line[0] := 0C;
+
+   StrAppend(line, "name: ");
+   CStrToM2(gtk_editable_get_text(entry), name);
+   IF name[0] = 0C THEN
+      StrAppend(line, "(empty)")
+   ELSE
+      StrAppend(line, name)
+   END;
+
+   StrAppend(line, "   feature: ");
+   IF gtk_check_button_get_active(check) # 0 THEN
+      StrAppend(line, "on")
+   ELSE
+      StrAppend(line, "off")
+   END;
+
+   StrAppend(line, "   switch: ");
+   IF gtk_switch_get_active(sw) # 0 THEN
+      StrAppend(line, "on")
+   ELSE
+      StrAppend(line, "off")
+   END;
+
+   StrAppend(line, "   value: ");
+   IntToStr(TRUNC(gtk_range_get_value(scale)), value);
+   StrAppend(line, value);
+
+   gtk_label_set_text(status, line)
+END UpdateStatus;
+
+PROCEDURE OnEntryChanged (editable: ADDRESS; data: ADDRESS);
+BEGIN
+   UpdateStatus
+END OnEntryChanged;
+
+PROCEDURE OnToggled (button: ADDRESS; data: ADDRESS);
+BEGIN
+   UpdateStatus
+END OnToggled;
+
+(* void notify(GObject *obj, GParamSpec *pspec, gpointer data) *)
+PROCEDURE OnSwitchNotify (obj: ADDRESS; pspec: ADDRESS; data: ADDRESS);
+BEGIN
+   UpdateStatus
+END OnSwitchNotify;
+
+PROCEDURE OnScaleChanged (range: ADDRESS; data: ADDRESS);
+BEGIN
+   UpdateStatus
+END OnScaleChanged;
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   window, box: ADDRESS;
+BEGIN
+   box := gtk_box_new(GtkVertical, 10);
+   gtk_box_set_spacing(box, 10);
+   gtk_widget_set_margin_top(box, 14);
+   gtk_widget_set_margin_bottom(box, 14);
+   gtk_widget_set_margin_start(box, 14);
+   gtk_widget_set_margin_end(box, 14);
+
+   entry := gtk_entry_new();
+   gtk_entry_set_placeholder_text(entry, "type your name");
+   Connect(entry, "changed", ADR(OnEntryChanged), NIL);
+   gtk_box_append(box, entry);
+
+   check := gtk_check_button_new_with_label("Enable feature");
+   Connect(check, "toggled", ADR(OnToggled), NIL);
+   gtk_box_append(box, check);
+
+   sw := gtk_switch_new();
+   Connect(sw, "notify::active", ADR(OnSwitchNotify), NIL);
+   gtk_box_append(box, sw);
+
+   scale := gtk_scale_new_with_range(GtkHorizontal, 0.0, 100.0, 1.0);
+   gtk_scale_set_digits(scale, 0);
+   Connect(scale, "value-changed", ADR(OnScaleChanged), NIL);
+   gtk_box_append(box, scale);
+
+   status := gtk_label_new(" ");
+   gtk_box_append(box, status);
+
+   window := gtk_application_window_new(application);
+   gtk_window_set_title(window, "m2-GTK4 Inputs");
+   gtk_window_set_default_size(window, 460, 240);
+   gtk_window_set_child(window, box);
+   gtk_window_present(window);
+
+   UpdateStatus
+END OnActivate;
+
+VAR
+   app: ADDRESS;
+BEGIN
+   app := gtk_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("gtk_application_new failed\n");
+      HALT(1)
+   END;
+   Connect(app, "activate", ADR(OnActivate), NIL);
+   g_application_run(app, 0, NIL)
+END inputs.

+ 126 - 0
examples/layouts.mod

@@ -0,0 +1,126 @@
+MODULE layouts ;
+
+(*
+   m2-GTK4 example - the second container batch.
+
+   A GtkPaned splits the window:
+     start - a GtkFrame containing a GtkExpander
+     end   - a GtkOverlay whose main child is a GtkListBox, with a
+             corner label on top
+   Activating a list row updates the status label underneath.
+
+   Build:  make examples
+   Run:    ./build/examples/layouts
+*)
+
+FROM Gio IMPORT g_application_run;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkApplicationWindow IMPORT gtk_application_window_new;
+FROM GtkWindow IMPORT gtk_window_set_title, gtk_window_set_default_size,
+   gtk_window_set_child, gtk_window_present;
+FROM GtkBox IMPORT gtk_box_new, gtk_box_append;
+FROM GtkEnums IMPORT GtkVertical, GtkHorizontal, GtkAlignEnd, GtkAlignStart,
+   GtkSelectionSingle;
+FROM GtkLabel IMPORT gtk_label_new, gtk_label_set_text;
+FROM GtkWidget IMPORT gtk_widget_set_vexpand, gtk_widget_set_halign,
+   gtk_widget_set_valign, gtk_widget_set_margin_top,
+   gtk_widget_set_margin_end;
+FROM GtkFrame IMPORT gtk_frame_new, gtk_frame_set_child;
+FROM GtkExpander IMPORT gtk_expander_new, gtk_expander_set_child,
+   gtk_expander_set_expanded;
+FROM GtkPaned IMPORT gtk_paned_new, gtk_paned_set_start_child,
+   gtk_paned_set_end_child, gtk_paned_set_position;
+FROM GtkOverlay IMPORT gtk_overlay_new, gtk_overlay_set_child,
+   gtk_overlay_add_overlay;
+FROM GtkListBox IMPORT gtk_list_box_new, gtk_list_box_append,
+   gtk_list_box_row_new, gtk_list_box_row_set_child,
+   gtk_list_box_row_get_index, gtk_list_box_set_selection_mode;
+FROM GtkClosures IMPORT Connect2, Connect3;
+FROM GtkUtils IMPORT IntToStr, StrAppend;
+FROM SYSTEM IMPORT ADDRESS;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.Layouts";
+
+VAR
+   status: ADDRESS;
+
+(* 3-argument: "row-activated" carries the GtkListBoxRow *)
+PROCEDURE OnRowActivated (listbox: ADDRESS; row: ADDRESS; user: ADDRESS);
+VAR
+   buf: ARRAY [0..15] OF CHAR;
+   line: ARRAY [0..63] OF CHAR;
+BEGIN
+   line[0] := 0C;
+   StrAppend(line, "activated row ");
+   IntToStr(gtk_list_box_row_get_index(row), buf);
+   StrAppend(line, buf);
+   gtk_label_set_text(status, line)
+END OnRowActivated;
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   window, box, paned, frame, expander, overlay, overlayLabel,
+   listbox, row: ADDRESS;
+   i: INTEGER;
+   text: ARRAY [0..15] OF CHAR;
+BEGIN
+   status := gtk_label_new("Select a row");
+
+   (* start pane: frame > expander > label *)
+   expander := gtk_expander_new("Details");
+   gtk_expander_set_child(expander, gtk_label_new("Collapsible content"));
+   gtk_expander_set_expanded(expander, 1);
+   frame := gtk_frame_new("Left pane");
+   gtk_frame_set_child(frame, expander);
+
+   (* end pane: overlay > list box, plus a top-right corner label *)
+   listbox := gtk_list_box_new();
+   gtk_list_box_set_selection_mode(listbox, GtkSelectionSingle);
+   FOR i := 0 TO 4 DO
+      IntToStr(i, text);
+      row := gtk_list_box_row_new();
+      gtk_list_box_row_set_child(row, gtk_label_new(text));
+      gtk_list_box_append(listbox, row)
+   END;
+
+   overlayLabel := gtk_label_new("overlay");
+   overlay := gtk_overlay_new();
+   gtk_overlay_set_child(overlay, listbox);
+   gtk_overlay_add_overlay(overlay, overlayLabel);
+   gtk_widget_set_halign(overlayLabel, GtkAlignEnd);
+   gtk_widget_set_valign(overlayLabel, GtkAlignStart);
+   gtk_widget_set_margin_top(overlayLabel, 8);
+   gtk_widget_set_margin_end(overlayLabel, 8);
+
+   paned := gtk_paned_new(GtkHorizontal);
+   gtk_paned_set_start_child(paned, frame);
+   gtk_paned_set_end_child(paned, overlay);
+   gtk_paned_set_position(paned, 180);
+   gtk_widget_set_vexpand(paned, 1);
+
+   Connect3(listbox, "row-activated", OnRowActivated, NIL);
+
+   box := gtk_box_new(GtkVertical, 8);
+   gtk_box_append(box, paned);
+   gtk_box_append(box, status);
+
+   window := gtk_application_window_new(application);
+   gtk_window_set_title(window, "m2-GTK4 Layouts");
+   gtk_window_set_default_size(window, 520, 340);
+   gtk_window_set_child(window, box);
+   gtk_window_present(window)
+END OnActivate;
+
+VAR
+   app: ADDRESS;
+BEGIN
+   app := gtk_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("gtk_application_new failed\n");
+      HALT(1)
+   END;
+   Connect2(app, "activate", OnActivate, NIL);
+   g_application_run(app, 0, NIL)
+END layouts.

+ 202 - 0
examples/views.mod

@@ -0,0 +1,202 @@
+MODULE views ;
+
+(*
+   m2-GTK4 example - model-backed views.
+
+   One GListStore of strings feeds three views in a GtkNotebook:
+     List    - GtkListView with a GtkSingleSelection; the selected item
+               is reported in a status label ("notify::selected")
+     Grid    - GtkGridView (display only)
+     Columns - GtkColumnView with "Name" and "#" columns
+
+   Build:  make examples
+   Run:    ./build/examples/views
+*)
+
+FROM Gio IMPORT g_application_run;
+FROM GtkApplication IMPORT gtk_application_new;
+FROM GtkApplicationWindow IMPORT gtk_application_window_new;
+FROM GtkWindow IMPORT gtk_window_set_title, gtk_window_set_default_size,
+   gtk_window_set_child, gtk_window_present;
+FROM GtkBox IMPORT gtk_box_new, gtk_box_append;
+FROM GtkEnums IMPORT GtkVertical;
+FROM GtkNotebook IMPORT gtk_notebook_new, gtk_notebook_append_page;
+FROM GtkLabel IMPORT gtk_label_new, gtk_label_set_text;
+FROM GtkScrolledWindow IMPORT gtk_scrolled_window_new,
+   gtk_scrolled_window_set_child;
+FROM GListStore IMPORT g_list_store_new, g_list_store_append;
+FROM GListModel IMPORT g_list_model_get_item;
+FROM GtkStringObject IMPORT gtk_string_object_new,
+   gtk_string_object_get_string, gtk_string_object_get_type;
+FROM GtkSignalListItemFactory IMPORT gtk_signal_list_item_factory_new;
+FROM GtkListItem IMPORT gtk_list_item_get_item, gtk_list_item_get_child,
+   gtk_list_item_set_child;
+FROM GtkColumnViewCell IMPORT gtk_column_view_cell_get_item,
+   gtk_column_view_cell_get_child, gtk_column_view_cell_set_child,
+   gtk_column_view_cell_get_position;
+FROM GtkSingleSelection IMPORT gtk_single_selection_new,
+   gtk_single_selection_get_selected;
+FROM GtkNoSelection IMPORT gtk_no_selection_new;
+FROM GtkListView IMPORT gtk_list_view_new;
+FROM GtkGridView IMPORT gtk_grid_view_new, gtk_grid_view_set_max_columns;
+FROM GtkColumnView IMPORT gtk_column_view_new, gtk_column_view_append_column;
+FROM GtkColumnViewColumn IMPORT gtk_column_view_column_new;
+FROM GObject IMPORT g_object_unref;
+FROM GtkClosures IMPORT Connect2, Connect3;
+FROM GtkUtils IMPORT CStrToM2, StrAppend, IntToStr;
+FROM SYSTEM IMPORT ADDRESS, ADR;
+FROM libc IMPORT printf;
+
+CONST
+   AppId = "org.example.m2gtk4.Views";
+   InvalidListPosition = 0FFFFFFFFH;
+
+VAR
+   store, selection, status: ADDRESS;
+
+(* --- list / grid label factory --- *)
+
+PROCEDURE RowSetup (factory: ADDRESS; item: ADDRESS; user: ADDRESS);
+BEGIN
+   gtk_list_item_set_child(item, gtk_label_new(""))
+END RowSetup;
+
+PROCEDURE RowBind (factory: ADDRESS; item: ADDRESS; user: ADDRESS);
+VAR
+   obj, child: ADDRESS;
+   buf: ARRAY [0..63] OF CHAR;
+BEGIN
+   obj := gtk_list_item_get_item(item);
+   CStrToM2(gtk_string_object_get_string(obj), buf);
+   child := gtk_list_item_get_child(item);
+   gtk_label_set_text(child, buf)
+END RowBind;
+
+(* --- column factories (cells) --- *)
+
+PROCEDURE CellSetup (factory: ADDRESS; cell: ADDRESS; user: ADDRESS);
+BEGIN
+   gtk_column_view_cell_set_child(cell, gtk_label_new(""))
+END CellSetup;
+
+PROCEDURE NameBind (factory: ADDRESS; cell: ADDRESS; user: ADDRESS);
+VAR
+   obj, child: ADDRESS;
+   buf: ARRAY [0..63] OF CHAR;
+BEGIN
+   obj := gtk_column_view_cell_get_item(cell);
+   CStrToM2(gtk_string_object_get_string(obj), buf);
+   child := gtk_column_view_cell_get_child(cell);
+   gtk_label_set_text(child, buf)
+END NameBind;
+
+PROCEDURE PositionBind (factory: ADDRESS; cell: ADDRESS; user: ADDRESS);
+VAR
+   child: ADDRESS;
+   buf: ARRAY [0..15] OF CHAR;
+BEGIN
+   child := gtk_column_view_cell_get_child(cell);
+   IntToStr(gtk_column_view_cell_get_position(cell), buf);
+   gtk_label_set_text(child, buf)
+END PositionBind;
+
+(* --- selection --- *)
+
+PROCEDURE OnSelected (model: ADDRESS; pspec: ADDRESS; user: ADDRESS);
+VAR
+   index: CARDINAL;
+   item: ADDRESS;
+   buf: ARRAY [0..63] OF CHAR;
+   line: ARRAY [0..127] OF CHAR;
+BEGIN
+   line[0] := 0C;
+   index := gtk_single_selection_get_selected(selection);
+   IF index = InvalidListPosition THEN
+      StrAppend(line, "Selected: (none)")
+   ELSE
+      StrAppend(line, "Selected: ");
+      item := g_list_model_get_item(store, index);
+      CStrToM2(gtk_string_object_get_string(item), buf);
+      g_object_unref(item);
+      StrAppend(line, buf)
+   END;
+   gtk_label_set_text(status, line)
+END OnSelected;
+
+PROCEDURE Scrolled (child: ADDRESS) : ADDRESS;
+VAR
+   sw: ADDRESS;
+BEGIN
+   sw := gtk_scrolled_window_new();
+   gtk_scrolled_window_set_child(sw, child);
+   RETURN sw
+END Scrolled;
+
+PROCEDURE OnActivate (application: ADDRESS; data: ADDRESS);
+VAR
+   window, box, notebook, factory, colFactory, listView, gridView,
+   columnView, nameColumn, posColumn: ADDRESS;
+BEGIN
+   store := g_list_store_new(gtk_string_object_get_type());
+   g_list_store_append(store, gtk_string_object_new("Apple"));
+   g_list_store_append(store, gtk_string_object_new("Banana"));
+   g_list_store_append(store, gtk_string_object_new("Cherry"));
+   g_list_store_append(store, gtk_string_object_new("Damson"));
+   g_list_store_append(store, gtk_string_object_new("Elderberry"));
+
+   factory := gtk_signal_list_item_factory_new();
+   Connect3(factory, "setup", RowSetup, NIL);
+   Connect3(factory, "bind", RowBind, NIL);
+
+   colFactory := gtk_signal_list_item_factory_new();
+   Connect3(colFactory, "setup", CellSetup, NIL);
+   Connect3(colFactory, "bind", NameBind, NIL);
+
+   (* list page *)
+   selection := gtk_single_selection_new(store);
+   Connect3(selection, "notify::selected", OnSelected, NIL);
+   listView := gtk_list_view_new(selection, factory);
+
+   (* grid page *)
+   gridView := gtk_grid_view_new(gtk_no_selection_new(store), factory);
+   gtk_grid_view_set_max_columns(gridView, 3);
+
+   (* columns page *)
+   columnView := gtk_column_view_new(gtk_no_selection_new(store));
+   nameColumn := gtk_column_view_column_new("Name", colFactory);
+   posColumn := gtk_column_view_column_new("#", factory);
+   gtk_column_view_append_column(columnView, nameColumn);
+   gtk_column_view_append_column(columnView, posColumn);
+
+   notebook := gtk_notebook_new();
+   gtk_notebook_append_page(notebook, Scrolled(listView),
+                            gtk_label_new("List"));
+   gtk_notebook_append_page(notebook, Scrolled(gridView),
+                            gtk_label_new("Grid"));
+   gtk_notebook_append_page(notebook, Scrolled(columnView),
+                            gtk_label_new("Columns"));
+
+   status := gtk_label_new("Selected: (none)");
+
+   box := gtk_box_new(GtkVertical, 8);
+   gtk_box_append(box, notebook);
+   gtk_box_append(box, status);
+
+   window := gtk_application_window_new(application);
+   gtk_window_set_title(window, "m2-GTK4 Views");
+   gtk_window_set_default_size(window, 460, 360);
+   gtk_window_set_child(window, box);
+   gtk_window_present(window)
+END OnActivate;
+
+VAR
+   app: ADDRESS;
+BEGIN
+   app := gtk_application_new(AppId, 0);
+   IF app = NIL THEN
+      printf("gtk_application_new failed\n");
+      HALT(1)
+   END;
+   Connect2(app, "activate", OnActivate, NIL);
+   g_application_run(app, 0, NIL)
+END views.

+ 68 - 0
lib/GtkClosures.def

@@ -0,0 +1,68 @@
+DEFINITION MODULE GtkClosures ;
+
+(*
+   m2-GTK4 - per-connection signal closures.
+
+   GObject signals carry a single gpointer of user data.  This module
+   allocates a small context for each connection, stores the handler and
+   the user payload in it, and installs a trampoline as the C callback.
+   When the connection is removed - explicitly with
+   g_signal_handler_disconnect(), or implicitly when the GObject is
+   finalized - the optional destroy procedure runs and the context is
+   freed.  Every connection therefore owns its own state and cleans up
+   after itself.
+
+   Handlers receive exactly the payload passed to Connect*; recover the
+   typed state with SYSTEM.CAST:
+
+      PROCEDURE OnClick (button, user: ADDRESS);
+      VAR state: State;
+      BEGIN state := CAST(State, user); ... END OnClick;
+      ...
+      Connect2(button, "clicked", OnClick, CAST(ADDRESS, state));
+
+   ISO dialect required
+   --------------------
+   This module (and therefore the whole build) uses -fiso: CAST comes
+   from ISO's SYSTEM, and NEW/DISPOSE need ALLOCATE/DEALLOCATE from the
+   ISO Storage module.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   Handler2, Handler3, DestroyProc,
+   Connect2, Connect3, Connect2Owned, Connect3Owned;
+
+TYPE
+   (* void handler(instance, user_data)
+      e.g. GtkButton "clicked". *)
+   Handler2 = PROCEDURE (ADDRESS, ADDRESS);
+
+   (* void handler(instance, parameter, user_data)
+      e.g. GAction "activate"/"change-state", GObject "notify". *)
+   Handler3 = PROCEDURE (ADDRESS, ADDRESS, ADDRESS);
+
+   (* void destroy(user_data) - release the payload when the connection
+      goes away; pass NIL when the payload is not owned. *)
+   DestroyProc = PROCEDURE (ADDRESS);
+
+(* Connect a 2-argument handler; the payload is not owned. *)
+PROCEDURE Connect2 (instance: ADDRESS; signal: ARRAY OF CHAR;
+                    handler: Handler2; user: ADDRESS) : [ LONGCARD ];
+
+(* Connect a 3-argument handler; the payload is not owned. *)
+PROCEDURE Connect3 (instance: ADDRESS; signal: ARRAY OF CHAR;
+                    handler: Handler3; user: ADDRESS) : [ LONGCARD ];
+
+(* As Connect2, but destroy(user) runs when the connection is removed. *)
+PROCEDURE Connect2Owned (instance: ADDRESS; signal: ARRAY OF CHAR;
+                         handler: Handler2; user: ADDRESS;
+                         destroy: DestroyProc) : [ LONGCARD ];
+
+(* As Connect3, but destroy(user) runs when the connection is removed. *)
+PROCEDURE Connect3Owned (instance: ADDRESS; signal: ARRAY OF CHAR;
+                         handler: Handler3; user: ADDRESS;
+                         destroy: DestroyProc) : [ LONGCARD ];
+
+END GtkClosures.

+ 114 - 0
lib/GtkClosures.mod

@@ -0,0 +1,114 @@
+IMPLEMENTATION MODULE GtkClosures ;
+
+(*
+   Each connection gets a Context holding the handler, the user payload
+   and an optional destroy procedure.  Two trampolines (2-argument and
+   3-argument) recover the Context from their pointer parameter and
+   forward the call.  DestroyCtx is registered as the GClosure destroy
+   notify, so it runs on both explicit disconnect and object finalize.
+
+   Trampoline parameters are typed pointers (ContextPtr), so the C
+   gpointer is received without a CAST on the hot path.
+*)
+
+FROM SYSTEM IMPORT ADDRESS, CAST, ADR;
+FROM Storage IMPORT ALLOCATE, DEALLOCATE;
+FROM GObject IMPORT g_signal_connect_data, GConnectDefault;
+
+TYPE
+   Context = RECORD
+      user: ADDRESS;
+      destroy: DestroyProc;
+      h2: Handler2;
+      h3: Handler3;
+   END;
+   ContextPtr = POINTER TO Context;
+
+PROCEDURE Tramp2 (instance: ADDRESS; ctx: ContextPtr);
+BEGIN
+   ctx^.h2(instance, ctx^.user)
+END Tramp2;
+
+PROCEDURE Tramp3 (instance: ADDRESS; param: ADDRESS; ctx: ContextPtr);
+BEGIN
+   ctx^.h3(instance, param, ctx^.user)
+END Tramp3;
+
+PROCEDURE DestroyCtx (ctx: ContextPtr; closure: ADDRESS);
+BEGIN
+   IF ctx # NIL THEN
+      IF ctx^.destroy # NIL THEN
+         ctx^.destroy(ctx^.user)
+      END;
+      DISPOSE(ctx)
+   END
+END DestroyCtx;
+
+PROCEDURE NewCtx () : ContextPtr;
+VAR
+   ctx: ContextPtr;
+BEGIN
+   NEW(ctx);
+   ctx^.user := NIL;
+   ctx^.destroy := NIL;
+   ctx^.h2 := NIL;
+   ctx^.h3 := NIL;
+   RETURN ctx
+END NewCtx;
+
+PROCEDURE RawConnect (instance: ADDRESS; signal: ARRAY OF CHAR;
+                      ctx: ContextPtr; tramp: ADDRESS) : [ LONGCARD ];
+BEGIN
+   RETURN g_signal_connect_data(instance, signal, tramp, CAST(ADDRESS, ctx),
+                                ADR(DestroyCtx), GConnectDefault)
+END RawConnect;
+
+PROCEDURE Connect2 (instance: ADDRESS; signal: ARRAY OF CHAR;
+                    handler: Handler2; user: ADDRESS) : [ LONGCARD ];
+VAR
+   ctx: ContextPtr;
+BEGIN
+   ctx := NewCtx();
+   ctx^.h2 := handler;
+   ctx^.user := user;
+   RETURN RawConnect(instance, signal, ctx, ADR(Tramp2))
+END Connect2;
+
+PROCEDURE Connect3 (instance: ADDRESS; signal: ARRAY OF CHAR;
+                    handler: Handler3; user: ADDRESS) : [ LONGCARD ];
+VAR
+   ctx: ContextPtr;
+BEGIN
+   ctx := NewCtx();
+   ctx^.h3 := handler;
+   ctx^.user := user;
+   RETURN RawConnect(instance, signal, ctx, ADR(Tramp3))
+END Connect3;
+
+PROCEDURE Connect2Owned (instance: ADDRESS; signal: ARRAY OF CHAR;
+                         handler: Handler2; user: ADDRESS;
+                         destroy: DestroyProc) : [ LONGCARD ];
+VAR
+   ctx: ContextPtr;
+BEGIN
+   ctx := NewCtx();
+   ctx^.h2 := handler;
+   ctx^.user := user;
+   ctx^.destroy := destroy;
+   RETURN RawConnect(instance, signal, ctx, ADR(Tramp2))
+END Connect2Owned;
+
+PROCEDURE Connect3Owned (instance: ADDRESS; signal: ARRAY OF CHAR;
+                         handler: Handler3; user: ADDRESS;
+                         destroy: DestroyProc) : [ LONGCARD ];
+VAR
+   ctx: ContextPtr;
+BEGIN
+   ctx := NewCtx();
+   ctx^.h3 := handler;
+   ctx^.user := user;
+   ctx^.destroy := destroy;
+   RETURN RawConnect(instance, signal, ctx, ADR(Tramp3))
+END Connect3Owned;
+
+END GtkClosures.

+ 59 - 0
lib/GtkUtils.def

@@ -0,0 +1,59 @@
+DEFINITION MODULE GtkUtils ;
+
+(*
+   m2-GTK4 - small pure-Modula-2 helpers over the FOR "C" bindings.
+
+   CStrToM2   copies a borrowed NUL-terminated C string (ADDRESS) into
+              a Modula-2 CHAR array.  The destination is always
+              NUL-terminated and the copy is truncated to fit.
+   StrAppend  appends a NUL-terminated string onto the end of another,
+              truncating to fit and keeping it NUL-terminated.
+   IntToStr   renders an INTEGER as a decimal string.
+   Connect    wraps GObject.g_signal_connect_data() with the defaults
+              C's g_signal_connect() macro would use, returning the
+              handler id so it can be disconnected later.
+   SetAccel   installs one keyboard accelerator for a detailed action
+              name (e.g. SetAccel(app, "app.quit", "<primary>q")).
+              C wants a NULL-terminated array of strings, which this
+              builds on the stack and passes to
+              gtk_application_set_accels_for_action().
+   Unref      releases a GObject reference (NIL-checked).
+   Free       releases memory from g_malloc/g_strdup/... (NIL-checked).
+   ErrorMessage copies a GError's message into a CHAR array.
+   ClearError frees a GError and sets the variable to NIL.
+
+   Connect is a real procedure (not a C binding): pass the handler as
+   ADR(proc), e.g.
+
+      Connect(button, "clicked", ADR(OnClicked), NIL);
+
+   Ownership
+   ---------
+   Modula-2 has no destructors, so follow the C transfer rules:
+     * GtkUtils.Unref (g_object_unref) for GObject handles;
+     * GtkUtils.Free (g_free) for strings returned by getters
+       (g_file_get_basename, g_settings_get_string, ...);
+     * GtkUtils.ClearError for GError values;
+     * GVariant values from g_variant_get_*/g_action_get_state need
+       g_variant_unref, while g_variant_new_* are floating.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+FROM GError IMPORT GError;
+
+EXPORT UNQUALIFIED CStrToM2, StrAppend, IntToStr, Connect, SetAccel,
+   Unref, Free, ErrorMessage, ClearError;
+
+PROCEDURE CStrToM2 (src: ADDRESS; VAR dst: ARRAY OF CHAR);
+PROCEDURE StrAppend (VAR dst: ARRAY OF CHAR; src: ARRAY OF CHAR);
+PROCEDURE IntToStr (n: INTEGER; VAR dst: ARRAY OF CHAR);
+PROCEDURE Connect (instance: ADDRESS; signal: ARRAY OF CHAR;
+                   handler: ADDRESS; data: ADDRESS) : [ LONGCARD ];
+PROCEDURE SetAccel (application: ADDRESS; action: ARRAY OF CHAR;
+                    accel: ARRAY OF CHAR);
+PROCEDURE Unref (obj: ADDRESS);
+PROCEDURE Free (ptr: ADDRESS);
+PROCEDURE ErrorMessage (err: GError; VAR dst: ARRAY OF CHAR);
+PROCEDURE ClearError (VAR err: GError);
+
+END GtkUtils.

+ 129 - 0
lib/GtkUtils.mod

@@ -0,0 +1,129 @@
+IMPLEMENTATION MODULE GtkUtils ;
+
+(*
+   Implementation notes
+   --------------------
+   CStrToM2 uses libc strncpy(): when the source is shorter than the
+   buffer strncpy() pads with NUL, and we force the last byte to NUL so
+   the result is always terminated.  This avoids pointer walking (gm2
+   has no pointer arithmetic) and any CAST between integer sizes.
+
+   IntToStr works on a LONGINT so that the magnitude of MIN(INTEGER)
+   is representable, then reverses the digits into the caller buffer.
+*)
+
+FROM SYSTEM IMPORT ADDRESS, ADR;
+FROM libc IMPORT strncpy;
+FROM GObject IMPORT g_signal_connect_data, GConnectDefault, g_object_unref;
+FROM GLib IMPORT g_free;
+FROM GError IMPORT GError, g_error_free;
+FROM GtkApplication IMPORT gtk_application_set_accels_for_action;
+
+PROCEDURE CStrToM2 (src: ADDRESS; VAR dst: ARRAY OF CHAR);
+BEGIN
+   IF src = NIL THEN
+      dst[0] := 0C;
+      RETURN
+   END;
+   strncpy(ADR(dst), src, HIGH(dst) + 1);
+   dst[HIGH(dst)] := 0C
+END CStrToM2;
+
+PROCEDURE StrAppend (VAR dst: ARRAY OF CHAR; src: ARRAY OF CHAR);
+VAR
+   i, j: CARDINAL;
+BEGIN
+   (* locate the current end of dst *)
+   i := 0;
+   WHILE (i <= HIGH(dst)) AND (dst[i] # 0C) DO
+      INC(i)
+   END;
+
+   (* append src, leaving room for the terminator *)
+   j := 0;
+   WHILE (i < HIGH(dst)) AND (j <= HIGH(src)) AND (src[j] # 0C) DO
+      dst[i] := src[j];
+      INC(i);
+      INC(j)
+   END;
+   IF i <= HIGH(dst) THEN dst[i] := 0C ELSE dst[HIGH(dst)] := 0C END
+END StrAppend;
+
+PROCEDURE IntToStr (n: INTEGER; VAR dst: ARRAY OF CHAR);
+VAR
+   digits: ARRAY [0..31] OF CHAR;
+   v: INTEGER;
+   i, j: CARDINAL;
+   negative: BOOLEAN;
+BEGIN
+   v := n;
+   negative := v < 0;
+   IF negative THEN v := -v END;
+
+   (* collect digits least-significant first *)
+   i := 0;
+   REPEAT
+      digits[i] := CHR(ORD('0') + CARDINAL(v MOD 10));
+      v := v DIV 10;
+      INC(i)
+   UNTIL v = 0;
+   IF negative THEN
+      digits[i] := '-';
+      INC(i)
+   END;
+
+   (* reverse into dst *)
+   j := 0;
+   WHILE (i > 0) AND (j <= HIGH(dst)) DO
+      DEC(i);
+      dst[j] := digits[i];
+      INC(j)
+   END;
+   IF j <= HIGH(dst) THEN dst[j] := 0C ELSE dst[HIGH(dst)] := 0C END
+END IntToStr;
+
+PROCEDURE Connect (instance: ADDRESS; signal: ARRAY OF CHAR;
+                   handler: ADDRESS; data: ADDRESS) : [ LONGCARD ];
+BEGIN
+   RETURN g_signal_connect_data(instance, signal, handler, data, NIL,
+                                GConnectDefault)
+END Connect;
+
+PROCEDURE SetAccel (application: ADDRESS; action: ARRAY OF CHAR;
+                    accel: ARRAY OF CHAR);
+VAR
+   accels: ARRAY [0..1] OF ADDRESS;
+BEGIN
+   accels[0] := ADR(accel);
+   accels[1] := NIL;
+   gtk_application_set_accels_for_action(application, action, ADR(accels))
+END SetAccel;
+
+PROCEDURE Unref (obj: ADDRESS);
+BEGIN
+   IF obj # NIL THEN g_object_unref(obj) END
+END Unref;
+
+PROCEDURE Free (ptr: ADDRESS);
+BEGIN
+   IF ptr # NIL THEN g_free(ptr) END
+END Free;
+
+PROCEDURE ErrorMessage (err: GError; VAR dst: ARRAY OF CHAR);
+BEGIN
+   IF err = NIL THEN
+      dst[0] := 0C
+   ELSE
+      CStrToM2(err^.message, dst)
+   END
+END ErrorMessage;
+
+PROCEDURE ClearError (VAR err: GError);
+BEGIN
+   IF err # NIL THEN
+      g_error_free(err);
+      err := NIL
+   END
+END ClearError;
+
+END GtkUtils.

+ 148 - 0
src/AdwAboutWindow.def

@@ -0,0 +1,148 @@
+DEFINITION MODULE FOR "C" AdwAboutWindow ;
+
+(*
+   m2-GTK4 - AdwAboutWindow: the Adwaita about dialog.  Mapped onto
+   <libadwaita-1/adw-about-window.h>.
+
+   It derives from GtkWindow; create it, fill in the fields, then
+   gtk_window_present() it.  add_credit_section()/add_link() take
+   NULL-terminated arrays of strings for the people/URLs.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwAboutWindow,
+   adw_about_window_new, adw_about_window_new_from_appdata,
+   adw_about_window_set_application_name,
+   adw_about_window_get_application_name,
+   adw_about_window_set_application_icon,
+   adw_about_window_set_version, adw_about_window_get_version,
+   adw_about_window_set_developer_name, adw_about_window_get_developer_name,
+   adw_about_window_set_comments, adw_about_window_get_comments,
+   adw_about_window_set_website, adw_about_window_get_website,
+   adw_about_window_set_issue_url, adw_about_window_get_issue_url,
+   adw_about_window_set_support_url, adw_about_window_get_support_url,
+   adw_about_window_set_copyright, adw_about_window_get_copyright,
+   adw_about_window_set_license, adw_about_window_get_license,
+   adw_about_window_set_license_type, adw_about_window_get_license_type,
+   adw_about_window_add_link, adw_about_window_add_credit_section,
+   adw_about_window_add_acknowledgement_section,
+   adw_about_window_set_release_notes,
+   adw_about_window_set_release_notes_version;
+
+
+TYPE
+   AdwAboutWindow = ADDRESS;
+
+(* GtkWidget *adw_about_window_new(void) *)
+PROCEDURE adw_about_window_new () : AdwAboutWindow;
+
+(* GtkWidget *adw_about_window_new_from_appdata(const char *resource_path,
+                                                 const char *release_notes_version) *)
+PROCEDURE adw_about_window_new_from_appdata (resource_path: ARRAY OF CHAR;
+                                             release_notes_version: ARRAY OF CHAR) : AdwAboutWindow;
+
+(* void adw_about_window_set_application_name(AdwAboutWindow *self, const char *application_name) *)
+PROCEDURE adw_about_window_set_application_name (self: AdwAboutWindow;
+                                                 application_name: ARRAY OF CHAR);
+
+(* const char *adw_about_window_get_application_name(AdwAboutWindow *self) *)
+PROCEDURE adw_about_window_get_application_name (self: AdwAboutWindow) : ADDRESS;
+
+(* void adw_about_window_set_application_icon(AdwAboutWindow *self, const char *application_icon) *)
+PROCEDURE adw_about_window_set_application_icon (self: AdwAboutWindow;
+                                                 application_icon: ARRAY OF CHAR);
+
+(* void adw_about_window_set_version(AdwAboutWindow *self, const char *version) *)
+PROCEDURE adw_about_window_set_version (self: AdwAboutWindow;
+                                        version: ARRAY OF CHAR);
+
+(* const char *adw_about_window_get_version(AdwAboutWindow *self) *)
+PROCEDURE adw_about_window_get_version (self: AdwAboutWindow) : ADDRESS;
+
+(* void adw_about_window_set_developer_name(AdwAboutWindow *self, const char *developer_name) *)
+PROCEDURE adw_about_window_set_developer_name (self: AdwAboutWindow;
+                                               developer_name: ARRAY OF CHAR);
+
+(* const char *adw_about_window_get_developer_name(AdwAboutWindow *self) *)
+PROCEDURE adw_about_window_get_developer_name (self: AdwAboutWindow) : ADDRESS;
+
+(* void adw_about_window_set_comments(AdwAboutWindow *self, const char *comments) *)
+PROCEDURE adw_about_window_set_comments (self: AdwAboutWindow;
+                                         comments: ARRAY OF CHAR);
+
+(* const char *adw_about_window_get_comments(AdwAboutWindow *self) *)
+PROCEDURE adw_about_window_get_comments (self: AdwAboutWindow) : ADDRESS;
+
+(* void adw_about_window_set_website(AdwAboutWindow *self, const char *website) *)
+PROCEDURE adw_about_window_set_website (self: AdwAboutWindow;
+                                        website: ARRAY OF CHAR);
+
+(* const char *adw_about_window_get_website(AdwAboutWindow *self) *)
+PROCEDURE adw_about_window_get_website (self: AdwAboutWindow) : ADDRESS;
+
+(* void adw_about_window_set_issue_url(AdwAboutWindow *self, const char *issue_url) *)
+PROCEDURE adw_about_window_set_issue_url (self: AdwAboutWindow;
+                                          issue_url: ARRAY OF CHAR);
+
+(* const char *adw_about_window_get_issue_url(AdwAboutWindow *self) *)
+PROCEDURE adw_about_window_get_issue_url (self: AdwAboutWindow) : ADDRESS;
+
+(* void adw_about_window_set_support_url(AdwAboutWindow *self, const char *support_url) *)
+PROCEDURE adw_about_window_set_support_url (self: AdwAboutWindow;
+                                            support_url: ARRAY OF CHAR);
+
+(* const char *adw_about_window_get_support_url(AdwAboutWindow *self) *)
+PROCEDURE adw_about_window_get_support_url (self: AdwAboutWindow) : ADDRESS;
+
+(* void adw_about_window_set_copyright(AdwAboutWindow *self, const char *copyright) *)
+PROCEDURE adw_about_window_set_copyright (self: AdwAboutWindow;
+                                          copyright: ARRAY OF CHAR);
+
+(* const char *adw_about_window_get_copyright(AdwAboutWindow *self) *)
+PROCEDURE adw_about_window_get_copyright (self: AdwAboutWindow) : ADDRESS;
+
+(* void adw_about_window_set_license(AdwAboutWindow *self, const char *license) *)
+PROCEDURE adw_about_window_set_license (self: AdwAboutWindow;
+                                        license: ARRAY OF CHAR);
+
+(* const char *adw_about_window_get_license(AdwAboutWindow *self) *)
+PROCEDURE adw_about_window_get_license (self: AdwAboutWindow) : ADDRESS;
+
+(* void adw_about_window_set_license_type(AdwAboutWindow *self,
+                                           AdwLicense license_type) *)
+PROCEDURE adw_about_window_set_license_type (self: AdwAboutWindow;
+                                             license_type: CARDINAL);
+
+(* AdwLicense adw_about_window_get_license_type(AdwAboutWindow *self) *)
+PROCEDURE adw_about_window_get_license_type (self: AdwAboutWindow) : CARDINAL;
+
+(* void adw_about_window_add_link(AdwAboutWindow *self, const char *title,
+                                   const char *url) *)
+PROCEDURE adw_about_window_add_link (self: AdwAboutWindow;
+                                     title, url: ARRAY OF CHAR);
+
+(* void adw_about_window_add_credit_section(AdwAboutWindow *self,
+                                             const char *name, const char * const *people) *)
+PROCEDURE adw_about_window_add_credit_section (self: AdwAboutWindow;
+                                               name: ARRAY OF CHAR;
+                                               people: ADDRESS);
+
+(* void adw_about_window_add_acknowledgement_section(AdwAboutWindow *self,
+                                                      const char *name,
+                                                      const char * const *people) *)
+PROCEDURE adw_about_window_add_acknowledgement_section (self: AdwAboutWindow;
+                                                        name: ARRAY OF CHAR;
+                                                        people: ADDRESS);
+
+(* void adw_about_window_set_release_notes(AdwAboutWindow *self, const char *release_notes) *)
+PROCEDURE adw_about_window_set_release_notes (self: AdwAboutWindow;
+                                              release_notes: ARRAY OF CHAR);
+
+(* void adw_about_window_set_release_notes_version(AdwAboutWindow *self,
+                                                     const char *version) *)
+PROCEDURE adw_about_window_set_release_notes_version (self: AdwAboutWindow;
+                                                      version: ARRAY OF CHAR);
+
+END AdwAboutWindow.

+ 82 - 0
src/AdwActionRow.def

@@ -0,0 +1,82 @@
+DEFINITION MODULE FOR "C" AdwActionRow ;
+
+(*
+   m2-GTK4 - AdwActionRow: a settings row with title, subtitle, icon and
+   child prefix/suffix widgets.  Mapped onto
+   <libadwaita-1/adw-action-row.h>.
+
+   The title comes from the parent, AdwPreferencesRow
+   (adw_preferences_row_set_title).  Signal: "activated",
+   void(AdwActionRow*, gpointer) - connect with GtkClosures.Connect2 and
+   make the row activatable.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwActionRow,
+   adw_action_row_new,
+   adw_action_row_add_prefix, adw_action_row_add_suffix,
+   adw_action_row_remove, adw_action_row_activate,
+   adw_action_row_set_subtitle, adw_action_row_get_subtitle,
+   adw_action_row_set_subtitle_lines, adw_action_row_get_subtitle_lines,
+   adw_action_row_set_title_lines, adw_action_row_get_title_lines,
+   adw_action_row_set_icon_name, adw_action_row_get_icon_name,
+   adw_action_row_set_activatable_widget,
+   adw_action_row_get_activatable_widget;
+
+
+TYPE
+   AdwActionRow = ADDRESS;
+
+(* GtkWidget *adw_action_row_new(void) *)
+PROCEDURE adw_action_row_new () : AdwActionRow;
+
+(* void adw_action_row_add_prefix(AdwActionRow *self, GtkWidget *widget) *)
+PROCEDURE adw_action_row_add_prefix (self: AdwActionRow; widget: ADDRESS);
+
+(* void adw_action_row_add_suffix(AdwActionRow *self, GtkWidget *widget) *)
+PROCEDURE adw_action_row_add_suffix (self: AdwActionRow; widget: ADDRESS);
+
+(* void adw_action_row_remove(AdwActionRow *self, GtkWidget *widget) *)
+PROCEDURE adw_action_row_remove (self: AdwActionRow; widget: ADDRESS);
+
+(* void adw_action_row_activate(AdwActionRow *self) *)
+PROCEDURE adw_action_row_activate (self: AdwActionRow);
+
+(* void adw_action_row_set_subtitle(AdwActionRow *self, const char *subtitle) *)
+PROCEDURE adw_action_row_set_subtitle (self: AdwActionRow;
+                                       subtitle: ARRAY OF CHAR);
+
+(* const char *adw_action_row_get_subtitle(AdwActionRow *self) *)
+PROCEDURE adw_action_row_get_subtitle (self: AdwActionRow) : ADDRESS;
+
+(* void adw_action_row_set_subtitle_lines(AdwActionRow *self, int subtitle_lines) *)
+PROCEDURE adw_action_row_set_subtitle_lines (self: AdwActionRow;
+                                             subtitle_lines: INTEGER);
+
+(* int adw_action_row_get_subtitle_lines(AdwActionRow *self) *)
+PROCEDURE adw_action_row_get_subtitle_lines (self: AdwActionRow) : INTEGER;
+
+(* void adw_action_row_set_title_lines(AdwActionRow *self, int title_lines) *)
+PROCEDURE adw_action_row_set_title_lines (self: AdwActionRow;
+                                          title_lines: INTEGER);
+
+(* int adw_action_row_get_title_lines(AdwActionRow *self) *)
+PROCEDURE adw_action_row_get_title_lines (self: AdwActionRow) : INTEGER;
+
+(* void adw_action_row_set_icon_name(AdwActionRow *self, const char *icon_name) *)
+PROCEDURE adw_action_row_set_icon_name (self: AdwActionRow;
+                                        icon_name: ARRAY OF CHAR);
+
+(* const char *adw_action_row_get_icon_name(AdwActionRow *self) *)
+PROCEDURE adw_action_row_get_icon_name (self: AdwActionRow) : ADDRESS;
+
+(* void adw_action_row_set_activatable_widget(AdwActionRow *self, GtkWidget *widget) *)
+PROCEDURE adw_action_row_set_activatable_widget (self: AdwActionRow;
+                                                 widget: ADDRESS);
+
+(* GtkWidget *adw_action_row_get_activatable_widget(AdwActionRow *self) *)
+PROCEDURE adw_action_row_get_activatable_widget (self: AdwActionRow) : ADDRESS;
+
+END AdwActionRow.

+ 27 - 0
src/AdwApplication.def

@@ -0,0 +1,27 @@
+DEFINITION MODULE FOR "C" AdwApplication ;
+
+(*
+   m2-GTK4 - AdwApplication: a GtkApplication that initialises
+   libadwaita (and its style manager).  Mapped onto
+   <libadwaita-1/adw-application.h>.
+
+   Create it with adw_application_new(id, flags) and drive it with
+   Gio.g_application_run(), exactly like a GtkApplication.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwApplication,
+   adw_application_new;
+
+
+TYPE
+   AdwApplication = ADDRESS;
+
+(* AdwApplication *adw_application_new(const char *application_id,
+                                       GApplicationFlags flags) *)
+PROCEDURE adw_application_new (application_id: ARRAY OF CHAR;
+                               flags: CARDINAL) : AdwApplication;
+
+END AdwApplication.

+ 34 - 0
src/AdwApplicationWindow.def

@@ -0,0 +1,34 @@
+DEFINITION MODULE FOR "C" AdwApplicationWindow ;
+
+(*
+   m2-GTK4 - AdwApplicationWindow: an Adw window that implements
+   GtkActionMap ("win." actions).  Mapped onto
+   <libadwaita-1/adw-application-window.h>.
+
+   It derives from GtkWindow, so all GtkWindow functions apply.  Put
+   content inside an AdwToolbarView and set that as the window content.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwApplicationWindow,
+   adw_application_window_new,
+   adw_application_window_set_content, adw_application_window_get_content;
+
+
+TYPE
+   AdwApplicationWindow = ADDRESS;
+
+(* GtkWidget *adw_application_window_new(GtkApplication *app) *)
+PROCEDURE adw_application_window_new (app: ADDRESS) : AdwApplicationWindow;
+
+(* void adw_application_window_set_content(AdwApplicationWindow *self,
+                                            GtkWidget *content) *)
+PROCEDURE adw_application_window_set_content (self: AdwApplicationWindow;
+                                              content: ADDRESS);
+
+(* GtkWidget *adw_application_window_get_content(AdwApplicationWindow *self) *)
+PROCEDURE adw_application_window_get_content (self: AdwApplicationWindow) : ADDRESS;
+
+END AdwApplicationWindow.

+ 52 - 0
src/AdwBanner.def

@@ -0,0 +1,52 @@
+DEFINITION MODULE FOR "C" AdwBanner ;
+
+(*
+   m2-GTK4 - AdwBanner: a dismissible info bar with a title and an
+   optional button.  Mapped onto <libadwaita-1/adw-banner.h>.
+
+   Signal: "button-clicked".  Usually placed as the first row of an
+   AdwPreferencesPage via set_banner().
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwBanner,
+   adw_banner_new,
+   adw_banner_set_title, adw_banner_get_title,
+   adw_banner_set_button_label, adw_banner_get_button_label,
+   adw_banner_set_revealed, adw_banner_get_revealed,
+   adw_banner_set_use_markup, adw_banner_set_button_style;
+
+
+TYPE
+   AdwBanner = ADDRESS;
+
+(* GtkWidget *adw_banner_new(const char *title) *)
+PROCEDURE adw_banner_new (title: ARRAY OF CHAR) : AdwBanner;
+
+(* void adw_banner_set_title(AdwBanner *self, const char *title) *)
+PROCEDURE adw_banner_set_title (self: AdwBanner; title: ARRAY OF CHAR);
+
+(* const char *adw_banner_get_title(AdwBanner *self) *)
+PROCEDURE adw_banner_get_title (self: AdwBanner) : ADDRESS;
+
+(* void adw_banner_set_button_label(AdwBanner *self, const char *label) *)
+PROCEDURE adw_banner_set_button_label (self: AdwBanner; label: ARRAY OF CHAR);
+
+(* const char *adw_banner_get_button_label(AdwBanner *self) *)
+PROCEDURE adw_banner_get_button_label (self: AdwBanner) : ADDRESS;
+
+(* void adw_banner_set_revealed(AdwBanner *self, gboolean revealed) *)
+PROCEDURE adw_banner_set_revealed (self: AdwBanner; revealed: INTEGER);
+
+(* gboolean adw_banner_get_revealed(AdwBanner *self) *)
+PROCEDURE adw_banner_get_revealed (self: AdwBanner) : [ INTEGER ];
+
+(* void adw_banner_set_use_markup(AdwBanner *self, gboolean use_markup) *)
+PROCEDURE adw_banner_set_use_markup (self: AdwBanner; use_markup: INTEGER);
+
+(* void adw_banner_set_button_style(AdwBanner *self, AdwBannerButtonStyle style) *)
+PROCEDURE adw_banner_set_button_style (self: AdwBanner; style: CARDINAL);
+
+END AdwBanner.

+ 44 - 0
src/AdwClamp.def

@@ -0,0 +1,44 @@
+DEFINITION MODULE FOR "C" AdwClamp ;
+
+(*
+   m2-GTK4 - AdwClamp: constrains its child to a maximum size and
+   centres it.  Mapped onto <libadwaita-1/adw-clamp.h>.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwClamp,
+   adw_clamp_new,
+   adw_clamp_set_child, adw_clamp_get_child,
+   adw_clamp_set_maximum_size, adw_clamp_get_maximum_size,
+   adw_clamp_set_tightening_threshold,
+   adw_clamp_get_tightening_threshold;
+
+
+TYPE
+   AdwClamp = ADDRESS;
+
+(* GtkWidget *adw_clamp_new(void) *)
+PROCEDURE adw_clamp_new () : AdwClamp;
+
+(* void adw_clamp_set_child(AdwClamp *self, GtkWidget *child) *)
+PROCEDURE adw_clamp_set_child (self: AdwClamp; child: ADDRESS);
+
+(* GtkWidget *adw_clamp_get_child(AdwClamp *self) *)
+PROCEDURE adw_clamp_get_child (self: AdwClamp) : ADDRESS;
+
+(* void adw_clamp_set_maximum_size(AdwClamp *self, int maximum_size) *)
+PROCEDURE adw_clamp_set_maximum_size (self: AdwClamp; maximum_size: INTEGER);
+
+(* int adw_clamp_get_maximum_size(AdwClamp *self) *)
+PROCEDURE adw_clamp_get_maximum_size (self: AdwClamp) : INTEGER;
+
+(* void adw_clamp_set_tightening_threshold(AdwClamp *self, int tightening_threshold) *)
+PROCEDURE adw_clamp_set_tightening_threshold (self: AdwClamp;
+                                              tightening_threshold: INTEGER);
+
+(* int adw_clamp_get_tightening_threshold(AdwClamp *self) *)
+PROCEDURE adw_clamp_get_tightening_threshold (self: AdwClamp) : INTEGER;
+
+END AdwClamp.

+ 58 - 0
src/AdwComboRow.def

@@ -0,0 +1,58 @@
+DEFINITION MODULE FOR "C" AdwComboRow ;
+
+(*
+   m2-GTK4 - AdwComboRow: a settings row with a drop-down.
+   Mapped onto <libadwaita-1/adw-combo-row.h>.
+
+   The model is a GListModel (e.g. a GtkStringList).  Title via
+   AdwPreferencesRow.  Signal: "notify::selected".
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwComboRow,
+   adw_combo_row_new,
+   adw_combo_row_set_model, adw_combo_row_get_model,
+   adw_combo_row_set_selected, adw_combo_row_get_selected,
+   adw_combo_row_get_selected_item,
+   adw_combo_row_set_enable_search, adw_combo_row_get_enable_search,
+   adw_combo_row_set_use_subtitle, adw_combo_row_get_use_subtitle;
+
+
+TYPE
+   AdwComboRow = ADDRESS;
+
+(* GtkWidget *adw_combo_row_new(void) *)
+PROCEDURE adw_combo_row_new () : AdwComboRow;
+
+(* void adw_combo_row_set_model(AdwComboRow *self, GListModel *model) *)
+PROCEDURE adw_combo_row_set_model (self: AdwComboRow; model: ADDRESS);
+
+(* GListModel *adw_combo_row_get_model(AdwComboRow *self) *)
+PROCEDURE adw_combo_row_get_model (self: AdwComboRow) : ADDRESS;
+
+(* void adw_combo_row_set_selected(AdwComboRow *self, guint position) *)
+PROCEDURE adw_combo_row_set_selected (self: AdwComboRow; position: CARDINAL);
+
+(* guint adw_combo_row_get_selected(AdwComboRow *self) *)
+PROCEDURE adw_combo_row_get_selected (self: AdwComboRow) : CARDINAL;
+
+(* GObject *adw_combo_row_get_selected_item(AdwComboRow *self) *)
+PROCEDURE adw_combo_row_get_selected_item (self: AdwComboRow) : ADDRESS;
+
+(* void adw_combo_row_set_enable_search(AdwComboRow *self, gboolean enable_search) *)
+PROCEDURE adw_combo_row_set_enable_search (self: AdwComboRow;
+                                           enable_search: INTEGER);
+
+(* gboolean adw_combo_row_get_enable_search(AdwComboRow *self) *)
+PROCEDURE adw_combo_row_get_enable_search (self: AdwComboRow) : [ INTEGER ];
+
+(* void adw_combo_row_set_use_subtitle(AdwComboRow *self, gboolean use_subtitle) *)
+PROCEDURE adw_combo_row_set_use_subtitle (self: AdwComboRow;
+                                          use_subtitle: INTEGER);
+
+(* gboolean adw_combo_row_get_use_subtitle(AdwComboRow *self) *)
+PROCEDURE adw_combo_row_get_use_subtitle (self: AdwComboRow) : [ INTEGER ];
+
+END AdwComboRow.

+ 68 - 0
src/AdwEntryRow.def

@@ -0,0 +1,68 @@
+DEFINITION MODULE FOR "C" AdwEntryRow ;
+
+(*
+   m2-GTK4 - AdwEntryRow: a settings row containing a text entry.
+   Mapped onto <libadwaita-1/adw-entry-row.h>.
+
+   AdwEntryRow implements GtkEditable, so use
+   gtk_editable_get_text()/gtk_editable_set_text() (GtkEditable.def) to
+   read and write the text.  Title via AdwPreferencesRow.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwEntryRow,
+   adw_entry_row_new,
+   adw_entry_row_add_prefix, adw_entry_row_add_suffix,
+   adw_entry_row_remove,
+   adw_entry_row_set_max_length, adw_entry_row_get_max_length,
+   adw_entry_row_get_text_length,
+   adw_entry_row_set_show_apply_button, adw_entry_row_get_show_apply_button,
+   adw_entry_row_set_activates_default,
+   adw_entry_row_get_activates_default,
+   adw_entry_row_grab_focus_without_selecting;
+
+
+TYPE
+   AdwEntryRow = ADDRESS;
+
+(* GtkWidget *adw_entry_row_new(void) *)
+PROCEDURE adw_entry_row_new () : AdwEntryRow;
+
+(* void adw_entry_row_add_prefix(AdwEntryRow *self, GtkWidget *widget) *)
+PROCEDURE adw_entry_row_add_prefix (self: AdwEntryRow; widget: ADDRESS);
+
+(* void adw_entry_row_add_suffix(AdwEntryRow *self, GtkWidget *widget) *)
+PROCEDURE adw_entry_row_add_suffix (self: AdwEntryRow; widget: ADDRESS);
+
+(* void adw_entry_row_remove(AdwEntryRow *self, GtkWidget *widget) *)
+PROCEDURE adw_entry_row_remove (self: AdwEntryRow; widget: ADDRESS);
+
+(* void adw_entry_row_set_max_length(AdwEntryRow *self, int max_length) *)
+PROCEDURE adw_entry_row_set_max_length (self: AdwEntryRow; max_length: INTEGER);
+
+(* int adw_entry_row_get_max_length(AdwEntryRow *self) *)
+PROCEDURE adw_entry_row_get_max_length (self: AdwEntryRow) : INTEGER;
+
+(* guint16 adw_entry_row_get_text_length(AdwEntryRow *self) *)
+PROCEDURE adw_entry_row_get_text_length (self: AdwEntryRow) : CARDINAL;
+
+(* void adw_entry_row_set_show_apply_button(AdwEntryRow *self, gboolean show_apply_button) *)
+PROCEDURE adw_entry_row_set_show_apply_button (self: AdwEntryRow;
+                                               show_apply_button: INTEGER);
+
+(* gboolean adw_entry_row_get_show_apply_button(AdwEntryRow *self) *)
+PROCEDURE adw_entry_row_get_show_apply_button (self: AdwEntryRow) : [ INTEGER ];
+
+(* void adw_entry_row_set_activates_default(AdwEntryRow *self, gboolean activates) *)
+PROCEDURE adw_entry_row_set_activates_default (self: AdwEntryRow;
+                                               activates: INTEGER);
+
+(* gboolean adw_entry_row_get_activates_default(AdwEntryRow *self) *)
+PROCEDURE adw_entry_row_get_activates_default (self: AdwEntryRow) : [ INTEGER ];
+
+(* gboolean adw_entry_row_grab_focus_without_selecting(AdwEntryRow *self) *)
+PROCEDURE adw_entry_row_grab_focus_without_selecting (self: AdwEntryRow) : [ INTEGER ];
+
+END AdwEntryRow.

+ 100 - 0
src/AdwExpanderRow.def

@@ -0,0 +1,100 @@
+DEFINITION MODULE FOR "C" AdwExpanderRow ;
+
+(*
+   m2-GTK4 - AdwExpanderRow: a settings row that expands to reveal child
+   rows.  Mapped onto <libadwaita-1/adw-expander-row.h>.
+
+   Use add_row() for child rows and add_action()/add_prefix()/add_suffix()
+   for controls next to the title.  Title via AdwPreferencesRow.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwExpanderRow,
+   adw_expander_row_new,
+   adw_expander_row_add_row, adw_expander_row_remove,
+   adw_expander_row_add_action, adw_expander_row_add_prefix,
+   adw_expander_row_add_suffix,
+   adw_expander_row_set_expanded, adw_expander_row_get_expanded,
+   adw_expander_row_set_enable_expansion,
+   adw_expander_row_get_enable_expansion,
+   adw_expander_row_set_show_enable_switch,
+   adw_expander_row_get_show_enable_switch,
+   adw_expander_row_set_subtitle, adw_expander_row_get_subtitle,
+   adw_expander_row_set_title_lines, adw_expander_row_get_title_lines,
+   adw_expander_row_set_subtitle_lines, adw_expander_row_get_subtitle_lines,
+   adw_expander_row_set_icon_name, adw_expander_row_get_icon_name;
+
+
+TYPE
+   AdwExpanderRow = ADDRESS;
+
+(* GtkWidget *adw_expander_row_new(void) *)
+PROCEDURE adw_expander_row_new () : AdwExpanderRow;
+
+(* void adw_expander_row_add_row(AdwExpanderRow *self, GtkWidget *child) *)
+PROCEDURE adw_expander_row_add_row (self: AdwExpanderRow; child: ADDRESS);
+
+(* void adw_expander_row_remove(AdwExpanderRow *self, GtkWidget *child) *)
+PROCEDURE adw_expander_row_remove (self: AdwExpanderRow; child: ADDRESS);
+
+(* void adw_expander_row_add_action(AdwExpanderRow *self, GtkWidget *widget) *)
+PROCEDURE adw_expander_row_add_action (self: AdwExpanderRow; widget: ADDRESS);
+
+(* void adw_expander_row_add_prefix(AdwExpanderRow *self, GtkWidget *widget) *)
+PROCEDURE adw_expander_row_add_prefix (self: AdwExpanderRow; widget: ADDRESS);
+
+(* void adw_expander_row_add_suffix(AdwExpanderRow *self, GtkWidget *widget) *)
+PROCEDURE adw_expander_row_add_suffix (self: AdwExpanderRow; widget: ADDRESS);
+
+(* void adw_expander_row_set_expanded(AdwExpanderRow *self, gboolean expanded) *)
+PROCEDURE adw_expander_row_set_expanded (self: AdwExpanderRow;
+                                         expanded: INTEGER);
+
+(* gboolean adw_expander_row_get_expanded(AdwExpanderRow *self) *)
+PROCEDURE adw_expander_row_get_expanded (self: AdwExpanderRow) : [ INTEGER ];
+
+(* void adw_expander_row_set_enable_expansion(AdwExpanderRow *self, gboolean enable_expansion) *)
+PROCEDURE adw_expander_row_set_enable_expansion (self: AdwExpanderRow;
+                                                 enable_expansion: INTEGER);
+
+(* gboolean adw_expander_row_get_enable_expansion(AdwExpanderRow *self) *)
+PROCEDURE adw_expander_row_get_enable_expansion (self: AdwExpanderRow) : [ INTEGER ];
+
+(* void adw_expander_row_set_show_enable_switch(AdwExpanderRow *self, gboolean show_enable_switch) *)
+PROCEDURE adw_expander_row_set_show_enable_switch (self: AdwExpanderRow;
+                                                   show_enable_switch: INTEGER);
+
+(* gboolean adw_expander_row_get_show_enable_switch(AdwExpanderRow *self) *)
+PROCEDURE adw_expander_row_get_show_enable_switch (self: AdwExpanderRow) : [ INTEGER ];
+
+(* void adw_expander_row_set_subtitle(AdwExpanderRow *self, const char *subtitle) *)
+PROCEDURE adw_expander_row_set_subtitle (self: AdwExpanderRow;
+                                         subtitle: ARRAY OF CHAR);
+
+(* const char *adw_expander_row_get_subtitle(AdwExpanderRow *self) *)
+PROCEDURE adw_expander_row_get_subtitle (self: AdwExpanderRow) : ADDRESS;
+
+(* void adw_expander_row_set_title_lines(AdwExpanderRow *self, int title_lines) *)
+PROCEDURE adw_expander_row_set_title_lines (self: AdwExpanderRow;
+                                            title_lines: INTEGER);
+
+(* int adw_expander_row_get_title_lines(AdwExpanderRow *self) *)
+PROCEDURE adw_expander_row_get_title_lines (self: AdwExpanderRow) : INTEGER;
+
+(* void adw_expander_row_set_subtitle_lines(AdwExpanderRow *self, int subtitle_lines) *)
+PROCEDURE adw_expander_row_set_subtitle_lines (self: AdwExpanderRow;
+                                               subtitle_lines: INTEGER);
+
+(* int adw_expander_row_get_subtitle_lines(AdwExpanderRow *self) *)
+PROCEDURE adw_expander_row_get_subtitle_lines (self: AdwExpanderRow) : INTEGER;
+
+(* void adw_expander_row_set_icon_name(AdwExpanderRow *self, const char *icon_name) *)
+PROCEDURE adw_expander_row_set_icon_name (self: AdwExpanderRow;
+                                          icon_name: ARRAY OF CHAR);
+
+(* const char *adw_expander_row_get_icon_name(AdwExpanderRow *self) *)
+PROCEDURE adw_expander_row_get_icon_name (self: AdwExpanderRow) : ADDRESS;
+
+END AdwExpanderRow.

+ 82 - 0
src/AdwHeaderBar.def

@@ -0,0 +1,82 @@
+DEFINITION MODULE FOR "C" AdwHeaderBar ;
+
+(*
+   m2-GTK4 - AdwHeaderBar: a header bar with Adwaita behaviour (window
+   controls, automatic back button).  Mapped onto
+   <libadwaita-1/adw-header-bar.h>.
+
+   Pack controls with pack_start()/pack_end(); a title widget can be
+   set with set_title_widget().
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwHeaderBar, AdwCenteringPolicy, AdwCenteringLoose, AdwCenteringStrict,
+   adw_header_bar_new,
+   adw_header_bar_pack_start, adw_header_bar_pack_end, adw_header_bar_remove,
+   adw_header_bar_set_title_widget, adw_header_bar_get_title_widget,
+   adw_header_bar_set_show_title, adw_header_bar_get_show_title,
+   adw_header_bar_set_show_start_title_buttons,
+   adw_header_bar_set_show_end_title_buttons,
+   adw_header_bar_set_decoration_layout, adw_header_bar_get_decoration_layout,
+   adw_header_bar_set_centering_policy, adw_header_bar_get_centering_policy;
+
+
+TYPE
+   AdwHeaderBar = ADDRESS;
+   AdwCenteringPolicy = CARDINAL;
+
+CONST
+   AdwCenteringLoose  = 0;
+   AdwCenteringStrict = 1;
+
+(* GtkWidget *adw_header_bar_new(void) *)
+PROCEDURE adw_header_bar_new () : AdwHeaderBar;
+
+(* void adw_header_bar_pack_start(AdwHeaderBar *self, GtkWidget *child) *)
+PROCEDURE adw_header_bar_pack_start (self: AdwHeaderBar; child: ADDRESS);
+
+(* void adw_header_bar_pack_end(AdwHeaderBar *self, GtkWidget *child) *)
+PROCEDURE adw_header_bar_pack_end (self: AdwHeaderBar; child: ADDRESS);
+
+(* void adw_header_bar_remove(AdwHeaderBar *self, GtkWidget *child) *)
+PROCEDURE adw_header_bar_remove (self: AdwHeaderBar; child: ADDRESS);
+
+(* void adw_header_bar_set_title_widget(AdwHeaderBar *self, GtkWidget *title_widget) *)
+PROCEDURE adw_header_bar_set_title_widget (self: AdwHeaderBar;
+                                           title_widget: ADDRESS);
+
+(* GtkWidget *adw_header_bar_get_title_widget(AdwHeaderBar *self) *)
+PROCEDURE adw_header_bar_get_title_widget (self: AdwHeaderBar) : ADDRESS;
+
+(* void adw_header_bar_set_show_title(AdwHeaderBar *self, gboolean show_title) *)
+PROCEDURE adw_header_bar_set_show_title (self: AdwHeaderBar; show_title: INTEGER);
+
+(* gboolean adw_header_bar_get_show_title(AdwHeaderBar *self) *)
+PROCEDURE adw_header_bar_get_show_title (self: AdwHeaderBar) : [ INTEGER ];
+
+(* void adw_header_bar_set_show_start_title_buttons(AdwHeaderBar *self, gboolean setting) *)
+PROCEDURE adw_header_bar_set_show_start_title_buttons (self: AdwHeaderBar;
+                                                       setting: INTEGER);
+
+(* void adw_header_bar_set_show_end_title_buttons(AdwHeaderBar *self, gboolean setting) *)
+PROCEDURE adw_header_bar_set_show_end_title_buttons (self: AdwHeaderBar;
+                                                     setting: INTEGER);
+
+(* void adw_header_bar_set_decoration_layout(AdwHeaderBar *self, const char *layout) *)
+PROCEDURE adw_header_bar_set_decoration_layout (self: AdwHeaderBar;
+                                                layout: ARRAY OF CHAR);
+
+(* const char *adw_header_bar_get_decoration_layout(AdwHeaderBar *self) *)
+PROCEDURE adw_header_bar_get_decoration_layout (self: AdwHeaderBar) : ADDRESS;
+
+(* void adw_header_bar_set_centering_policy(AdwHeaderBar *self,
+                                             AdwCenteringPolicy centering_policy) *)
+PROCEDURE adw_header_bar_set_centering_policy (self: AdwHeaderBar;
+                                               centering_policy: AdwCenteringPolicy);
+
+(* AdwCenteringPolicy adw_header_bar_get_centering_policy(AdwHeaderBar *self) *)
+PROCEDURE adw_header_bar_get_centering_policy (self: AdwHeaderBar) : AdwCenteringPolicy;
+
+END AdwHeaderBar.

+ 149 - 0
src/AdwMessageDialog.def

@@ -0,0 +1,149 @@
+DEFINITION MODULE FOR "C" AdwMessageDialog ;
+
+(*
+   m2-GTK4 - AdwMessageDialog: a modern message/confirmation dialog.
+   Mapped onto <libadwaita-1/adw-message-dialog.h>.
+
+   It derives from GtkWindow: add responses, then gtk_window_present()
+   it.  Signal: "response", void(AdwMessageDialog*, const char *response,
+   gpointer).  For the asynchronous API use choose()/choose_finish().
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwMessageDialog, AdwResponseAppearance,
+   AdwResponseDefault, AdwResponseSuggested, AdwResponseDestructive,
+   adw_message_dialog_new,
+   adw_message_dialog_add_response, adw_message_dialog_remove_response,
+   adw_message_dialog_has_response, adw_message_dialog_response,
+   adw_message_dialog_set_response_appearance,
+   adw_message_dialog_get_response_appearance,
+   adw_message_dialog_set_response_enabled,
+   adw_message_dialog_get_response_enabled,
+   adw_message_dialog_set_response_label,
+   adw_message_dialog_get_response_label,
+   adw_message_dialog_set_default_response,
+   adw_message_dialog_get_default_response,
+   adw_message_dialog_set_close_response,
+   adw_message_dialog_get_close_response,
+   adw_message_dialog_set_heading, adw_message_dialog_get_heading,
+   adw_message_dialog_set_body, adw_message_dialog_get_body,
+   adw_message_dialog_set_extra_child, adw_message_dialog_get_extra_child,
+   adw_message_dialog_set_heading_use_markup,
+   adw_message_dialog_get_heading_use_markup;
+
+
+TYPE
+   AdwMessageDialog = ADDRESS;
+   AdwResponseAppearance = CARDINAL;
+
+CONST
+   AdwResponseDefault     = 0;
+   AdwResponseSuggested   = 1;
+   AdwResponseDestructive = 2;
+
+(* GtkWidget *adw_message_dialog_new(GtkWindow *parent, const char *heading,
+                                      const char *body) *)
+PROCEDURE adw_message_dialog_new (parent: ADDRESS; heading: ARRAY OF CHAR;
+                                  body: ARRAY OF CHAR) : AdwMessageDialog;
+
+(* void adw_message_dialog_add_response(AdwMessageDialog *self,
+                                         const char *id, const char *label) *)
+PROCEDURE adw_message_dialog_add_response (self: AdwMessageDialog;
+                                           id, label: ARRAY OF CHAR);
+
+(* void adw_message_dialog_remove_response(AdwMessageDialog *self, const char *id) *)
+PROCEDURE adw_message_dialog_remove_response (self: AdwMessageDialog;
+                                              id: ARRAY OF CHAR);
+
+(* gboolean adw_message_dialog_has_response(AdwMessageDialog *self, const char *response) *)
+PROCEDURE adw_message_dialog_has_response (self: AdwMessageDialog;
+                                           response: ARRAY OF CHAR) : [ INTEGER ];
+
+(* void adw_message_dialog_response(AdwMessageDialog *self, const char *response) *)
+PROCEDURE adw_message_dialog_response (self: AdwMessageDialog;
+                                       response: ARRAY OF CHAR);
+
+(* void adw_message_dialog_set_response_appearance(AdwMessageDialog *self,
+                                                    const char *response,
+                                                    AdwResponseAppearance appearance) *)
+PROCEDURE adw_message_dialog_set_response_appearance (self: AdwMessageDialog;
+                                                      response: ARRAY OF CHAR;
+                                                      appearance: AdwResponseAppearance);
+
+(* AdwResponseAppearance adw_message_dialog_get_response_appearance(
+                             AdwMessageDialog *self, const char *response) *)
+PROCEDURE adw_message_dialog_get_response_appearance (self: AdwMessageDialog;
+                                                      response: ARRAY OF CHAR) : AdwResponseAppearance;
+
+(* void adw_message_dialog_set_response_enabled(AdwMessageDialog *self,
+                                                 const char *response,
+                                                 gboolean enabled) *)
+PROCEDURE adw_message_dialog_set_response_enabled (self: AdwMessageDialog;
+                                                   response: ARRAY OF CHAR;
+                                                   enabled: INTEGER);
+
+(* gboolean adw_message_dialog_get_response_enabled(AdwMessageDialog *self,
+                                                     const char *response) *)
+PROCEDURE adw_message_dialog_get_response_enabled (self: AdwMessageDialog;
+                                                   response: ARRAY OF CHAR) : [ INTEGER ];
+
+(* void adw_message_dialog_set_response_label(AdwMessageDialog *self,
+                                               const char *response,
+                                               const char *label) *)
+PROCEDURE adw_message_dialog_set_response_label (self: AdwMessageDialog;
+                                                 response: ARRAY OF CHAR;
+                                                 label: ARRAY OF CHAR);
+
+(* const char *adw_message_dialog_get_response_label(AdwMessageDialog *self,
+                                                      const char *response) *)
+PROCEDURE adw_message_dialog_get_response_label (self: AdwMessageDialog;
+                                                 response: ARRAY OF CHAR) : ADDRESS;
+
+(* void adw_message_dialog_set_default_response(AdwMessageDialog *self,
+                                                 const char *response) *)
+PROCEDURE adw_message_dialog_set_default_response (self: AdwMessageDialog;
+                                                   response: ARRAY OF CHAR);
+
+(* const char *adw_message_dialog_get_default_response(AdwMessageDialog *self) *)
+PROCEDURE adw_message_dialog_get_default_response (self: AdwMessageDialog) : ADDRESS;
+
+(* void adw_message_dialog_set_close_response(AdwMessageDialog *self,
+                                               const char *response) *)
+PROCEDURE adw_message_dialog_set_close_response (self: AdwMessageDialog;
+                                                 response: ARRAY OF CHAR);
+
+(* const char *adw_message_dialog_get_close_response(AdwMessageDialog *self) *)
+PROCEDURE adw_message_dialog_get_close_response (self: AdwMessageDialog) : ADDRESS;
+
+(* void adw_message_dialog_set_heading(AdwMessageDialog *self, const char *heading) *)
+PROCEDURE adw_message_dialog_set_heading (self: AdwMessageDialog;
+                                          heading: ARRAY OF CHAR);
+
+(* const char *adw_message_dialog_get_heading(AdwMessageDialog *self) *)
+PROCEDURE adw_message_dialog_get_heading (self: AdwMessageDialog) : ADDRESS;
+
+(* void adw_message_dialog_set_body(AdwMessageDialog *self, const char *body) *)
+PROCEDURE adw_message_dialog_set_body (self: AdwMessageDialog;
+                                       body: ARRAY OF CHAR);
+
+(* const char *adw_message_dialog_get_body(AdwMessageDialog *self) *)
+PROCEDURE adw_message_dialog_get_body (self: AdwMessageDialog) : ADDRESS;
+
+(* void adw_message_dialog_set_extra_child(AdwMessageDialog *self, GtkWidget *child) *)
+PROCEDURE adw_message_dialog_set_extra_child (self: AdwMessageDialog;
+                                              child: ADDRESS);
+
+(* GtkWidget *adw_message_dialog_get_extra_child(AdwMessageDialog *self) *)
+PROCEDURE adw_message_dialog_get_extra_child (self: AdwMessageDialog) : ADDRESS;
+
+(* void adw_message_dialog_set_heading_use_markup(AdwMessageDialog *self,
+                                                   gboolean use_markup) *)
+PROCEDURE adw_message_dialog_set_heading_use_markup (self: AdwMessageDialog;
+                                                     use_markup: INTEGER);
+
+(* gboolean adw_message_dialog_get_heading_use_markup(AdwMessageDialog *self) *)
+PROCEDURE adw_message_dialog_get_heading_use_markup (self: AdwMessageDialog) : [ INTEGER ];
+
+END AdwMessageDialog.

+ 70 - 0
src/AdwPreferencesGroup.def

@@ -0,0 +1,70 @@
+DEFINITION MODULE FOR "C" AdwPreferencesGroup ;
+
+(*
+   m2-GTK4 - AdwPreferencesGroup: a titled box of settings rows.
+   Mapped onto <libadwaita-1/adw-preferences-group.h>.
+
+   Add AdwActionRow/AdwSwitchRow/... with add(); an optional header
+   suffix widget can be set with set_header_suffix().
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwPreferencesGroup,
+   adw_preferences_group_new,
+   adw_preferences_group_add, adw_preferences_group_remove,
+   adw_preferences_group_set_title, adw_preferences_group_get_title,
+   adw_preferences_group_set_description,
+   adw_preferences_group_get_description,
+   adw_preferences_group_set_header_suffix,
+   adw_preferences_group_get_header_suffix,
+   adw_preferences_group_set_separate_rows,
+   adw_preferences_group_get_separate_rows;
+
+
+TYPE
+   AdwPreferencesGroup = ADDRESS;
+
+(* GtkWidget *adw_preferences_group_new(void) *)
+PROCEDURE adw_preferences_group_new () : AdwPreferencesGroup;
+
+(* void adw_preferences_group_add(AdwPreferencesGroup *self, GtkWidget *child) *)
+PROCEDURE adw_preferences_group_add (self: AdwPreferencesGroup; child: ADDRESS);
+
+(* void adw_preferences_group_remove(AdwPreferencesGroup *self, GtkWidget *child) *)
+PROCEDURE adw_preferences_group_remove (self: AdwPreferencesGroup;
+                                        child: ADDRESS);
+
+(* void adw_preferences_group_set_title(AdwPreferencesGroup *self, const char *title) *)
+PROCEDURE adw_preferences_group_set_title (self: AdwPreferencesGroup;
+                                           title: ARRAY OF CHAR);
+
+(* const char *adw_preferences_group_get_title(AdwPreferencesGroup *self) *)
+PROCEDURE adw_preferences_group_get_title (self: AdwPreferencesGroup) : ADDRESS;
+
+(* void adw_preferences_group_set_description(AdwPreferencesGroup *self,
+                                               const char *description) *)
+PROCEDURE adw_preferences_group_set_description (self: AdwPreferencesGroup;
+                                                 description: ARRAY OF CHAR);
+
+(* const char *adw_preferences_group_get_description(AdwPreferencesGroup *self) *)
+PROCEDURE adw_preferences_group_get_description (self: AdwPreferencesGroup) : ADDRESS;
+
+(* void adw_preferences_group_set_header_suffix(AdwPreferencesGroup *self,
+                                                 GtkWidget *suffix) *)
+PROCEDURE adw_preferences_group_set_header_suffix (self: AdwPreferencesGroup;
+                                                   suffix: ADDRESS);
+
+(* GtkWidget *adw_preferences_group_get_header_suffix(AdwPreferencesGroup *self) *)
+PROCEDURE adw_preferences_group_get_header_suffix (self: AdwPreferencesGroup) : ADDRESS;
+
+(* void adw_preferences_group_set_separate_rows(AdwPreferencesGroup *self,
+                                                 gboolean separate_rows) *)
+PROCEDURE adw_preferences_group_set_separate_rows (self: AdwPreferencesGroup;
+                                                   separate_rows: INTEGER);
+
+(* gboolean adw_preferences_group_get_separate_rows(AdwPreferencesGroup *self) *)
+PROCEDURE adw_preferences_group_get_separate_rows (self: AdwPreferencesGroup) : [ INTEGER ];
+
+END AdwPreferencesGroup.

+ 87 - 0
src/AdwPreferencesPage.def

@@ -0,0 +1,87 @@
+DEFINITION MODULE FOR "C" AdwPreferencesPage ;
+
+(*
+   m2-GTK4 - AdwPreferencesPage: a scrollable page of preferences
+   groups.  Mapped onto <libadwaita-1/adw-preferences-page.h>.
+
+   Use it as the content of an AdwToolbarView or as a window child.
+   Title and icon are only shown when the page is inside an
+   AdwPreferencesWindow / AdwNavigationView.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwPreferencesPage,
+   adw_preferences_page_new,
+   adw_preferences_page_add, adw_preferences_page_remove,
+   adw_preferences_page_set_title, adw_preferences_page_get_title,
+   adw_preferences_page_set_icon_name, adw_preferences_page_get_icon_name,
+   adw_preferences_page_set_description,
+   adw_preferences_page_get_description,
+   adw_preferences_page_set_name, adw_preferences_page_get_name,
+   adw_preferences_page_set_banner, adw_preferences_page_get_banner,
+   adw_preferences_page_set_description_centered,
+   adw_preferences_page_scroll_to_top;
+
+
+TYPE
+   AdwPreferencesPage = ADDRESS;
+
+(* GtkWidget *adw_preferences_page_new(void) *)
+PROCEDURE adw_preferences_page_new () : AdwPreferencesPage;
+
+(* void adw_preferences_page_add(AdwPreferencesPage *self,
+                                  AdwPreferencesGroup *group) *)
+PROCEDURE adw_preferences_page_add (self: AdwPreferencesPage; group: ADDRESS);
+
+(* void adw_preferences_page_remove(AdwPreferencesPage *self,
+                                     AdwPreferencesGroup *group) *)
+PROCEDURE adw_preferences_page_remove (self: AdwPreferencesPage;
+                                       group: ADDRESS);
+
+(* void adw_preferences_page_set_title(AdwPreferencesPage *self, const char *title) *)
+PROCEDURE adw_preferences_page_set_title (self: AdwPreferencesPage;
+                                          title: ARRAY OF CHAR);
+
+(* const char *adw_preferences_page_get_title(AdwPreferencesPage *self) *)
+PROCEDURE adw_preferences_page_get_title (self: AdwPreferencesPage) : ADDRESS;
+
+(* void adw_preferences_page_set_icon_name(AdwPreferencesPage *self, const char *icon_name) *)
+PROCEDURE adw_preferences_page_set_icon_name (self: AdwPreferencesPage;
+                                              icon_name: ARRAY OF CHAR);
+
+(* const char *adw_preferences_page_get_icon_name(AdwPreferencesPage *self) *)
+PROCEDURE adw_preferences_page_get_icon_name (self: AdwPreferencesPage) : ADDRESS;
+
+(* void adw_preferences_page_set_description(AdwPreferencesPage *self, const char *description) *)
+PROCEDURE adw_preferences_page_set_description (self: AdwPreferencesPage;
+                                                description: ARRAY OF CHAR);
+
+(* const char *adw_preferences_page_get_description(AdwPreferencesPage *self) *)
+PROCEDURE adw_preferences_page_get_description (self: AdwPreferencesPage) : ADDRESS;
+
+(* void adw_preferences_page_set_name(AdwPreferencesPage *self, const char *name) *)
+PROCEDURE adw_preferences_page_set_name (self: AdwPreferencesPage;
+                                         name: ARRAY OF CHAR);
+
+(* const char *adw_preferences_page_get_name(AdwPreferencesPage *self) *)
+PROCEDURE adw_preferences_page_get_name (self: AdwPreferencesPage) : ADDRESS;
+
+(* void adw_preferences_page_set_banner(AdwPreferencesPage *self,
+                                         AdwBanner *banner) *)
+PROCEDURE adw_preferences_page_set_banner (self: AdwPreferencesPage;
+                                           banner: ADDRESS);
+
+(* AdwBanner *adw_preferences_page_get_banner(AdwPreferencesPage *self) *)
+PROCEDURE adw_preferences_page_get_banner (self: AdwPreferencesPage) : ADDRESS;
+
+(* void adw_preferences_page_set_description_centered(AdwPreferencesPage *self,
+                                                       gboolean centered) *)
+PROCEDURE adw_preferences_page_set_description_centered (self: AdwPreferencesPage;
+                                                         centered: INTEGER);
+
+(* void adw_preferences_page_scroll_to_top(AdwPreferencesPage *self) *)
+PROCEDURE adw_preferences_page_scroll_to_top (self: AdwPreferencesPage);
+
+END AdwPreferencesPage.

+ 47 - 0
src/AdwPreferencesRow.def

@@ -0,0 +1,47 @@
+DEFINITION MODULE FOR "C" AdwPreferencesRow ;
+
+(*
+   m2-GTK4 - AdwPreferencesRow: the base of the Adwaita settings rows.
+   Mapped onto <libadwaita-1/adw-preferences-row.h>.
+
+   It provides the title (with optional markup/underline).  Subclasses
+   such as AdwActionRow add subtitle, prefixes, suffixes, etc.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwPreferencesRow,
+   adw_preferences_row_new,
+   adw_preferences_row_set_title, adw_preferences_row_get_title,
+   adw_preferences_row_set_use_markup,
+   adw_preferences_row_set_use_underline,
+   adw_preferences_row_set_title_selectable;
+
+
+TYPE
+   AdwPreferencesRow = ADDRESS;
+
+(* GtkWidget *adw_preferences_row_new(void) *)
+PROCEDURE adw_preferences_row_new () : AdwPreferencesRow;
+
+(* void adw_preferences_row_set_title(AdwPreferencesRow *self, const char *title) *)
+PROCEDURE adw_preferences_row_set_title (self: AdwPreferencesRow;
+                                         title: ARRAY OF CHAR);
+
+(* const char *adw_preferences_row_get_title(AdwPreferencesRow *self) *)
+PROCEDURE adw_preferences_row_get_title (self: AdwPreferencesRow) : ADDRESS;
+
+(* void adw_preferences_row_set_use_markup(AdwPreferencesRow *self, gboolean use_markup) *)
+PROCEDURE adw_preferences_row_set_use_markup (self: AdwPreferencesRow;
+                                              use_markup: INTEGER);
+
+(* void adw_preferences_row_set_use_underline(AdwPreferencesRow *self, gboolean use_underline) *)
+PROCEDURE adw_preferences_row_set_use_underline (self: AdwPreferencesRow;
+                                                 use_underline: INTEGER);
+
+(* void adw_preferences_row_set_title_selectable(AdwPreferencesRow *self, gboolean title_selectable) *)
+PROCEDURE adw_preferences_row_set_title_selectable (self: AdwPreferencesRow;
+                                                    title_selectable: INTEGER);
+
+END AdwPreferencesRow.

+ 52 - 0
src/AdwStatusPage.def

@@ -0,0 +1,52 @@
+DEFINITION MODULE FOR "C" AdwStatusPage ;
+
+(*
+   m2-GTK4 - AdwStatusPage: a placeholder page with icon, title,
+   description and optional child.  Mapped onto
+   <libadwaita-1/adw-status-page.h>.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwStatusPage,
+   adw_status_page_new,
+   adw_status_page_set_child, adw_status_page_get_child,
+   adw_status_page_set_icon_name, adw_status_page_get_icon_name,
+   adw_status_page_set_title, adw_status_page_get_title,
+   adw_status_page_set_description, adw_status_page_get_description;
+
+
+TYPE
+   AdwStatusPage = ADDRESS;
+
+(* GtkWidget *adw_status_page_new(void) *)
+PROCEDURE adw_status_page_new () : AdwStatusPage;
+
+(* void adw_status_page_set_child(AdwStatusPage *self, GtkWidget *child) *)
+PROCEDURE adw_status_page_set_child (self: AdwStatusPage; child: ADDRESS);
+
+(* GtkWidget *adw_status_page_get_child(AdwStatusPage *self) *)
+PROCEDURE adw_status_page_get_child (self: AdwStatusPage) : ADDRESS;
+
+(* void adw_status_page_set_icon_name(AdwStatusPage *self, const char *icon_name) *)
+PROCEDURE adw_status_page_set_icon_name (self: AdwStatusPage;
+                                         icon_name: ARRAY OF CHAR);
+
+(* const char *adw_status_page_get_icon_name(AdwStatusPage *self) *)
+PROCEDURE adw_status_page_get_icon_name (self: AdwStatusPage) : ADDRESS;
+
+(* void adw_status_page_set_title(AdwStatusPage *self, const char *title) *)
+PROCEDURE adw_status_page_set_title (self: AdwStatusPage; title: ARRAY OF CHAR);
+
+(* const char *adw_status_page_get_title(AdwStatusPage *self) *)
+PROCEDURE adw_status_page_get_title (self: AdwStatusPage) : ADDRESS;
+
+(* void adw_status_page_set_description(AdwStatusPage *self, const char *description) *)
+PROCEDURE adw_status_page_set_description (self: AdwStatusPage;
+                                           description: ARRAY OF CHAR);
+
+(* const char *adw_status_page_get_description(AdwStatusPage *self) *)
+PROCEDURE adw_status_page_get_description (self: AdwStatusPage) : ADDRESS;
+
+END AdwStatusPage.

+ 30 - 0
src/AdwSwitchRow.def

@@ -0,0 +1,30 @@
+DEFINITION MODULE FOR "C" AdwSwitchRow ;
+
+(*
+   m2-GTK4 - AdwSwitchRow: a settings row with a switch.  Mapped onto
+   <libadwaita-1/adw-switch-row.h>.
+
+   Title via AdwPreferencesRow.  Signal: "notify::active".
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwSwitchRow,
+   adw_switch_row_new,
+   adw_switch_row_set_active, adw_switch_row_get_active;
+
+
+TYPE
+   AdwSwitchRow = ADDRESS;
+
+(* GtkWidget *adw_switch_row_new(void) *)
+PROCEDURE adw_switch_row_new () : AdwSwitchRow;
+
+(* void adw_switch_row_set_active(AdwSwitchRow *self, gboolean is_active) *)
+PROCEDURE adw_switch_row_set_active (self: AdwSwitchRow; is_active: INTEGER);
+
+(* gboolean adw_switch_row_get_active(AdwSwitchRow *self) *)
+PROCEDURE adw_switch_row_get_active (self: AdwSwitchRow) : [ INTEGER ];
+
+END AdwSwitchRow.

+ 73 - 0
src/AdwToast.def

@@ -0,0 +1,73 @@
+DEFINITION MODULE FOR "C" AdwToast ;
+
+(*
+   m2-GTK4 - AdwToast: a small transient notification shown by an
+   AdwToastOverlay.  Mapped onto <libadwaita-1/adw-toast.h>.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwToast, AdwToastPriority, AdwToastLow, AdwToastNormal, AdwToastHigh,
+   adw_toast_new,
+   adw_toast_set_title, adw_toast_get_title,
+   adw_toast_set_timeout, adw_toast_get_timeout,
+   adw_toast_set_button_label, adw_toast_get_button_label,
+   adw_toast_set_action_name, adw_toast_set_detailed_action_name,
+   adw_toast_set_priority, adw_toast_get_priority,
+   adw_toast_set_use_markup, adw_toast_dismiss;
+
+
+TYPE
+   AdwToast = ADDRESS;
+   AdwToastPriority = CARDINAL;
+
+CONST
+   AdwToastLow    = 0;
+   AdwToastNormal = 1;
+   AdwToastHigh   = 2;
+
+(* AdwToast *adw_toast_new(const char *title) *)
+PROCEDURE adw_toast_new (title: ARRAY OF CHAR) : AdwToast;
+
+(* void adw_toast_set_title(AdwToast *self, const char *title) *)
+PROCEDURE adw_toast_set_title (self: AdwToast; title: ARRAY OF CHAR);
+
+(* const char *adw_toast_get_title(AdwToast *self) *)
+PROCEDURE adw_toast_get_title (self: AdwToast) : ADDRESS;
+
+(* void adw_toast_set_timeout(AdwToast *self, guint timeout) *)
+PROCEDURE adw_toast_set_timeout (self: AdwToast; timeout: CARDINAL);
+
+(* guint adw_toast_get_timeout(AdwToast *self) *)
+PROCEDURE adw_toast_get_timeout (self: AdwToast) : CARDINAL;
+
+(* void adw_toast_set_button_label(AdwToast *self, const char *button_label) *)
+PROCEDURE adw_toast_set_button_label (self: AdwToast;
+                                      button_label: ARRAY OF CHAR);
+
+(* const char *adw_toast_get_button_label(AdwToast *self) *)
+PROCEDURE adw_toast_get_button_label (self: AdwToast) : ADDRESS;
+
+(* void adw_toast_set_action_name(AdwToast *self, const char *action_name) *)
+PROCEDURE adw_toast_set_action_name (self: AdwToast;
+                                     action_name: ARRAY OF CHAR);
+
+(* void adw_toast_set_detailed_action_name(AdwToast *self,
+                                            const char *detailed_action_name) *)
+PROCEDURE adw_toast_set_detailed_action_name (self: AdwToast;
+                                              detailed_action_name: ARRAY OF CHAR);
+
+(* void adw_toast_set_priority(AdwToast *self, AdwToastPriority priority) *)
+PROCEDURE adw_toast_set_priority (self: AdwToast; priority: AdwToastPriority);
+
+(* AdwToastPriority adw_toast_get_priority(AdwToast *self) *)
+PROCEDURE adw_toast_get_priority (self: AdwToast) : AdwToastPriority;
+
+(* void adw_toast_set_use_markup(AdwToast *self, gboolean use_markup) *)
+PROCEDURE adw_toast_set_use_markup (self: AdwToast; use_markup: INTEGER);
+
+(* void adw_toast_dismiss(AdwToast *self) *)
+PROCEDURE adw_toast_dismiss (self: AdwToast);
+
+END AdwToast.

+ 38 - 0
src/AdwToastOverlay.def

@@ -0,0 +1,38 @@
+DEFINITION MODULE FOR "C" AdwToastOverlay ;
+
+(*
+   m2-GTK4 - AdwToastOverlay: wraps a child and displays AdwToasts on
+   top of it.  Mapped onto <libadwaita-1/adw-toast-overlay.h>.
+
+   Set the main content with set_child(), then call add_toast() whenever
+   you want to show a notification.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwToastOverlay,
+   adw_toast_overlay_new,
+   adw_toast_overlay_add_toast, adw_toast_overlay_dismiss_all,
+   adw_toast_overlay_set_child, adw_toast_overlay_get_child;
+
+
+TYPE
+   AdwToastOverlay = ADDRESS;
+
+(* GtkWidget *adw_toast_overlay_new(void) *)
+PROCEDURE adw_toast_overlay_new () : AdwToastOverlay;
+
+(* void adw_toast_overlay_add_toast(AdwToastOverlay *self, AdwToast *toast) *)
+PROCEDURE adw_toast_overlay_add_toast (self: AdwToastOverlay; toast: ADDRESS);
+
+(* void adw_toast_overlay_dismiss_all(AdwToastOverlay *self) *)
+PROCEDURE adw_toast_overlay_dismiss_all (self: AdwToastOverlay);
+
+(* void adw_toast_overlay_set_child(AdwToastOverlay *self, GtkWidget *child) *)
+PROCEDURE adw_toast_overlay_set_child (self: AdwToastOverlay; child: ADDRESS);
+
+(* GtkWidget *adw_toast_overlay_get_child(AdwToastOverlay *self) *)
+PROCEDURE adw_toast_overlay_get_child (self: AdwToastOverlay) : ADDRESS;
+
+END AdwToastOverlay.

+ 68 - 0
src/AdwToolbarView.def

@@ -0,0 +1,68 @@
+DEFINITION MODULE FOR "C" AdwToolbarView ;
+
+(*
+   m2-GTK4 - AdwToolbarView: a container with top and bottom bars around
+   a content widget.  Mapped onto <libadwaita-1/adw-toolbar-view.h>.
+
+   Typical use: add an AdwHeaderBar as a top bar and set the page as
+   content.  The bar style controls the flat/raised look.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   AdwToolbarView, AdwToolbarStyle,
+   AdwToolbarFlat, AdwToolbarRaised, AdwToolbarRaisedBorder,
+   adw_toolbar_view_new,
+   adw_toolbar_view_add_top_bar, adw_toolbar_view_add_bottom_bar,
+   adw_toolbar_view_remove,
+   adw_toolbar_view_set_content, adw_toolbar_view_get_content,
+   adw_toolbar_view_set_top_bar_style, adw_toolbar_view_get_top_bar_style,
+   adw_toolbar_view_set_bottom_bar_style, adw_toolbar_view_get_bottom_bar_style;
+
+
+TYPE
+   AdwToolbarView = ADDRESS;
+   AdwToolbarStyle = CARDINAL;
+
+CONST
+   AdwToolbarFlat         = 0;
+   AdwToolbarRaised       = 1;
+   AdwToolbarRaisedBorder = 2;
+
+(* GtkWidget *adw_toolbar_view_new(void) *)
+PROCEDURE adw_toolbar_view_new () : AdwToolbarView;
+
+(* void adw_toolbar_view_add_top_bar(AdwToolbarView *self, GtkWidget *widget) *)
+PROCEDURE adw_toolbar_view_add_top_bar (self: AdwToolbarView; widget: ADDRESS);
+
+(* void adw_toolbar_view_add_bottom_bar(AdwToolbarView *self, GtkWidget *widget) *)
+PROCEDURE adw_toolbar_view_add_bottom_bar (self: AdwToolbarView;
+                                           widget: ADDRESS);
+
+(* void adw_toolbar_view_remove(AdwToolbarView *self, GtkWidget *widget) *)
+PROCEDURE adw_toolbar_view_remove (self: AdwToolbarView; widget: ADDRESS);
+
+(* void adw_toolbar_view_set_content(AdwToolbarView *self, GtkWidget *content) *)
+PROCEDURE adw_toolbar_view_set_content (self: AdwToolbarView; content: ADDRESS);
+
+(* GtkWidget *adw_toolbar_view_get_content(AdwToolbarView *self) *)
+PROCEDURE adw_toolbar_view_get_content (self: AdwToolbarView) : ADDRESS;
+
+(* void adw_toolbar_view_set_top_bar_style(AdwToolbarView *self,
+                                            AdwToolbarStyle style) *)
+PROCEDURE adw_toolbar_view_set_top_bar_style (self: AdwToolbarView;
+                                              style: AdwToolbarStyle);
+
+(* AdwToolbarStyle adw_toolbar_view_get_top_bar_style(AdwToolbarView *self) *)
+PROCEDURE adw_toolbar_view_get_top_bar_style (self: AdwToolbarView) : AdwToolbarStyle;
+
+(* void adw_toolbar_view_set_bottom_bar_style(AdwToolbarView *self,
+                                               AdwToolbarStyle style) *)
+PROCEDURE adw_toolbar_view_set_bottom_bar_style (self: AdwToolbarView;
+                                                 style: AdwToolbarStyle);
+
+(* AdwToolbarStyle adw_toolbar_view_get_bottom_bar_style(AdwToolbarView *self) *)
+PROCEDURE adw_toolbar_view_get_bottom_bar_style (self: AdwToolbarView) : AdwToolbarStyle;
+
+END AdwToolbarView.

+ 42 - 0
src/GAction.def

@@ -0,0 +1,42 @@
+DEFINITION MODULE FOR "C" GAction ;
+
+(*
+   m2-GTK4 - GAction: the interface for named, activatable actions.
+   Mapped onto <gio/gaction.h>.
+
+   An action has a name and may be parameterless, may carry a
+   parameter, and may be stateful.  Stateful actions are driven with
+   g_action_change_state() (usually by a menu item or accelerator);
+   g_action_get_state() returns the current state as a GVariant that
+   the caller owns and must unref.
+
+   Concrete implementation: GSimpleAction (GSimpleAction.def).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GAction,
+   g_action_activate, g_action_get_name, g_action_get_enabled,
+   g_action_get_state, g_action_change_state;
+
+
+TYPE
+   GAction = ADDRESS;
+
+(* void g_action_activate(GAction *action, GVariant *parameter) *)
+PROCEDURE g_action_activate (action: GAction; parameter: ADDRESS);
+
+(* const gchar *g_action_get_name(GAction *action) *)
+PROCEDURE g_action_get_name (action: GAction) : ADDRESS;
+
+(* gboolean g_action_get_enabled(GAction *action) *)
+PROCEDURE g_action_get_enabled (action: GAction) : [ INTEGER ];
+
+(* GVariant *g_action_get_state(GAction *action) *)
+PROCEDURE g_action_get_state (action: GAction) : ADDRESS;
+
+(* void g_action_change_state(GAction *action, GVariant *value) *)
+PROCEDURE g_action_change_state (action: GAction; value: ADDRESS);
+
+END GAction.

+ 38 - 0
src/GActionMap.def

@@ -0,0 +1,38 @@
+DEFINITION MODULE FOR "C" GActionMap ;
+
+(*
+   m2-GTK4 - GActionMap: a named collection of actions.  Mapped onto
+   <gio/gactionmap.h>.
+
+   Both GApplication and GtkApplicationWindow implement GActionMap.
+   Actions added to the application are referenced as "app.<name>";
+   actions added to a GtkApplicationWindow are referenced as
+   "win.<name>" (the window's action group is exported with the "win"
+   prefix).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GActionMap,
+   g_action_map_add_action, g_action_map_lookup_action,
+   g_action_map_remove_action;
+
+
+TYPE
+   GActionMap = ADDRESS;
+
+(* void g_action_map_add_action(GActionMap *action_map, GAction *action) *)
+PROCEDURE g_action_map_add_action (action_map: GActionMap; action: ADDRESS);
+
+(* GAction *g_action_map_lookup_action(GActionMap *action_map,
+                                        const gchar *action_name) *)
+PROCEDURE g_action_map_lookup_action (action_map: GActionMap;
+                                      action_name: ARRAY OF CHAR) : ADDRESS;
+
+(* void g_action_map_remove_action(GActionMap *action_map,
+                                    const gchar *action_name) *)
+PROCEDURE g_action_map_remove_action (action_map: GActionMap;
+                                      action_name: ARRAY OF CHAR);
+
+END GActionMap.

+ 50 - 0
src/GError.def

@@ -0,0 +1,50 @@
+DEFINITION MODULE FOR "C" GError ;
+
+(*
+   m2-GTK4 - GError: the GLib error value.  Mapped onto
+   <glib/gerror.h>.
+
+   The C struct is public, so it is modelled directly.  Most C APIs
+   take a GError ** out-parameter; in Modula-2 declare a VAR of type
+   GError and pass its address:
+
+      VAR err: GError;
+      ...
+      err := NIL;
+      ok := g_file_delete(file, NIL, ADR(err));
+      IF err # NIL THEN ... END;
+
+   Use GtkUtils.ErrorMessage() to read the message and
+   GtkUtils.ClearError() (or g_error_free) to release it.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GError, GErrorRec,
+   g_error_free, g_error_copy, g_error_matches, g_clear_error;
+
+
+TYPE
+   GError = POINTER TO GErrorRec;
+   (* struct _GError { GQuark domain; gint code; gchar *message; }; *)
+   GErrorRec = RECORD
+      domain: CARDINAL;
+      code: INTEGER;
+      message: ADDRESS;
+   END;
+
+(* void g_error_free(GError *error) *)
+PROCEDURE g_error_free (error: GError);
+
+(* GError *g_error_copy(const GError *error) *)
+PROCEDURE g_error_copy (error: GError) : GError;
+
+(* gboolean g_error_matches(const GError *error, GQuark domain, gint code) *)
+PROCEDURE g_error_matches (error: GError; domain: CARDINAL;
+                           code: INTEGER) : [ INTEGER ];
+
+(* void g_clear_error(GError **err) *)
+PROCEDURE g_clear_error (VAR err: GError);
+
+END GError.

+ 48 - 0
src/GFile.def

@@ -0,0 +1,48 @@
+DEFINITION MODULE FOR "C" GFile ;
+
+(*
+   m2-GTK4 - GFile: an abstract file handle (local path or URI).
+   Mapped onto <gio/gfile.h>.
+
+   GFile is an interface; the functions here are the static
+   constructors and accessors.  g_file_get_basename(), g_file_get_path()
+   and g_file_get_uri() return newly allocated strings that must be
+   released with GLib.g_free().  A GFile is a GObject: release it with
+   GObject.g_object_unref().
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GFile,
+   g_file_new_for_path, g_file_new_for_uri,
+   g_file_get_basename, g_file_get_path, g_file_get_uri,
+   g_file_query_exists, g_file_delete;
+
+
+TYPE
+   GFile = ADDRESS;
+
+(* GFile *g_file_new_for_path(const char *path) *)
+PROCEDURE g_file_new_for_path (path: ARRAY OF CHAR) : GFile;
+
+(* GFile *g_file_new_for_uri(const char *uri) *)
+PROCEDURE g_file_new_for_uri (uri: ARRAY OF CHAR) : GFile;
+
+(* char *g_file_get_basename(GFile *file) *)
+PROCEDURE g_file_get_basename (file: GFile) : ADDRESS;
+
+(* char *g_file_get_path(GFile *file) *)
+PROCEDURE g_file_get_path (file: GFile) : ADDRESS;
+
+(* char *g_file_get_uri(GFile *file) *)
+PROCEDURE g_file_get_uri (file: GFile) : ADDRESS;
+
+(* gboolean g_file_query_exists(GFile *file, GCancellable *cancellable) *)
+PROCEDURE g_file_query_exists (file: GFile; cancellable: ADDRESS) : [ INTEGER ];
+
+(* gboolean g_file_delete(GFile *file, GCancellable *cancellable, GError **error) *)
+PROCEDURE g_file_delete (file: GFile; cancellable: ADDRESS;
+                         error: ADDRESS) : [ INTEGER ];
+
+END GFile.

+ 134 - 0
src/GLib.def

@@ -0,0 +1,134 @@
+DEFINITION MODULE FOR "C" GLib ;
+
+(*
+   m2-GTK4 - GLib core: base C types, the main loop, timeouts/idle
+   sources, memory and string helpers.  Mapped onto <glib.h>.
+
+   Why GLib first?
+   ---------------
+   Every GTK4 type is a GObject and every GTK4 program runs a
+   GMainLoop.  GLib also defines the fundamental C types GTK uses
+   (gboolean, gint, guint, gpointer, ...), so all other binding
+   modules refer back to this one.
+
+   Mapping notes
+   -------------
+   * INTEGER   <-> gboolean / gint / int
+   * CARDINAL  <-> guint / unsigned int
+   * LONGCARD  <-> gulong / gsize / guint64
+   * LONGINT   <-> glong / gssize / gint64
+   * LONGREAL  <-> (Modula-2 only; C has no 16-byte long double use here)
+   * REAL      <-> gdouble (double, 8 bytes)
+   * SHORTREAL <-> gfloat (float, 4 bytes)
+   * ADDRESS   <-> gpointer (void ptr)
+   * The callbacks below are plain C function pointers; a top-level
+   * Modula-2 procedure is passed directly (or via ADR(...)).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   (* C type aliases *)
+   gboolean, gint, guint, gchar, guchar, glong, gulong,
+   gint64, guint64, gsize, gssize, gdouble, gfloat, gpointer,
+   (* opaque handles *)
+   GMainContext, GMainLoop,
+   (* callback type *)
+   GSourceFunc,
+   (* constants *)
+   gFalse, gTrue, GSourceRemove, GSourceContinue,
+   (* main loop *)
+   g_main_context_default,
+   g_main_loop_new, g_main_loop_run, g_main_loop_quit, g_main_loop_unref,
+   (* sources *)
+   g_timeout_add, g_timeout_add_seconds, g_idle_add, g_source_remove,
+   (* memory / strings *)
+   g_malloc, g_malloc0, g_free, g_strdup, g_strcmp0,
+   (* time *)
+   g_usleep, g_get_monotonic_time, g_get_real_time;
+
+
+TYPE
+   gboolean = INTEGER;
+   gint     = INTEGER;
+   guint    = CARDINAL;
+   gchar    = CHAR;
+   guchar   = CHAR;
+   glong    = LONGINT;
+   gulong   = LONGCARD;
+   gint64   = LONGINT;
+   guint64  = LONGCARD;
+   gsize    = LONGCARD;
+   gssize   = LONGINT;
+   gdouble  = REAL;
+   gfloat   = SHORTREAL;
+   gpointer = ADDRESS;
+
+   GMainContext = ADDRESS;
+   GMainLoop    = ADDRESS;
+
+   (* gboolean GSourceFunc(gpointer user_data) *)
+   GSourceFunc = PROCEDURE (ADDRESS) : INTEGER;
+
+CONST
+   gFalse = 0;
+   gTrue  = 1;
+
+   (* GSourceFunc return values: keep (Continue) or drop (Remove) the source *)
+   GSourceRemove   = 0;
+   GSourceContinue = 1;
+
+(* GMainContext *g_main_context_default(void) *)
+PROCEDURE g_main_context_default () : GMainContext;
+
+(* GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) *)
+PROCEDURE g_main_loop_new (context: GMainContext; is_running: gboolean) : GMainLoop;
+
+(* void g_main_loop_run(GMainLoop *loop) *)
+PROCEDURE g_main_loop_run (loop: GMainLoop);
+
+(* void g_main_loop_quit(GMainLoop *loop) *)
+PROCEDURE g_main_loop_quit (loop: GMainLoop);
+
+(* void g_main_loop_unref(GMainLoop *loop) *)
+PROCEDURE g_main_loop_unref (loop: GMainLoop);
+
+(* guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) *)
+PROCEDURE g_timeout_add (interval: guint; function: GSourceFunc;
+                         data: ADDRESS) : [ guint ];
+
+(* guint g_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data) *)
+PROCEDURE g_timeout_add_seconds (interval: guint; function: GSourceFunc;
+                                 data: ADDRESS) : [ guint ];
+
+(* guint g_idle_add(GSourceFunc function, gpointer data) *)
+PROCEDURE g_idle_add (function: GSourceFunc; data: ADDRESS) : [ guint ];
+
+(* gboolean g_source_remove(guint tag) *)
+PROCEDURE g_source_remove (tag: guint) : [ gboolean ];
+
+(* gpointer g_malloc(gsize n_bytes) *)
+PROCEDURE g_malloc (n_bytes: gsize) : ADDRESS;
+
+(* gpointer g_malloc0(gsize n_bytes) *)
+PROCEDURE g_malloc0 (n_bytes: gsize) : ADDRESS;
+
+(* void g_free(gpointer mem) *)
+PROCEDURE g_free (mem: ADDRESS);
+
+(* gchar *g_strdup(const gchar *str) *)
+PROCEDURE g_strdup (str: ARRAY OF CHAR) : ADDRESS;
+
+(* gint g_strcmp0(const char *str1, const char *str2) *)
+PROCEDURE g_strcmp0 (str1, str2: ADDRESS) : INTEGER;
+
+(* void g_usleep(gulong microseconds) *)
+PROCEDURE g_usleep (microseconds: gulong);
+
+(* gint64 g_get_monotonic_time(void) *)
+PROCEDURE g_get_monotonic_time () : gint64;
+
+(* gint64 g_get_real_time(void) *)
+PROCEDURE g_get_real_time () : gint64;
+
+END GLib.

+ 28 - 0
src/GListModel.def

@@ -0,0 +1,28 @@
+DEFINITION MODULE FOR "C" GListModel ;
+
+(*
+   m2-GTK4 - GListModel: the GIO interface for flat, indexed models.
+   Mapped onto <gio/glistmodel.h>.
+
+   Implemented by GtkStringList, GListStore and others.  Note that
+   g_list_model_get_item() returns a reference the caller owns (release
+   with g_object_unref) and NIL for a NULL item.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GListModel,
+   g_list_model_get_n_items, g_list_model_get_item;
+
+
+TYPE
+   GListModel = ADDRESS;
+
+(* guint g_list_model_get_n_items(GListModel *list) *)
+PROCEDURE g_list_model_get_n_items (list: GListModel) : CARDINAL;
+
+(* gpointer g_list_model_get_item(GListModel *list, guint position) *)
+PROCEDURE g_list_model_get_item (list: GListModel; position: CARDINAL) : ADDRESS;
+
+END GListModel.

+ 47 - 0
src/GListStore.def

@@ -0,0 +1,47 @@
+DEFINITION MODULE FOR "C" GListStore ;
+
+(*
+   m2-GTK4 - GListStore: a simple in-memory GListModel backed by an
+   array.  Mapped onto <gio/gliststore.h>.
+
+   Create it with the GType of the items it will hold, e.g.
+   gtk_string_object_get_type() for strings or g_object_get_type() for
+   plain objects.  The store takes a reference on each item; the caller
+   may release its own reference after appending.
+
+   Signal: "items-changed" (the GListModel contract).  Read the contents
+   through the GListModel functions (GListModel.def).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GListStore,
+   g_list_store_new, g_list_store_append, g_list_store_insert,
+   g_list_store_remove, g_list_store_remove_all, g_list_store_find;
+
+
+TYPE
+   GListStore = ADDRESS;
+
+(* GListStore *g_list_store_new(GType item_type) *)
+PROCEDURE g_list_store_new (item_type: LONGCARD) : GListStore;
+
+(* void g_list_store_append(GListStore *store, gpointer item) *)
+PROCEDURE g_list_store_append (store: GListStore; item: ADDRESS);
+
+(* void g_list_store_insert(GListStore *store, guint position, gpointer item) *)
+PROCEDURE g_list_store_insert (store: GListStore; position: CARDINAL;
+                               item: ADDRESS);
+
+(* void g_list_store_remove(GListStore *store, guint position) *)
+PROCEDURE g_list_store_remove (store: GListStore; position: CARDINAL);
+
+(* void g_list_store_remove_all(GListStore *store) *)
+PROCEDURE g_list_store_remove_all (store: GListStore);
+
+(* gboolean g_list_store_find(GListStore *store, gpointer item, guint *position) *)
+PROCEDURE g_list_store_find (store: GListStore; item: ADDRESS;
+                             VAR position: CARDINAL) : [ INTEGER ];
+
+END GListStore.

+ 87 - 0
src/GMenu.def

@@ -0,0 +1,87 @@
+DEFINITION MODULE FOR "C" GMenu ;
+
+(*
+   m2-GTK4 - GMenu and GMenuItem: a concrete GMenuModel.  Mapped onto
+   <gio/gmenu.h> (GMenuItem is declared in the same header).
+
+   The easy form names a label and a "detailed action" to activate:
+
+      g_menu_append(fileMenu, "Quit", "app.quit");
+      g_menu_append(viewMenu, "Bold", "win.bold");
+
+   where "app." / "win." select the application's or a
+   GtkApplicationWindow's action map.  Submenus are built as separate
+   GMenu objects and attached with g_menu_append_submenu().
+
+   g_menu_append() passes NIL as the item's target; for an action with
+   a parameter use a GMenuItem and set_action_and_target_value().
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GMenu, GMenuItem,
+   g_menu_new, g_menu_append, g_menu_prepend, g_menu_insert,
+   g_menu_append_submenu, g_menu_append_item,
+   g_menu_remove, g_menu_remove_all,
+   g_menu_item_new, g_menu_item_set_label, g_menu_item_set_submenu,
+   g_menu_item_set_action_and_target_value;
+
+
+TYPE
+   GMenu = ADDRESS;
+   GMenuItem = ADDRESS;
+
+(* GMenu *g_menu_new(void) *)
+PROCEDURE g_menu_new () : GMenu;
+
+(* void g_menu_append(GMenu *menu, const gchar *label,
+                      const gchar *detailed_action) *)
+PROCEDURE g_menu_append (menu: GMenu; label: ARRAY OF CHAR;
+                         detailed_action: ARRAY OF CHAR);
+
+(* void g_menu_prepend(GMenu *menu, const gchar *label,
+                       const gchar *detailed_action) *)
+PROCEDURE g_menu_prepend (menu: GMenu; label: ARRAY OF CHAR;
+                          detailed_action: ARRAY OF CHAR);
+
+(* void g_menu_insert(GMenu *menu, gint position, const gchar *label,
+                      const gchar *detailed_action) *)
+PROCEDURE g_menu_insert (menu: GMenu; position: INTEGER;
+                         label: ARRAY OF CHAR;
+                         detailed_action: ARRAY OF CHAR);
+
+(* void g_menu_append_submenu(GMenu *menu, const gchar *label,
+                              GMenuModel *submenu) *)
+PROCEDURE g_menu_append_submenu (menu: GMenu; label: ARRAY OF CHAR;
+                                 submenu: ADDRESS);
+
+(* void g_menu_append_item(GMenu *menu, GMenuItem *item) *)
+PROCEDURE g_menu_append_item (menu: GMenu; item: ADDRESS);
+
+(* void g_menu_remove(GMenu *menu, gint position) *)
+PROCEDURE g_menu_remove (menu: GMenu; position: INTEGER);
+
+(* void g_menu_remove_all(GMenu *menu) *)
+PROCEDURE g_menu_remove_all (menu: GMenu);
+
+(* GMenuItem *g_menu_item_new(const gchar *label,
+                              const gchar *detailed_action) *)
+PROCEDURE g_menu_item_new (label: ARRAY OF CHAR;
+                           detailed_action: ARRAY OF CHAR) : GMenuItem;
+
+(* void g_menu_item_set_label(GMenuItem *menu_item, const gchar *label) *)
+PROCEDURE g_menu_item_set_label (menu_item: GMenuItem;
+                                 label: ARRAY OF CHAR);
+
+(* void g_menu_item_set_submenu(GMenuItem *menu_item, GMenuModel *submenu) *)
+PROCEDURE g_menu_item_set_submenu (menu_item: GMenuItem; submenu: ADDRESS);
+
+(* void g_menu_item_set_action_and_target_value(GMenuItem *menu_item,
+                                                 const gchar *action_and_target,
+                                                 GVariant *target_value) *)
+PROCEDURE g_menu_item_set_action_and_target_value (menu_item: GMenuItem;
+                                                   action_and_target: ARRAY OF CHAR;
+                                                   target_value: ADDRESS);
+
+END GMenu.

+ 24 - 0
src/GMenuModel.def

@@ -0,0 +1,24 @@
+DEFINITION MODULE FOR "C" GMenuModel ;
+
+(*
+   m2-GTK4 - GMenuModel: the abstract model behind menus and menu
+   bars.  Mapped onto <gio/gmenumodel.h>.
+
+   GMenu (GMenu.def) is the concrete, easily built implementation.
+   GtkPopoverMenuBar and GtkMenuButton consume a GMenuModel.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GMenuModel,
+   g_menu_model_get_n_items;
+
+
+TYPE
+   GMenuModel = ADDRESS;
+
+(* gint g_menu_model_get_n_items(GMenuModel *model) *)
+PROCEDURE g_menu_model_get_n_items (model: GMenuModel) : INTEGER;
+
+END GMenuModel.

+ 94 - 0
src/GObject.def

@@ -0,0 +1,94 @@
+DEFINITION MODULE FOR "C" GObject ;
+
+(*
+   m2-GTK4 - GObject: reference counting, properties and signals.
+   Mapped onto <glib-object.h>.
+
+   Signals
+   -------
+   C exposes the g_signal_connect() macro which expands to
+   g_signal_connect_data(instance, name, handler, data, NULL, 0).
+   Because macros have no symbol, this binding calls the real
+   function g_signal_connect_data() directly; the pure-M2 helper
+   GtkUtils.Connect wraps the common case.
+
+   A signal handler is a normal C function pointer whose first
+   argument is the emitting instance and whose second is the
+   user data.  Declare a top-level Modula-2 procedure with the
+   right signature and pass it directly or via ADR(...):
+
+      PROCEDURE OnClicked (button: ADDRESS; data: ADDRESS);
+      ...
+      Connect(button, "clicked", ADR(OnClicked), NIL);
+
+   Because the arity and return type depend on the signal, the
+   generic GCallback below is an ADDRESS, as in C.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GObject, GType, GCallback, GClosureNotify, GConnectFlags, GSignalHandlerID,
+   GConnectDefault, GConnectAfter, GConnectSwapped,
+   g_object_get_type, g_object_new,
+   g_object_ref, g_object_unref,
+   g_signal_connect_data, g_signal_handler_disconnect,
+   g_signal_emit_by_name,
+   g_object_set, g_object_get;
+
+
+TYPE
+   GObject = ADDRESS;
+   (* A GType is a gsize-wide run-time type identifier. *)
+   GType = LONGCARD;
+   (* generic function pointer - pass ADR(proc) *)
+   GCallback = ADDRESS;
+   GClosureNotify = ADDRESS;
+   GConnectFlags = CARDINAL;
+   GSignalHandlerID = LONGCARD;
+
+CONST
+   GConnectDefault = 0;
+   GConnectAfter   = 1;   (* call the handler after the default handler *)
+   GConnectSwapped = 2;   (* swap instance and user data *)
+
+(* GType g_object_get_type(void) *)
+PROCEDURE g_object_get_type () : GType;
+
+(* gpointer g_object_new(GType object_type, const gchar *first_property_name, ...) *)
+PROCEDURE g_object_new (object_type: GType;
+                        first_property_name: ARRAY OF CHAR; ...) : ADDRESS;
+
+(* gpointer g_object_ref(gpointer object) *)
+PROCEDURE g_object_ref (object: GObject) : GObject;
+
+(* void g_object_unref(gpointer object) *)
+PROCEDURE g_object_unref (object: GObject);
+
+(* gulong g_signal_connect_data(gpointer instance, const gchar *detailed_signal,
+      GCallback c_handler, gpointer data, GClosureNotify destroy_data,
+      GConnectFlags connect_flags) *)
+PROCEDURE g_signal_connect_data (instance: GObject;
+                                 detailed_signal: ARRAY OF CHAR;
+                                 c_handler: GCallback;
+                                 data: ADDRESS;
+                                 destroy_data: GClosureNotify;
+                                 connect_flags: GConnectFlags) : [ GSignalHandlerID ];
+
+(* void g_signal_handler_disconnect(gpointer instance, gulong handler_id) *)
+PROCEDURE g_signal_handler_disconnect (instance: GObject;
+                                       handler_id: GSignalHandlerID);
+
+(* void g_signal_emit_by_name(gpointer instance, const gchar *detailed_signal, ...) *)
+PROCEDURE g_signal_emit_by_name (instance: GObject;
+                                 detailed_signal: ARRAY OF CHAR; ...);
+
+(* void g_object_set(gpointer object, const gchar *first_property_name, ...) *)
+PROCEDURE g_object_set (object: GObject;
+                        first_property_name: ARRAY OF CHAR; ...);
+
+(* void g_object_get(gpointer object, const gchar *first_property_name, ...) *)
+PROCEDURE g_object_get (object: GObject;
+                        first_property_name: ARRAY OF CHAR; ...);
+
+END GObject.

+ 72 - 0
src/GSettings.def

@@ -0,0 +1,72 @@
+DEFINITION MODULE FOR "C" GSettings ;
+
+(*
+   m2-GTK4 - GSettings: typed access to a schema's keys.  Mapped onto
+   <gio/gsettings.h>.
+
+   Create one with g_settings_new(schema_id); the schema must be
+   installed (or found via GSETTINGS_SCHEMA_DIR - see
+   GSettingsSchema.def for a safe existence check).  GSettings is a
+   GObject: release it with GObject.g_object_unref().
+
+   g_settings_get_string() returns a newly allocated string to be freed
+   with GLib.g_free().
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GSettings,
+   g_settings_new,
+   g_settings_get_boolean, g_settings_set_boolean,
+   g_settings_get_int, g_settings_set_int,
+   g_settings_get_string, g_settings_set_string,
+   g_settings_reset, g_settings_sync, g_settings_is_writable;
+
+
+TYPE
+   GSettings = ADDRESS;
+
+(* GSettings *g_settings_new(const gchar *schema_id) *)
+PROCEDURE g_settings_new (schema_id: ARRAY OF CHAR) : GSettings;
+
+(* gboolean g_settings_get_boolean(GSettings *settings, const gchar *key) *)
+PROCEDURE g_settings_get_boolean (settings: GSettings;
+                                  key: ARRAY OF CHAR) : [ INTEGER ];
+
+(* gboolean g_settings_set_boolean(GSettings *settings, const gchar *key,
+                                    gboolean value) *)
+PROCEDURE g_settings_set_boolean (settings: GSettings;
+                                  key: ARRAY OF CHAR;
+                                  value: INTEGER) : [ INTEGER ];
+
+(* gint g_settings_get_int(GSettings *settings, const gchar *key) *)
+PROCEDURE g_settings_get_int (settings: GSettings;
+                              key: ARRAY OF CHAR) : [ INTEGER ];
+
+(* gboolean g_settings_set_int(GSettings *settings, const gchar *key, gint value) *)
+PROCEDURE g_settings_set_int (settings: GSettings;
+                              key: ARRAY OF CHAR;
+                              value: INTEGER) : [ INTEGER ];
+
+(* gchar *g_settings_get_string(GSettings *settings, const gchar *key) *)
+PROCEDURE g_settings_get_string (settings: GSettings;
+                                 key: ARRAY OF CHAR) : ADDRESS;
+
+(* gboolean g_settings_set_string(GSettings *settings, const gchar *key,
+                                   const gchar *value) *)
+PROCEDURE g_settings_set_string (settings: GSettings;
+                                 key: ARRAY OF CHAR;
+                                 value: ARRAY OF CHAR) : [ INTEGER ];
+
+(* void g_settings_reset(GSettings *settings, const gchar *key) *)
+PROCEDURE g_settings_reset (settings: GSettings; key: ARRAY OF CHAR);
+
+(* void g_settings_sync(void) *)
+PROCEDURE g_settings_sync ();
+
+(* gboolean g_settings_is_writable(GSettings *settings, const gchar *name) *)
+PROCEDURE g_settings_is_writable (settings: GSettings;
+                                  name: ARRAY OF CHAR) : [ INTEGER ];
+
+END GSettings.

+ 44 - 0
src/GSettingsSchema.def

@@ -0,0 +1,44 @@
+DEFINITION MODULE FOR "C" GSettingsSchema ;
+
+(*
+   m2-GTK4 - GSettingsSchema: inspect installed schemas.  Mapped onto
+   <gio/gsettingsschema.h>.
+
+   g_settings_new() aborts the process if the schema does not exist, so
+   look it up first with g_settings_schema_source_lookup() when the
+   schema may be optional.  Release a looked-up schema with
+   g_settings_schema_unref().
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GSettingsSchemaSource, GSettingsSchema,
+   g_settings_schema_source_get_default,
+   g_settings_schema_source_lookup,
+   g_settings_schema_unref,
+   g_settings_schema_has_key;
+
+
+TYPE
+   GSettingsSchemaSource = ADDRESS;
+   GSettingsSchema = ADDRESS;
+
+(* GSettingsSchemaSource *g_settings_schema_source_get_default(void) *)
+PROCEDURE g_settings_schema_source_get_default () : GSettingsSchemaSource;
+
+(* GSettingsSchema *g_settings_schema_source_lookup(GSettingsSchemaSource *source,
+                                                     const gchar *schema_id,
+                                                     gboolean recursive) *)
+PROCEDURE g_settings_schema_source_lookup (source: GSettingsSchemaSource;
+                                           schema_id: ARRAY OF CHAR;
+                                           recursive: INTEGER) : GSettingsSchema;
+
+(* void g_settings_schema_unref(GSettingsSchema *schema) *)
+PROCEDURE g_settings_schema_unref (schema: GSettingsSchema);
+
+(* gboolean g_settings_schema_has_key(GSettingsSchema *schema, const gchar *name) *)
+PROCEDURE g_settings_schema_has_key (schema: GSettingsSchema;
+                                     name: ARRAY OF CHAR) : [ INTEGER ];
+
+END GSettingsSchema.

+ 49 - 0
src/GSimpleAction.def

@@ -0,0 +1,49 @@
+DEFINITION MODULE FOR "C" GSimpleAction ;
+
+(*
+   m2-GTK4 - GSimpleAction: the simplest GAction implementation.
+   Mapped onto <gio/gsimpleaction.h>.
+
+   A parameterless action is created with a NIL parameter type:
+      action := g_simple_action_new("quit", NIL);
+   A stateful action carries an initial GVariant state:
+      action := g_simple_action_new_stateful("bold", NIL,
+                                             g_variant_new_boolean(0));
+
+   Signals:
+     "activate"     void(GSimpleAction*, GVariant *parameter, gpointer)
+     "change-state" void(GSimpleAction*, GVariant *value, gpointer)
+   Both callbacks have the same (action, variant, data) shape.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GSimpleAction,
+   g_simple_action_new, g_simple_action_new_stateful,
+   g_simple_action_set_enabled, g_simple_action_set_state;
+
+
+TYPE
+   GSimpleAction = ADDRESS;
+
+(* GSimpleAction *g_simple_action_new(const gchar *name,
+                                       const GVariantType *parameter_type) *)
+PROCEDURE g_simple_action_new (name: ARRAY OF CHAR;
+                               parameter_type: ADDRESS) : GSimpleAction;
+
+(* GSimpleAction *g_simple_action_new_stateful(const gchar *name,
+                                                const GVariantType *parameter_type,
+                                                GVariant *state) *)
+PROCEDURE g_simple_action_new_stateful (name: ARRAY OF CHAR;
+                                        parameter_type: ADDRESS;
+                                        state: ADDRESS) : GSimpleAction;
+
+(* void g_simple_action_set_enabled(GSimpleAction *simple, gboolean enabled) *)
+PROCEDURE g_simple_action_set_enabled (simple: GSimpleAction;
+                                       enabled: INTEGER);
+
+(* void g_simple_action_set_state(GSimpleAction *simple, GVariant *value) *)
+PROCEDURE g_simple_action_set_state (simple: GSimpleAction; value: ADDRESS);
+
+END GSimpleAction.

+ 55 - 0
src/GVariant.def

@@ -0,0 +1,55 @@
+DEFINITION MODULE FOR "C" GVariant ;
+
+(*
+   m2-GTK4 - GVariant: GIO's tagged value type.  Mapped onto
+   <glib/gvariant.h>.
+
+   Only the small subset used by actions and menu targets is bound
+   here: booleans, strings and 32-bit integers.  GVariant is an
+   opaque, reference-counted value; g_variant_new_* return a "floating"
+   reference that is consumed when handed to a GAction or menu item,
+   whereas values obtained with g_variant_get / g_action_get_state own
+   a reference and must be released with g_variant_unref.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GVariant,
+   g_variant_new_boolean, g_variant_get_boolean,
+   g_variant_new_string, g_variant_get_string,
+   g_variant_new_int32, g_variant_get_int32,
+   g_variant_ref, g_variant_unref, g_variant_is_floating;
+
+
+TYPE
+   GVariant = ADDRESS;
+
+(* GVariant *g_variant_new_boolean(gboolean value) *)
+PROCEDURE g_variant_new_boolean (value: INTEGER) : GVariant;
+
+(* gboolean g_variant_get_boolean(GVariant *value) *)
+PROCEDURE g_variant_get_boolean (value: GVariant) : [ INTEGER ];
+
+(* GVariant *g_variant_new_string(const gchar *string) *)
+PROCEDURE g_variant_new_string (str: ARRAY OF CHAR) : GVariant;
+
+(* const gchar *g_variant_get_string(GVariant *value, gsize *length) *)
+PROCEDURE g_variant_get_string (value: GVariant; length: ADDRESS) : ADDRESS;
+
+(* GVariant *g_variant_new_int32(gint32 value) *)
+PROCEDURE g_variant_new_int32 (value: INTEGER) : GVariant;
+
+(* gint32 g_variant_get_int32(GVariant *value) *)
+PROCEDURE g_variant_get_int32 (value: GVariant) : [ INTEGER ];
+
+(* GVariant *g_variant_ref(GVariant *value) *)
+PROCEDURE g_variant_ref (value: GVariant) : GVariant;
+
+(* void g_variant_unref(GVariant *value) *)
+PROCEDURE g_variant_unref (value: GVariant);
+
+(* gboolean g_variant_is_floating(GVariant *value) *)
+PROCEDURE g_variant_is_floating (value: GVariant) : [ INTEGER ];
+
+END GVariant.

+ 57 - 0
src/Gio.def

@@ -0,0 +1,57 @@
+DEFINITION MODULE FOR "C" Gio ;
+
+(*
+   m2-GTK4 - GIO application core: GApplication, the object that owns
+   the process main loop.  Mapped onto <gio/gapplication.h>.
+
+   GTK4 programs no longer call gtk_main(); a GtkApplication (which is
+   a GApplication) drives the loop through g_application_run().  The
+   loop keeps running while the application holds at least one window
+   or an explicit hold().
+
+   Flags map 1:1 onto GApplicationFlags (<gio/gioenums.h>).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GApplication, GApplicationFlags,
+   GApplicationDefaultFlags, GApplicationIsService, GApplicationIsLauncher,
+   GApplicationHandlesOpen, GApplicationHandlesCommandLine,
+   GApplicationSendEnvironment, GApplicationNonUnique,
+   GApplicationCanOverrideAppId,
+   g_application_run, g_application_quit,
+   g_application_hold, g_application_release, g_application_get_is_running;
+
+
+TYPE
+   GApplication = ADDRESS;
+   GApplicationFlags = CARDINAL;
+
+CONST
+   GApplicationDefaultFlags       = 0;
+   GApplicationIsService          = 1;    (* 1 << 0 *)
+   GApplicationIsLauncher         = 2;    (* 1 << 1 *)
+   GApplicationHandlesOpen        = 4;    (* 1 << 2 *)
+   GApplicationHandlesCommandLine = 8;    (* 1 << 3 *)
+   GApplicationSendEnvironment    = 16;   (* 1 << 4 *)
+   GApplicationNonUnique          = 32;   (* 1 << 5 *)
+   GApplicationCanOverrideAppId   = 64;   (* 1 << 6 *)
+
+(* int g_application_run(GApplication *application, int argc, char **argv) *)
+PROCEDURE g_application_run (application: GApplication;
+                             argc: INTEGER; argv: ADDRESS) : [ INTEGER ];
+
+(* void g_application_quit(GApplication *application) *)
+PROCEDURE g_application_quit (application: GApplication);
+
+(* void g_application_hold(GApplication *application) *)
+PROCEDURE g_application_hold (application: GApplication);
+
+(* void g_application_release(GApplication *application) *)
+PROCEDURE g_application_release (application: GApplication);
+
+(* gboolean g_application_get_is_running(GApplication *application) *)
+PROCEDURE g_application_get_is_running (application: GApplication) : [ INTEGER ];
+
+END Gio.

+ 37 - 0
src/GioError.def

@@ -0,0 +1,37 @@
+DEFINITION MODULE FOR "C" GioError ;
+
+(*
+   m2-GTK4 - GioError: the GIO error domain.  Mapped onto
+   <gio/gioerror.h>.
+
+   Combine g_io_error_quark() with a code and GError.g_error_matches()
+   to test what went wrong:
+
+      IF g_error_matches(err, g_io_error_quark(), GIOErrorNotFound) # 0 THEN ...
+*)
+
+EXPORT UNQUALIFIED
+   GIOErrorEnum,
+   GIOErrorFailed, GIOErrorNotFound, GIOErrorExists, GIOErrorIsDirectory,
+   GIOErrorNotDirectory, GIOErrorNotEmpty, GIOErrorPermissionDenied,
+   GIOErrorNotSupported,
+   g_io_error_quark;
+
+
+TYPE
+   GIOErrorEnum = CARDINAL;
+
+CONST
+   GIOErrorFailed         = 0;
+   GIOErrorNotFound       = 1;
+   GIOErrorExists         = 2;
+   GIOErrorIsDirectory    = 3;
+   GIOErrorNotDirectory   = 4;
+   GIOErrorNotEmpty       = 5;
+   GIOErrorPermissionDenied = 14;
+   GIOErrorNotSupported   = 15;
+
+(* GQuark g_io_error_quark(void) *)
+PROCEDURE g_io_error_quark () : CARDINAL;
+
+END GioError.

+ 40 - 0
src/Gtk.def

@@ -0,0 +1,40 @@
+DEFINITION MODULE FOR "C" Gtk ;
+
+(*
+   m2-GTK4 - GTK library init and version.  Mapped onto <gtk/gtk.h>.
+
+   In GTK4 the classic gtk_init()/gtk_main() pair is gone: use a
+   GtkApplication (see GtkApplication.def / Gio.def) and
+   g_application_run().  gtk_init() still exists and is harmless to
+   call from a plain (non-application) program, so both are bound.
+
+   Version helpers are real functions and are handy in tests.
+*)
+
+EXPORT UNQUALIFIED
+   gtk_init, gtk_init_check,
+   gtk_get_major_version, gtk_get_minor_version, gtk_get_micro_version,
+   gtk_get_binary_age, gtk_get_interface_age;
+
+(* void gtk_init(void) *)
+PROCEDURE gtk_init ();
+
+(* gboolean gtk_init_check(void) *)
+PROCEDURE gtk_init_check () : [ INTEGER ];
+
+(* guint gtk_get_major_version(void) *)
+PROCEDURE gtk_get_major_version () : CARDINAL;
+
+(* guint gtk_get_minor_version(void) *)
+PROCEDURE gtk_get_minor_version () : CARDINAL;
+
+(* guint gtk_get_micro_version(void) *)
+PROCEDURE gtk_get_micro_version () : CARDINAL;
+
+(* guint gtk_get_binary_age(void) *)
+PROCEDURE gtk_get_binary_age () : CARDINAL;
+
+(* guint gtk_get_interface_age(void) *)
+PROCEDURE gtk_get_interface_age () : CARDINAL;
+
+END Gtk.

+ 57 - 0
src/GtkApplication.def

@@ -0,0 +1,57 @@
+DEFINITION MODULE FOR "C" GtkApplication ;
+
+(*
+   m2-GTK4 - GtkApplication: a GApplication with GTK integration.
+   Mapped onto <gtk/gtkapplication.h>.
+
+   Create one with gtk_application_new(application_id, flags), connect
+   the "activate" signal, then hand it to g_application_run() (Gio).
+
+   The application id must be a valid D-Bus name (reverse DNS, e.g.
+   "org.example.MyApp") or the empty string to stay unique.  Passing
+   an empty id is allowed but then the NON_UNIQUE-style behaviour is
+   implied.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkApplication,
+   gtk_application_new,
+   gtk_application_add_window, gtk_application_remove_window,
+   gtk_application_get_windows,
+   gtk_application_set_menubar, gtk_application_set_accels_for_action;
+
+
+TYPE
+   GtkApplication = ADDRESS;
+
+(* GtkApplication *gtk_application_new(const char *application_id,
+                                       GApplicationFlags flags) *)
+PROCEDURE gtk_application_new (application_id: ARRAY OF CHAR;
+                               flags: CARDINAL) : GtkApplication;
+
+(* void gtk_application_add_window(GtkApplication *application, GtkWindow *window) *)
+PROCEDURE gtk_application_add_window (application: GtkApplication;
+                                      window: ADDRESS);
+
+(* void gtk_application_remove_window(GtkApplication *application, GtkWindow *window) *)
+PROCEDURE gtk_application_remove_window (application: GtkApplication;
+                                         window: ADDRESS);
+
+(* GList *gtk_application_get_windows(GtkApplication *application) *)
+PROCEDURE gtk_application_get_windows (application: GtkApplication) : ADDRESS;
+
+(* void gtk_application_set_menubar(GtkApplication *application,
+                                    GMenuModel *menubar) *)
+PROCEDURE gtk_application_set_menubar (application: GtkApplication;
+                                       menubar: ADDRESS);
+
+(* void gtk_application_set_accels_for_action(GtkApplication *application,
+                                              const char *detailed_action_name,
+                                              const char * const *accels) *)
+PROCEDURE gtk_application_set_accels_for_action (application: GtkApplication;
+                                                 detailed_action_name: ARRAY OF CHAR;
+                                                 accels: ADDRESS);
+
+END GtkApplication.

+ 38 - 0
src/GtkApplicationWindow.def

@@ -0,0 +1,38 @@
+DEFINITION MODULE FOR "C" GtkApplicationWindow ;
+
+(*
+   m2-GTK4 - GtkApplicationWindow: a GtkWindow that also implements
+   GActionMap, so window-scoped actions ("win.<name>") can be added to
+   it.  Mapped onto <gtk/gtkapplicationwindow.h>.
+
+   Because it derives from GtkWindow, all GtkWindow functions
+   (set_title, set_child, present, ...) apply.
+
+   The menu bar is only shown on platforms that use one (macOS); on
+   Linux build a GtkPopoverMenuBar yourself from the same GMenuModel.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkApplicationWindow,
+   gtk_application_window_new,
+   gtk_application_window_set_show_menubar,
+   gtk_application_window_get_show_menubar;
+
+
+TYPE
+   GtkApplicationWindow = ADDRESS;
+
+(* GtkWidget *gtk_application_window_new(GtkApplication *application) *)
+PROCEDURE gtk_application_window_new (application: ADDRESS) : GtkApplicationWindow;
+
+(* void gtk_application_window_set_show_menubar(GtkApplicationWindow *window,
+                                                 gboolean show_menubar) *)
+PROCEDURE gtk_application_window_set_show_menubar (window: GtkApplicationWindow;
+                                                   show_menubar: INTEGER);
+
+(* gboolean gtk_application_window_get_show_menubar(GtkApplicationWindow *window) *)
+PROCEDURE gtk_application_window_get_show_menubar (window: GtkApplicationWindow) : [ INTEGER ];
+
+END GtkApplicationWindow.

+ 42 - 0
src/GtkBox.def

@@ -0,0 +1,42 @@
+DEFINITION MODULE FOR "C" GtkBox ;
+
+(*
+   m2-GTK4 - GtkBox: a simple one-dimensional container.  Mapped onto
+   <gtk/gtkbox.h>.
+
+   GTK4 boxes take no "homogeneous"/"expand" child arguments: append
+   or prepend children, then use the per-widget GtkWidget layout
+   helpers (hexpand, halign, margins) to control their allocation.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+FROM GtkEnums IMPORT GtkOrientation;
+
+EXPORT UNQUALIFIED
+   GtkBox,
+   gtk_box_new, gtk_box_append, gtk_box_prepend, gtk_box_remove,
+   gtk_box_set_spacing, gtk_box_get_spacing;
+
+
+TYPE
+   GtkBox = ADDRESS;
+
+(* GtkWidget *gtk_box_new(GtkOrientation orientation, int spacing) *)
+PROCEDURE gtk_box_new (orientation: GtkOrientation; spacing: INTEGER) : GtkBox;
+
+(* void gtk_box_append(GtkBox *box, GtkWidget *child) *)
+PROCEDURE gtk_box_append (box: GtkBox; child: ADDRESS);
+
+(* void gtk_box_prepend(GtkBox *box, GtkWidget *child) *)
+PROCEDURE gtk_box_prepend (box: GtkBox; child: ADDRESS);
+
+(* void gtk_box_remove(GtkBox *box, GtkWidget *child) *)
+PROCEDURE gtk_box_remove (box: GtkBox; child: ADDRESS);
+
+(* void gtk_box_set_spacing(GtkBox *box, int spacing) *)
+PROCEDURE gtk_box_set_spacing (box: GtkBox; spacing: INTEGER);
+
+(* int gtk_box_get_spacing(GtkBox *box) *)
+PROCEDURE gtk_box_get_spacing (box: GtkBox) : INTEGER;
+
+END GtkBox.

+ 39 - 0
src/GtkButton.def

@@ -0,0 +1,39 @@
+DEFINITION MODULE FOR "C" GtkButton ;
+
+(*
+   m2-GTK4 - GtkButton: a push button.  Mapped onto <gtk/gtkbutton.h>.
+
+   The interesting signal is "clicked", a C callback of the shape
+   void handler(GtkButton *button, gpointer user_data).
+
+   connect it with GObject.g_signal_connect_data() or the
+   GtkUtils.Connect() helper.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkButton,
+   gtk_button_new, gtk_button_new_with_label, gtk_button_new_with_mnemonic,
+   gtk_button_set_label, gtk_button_get_label;
+
+
+TYPE
+   GtkButton = ADDRESS;
+
+(* GtkWidget *gtk_button_new(void) *)
+PROCEDURE gtk_button_new () : GtkButton;
+
+(* GtkWidget *gtk_button_new_with_label(const char *label) *)
+PROCEDURE gtk_button_new_with_label (label: ARRAY OF CHAR) : GtkButton;
+
+(* GtkWidget *gtk_button_new_with_mnemonic(const char *label) *)
+PROCEDURE gtk_button_new_with_mnemonic (label: ARRAY OF CHAR) : GtkButton;
+
+(* void gtk_button_set_label(GtkButton *button, const char *label) *)
+PROCEDURE gtk_button_set_label (button: GtkButton; label: ARRAY OF CHAR);
+
+(* const char *gtk_button_get_label(GtkButton *button) *)
+PROCEDURE gtk_button_get_label (button: GtkButton) : ADDRESS;
+
+END GtkButton.

+ 58 - 0
src/GtkCheckButton.def

@@ -0,0 +1,58 @@
+DEFINITION MODULE FOR "C" GtkCheckButton ;
+
+(*
+   m2-GTK4 - GtkCheckButton: a check box / toggle.  Mapped onto
+   <gtk/gtkcheckbutton.h>.
+
+   Use gtk_check_button_set_group() (not bound yet) to make members of
+   a group behave as radio buttons.
+
+   Signal: "toggled", handler void(GtkCheckButton*, gpointer).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkCheckButton,
+   gtk_check_button_new, gtk_check_button_new_with_label,
+   gtk_check_button_new_with_mnemonic,
+   gtk_check_button_get_active, gtk_check_button_set_active,
+   gtk_check_button_get_label, gtk_check_button_set_label,
+   gtk_check_button_get_inconsistent, gtk_check_button_set_inconsistent;
+
+
+TYPE
+   GtkCheckButton = ADDRESS;
+
+(* GtkWidget *gtk_check_button_new(void) *)
+PROCEDURE gtk_check_button_new () : GtkCheckButton;
+
+(* GtkWidget *gtk_check_button_new_with_label(const char *label) *)
+PROCEDURE gtk_check_button_new_with_label (label: ARRAY OF CHAR) : GtkCheckButton;
+
+(* GtkWidget *gtk_check_button_new_with_mnemonic(const char *label) *)
+PROCEDURE gtk_check_button_new_with_mnemonic (label: ARRAY OF CHAR) : GtkCheckButton;
+
+(* gboolean gtk_check_button_get_active(GtkCheckButton *self) *)
+PROCEDURE gtk_check_button_get_active (self: GtkCheckButton) : [ INTEGER ];
+
+(* void gtk_check_button_set_active(GtkCheckButton *self, gboolean is_active) *)
+PROCEDURE gtk_check_button_set_active (self: GtkCheckButton;
+                                       is_active: INTEGER);
+
+(* const char *gtk_check_button_get_label(GtkCheckButton *self) *)
+PROCEDURE gtk_check_button_get_label (self: GtkCheckButton) : ADDRESS;
+
+(* void gtk_check_button_set_label(GtkCheckButton *self, const char *label) *)
+PROCEDURE gtk_check_button_set_label (self: GtkCheckButton;
+                                      label: ARRAY OF CHAR);
+
+(* gboolean gtk_check_button_get_inconsistent(GtkCheckButton *check_button) *)
+PROCEDURE gtk_check_button_get_inconsistent (self: GtkCheckButton) : [ INTEGER ];
+
+(* void gtk_check_button_set_inconsistent(GtkCheckButton *check_button,
+                                           gboolean inconsistent) *)
+PROCEDURE gtk_check_button_set_inconsistent (self: GtkCheckButton;
+                                             inconsistent: INTEGER);
+
+END GtkCheckButton.

+ 63 - 0
src/GtkColumnView.def

@@ -0,0 +1,63 @@
+DEFINITION MODULE FOR "C" GtkColumnView ;
+
+(*
+   m2-GTK4 - GtkColumnView: a multi-column, model-driven table.
+   Mapped onto <gtk/gtkcolumnview.h>.
+
+   Created from a GtkSelectionModel; columns (GtkColumnViewColumn) are
+   appended afterwards, each with its own factory.  The factory
+   callbacks receive a GtkColumnViewCell.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkColumnView,
+   gtk_column_view_new,
+   gtk_column_view_set_model, gtk_column_view_get_model,
+   gtk_column_view_append_column, gtk_column_view_remove_column,
+   gtk_column_view_get_columns,
+   gtk_column_view_set_show_row_separators,
+   gtk_column_view_get_show_row_separators,
+   gtk_column_view_set_show_column_separators,
+   gtk_column_view_get_show_column_separators;
+
+
+TYPE
+   GtkColumnView = ADDRESS;
+
+(* GtkWidget *gtk_column_view_new(GtkSelectionModel *model) *)
+PROCEDURE gtk_column_view_new (model: ADDRESS) : GtkColumnView;
+
+(* void gtk_column_view_set_model(GtkColumnView *self, GtkSelectionModel *model) *)
+PROCEDURE gtk_column_view_set_model (self: GtkColumnView; model: ADDRESS);
+
+(* GtkSelectionModel *gtk_column_view_get_model(GtkColumnView *self) *)
+PROCEDURE gtk_column_view_get_model (self: GtkColumnView) : ADDRESS;
+
+(* void gtk_column_view_append_column(GtkColumnView *self, GtkColumnViewColumn *column) *)
+PROCEDURE gtk_column_view_append_column (self: GtkColumnView;
+                                         column: ADDRESS);
+
+(* void gtk_column_view_remove_column(GtkColumnView *self, GtkColumnViewColumn *column) *)
+PROCEDURE gtk_column_view_remove_column (self: GtkColumnView;
+                                         column: ADDRESS);
+
+(* GListModel *gtk_column_view_get_columns(GtkColumnView *self) *)
+PROCEDURE gtk_column_view_get_columns (self: GtkColumnView) : ADDRESS;
+
+(* void gtk_column_view_set_show_row_separators(GtkColumnView *self, gboolean show) *)
+PROCEDURE gtk_column_view_set_show_row_separators (self: GtkColumnView;
+                                                   show: INTEGER);
+
+(* gboolean gtk_column_view_get_show_row_separators(GtkColumnView *self) *)
+PROCEDURE gtk_column_view_get_show_row_separators (self: GtkColumnView) : [ INTEGER ];
+
+(* void gtk_column_view_set_show_column_separators(GtkColumnView *self, gboolean show) *)
+PROCEDURE gtk_column_view_set_show_column_separators (self: GtkColumnView;
+                                                      show: INTEGER);
+
+(* gboolean gtk_column_view_get_show_column_separators(GtkColumnView *self) *)
+PROCEDURE gtk_column_view_get_show_column_separators (self: GtkColumnView) : [ INTEGER ];
+
+END GtkColumnView.

+ 43 - 0
src/GtkColumnViewCell.def

@@ -0,0 +1,43 @@
+DEFINITION MODULE FOR "C" GtkColumnViewCell ;
+
+(*
+   m2-GTK4 - GtkColumnViewCell: the object handed to a GtkColumnView
+   column factory.  Mapped onto <gtk/gtkcolumnviewcell.h>.
+
+   GtkColumnViewCell derives from GtkListItem, so gtk_list_item_* also
+   applies; the cell-specific accessors below are the direct ones.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkColumnViewCell,
+   gtk_column_view_cell_get_item, gtk_column_view_cell_get_position,
+   gtk_column_view_cell_get_child, gtk_column_view_cell_set_child,
+   gtk_column_view_cell_get_focusable, gtk_column_view_cell_set_focusable;
+
+
+TYPE
+   GtkColumnViewCell = ADDRESS;
+
+(* gpointer gtk_column_view_cell_get_item(GtkColumnViewCell *self) *)
+PROCEDURE gtk_column_view_cell_get_item (self: GtkColumnViewCell) : ADDRESS;
+
+(* guint gtk_column_view_cell_get_position(GtkColumnViewCell *self) *)
+PROCEDURE gtk_column_view_cell_get_position (self: GtkColumnViewCell) : CARDINAL;
+
+(* GtkWidget *gtk_column_view_cell_get_child(GtkColumnViewCell *self) *)
+PROCEDURE gtk_column_view_cell_get_child (self: GtkColumnViewCell) : ADDRESS;
+
+(* void gtk_column_view_cell_set_child(GtkColumnViewCell *self, GtkWidget *child) *)
+PROCEDURE gtk_column_view_cell_set_child (self: GtkColumnViewCell;
+                                          child: ADDRESS);
+
+(* gboolean gtk_column_view_cell_get_focusable(GtkColumnViewCell *self) *)
+PROCEDURE gtk_column_view_cell_get_focusable (self: GtkColumnViewCell) : [ INTEGER ];
+
+(* void gtk_column_view_cell_set_focusable(GtkColumnViewCell *self, gboolean focusable) *)
+PROCEDURE gtk_column_view_cell_set_focusable (self: GtkColumnViewCell;
+                                              focusable: INTEGER);
+
+END GtkColumnViewCell.

+ 78 - 0
src/GtkColumnViewColumn.def

@@ -0,0 +1,78 @@
+DEFINITION MODULE FOR "C" GtkColumnViewColumn ;
+
+(*
+   m2-GTK4 - GtkColumnViewColumn: one column of a GtkColumnView.
+   Mapped onto <gtk/gtkcolumnviewcolumn.h>.
+
+   Create it with a title and a GtkListItemFactory (the factory's
+   callbacks receive a GtkColumnViewCell), then append it to the view.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkColumnViewColumn,
+   gtk_column_view_column_new,
+   gtk_column_view_column_set_title, gtk_column_view_column_get_title,
+   gtk_column_view_column_set_factory, gtk_column_view_column_get_factory,
+   gtk_column_view_column_set_expand, gtk_column_view_column_get_expand,
+   gtk_column_view_column_set_fixed_width,
+   gtk_column_view_column_get_fixed_width,
+   gtk_column_view_column_set_resizable,
+   gtk_column_view_column_get_resizable,
+   gtk_column_view_column_set_visible,
+   gtk_column_view_column_get_visible;
+
+
+TYPE
+   GtkColumnViewColumn = ADDRESS;
+
+(* GtkColumnViewColumn *gtk_column_view_column_new(const char *title,
+                                                    GtkListItemFactory *factory) *)
+PROCEDURE gtk_column_view_column_new (title: ARRAY OF CHAR;
+                                      factory: ADDRESS) : GtkColumnViewColumn;
+
+(* void gtk_column_view_column_set_title(GtkColumnViewColumn *self, const char *title) *)
+PROCEDURE gtk_column_view_column_set_title (self: GtkColumnViewColumn;
+                                            title: ARRAY OF CHAR);
+
+(* const char *gtk_column_view_column_get_title(GtkColumnViewColumn *self) *)
+PROCEDURE gtk_column_view_column_get_title (self: GtkColumnViewColumn) : ADDRESS;
+
+(* void gtk_column_view_column_set_factory(GtkColumnViewColumn *self,
+                                            GtkListItemFactory *factory) *)
+PROCEDURE gtk_column_view_column_set_factory (self: GtkColumnViewColumn;
+                                              factory: ADDRESS);
+
+(* GtkListItemFactory *gtk_column_view_column_get_factory(GtkColumnViewColumn *self) *)
+PROCEDURE gtk_column_view_column_get_factory (self: GtkColumnViewColumn) : ADDRESS;
+
+(* void gtk_column_view_column_set_expand(GtkColumnViewColumn *self, gboolean expand) *)
+PROCEDURE gtk_column_view_column_set_expand (self: GtkColumnViewColumn;
+                                             expand: INTEGER);
+
+(* gboolean gtk_column_view_column_get_expand(GtkColumnViewColumn *self) *)
+PROCEDURE gtk_column_view_column_get_expand (self: GtkColumnViewColumn) : [ INTEGER ];
+
+(* void gtk_column_view_column_set_fixed_width(GtkColumnViewColumn *self, int fixed_width) *)
+PROCEDURE gtk_column_view_column_set_fixed_width (self: GtkColumnViewColumn;
+                                                  fixed_width: INTEGER);
+
+(* int gtk_column_view_column_get_fixed_width(GtkColumnViewColumn *self) *)
+PROCEDURE gtk_column_view_column_get_fixed_width (self: GtkColumnViewColumn) : INTEGER;
+
+(* void gtk_column_view_column_set_resizable(GtkColumnViewColumn *self, gboolean resizable) *)
+PROCEDURE gtk_column_view_column_set_resizable (self: GtkColumnViewColumn;
+                                                resizable: INTEGER);
+
+(* gboolean gtk_column_view_column_get_resizable(GtkColumnViewColumn *self) *)
+PROCEDURE gtk_column_view_column_get_resizable (self: GtkColumnViewColumn) : [ INTEGER ];
+
+(* void gtk_column_view_column_set_visible(GtkColumnViewColumn *self, gboolean visible) *)
+PROCEDURE gtk_column_view_column_set_visible (self: GtkColumnViewColumn;
+                                              visible: INTEGER);
+
+(* gboolean gtk_column_view_column_get_visible(GtkColumnViewColumn *self) *)
+PROCEDURE gtk_column_view_column_get_visible (self: GtkColumnViewColumn) : [ INTEGER ];
+
+END GtkColumnViewColumn.

+ 57 - 0
src/GtkDropDown.def

@@ -0,0 +1,57 @@
+DEFINITION MODULE FOR "C" GtkDropDown ;
+
+(*
+   m2-GTK4 - GtkDropDown: choose one item from a model.  Mapped onto
+   <gtk/gtkdropdown.h>.
+
+   The model is a GListModel (e.g. GtkStringList).  The second argument
+   to gtk_drop_down_new() is a GtkExpression; pass NIL to display each
+   item with its default representation.
+
+   Signal: "notify::selected" (3-argument), emitted when the selection
+   changes.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkDropDown,
+   gtk_drop_down_new, gtk_drop_down_new_from_strings,
+   gtk_drop_down_set_model, gtk_drop_down_get_model,
+   gtk_drop_down_set_selected, gtk_drop_down_get_selected,
+   gtk_drop_down_get_selected_item,
+   gtk_drop_down_set_enable_search, gtk_drop_down_get_enable_search;
+
+
+TYPE
+   GtkDropDown = ADDRESS;
+
+(* GtkWidget *gtk_drop_down_new(GListModel *model, GtkExpression *expression) *)
+PROCEDURE gtk_drop_down_new (model: ADDRESS; expression: ADDRESS) : GtkDropDown;
+
+(* GtkWidget *gtk_drop_down_new_from_strings(const char * const *strings) *)
+PROCEDURE gtk_drop_down_new_from_strings (strings: ADDRESS) : GtkDropDown;
+
+(* void gtk_drop_down_set_model(GtkDropDown *self, GListModel *model) *)
+PROCEDURE gtk_drop_down_set_model (self: GtkDropDown; model: ADDRESS);
+
+(* GListModel *gtk_drop_down_get_model(GtkDropDown *self) *)
+PROCEDURE gtk_drop_down_get_model (self: GtkDropDown) : ADDRESS;
+
+(* void gtk_drop_down_set_selected(GtkDropDown *self, guint position) *)
+PROCEDURE gtk_drop_down_set_selected (self: GtkDropDown; position: CARDINAL);
+
+(* guint gtk_drop_down_get_selected(GtkDropDown *self) *)
+PROCEDURE gtk_drop_down_get_selected (self: GtkDropDown) : CARDINAL;
+
+(* gpointer gtk_drop_down_get_selected_item(GtkDropDown *self) *)
+PROCEDURE gtk_drop_down_get_selected_item (self: GtkDropDown) : ADDRESS;
+
+(* void gtk_drop_down_set_enable_search(GtkDropDown *self, gboolean enable_search) *)
+PROCEDURE gtk_drop_down_set_enable_search (self: GtkDropDown;
+                                           enable_search: INTEGER);
+
+(* gboolean gtk_drop_down_get_enable_search(GtkDropDown *self) *)
+PROCEDURE gtk_drop_down_get_enable_search (self: GtkDropDown) : [ INTEGER ];
+
+END GtkDropDown.

+ 62 - 0
src/GtkEditable.def

@@ -0,0 +1,62 @@
+DEFINITION MODULE FOR "C" GtkEditable ;
+
+(*
+   m2-GTK4 - GtkEditable: the text-editing interface implemented by
+   GtkEntry, GtkSearchEntry, GtkSpinButton, ...  Mapped onto
+   <gtk/gtkeditable.h>.
+
+   In GTK4 gtk_entry_get_text()/gtk_entry_set_text() are macros that
+   forward here, so this is where the real symbols live.  A GtkEntry
+   handle can be passed to any of these functions.
+
+   gtk_editable_get_text() returns a borrowed internal string - copy it
+   with GtkUtils.CStrToM2() before the widget changes.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkEditable,
+   gtk_editable_get_text, gtk_editable_set_text,
+   gtk_editable_get_editable, gtk_editable_set_editable,
+   gtk_editable_get_alignment, gtk_editable_set_alignment,
+   gtk_editable_select_region,
+   gtk_editable_set_position, gtk_editable_get_position;
+
+
+TYPE
+   GtkEditable = ADDRESS;
+
+(* const char *gtk_editable_get_text(GtkEditable *editable) *)
+PROCEDURE gtk_editable_get_text (editable: GtkEditable) : ADDRESS;
+
+(* void gtk_editable_set_text(GtkEditable *editable, const char *text) *)
+PROCEDURE gtk_editable_set_text (editable: GtkEditable; text: ARRAY OF CHAR);
+
+(* gboolean gtk_editable_get_editable(GtkEditable *editable) *)
+PROCEDURE gtk_editable_get_editable (editable: GtkEditable) : [ INTEGER ];
+
+(* void gtk_editable_set_editable(GtkEditable *editable, gboolean is_editable) *)
+PROCEDURE gtk_editable_set_editable (editable: GtkEditable;
+                                     is_editable: INTEGER);
+
+(* float gtk_editable_get_alignment(GtkEditable *editable) *)
+PROCEDURE gtk_editable_get_alignment (editable: GtkEditable) : SHORTREAL;
+
+(* void gtk_editable_set_alignment(GtkEditable *editable, float xalign) *)
+PROCEDURE gtk_editable_set_alignment (editable: GtkEditable;
+                                      xalign: SHORTREAL);
+
+(* void gtk_editable_select_region(GtkEditable *editable,
+                                    int start_pos, int end_pos) *)
+PROCEDURE gtk_editable_select_region (editable: GtkEditable;
+                                      start_pos, end_pos: INTEGER);
+
+(* void gtk_editable_set_position(GtkEditable *editable, int position) *)
+PROCEDURE gtk_editable_set_position (editable: GtkEditable;
+                                     position: INTEGER);
+
+(* int gtk_editable_get_position(GtkEditable *editable) *)
+PROCEDURE gtk_editable_get_position (editable: GtkEditable) : INTEGER;
+
+END GtkEditable.

+ 70 - 0
src/GtkEntry.def

@@ -0,0 +1,70 @@
+DEFINITION MODULE FOR "C" GtkEntry ;
+
+(*
+   m2-GTK4 - GtkEntry: a single-line text field.  Mapped onto
+   <gtk/gtkentry.h>.
+
+   GtkEntry implements GtkEditable, so use gtk_editable_get_text() /
+   gtk_editable_set_text() (GtkEditable.def) to read and write its
+   contents.  The entry-specific calls below cover placeholder text,
+   length limits, password visibility and the progress indicator.
+
+   Signals: "activate" (Enter pressed) and "changed" (text modified),
+   both handlers of the shape void(GtkEntry*, gpointer).
+*)
+
+FROM SYSTEM IMPORT ADDRESS, CARDINAL16;
+
+EXPORT UNQUALIFIED
+   GtkEntry,
+   gtk_entry_new,
+   gtk_entry_set_placeholder_text, gtk_entry_get_placeholder_text,
+   gtk_entry_set_max_length, gtk_entry_get_max_length,
+   gtk_entry_get_text_length,
+   gtk_entry_set_visibility, gtk_entry_get_visibility,
+   gtk_entry_set_activates_default, gtk_entry_get_activates_default,
+   gtk_entry_set_progress_fraction, gtk_entry_get_progress_fraction;
+
+
+TYPE
+   GtkEntry = ADDRESS;
+
+(* GtkWidget *gtk_entry_new(void) *)
+PROCEDURE gtk_entry_new () : GtkEntry;
+
+(* void gtk_entry_set_placeholder_text(GtkEntry *entry, const char *text) *)
+PROCEDURE gtk_entry_set_placeholder_text (entry: GtkEntry;
+                                          text: ARRAY OF CHAR);
+
+(* const char *gtk_entry_get_placeholder_text(GtkEntry *entry) *)
+PROCEDURE gtk_entry_get_placeholder_text (entry: GtkEntry) : ADDRESS;
+
+(* void gtk_entry_set_max_length(GtkEntry *entry, int max) *)
+PROCEDURE gtk_entry_set_max_length (entry: GtkEntry; max: INTEGER);
+
+(* int gtk_entry_get_max_length(GtkEntry *entry) *)
+PROCEDURE gtk_entry_get_max_length (entry: GtkEntry) : INTEGER;
+
+(* guint16 gtk_entry_get_text_length(GtkEntry *entry) *)
+PROCEDURE gtk_entry_get_text_length (entry: GtkEntry) : CARDINAL16;
+
+(* void gtk_entry_set_visibility(GtkEntry *entry, gboolean visible) *)
+PROCEDURE gtk_entry_set_visibility (entry: GtkEntry; visible: INTEGER);
+
+(* gboolean gtk_entry_get_visibility(GtkEntry *entry) *)
+PROCEDURE gtk_entry_get_visibility (entry: GtkEntry) : [ INTEGER ];
+
+(* void gtk_entry_set_activates_default(GtkEntry *entry, gboolean setting) *)
+PROCEDURE gtk_entry_set_activates_default (entry: GtkEntry; setting: INTEGER);
+
+(* gboolean gtk_entry_get_activates_default(GtkEntry *entry) *)
+PROCEDURE gtk_entry_get_activates_default (entry: GtkEntry) : [ INTEGER ];
+
+(* void gtk_entry_set_progress_fraction(GtkEntry *entry, double fraction) *)
+PROCEDURE gtk_entry_set_progress_fraction (entry: GtkEntry;
+                                           fraction: REAL);
+
+(* double gtk_entry_get_progress_fraction(GtkEntry *entry) *)
+PROCEDURE gtk_entry_get_progress_fraction (entry: GtkEntry) : REAL;
+
+END GtkEntry.

+ 58 - 0
src/GtkEnums.def

@@ -0,0 +1,58 @@
+DEFINITION MODULE FOR "C" GtkEnums ;
+
+(*
+   m2-GTK4 - GTK enumerations.  Mapped onto <gtk/gtkenums.h>.
+
+   Only constants and simple CARDINAL aliases live here, so this module
+   has no C symbols of its own: it is the shared home for enum values
+   that several widgets need (orientation, alignment, position).  The
+   numeric values match the C enumerators exactly.
+*)
+
+EXPORT UNQUALIFIED
+   GtkOrientation, GtkHorizontal, GtkVertical,
+   GtkAlign, GtkAlignFill, GtkAlignStart, GtkAlignEnd,
+   GtkAlignCenter, GtkAlignBaseline,
+   GtkPositionType, GtkPosLeft, GtkPosRight, GtkPosTop, GtkPosBottom,
+   GtkWrapMode, GtkWrapNone, GtkWrapChar, GtkWrapWord, GtkWrapWordChar,
+   GtkSelectionMode, GtkSelectionNone, GtkSelectionSingle,
+   GtkSelectionBrowse, GtkSelectionMultiple;
+
+TYPE
+   GtkOrientation = CARDINAL;
+   GtkAlign = CARDINAL;
+   GtkPositionType = CARDINAL;
+   GtkWrapMode = CARDINAL;
+   GtkSelectionMode = CARDINAL;
+
+CONST
+   (* GtkOrientation *)
+   GtkHorizontal = 0;
+   GtkVertical   = 1;
+
+   (* GtkAlign *)
+   GtkAlignFill     = 0;
+   GtkAlignStart    = 1;
+   GtkAlignEnd      = 2;
+   GtkAlignCenter   = 3;
+   GtkAlignBaseline = 4;
+
+   (* GtkPositionType *)
+   GtkPosLeft   = 0;
+   GtkPosRight  = 1;
+   GtkPosTop    = 2;
+   GtkPosBottom = 3;
+
+   (* GtkWrapMode *)
+   GtkWrapNone     = 0;
+   GtkWrapChar     = 1;
+   GtkWrapWord     = 2;
+   GtkWrapWordChar = 3;
+
+   (* GtkSelectionMode *)
+   GtkSelectionNone     = 0;
+   GtkSelectionSingle   = 1;
+   GtkSelectionBrowse   = 2;
+   GtkSelectionMultiple = 3;
+
+END GtkEnums.

+ 62 - 0
src/GtkExpander.def

@@ -0,0 +1,62 @@
+DEFINITION MODULE FOR "C" GtkExpander ;
+
+(*
+   m2-GTK4 - GtkExpander: a collapsible section with a label.
+   Mapped onto <gtk/gtkexpander.h>.
+
+   Signal: "notify::expanded" (3-argument) when the open/closed state
+   changes.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkExpander,
+   gtk_expander_new, gtk_expander_new_with_mnemonic,
+   gtk_expander_set_expanded, gtk_expander_get_expanded,
+   gtk_expander_set_label, gtk_expander_get_label,
+   gtk_expander_set_use_markup,
+   gtk_expander_set_resize_toplevel, gtk_expander_get_resize_toplevel,
+   gtk_expander_set_child, gtk_expander_get_child;
+
+
+TYPE
+   GtkExpander = ADDRESS;
+
+(* GtkWidget *gtk_expander_new(const char *label) *)
+PROCEDURE gtk_expander_new (label: ARRAY OF CHAR) : GtkExpander;
+
+(* GtkWidget *gtk_expander_new_with_mnemonic(const char *label) *)
+PROCEDURE gtk_expander_new_with_mnemonic (label: ARRAY OF CHAR) : GtkExpander;
+
+(* void gtk_expander_set_expanded(GtkExpander *expander, gboolean expanded) *)
+PROCEDURE gtk_expander_set_expanded (expander: GtkExpander; expanded: INTEGER);
+
+(* gboolean gtk_expander_get_expanded(GtkExpander *expander) *)
+PROCEDURE gtk_expander_get_expanded (expander: GtkExpander) : [ INTEGER ];
+
+(* void gtk_expander_set_label(GtkExpander *expander, const char *label) *)
+PROCEDURE gtk_expander_set_label (expander: GtkExpander; label: ARRAY OF CHAR);
+
+(* const char *gtk_expander_get_label(GtkExpander *expander) *)
+PROCEDURE gtk_expander_get_label (expander: GtkExpander) : ADDRESS;
+
+(* void gtk_expander_set_use_markup(GtkExpander *expander, gboolean use_markup) *)
+PROCEDURE gtk_expander_set_use_markup (expander: GtkExpander;
+                                       use_markup: INTEGER);
+
+(* void gtk_expander_set_resize_toplevel(GtkExpander *expander,
+                                          gboolean resize_toplevel) *)
+PROCEDURE gtk_expander_set_resize_toplevel (expander: GtkExpander;
+                                            resize_toplevel: INTEGER);
+
+(* gboolean gtk_expander_get_resize_toplevel(GtkExpander *expander) *)
+PROCEDURE gtk_expander_get_resize_toplevel (expander: GtkExpander) : [ INTEGER ];
+
+(* void gtk_expander_set_child(GtkExpander *expander, GtkWidget *child) *)
+PROCEDURE gtk_expander_set_child (expander: GtkExpander; child: ADDRESS);
+
+(* GtkWidget *gtk_expander_get_child(GtkExpander *expander) *)
+PROCEDURE gtk_expander_get_child (expander: GtkExpander) : ADDRESS;
+
+END GtkExpander.

+ 99 - 0
src/GtkFileDialog.def

@@ -0,0 +1,99 @@
+DEFINITION MODULE FOR "C" GtkFileDialog ;
+
+(*
+   m2-GTK4 - GtkFileDialog: the GTK4 native open/save/folder dialog.
+   Mapped onto <gtk/gtkfiledialog.h>.
+
+   This is the asynchronous API introduced in GTK 4.10 (it replaces
+   GtkFileChooserDialog).  Call gtk_file_dialog_open(), passing a
+   GAsyncReadyCallback (an ADDRESS here - pass ADR(proc)); when the user
+   finishes, the callback receives the GtkFileDialog as source object
+   and calls gtk_file_dialog_open_finish() to obtain a GFile (release it
+   with GObject.g_object_unref, and check for NIL).
+
+   The callback type is
+      void callback(GObject *source, GAsyncResult *result, gpointer user_data)
+   which matches GtkClosures.Handler3.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkFileDialog,
+   gtk_file_dialog_new,
+   gtk_file_dialog_open, gtk_file_dialog_open_finish,
+   gtk_file_dialog_save, gtk_file_dialog_save_finish,
+   gtk_file_dialog_select_folder, gtk_file_dialog_select_folder_finish,
+   gtk_file_dialog_set_title, gtk_file_dialog_get_title,
+   gtk_file_dialog_set_modal, gtk_file_dialog_get_modal,
+   gtk_file_dialog_set_initial_name, gtk_file_dialog_get_initial_name,
+   gtk_file_dialog_set_accept_label, gtk_file_dialog_get_accept_label;
+
+
+TYPE
+   GtkFileDialog = ADDRESS;
+
+(* GtkFileDialog *gtk_file_dialog_new(void) *)
+PROCEDURE gtk_file_dialog_new () : GtkFileDialog;
+
+(* void gtk_file_dialog_open(GtkFileDialog *self, GtkWindow *parent,
+                              GCancellable *cancellable,
+                              GAsyncReadyCallback callback, gpointer user_data) *)
+PROCEDURE gtk_file_dialog_open (self: GtkFileDialog; parent: ADDRESS;
+                                cancellable: ADDRESS;
+                                callback: ADDRESS; user_data: ADDRESS);
+
+(* GFile *gtk_file_dialog_open_finish(GtkFileDialog *self,
+                                       GAsyncResult *result, GError **error) *)
+PROCEDURE gtk_file_dialog_open_finish (self: GtkFileDialog;
+                                       result: ADDRESS;
+                                       error: ADDRESS) : ADDRESS;
+
+(* void gtk_file_dialog_save(...) - same shape as open *)
+PROCEDURE gtk_file_dialog_save (self: GtkFileDialog; parent: ADDRESS;
+                                cancellable: ADDRESS;
+                                callback: ADDRESS; user_data: ADDRESS);
+
+(* GFile *gtk_file_dialog_save_finish(...) *)
+PROCEDURE gtk_file_dialog_save_finish (self: GtkFileDialog;
+                                       result: ADDRESS;
+                                       error: ADDRESS) : ADDRESS;
+
+(* void gtk_file_dialog_select_folder(...) *)
+PROCEDURE gtk_file_dialog_select_folder (self: GtkFileDialog; parent: ADDRESS;
+                                         cancellable: ADDRESS;
+                                         callback: ADDRESS;
+                                         user_data: ADDRESS);
+
+(* GFile *gtk_file_dialog_select_folder_finish(...) *)
+PROCEDURE gtk_file_dialog_select_folder_finish (self: GtkFileDialog;
+                                                result: ADDRESS;
+                                                error: ADDRESS) : ADDRESS;
+
+(* void gtk_file_dialog_set_title(GtkFileDialog *self, const char *title) *)
+PROCEDURE gtk_file_dialog_set_title (self: GtkFileDialog; title: ARRAY OF CHAR);
+
+(* const char *gtk_file_dialog_get_title(GtkFileDialog *self) *)
+PROCEDURE gtk_file_dialog_get_title (self: GtkFileDialog) : ADDRESS;
+
+(* void gtk_file_dialog_set_modal(GtkFileDialog *self, gboolean modal) *)
+PROCEDURE gtk_file_dialog_set_modal (self: GtkFileDialog; modal: INTEGER);
+
+(* gboolean gtk_file_dialog_get_modal(GtkFileDialog *self) *)
+PROCEDURE gtk_file_dialog_get_modal (self: GtkFileDialog) : [ INTEGER ];
+
+(* void gtk_file_dialog_set_initial_name(GtkFileDialog *self, const char *name) *)
+PROCEDURE gtk_file_dialog_set_initial_name (self: GtkFileDialog;
+                                            name: ARRAY OF CHAR);
+
+(* const char *gtk_file_dialog_get_initial_name(GtkFileDialog *self) *)
+PROCEDURE gtk_file_dialog_get_initial_name (self: GtkFileDialog) : ADDRESS;
+
+(* void gtk_file_dialog_set_accept_label(GtkFileDialog *self, const char *label) *)
+PROCEDURE gtk_file_dialog_set_accept_label (self: GtkFileDialog;
+                                            label: ARRAY OF CHAR);
+
+(* const char *gtk_file_dialog_get_accept_label(GtkFileDialog *self) *)
+PROCEDURE gtk_file_dialog_get_accept_label (self: GtkFileDialog) : ADDRESS;
+
+END GtkFileDialog.

+ 51 - 0
src/GtkFrame.def

@@ -0,0 +1,51 @@
+DEFINITION MODULE FOR "C" GtkFrame ;
+
+(*
+   m2-GTK4 - GtkFrame: a container with an optional title/label border.
+   Mapped onto <gtk/gtkframe.h>.
+
+   The label can be a plain string (gtk_frame_set_label) or an arbitrary
+   widget (gtk_frame_set_label_widget).  The frame holds a single child.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkFrame,
+   gtk_frame_new, gtk_frame_set_label, gtk_frame_get_label,
+   gtk_frame_set_label_widget, gtk_frame_get_label_widget,
+   gtk_frame_set_label_align, gtk_frame_get_label_align,
+   gtk_frame_set_child, gtk_frame_get_child;
+
+
+TYPE
+   GtkFrame = ADDRESS;
+
+(* GtkWidget *gtk_frame_new(const char *label) *)
+PROCEDURE gtk_frame_new (label: ARRAY OF CHAR) : GtkFrame;
+
+(* void gtk_frame_set_label(GtkFrame *frame, const char *label) *)
+PROCEDURE gtk_frame_set_label (frame: GtkFrame; label: ARRAY OF CHAR);
+
+(* const char *gtk_frame_get_label(GtkFrame *frame) *)
+PROCEDURE gtk_frame_get_label (frame: GtkFrame) : ADDRESS;
+
+(* void gtk_frame_set_label_widget(GtkFrame *frame, GtkWidget *label_widget) *)
+PROCEDURE gtk_frame_set_label_widget (frame: GtkFrame; label_widget: ADDRESS);
+
+(* GtkWidget *gtk_frame_get_label_widget(GtkFrame *frame) *)
+PROCEDURE gtk_frame_get_label_widget (frame: GtkFrame) : ADDRESS;
+
+(* void gtk_frame_set_label_align(GtkFrame *frame, float xalign) *)
+PROCEDURE gtk_frame_set_label_align (frame: GtkFrame; xalign: SHORTREAL);
+
+(* float gtk_frame_get_label_align(GtkFrame *frame) *)
+PROCEDURE gtk_frame_get_label_align (frame: GtkFrame) : SHORTREAL;
+
+(* void gtk_frame_set_child(GtkFrame *frame, GtkWidget *child) *)
+PROCEDURE gtk_frame_set_child (frame: GtkFrame; child: ADDRESS);
+
+(* GtkWidget *gtk_frame_get_child(GtkFrame *frame) *)
+PROCEDURE gtk_frame_get_child (frame: GtkFrame) : ADDRESS;
+
+END GtkFrame.

+ 77 - 0
src/GtkGrid.def

@@ -0,0 +1,77 @@
+DEFINITION MODULE FOR "C" GtkGrid ;
+
+(*
+   m2-GTK4 - GtkGrid: a table-like container.  Mapped onto
+   <gtk/gtkgrid.h>.
+
+   Children are placed with gtk_grid_attach(child, column, row, width,
+   height); a widget may span several cells.  Rows and columns size
+   themselves to their content unless made homogeneous.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+FROM GtkEnums IMPORT GtkPositionType;
+
+EXPORT UNQUALIFIED
+   GtkGrid,
+   gtk_grid_new,
+   gtk_grid_attach, gtk_grid_attach_next_to, gtk_grid_remove,
+   gtk_grid_get_child_at,
+   gtk_grid_insert_row, gtk_grid_insert_column,
+   gtk_grid_set_row_spacing, gtk_grid_set_column_spacing,
+   gtk_grid_get_row_spacing, gtk_grid_get_column_spacing,
+   gtk_grid_set_row_homogeneous, gtk_grid_set_column_homogeneous;
+
+
+TYPE
+   GtkGrid = ADDRESS;
+
+(* GtkWidget *gtk_grid_new(void) *)
+PROCEDURE gtk_grid_new () : GtkGrid;
+
+(* void gtk_grid_attach(GtkGrid *grid, GtkWidget *child,
+                         int column, int row, int width, int height) *)
+PROCEDURE gtk_grid_attach (grid: GtkGrid; child: ADDRESS;
+                           column, row, width, height: INTEGER);
+
+(* void gtk_grid_attach_next_to(GtkGrid *grid, GtkWidget *child,
+                                 GtkWidget *sibling, GtkPositionType side,
+                                 int width, int height) *)
+PROCEDURE gtk_grid_attach_next_to (grid: GtkGrid; child: ADDRESS;
+                                   sibling: ADDRESS; side: GtkPositionType;
+                                   width, height: INTEGER);
+
+(* void gtk_grid_remove(GtkGrid *grid, GtkWidget *child) *)
+PROCEDURE gtk_grid_remove (grid: GtkGrid; child: ADDRESS);
+
+(* GtkWidget *gtk_grid_get_child_at(GtkGrid *grid, int column, int row) *)
+PROCEDURE gtk_grid_get_child_at (grid: GtkGrid;
+                                 column, row: INTEGER) : ADDRESS;
+
+(* void gtk_grid_insert_row(GtkGrid *grid, int position) *)
+PROCEDURE gtk_grid_insert_row (grid: GtkGrid; position: INTEGER);
+
+(* void gtk_grid_insert_column(GtkGrid *grid, int position) *)
+PROCEDURE gtk_grid_insert_column (grid: GtkGrid; position: INTEGER);
+
+(* void gtk_grid_set_row_spacing(GtkGrid *grid, guint spacing) *)
+PROCEDURE gtk_grid_set_row_spacing (grid: GtkGrid; spacing: CARDINAL);
+
+(* void gtk_grid_set_column_spacing(GtkGrid *grid, guint spacing) *)
+PROCEDURE gtk_grid_set_column_spacing (grid: GtkGrid; spacing: CARDINAL);
+
+(* guint gtk_grid_get_row_spacing(GtkGrid *grid) *)
+PROCEDURE gtk_grid_get_row_spacing (grid: GtkGrid) : CARDINAL;
+
+(* guint gtk_grid_get_column_spacing(GtkGrid *grid) *)
+PROCEDURE gtk_grid_get_column_spacing (grid: GtkGrid) : CARDINAL;
+
+(* void gtk_grid_set_row_homogeneous(GtkGrid *grid, gboolean homogeneous) *)
+PROCEDURE gtk_grid_set_row_homogeneous (grid: GtkGrid;
+                                        homogeneous: INTEGER);
+
+(* void gtk_grid_set_column_homogeneous(GtkGrid *grid, gboolean homogeneous) *)
+PROCEDURE gtk_grid_set_column_homogeneous (grid: GtkGrid;
+                                           homogeneous: INTEGER);
+
+END GtkGrid.

+ 65 - 0
src/GtkGridView.def

@@ -0,0 +1,65 @@
+DEFINITION MODULE FOR "C" GtkGridView ;
+
+(*
+   m2-GTK4 - GtkGridView: a grid of items driven by a model.  Mapped
+   onto <gtk/gtkgridview.h>.
+
+   Created from a GtkSelectionModel and a GtkListItemFactory, exactly
+   like GtkListView but laying items out in a wrapping grid of at most
+   max_columns columns.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkGridView,
+   gtk_grid_view_new,
+   gtk_grid_view_set_model, gtk_grid_view_get_model,
+   gtk_grid_view_set_factory, gtk_grid_view_get_factory,
+   gtk_grid_view_set_min_columns, gtk_grid_view_get_min_columns,
+   gtk_grid_view_set_max_columns, gtk_grid_view_get_max_columns,
+   gtk_grid_view_set_single_click_activate,
+   gtk_grid_view_get_single_click_activate;
+
+
+TYPE
+   GtkGridView = ADDRESS;
+
+(* GtkWidget *gtk_grid_view_new(GtkSelectionModel *model,
+                                 GtkListItemFactory *factory) *)
+PROCEDURE gtk_grid_view_new (model: ADDRESS; factory: ADDRESS) : GtkGridView;
+
+(* void gtk_grid_view_set_model(GtkGridView *self, GtkSelectionModel *model) *)
+PROCEDURE gtk_grid_view_set_model (self: GtkGridView; model: ADDRESS);
+
+(* GtkSelectionModel *gtk_grid_view_get_model(GtkGridView *self) *)
+PROCEDURE gtk_grid_view_get_model (self: GtkGridView) : ADDRESS;
+
+(* void gtk_grid_view_set_factory(GtkGridView *self, GtkListItemFactory *factory) *)
+PROCEDURE gtk_grid_view_set_factory (self: GtkGridView; factory: ADDRESS);
+
+(* GtkListItemFactory *gtk_grid_view_get_factory(GtkGridView *self) *)
+PROCEDURE gtk_grid_view_get_factory (self: GtkGridView) : ADDRESS;
+
+(* void gtk_grid_view_set_min_columns(GtkGridView *self, guint min_columns) *)
+PROCEDURE gtk_grid_view_set_min_columns (self: GtkGridView;
+                                         min_columns: CARDINAL);
+
+(* guint gtk_grid_view_get_min_columns(GtkGridView *self) *)
+PROCEDURE gtk_grid_view_get_min_columns (self: GtkGridView) : CARDINAL;
+
+(* void gtk_grid_view_set_max_columns(GtkGridView *self, guint max_columns) *)
+PROCEDURE gtk_grid_view_set_max_columns (self: GtkGridView;
+                                         max_columns: CARDINAL);
+
+(* guint gtk_grid_view_get_max_columns(GtkGridView *self) *)
+PROCEDURE gtk_grid_view_get_max_columns (self: GtkGridView) : CARDINAL;
+
+(* void gtk_grid_view_set_single_click_activate(GtkGridView *self, gboolean single_click) *)
+PROCEDURE gtk_grid_view_set_single_click_activate (self: GtkGridView;
+                                                   single_click: INTEGER);
+
+(* gboolean gtk_grid_view_get_single_click_activate(GtkGridView *self) *)
+PROCEDURE gtk_grid_view_get_single_click_activate (self: GtkGridView) : [ INTEGER ];
+
+END GtkGridView.

+ 70 - 0
src/GtkHeaderBar.def

@@ -0,0 +1,70 @@
+DEFINITION MODULE FOR "C" GtkHeaderBar ;
+
+(*
+   m2-GTK4 - GtkHeaderBar: a window title bar that can hold widgets.
+   Mapped onto <gtk/gtkheaderbar.h>.
+
+   Install it with gtk_window_set_titlebar() (GtkWindow.def).  The title
+   can be an arbitrary widget - a label, a stack switcher, a custom box
+   - set with set_title_widget(); other controls are added to the left
+   (pack_start) or right (pack_end), and removed with remove().
+
+   show_title_buttons controls GTK's own minimize/maximize/close
+   buttons; decoration_layout is the "minimize,maximize,close"-style
+   string describing where they sit.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkHeaderBar,
+   gtk_header_bar_new,
+   gtk_header_bar_set_title_widget, gtk_header_bar_get_title_widget,
+   gtk_header_bar_pack_start, gtk_header_bar_pack_end,
+   gtk_header_bar_remove,
+   gtk_header_bar_set_show_title_buttons,
+   gtk_header_bar_get_show_title_buttons,
+   gtk_header_bar_set_decoration_layout,
+   gtk_header_bar_get_decoration_layout;
+
+
+TYPE
+   GtkHeaderBar = ADDRESS;
+
+(* GtkWidget *gtk_header_bar_new(void) *)
+PROCEDURE gtk_header_bar_new () : GtkHeaderBar;
+
+(* void gtk_header_bar_set_title_widget(GtkHeaderBar *bar,
+                                         GtkWidget *title_widget) *)
+PROCEDURE gtk_header_bar_set_title_widget (bar: GtkHeaderBar;
+                                           title_widget: ADDRESS);
+
+(* GtkWidget *gtk_header_bar_get_title_widget(GtkHeaderBar *bar) *)
+PROCEDURE gtk_header_bar_get_title_widget (bar: GtkHeaderBar) : ADDRESS;
+
+(* void gtk_header_bar_pack_start(GtkHeaderBar *bar, GtkWidget *child) *)
+PROCEDURE gtk_header_bar_pack_start (bar: GtkHeaderBar; child: ADDRESS);
+
+(* void gtk_header_bar_pack_end(GtkHeaderBar *bar, GtkWidget *child) *)
+PROCEDURE gtk_header_bar_pack_end (bar: GtkHeaderBar; child: ADDRESS);
+
+(* void gtk_header_bar_remove(GtkHeaderBar *bar, GtkWidget *child) *)
+PROCEDURE gtk_header_bar_remove (bar: GtkHeaderBar; child: ADDRESS);
+
+(* void gtk_header_bar_set_show_title_buttons(GtkHeaderBar *bar,
+                                               gboolean setting) *)
+PROCEDURE gtk_header_bar_set_show_title_buttons (bar: GtkHeaderBar;
+                                                 setting: INTEGER);
+
+(* gboolean gtk_header_bar_get_show_title_buttons(GtkHeaderBar *bar) *)
+PROCEDURE gtk_header_bar_get_show_title_buttons (bar: GtkHeaderBar) : [ INTEGER ];
+
+(* void gtk_header_bar_set_decoration_layout(GtkHeaderBar *bar,
+                                              const char *layout) *)
+PROCEDURE gtk_header_bar_set_decoration_layout (bar: GtkHeaderBar;
+                                                layout: ARRAY OF CHAR);
+
+(* const char *gtk_header_bar_get_decoration_layout(GtkHeaderBar *bar) *)
+PROCEDURE gtk_header_bar_get_decoration_layout (bar: GtkHeaderBar) : ADDRESS;
+
+END GtkHeaderBar.

+ 39 - 0
src/GtkLabel.def

@@ -0,0 +1,39 @@
+DEFINITION MODULE FOR "C" GtkLabel ;
+
+(*
+   m2-GTK4 - GtkLabel: a text label.  Mapped onto <gtk/gtklabel.h>.
+
+   gtk_label_set_text() sets literal text; gtk_label_set_label() sets
+   text that is interpreted as Pango markup (see gtk_label_set_markup
+   and gtk_label_set_use_markup in the C API).  gtk_label_get_text()
+   returns an internal, borrowed C string - copy it with
+   GtkUtils.CStrToM2() before the label changes.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkLabel,
+   gtk_label_new, gtk_label_set_text, gtk_label_get_text,
+   gtk_label_set_markup, gtk_label_set_use_markup;
+
+
+TYPE
+   GtkLabel = ADDRESS;
+
+(* GtkWidget *gtk_label_new(const char *str) *)
+PROCEDURE gtk_label_new (str: ARRAY OF CHAR) : GtkLabel;
+
+(* void gtk_label_set_text(GtkLabel *self, const char *str) *)
+PROCEDURE gtk_label_set_text (label: GtkLabel; str: ARRAY OF CHAR);
+
+(* const char *gtk_label_get_text(GtkLabel *self) *)
+PROCEDURE gtk_label_get_text (label: GtkLabel) : ADDRESS;
+
+(* void gtk_label_set_markup(GtkLabel *self, const char *str) *)
+PROCEDURE gtk_label_set_markup (label: GtkLabel; str: ARRAY OF CHAR);
+
+(* void gtk_label_set_use_markup(GtkLabel *self, gboolean setting) *)
+PROCEDURE gtk_label_set_use_markup (label: GtkLabel; setting: INTEGER);
+
+END GtkLabel.

+ 118 - 0
src/GtkListBox.def

@@ -0,0 +1,118 @@
+DEFINITION MODULE FOR "C" GtkListBox ;
+
+(*
+   m2-GTK4 - GtkListBox and GtkListBoxRow: a vertical list of rows.
+   Mapped onto <gtk/gtklistbox.h> (both types share the header).
+
+   Children are GtkListBoxRow widgets (created with
+   gtk_list_box_row_new() and filled with set_child()), appended,
+   prepended or inserted.  Row selection is governed by a
+   GtkSelectionMode.
+
+   Signals: "row-activated" and "row-selected", both
+   void(GtkListBox*, GtkListBoxRow*, gpointer) - the 3-argument
+   GtkClosures form.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+FROM GtkEnums IMPORT GtkSelectionMode;
+
+EXPORT UNQUALIFIED
+   GtkListBox, GtkListBoxRow,
+   gtk_list_box_new,
+   gtk_list_box_append, gtk_list_box_prepend, gtk_list_box_insert,
+   gtk_list_box_remove, gtk_list_box_remove_all,
+   gtk_list_box_get_row_at_index,
+   gtk_list_box_select_row, gtk_list_box_unselect_row,
+   gtk_list_box_get_selected_row,
+   gtk_list_box_set_selection_mode, gtk_list_box_get_selection_mode,
+   gtk_list_box_set_show_separators, gtk_list_box_get_show_separators,
+   gtk_list_box_set_activate_on_single_click,
+   gtk_list_box_row_new, gtk_list_box_row_set_child,
+   gtk_list_box_row_get_child, gtk_list_box_row_get_index,
+   gtk_list_box_row_set_activatable, gtk_list_box_row_get_activatable,
+   gtk_list_box_row_set_selectable, gtk_list_box_row_get_selectable;
+
+
+TYPE
+   GtkListBox = ADDRESS;
+   GtkListBoxRow = ADDRESS;
+
+(* GtkWidget *gtk_list_box_new(void) *)
+PROCEDURE gtk_list_box_new () : GtkListBox;
+
+(* void gtk_list_box_append(GtkListBox *box, GtkWidget *child) *)
+PROCEDURE gtk_list_box_append (box: GtkListBox; child: ADDRESS);
+
+(* void gtk_list_box_prepend(GtkListBox *box, GtkWidget *child) *)
+PROCEDURE gtk_list_box_prepend (box: GtkListBox; child: ADDRESS);
+
+(* void gtk_list_box_insert(GtkListBox *box, GtkWidget *child, int position) *)
+PROCEDURE gtk_list_box_insert (box: GtkListBox; child: ADDRESS;
+                               position: INTEGER);
+
+(* void gtk_list_box_remove(GtkListBox *box, GtkWidget *child) *)
+PROCEDURE gtk_list_box_remove (box: GtkListBox; child: ADDRESS);
+
+(* void gtk_list_box_remove_all(GtkListBox *box) *)
+PROCEDURE gtk_list_box_remove_all (box: GtkListBox);
+
+(* GtkListBoxRow *gtk_list_box_get_row_at_index(GtkListBox *box, int index) *)
+PROCEDURE gtk_list_box_get_row_at_index (box: GtkListBox;
+                                         index: INTEGER) : ADDRESS;
+
+(* void gtk_list_box_select_row(GtkListBox *box, GtkListBoxRow *row) *)
+PROCEDURE gtk_list_box_select_row (box: GtkListBox; row: ADDRESS);
+
+(* void gtk_list_box_unselect_row(GtkListBox *box, GtkListBoxRow *row) *)
+PROCEDURE gtk_list_box_unselect_row (box: GtkListBox; row: ADDRESS);
+
+(* GtkListBoxRow *gtk_list_box_get_selected_row(GtkListBox *box) *)
+PROCEDURE gtk_list_box_get_selected_row (box: GtkListBox) : ADDRESS;
+
+(* void gtk_list_box_set_selection_mode(GtkListBox *box, GtkSelectionMode mode) *)
+PROCEDURE gtk_list_box_set_selection_mode (box: GtkListBox;
+                                           mode: GtkSelectionMode);
+
+(* GtkSelectionMode gtk_list_box_get_selection_mode(GtkListBox *box) *)
+PROCEDURE gtk_list_box_get_selection_mode (box: GtkListBox) : GtkSelectionMode;
+
+(* void gtk_list_box_set_show_separators(GtkListBox *box, gboolean show_separators) *)
+PROCEDURE gtk_list_box_set_show_separators (box: GtkListBox;
+                                            show_separators: INTEGER);
+
+(* gboolean gtk_list_box_get_show_separators(GtkListBox *box) *)
+PROCEDURE gtk_list_box_get_show_separators (box: GtkListBox) : [ INTEGER ];
+
+(* void gtk_list_box_set_activate_on_single_click(GtkListBox *box,
+                                                  gboolean single) *)
+PROCEDURE gtk_list_box_set_activate_on_single_click (box: GtkListBox;
+                                                     single: INTEGER);
+
+(* GtkWidget *gtk_list_box_row_new(void) *)
+PROCEDURE gtk_list_box_row_new () : GtkListBoxRow;
+
+(* void gtk_list_box_row_set_child(GtkListBoxRow *row, GtkWidget *child) *)
+PROCEDURE gtk_list_box_row_set_child (row: GtkListBoxRow; child: ADDRESS);
+
+(* GtkWidget *gtk_list_box_row_get_child(GtkListBoxRow *row) *)
+PROCEDURE gtk_list_box_row_get_child (row: GtkListBoxRow) : ADDRESS;
+
+(* int gtk_list_box_row_get_index(GtkListBoxRow *row) *)
+PROCEDURE gtk_list_box_row_get_index (row: GtkListBoxRow) : INTEGER;
+
+(* void gtk_list_box_row_set_activatable(GtkListBoxRow *row, gboolean activatable) *)
+PROCEDURE gtk_list_box_row_set_activatable (row: GtkListBoxRow;
+                                            activatable: INTEGER);
+
+(* gboolean gtk_list_box_row_get_activatable(GtkListBoxRow *row) *)
+PROCEDURE gtk_list_box_row_get_activatable (row: GtkListBoxRow) : [ INTEGER ];
+
+(* void gtk_list_box_row_set_selectable(GtkListBoxRow *row, gboolean selectable) *)
+PROCEDURE gtk_list_box_row_set_selectable (row: GtkListBoxRow;
+                                           selectable: INTEGER);
+
+(* gboolean gtk_list_box_row_get_selectable(GtkListBoxRow *row) *)
+PROCEDURE gtk_list_box_row_get_selectable (row: GtkListBoxRow) : [ INTEGER ];
+
+END GtkListBox.

+ 48 - 0
src/GtkListItem.def

@@ -0,0 +1,48 @@
+DEFINITION MODULE FOR "C" GtkListItem ;
+
+(*
+   m2-GTK4 - GtkListItem: the per-row object handed to a list/grid
+   factory callback.  Mapped onto <gtk/gtklistitem.h>.
+
+   In a factory's "setup" signal, set the row's child widget with
+   gtk_list_item_set_child(); in "bind", retrieve the bound model item
+   with gtk_list_item_get_item() and update the child.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkListItem,
+   gtk_list_item_get_item, gtk_list_item_get_position,
+   gtk_list_item_get_selected, gtk_list_item_get_child,
+   gtk_list_item_set_child, gtk_list_item_set_selectable,
+   gtk_list_item_set_activatable;
+
+
+TYPE
+   GtkListItem = ADDRESS;
+
+(* gpointer gtk_list_item_get_item(GtkListItem *self) *)
+PROCEDURE gtk_list_item_get_item (self: GtkListItem) : ADDRESS;
+
+(* guint gtk_list_item_get_position(GtkListItem *self) *)
+PROCEDURE gtk_list_item_get_position (self: GtkListItem) : CARDINAL;
+
+(* gboolean gtk_list_item_get_selected(GtkListItem *self) *)
+PROCEDURE gtk_list_item_get_selected (self: GtkListItem) : [ INTEGER ];
+
+(* GtkWidget *gtk_list_item_get_child(GtkListItem *self) *)
+PROCEDURE gtk_list_item_get_child (self: GtkListItem) : ADDRESS;
+
+(* void gtk_list_item_set_child(GtkListItem *self, GtkWidget *child) *)
+PROCEDURE gtk_list_item_set_child (self: GtkListItem; child: ADDRESS);
+
+(* void gtk_list_item_set_selectable(GtkListItem *self, gboolean selectable) *)
+PROCEDURE gtk_list_item_set_selectable (self: GtkListItem;
+                                        selectable: INTEGER);
+
+(* void gtk_list_item_set_activatable(GtkListItem *self, gboolean activatable) *)
+PROCEDURE gtk_list_item_set_activatable (self: GtkListItem;
+                                         activatable: INTEGER);
+
+END GtkListItem.

+ 66 - 0
src/GtkListView.def

@@ -0,0 +1,66 @@
+DEFINITION MODULE FOR "C" GtkListView ;
+
+(*
+   m2-GTK4 - GtkListView: a scrollable list driven by a model.
+   Mapped onto <gtk/gtklistview.h>.
+
+   Created from a GtkSelectionModel and a GtkListItemFactory
+   (GtkSignalListItemFactory).  The factory's callbacks build and fill
+   one GtkListItem per visible row.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkListView,
+   gtk_list_view_new,
+   gtk_list_view_set_model, gtk_list_view_get_model,
+   gtk_list_view_set_factory, gtk_list_view_get_factory,
+   gtk_list_view_set_show_separators, gtk_list_view_get_show_separators,
+   gtk_list_view_set_single_click_activate,
+   gtk_list_view_get_single_click_activate,
+   gtk_list_view_set_enable_rubberband,
+   gtk_list_view_get_enable_rubberband;
+
+
+TYPE
+   GtkListView = ADDRESS;
+
+(* GtkWidget *gtk_list_view_new(GtkSelectionModel *model,
+                                 GtkListItemFactory *factory) *)
+PROCEDURE gtk_list_view_new (model: ADDRESS; factory: ADDRESS) : GtkListView;
+
+(* void gtk_list_view_set_model(GtkListView *self, GtkSelectionModel *model) *)
+PROCEDURE gtk_list_view_set_model (self: GtkListView; model: ADDRESS);
+
+(* GtkSelectionModel *gtk_list_view_get_model(GtkListView *self) *)
+PROCEDURE gtk_list_view_get_model (self: GtkListView) : ADDRESS;
+
+(* void gtk_list_view_set_factory(GtkListView *self, GtkListItemFactory *factory) *)
+PROCEDURE gtk_list_view_set_factory (self: GtkListView; factory: ADDRESS);
+
+(* GtkListItemFactory *gtk_list_view_get_factory(GtkListView *self) *)
+PROCEDURE gtk_list_view_get_factory (self: GtkListView) : ADDRESS;
+
+(* void gtk_list_view_set_show_separators(GtkListView *self, gboolean show_separators) *)
+PROCEDURE gtk_list_view_set_show_separators (self: GtkListView;
+                                             show_separators: INTEGER);
+
+(* gboolean gtk_list_view_get_show_separators(GtkListView *self) *)
+PROCEDURE gtk_list_view_get_show_separators (self: GtkListView) : [ INTEGER ];
+
+(* void gtk_list_view_set_single_click_activate(GtkListView *self, gboolean single_click) *)
+PROCEDURE gtk_list_view_set_single_click_activate (self: GtkListView;
+                                                   single_click: INTEGER);
+
+(* gboolean gtk_list_view_get_single_click_activate(GtkListView *self) *)
+PROCEDURE gtk_list_view_get_single_click_activate (self: GtkListView) : [ INTEGER ];
+
+(* void gtk_list_view_set_enable_rubberband(GtkListView *self, gboolean enable_rubberband) *)
+PROCEDURE gtk_list_view_set_enable_rubberband (self: GtkListView;
+                                               enable_rubberband: INTEGER);
+
+(* gboolean gtk_list_view_get_enable_rubberband(GtkListView *self) *)
+PROCEDURE gtk_list_view_get_enable_rubberband (self: GtkListView) : [ INTEGER ];
+
+END GtkListView.

+ 56 - 0
src/GtkMenuButton.def

@@ -0,0 +1,56 @@
+DEFINITION MODULE FOR "C" GtkMenuButton ;
+
+(*
+   m2-GTK4 - GtkMenuButton: a button that pops up a menu.  Mapped onto
+   <gtk/gtkmenubutton.h>.
+
+   Hand it a GMenuModel (GMenu.def) with set_menu_model(); the button
+   shows its label or icon.  Commonly packed into a GtkHeaderBar as the
+   window's application-menu control.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkMenuButton,
+   gtk_menu_button_new,
+   gtk_menu_button_set_menu_model, gtk_menu_button_get_menu_model,
+   gtk_menu_button_set_label, gtk_menu_button_get_label,
+   gtk_menu_button_set_icon_name,
+   gtk_menu_button_popup, gtk_menu_button_popdown;
+
+
+TYPE
+   GtkMenuButton = ADDRESS;
+
+(* GtkWidget *gtk_menu_button_new(void) *)
+PROCEDURE gtk_menu_button_new () : GtkMenuButton;
+
+(* void gtk_menu_button_set_menu_model(GtkMenuButton *menu_button,
+                                        GMenuModel *menu_model) *)
+PROCEDURE gtk_menu_button_set_menu_model (menu_button: GtkMenuButton;
+                                          menu_model: ADDRESS);
+
+(* GMenuModel *gtk_menu_button_get_menu_model(GtkMenuButton *menu_button) *)
+PROCEDURE gtk_menu_button_get_menu_model (menu_button: GtkMenuButton) : ADDRESS;
+
+(* void gtk_menu_button_set_label(GtkMenuButton *menu_button,
+                                   const char *label) *)
+PROCEDURE gtk_menu_button_set_label (menu_button: GtkMenuButton;
+                                     label: ARRAY OF CHAR);
+
+(* const char *gtk_menu_button_get_label(GtkMenuButton *menu_button) *)
+PROCEDURE gtk_menu_button_get_label (menu_button: GtkMenuButton) : ADDRESS;
+
+(* void gtk_menu_button_set_icon_name(GtkMenuButton *menu_button,
+                                       const char *icon_name) *)
+PROCEDURE gtk_menu_button_set_icon_name (menu_button: GtkMenuButton;
+                                         icon_name: ARRAY OF CHAR);
+
+(* void gtk_menu_button_popup(GtkMenuButton *menu_button) *)
+PROCEDURE gtk_menu_button_popup (menu_button: GtkMenuButton);
+
+(* void gtk_menu_button_popdown(GtkMenuButton *menu_button) *)
+PROCEDURE gtk_menu_button_popdown (menu_button: GtkMenuButton);
+
+END GtkMenuButton.

+ 31 - 0
src/GtkNoSelection.def

@@ -0,0 +1,31 @@
+DEFINITION MODULE FOR "C" GtkNoSelection ;
+
+(*
+   m2-GTK4 - GtkNoSelection: a GtkSelectionModel that never selects
+   anything.  Mapped onto <gtk/gtknoselection.h>.
+
+   Wrap a GListModel to make a display-only view (no selection is
+   possible at all).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkNoSelection,
+   gtk_no_selection_new,
+   gtk_no_selection_set_model, gtk_no_selection_get_model;
+
+
+TYPE
+   GtkNoSelection = ADDRESS;
+
+(* GtkNoSelection *gtk_no_selection_new(GListModel *model) *)
+PROCEDURE gtk_no_selection_new (model: ADDRESS) : GtkNoSelection;
+
+(* void gtk_no_selection_set_model(GtkNoSelection *self, GListModel *model) *)
+PROCEDURE gtk_no_selection_set_model (self: GtkNoSelection; model: ADDRESS);
+
+(* GListModel *gtk_no_selection_get_model(GtkNoSelection *self) *)
+PROCEDURE gtk_no_selection_get_model (self: GtkNoSelection) : ADDRESS;
+
+END GtkNoSelection.

+ 83 - 0
src/GtkNotebook.def

@@ -0,0 +1,83 @@
+DEFINITION MODULE FOR "C" GtkNotebook ;
+
+(*
+   m2-GTK4 - GtkNotebook: tabbed pages.  Mapped onto
+   <gtk/gtknotebook.h>.
+
+   Each page has a child and a tab label widget (pass NIL for no
+   label).  gtk_notebook_append_page() returns the page index.
+   gtk_notebook_set_current_page() takes -1 to clear the selection.
+
+   Signal: "switch-page", handler void(GtkNotebook*, GtkWidget *child,
+   guint page_num, gpointer).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+FROM GtkEnums IMPORT GtkPositionType;
+
+EXPORT UNQUALIFIED
+   GtkNotebook,
+   gtk_notebook_new,
+   gtk_notebook_append_page, gtk_notebook_prepend_page,
+   gtk_notebook_insert_page, gtk_notebook_remove_page,
+   gtk_notebook_get_n_pages, gtk_notebook_get_current_page,
+   gtk_notebook_set_current_page, gtk_notebook_next_page,
+   gtk_notebook_prev_page,
+   gtk_notebook_set_tab_pos, gtk_notebook_set_show_border,
+   gtk_notebook_set_scrollable;
+
+
+TYPE
+   GtkNotebook = ADDRESS;
+
+(* GtkWidget *gtk_notebook_new(void) *)
+PROCEDURE gtk_notebook_new () : GtkNotebook;
+
+(* int gtk_notebook_append_page(GtkNotebook *notebook, GtkWidget *child,
+                                 GtkWidget *tab_label) *)
+PROCEDURE gtk_notebook_append_page (notebook: GtkNotebook; child: ADDRESS;
+                                    tab_label: ADDRESS) : [ INTEGER ];
+
+(* int gtk_notebook_prepend_page(GtkNotebook *notebook, GtkWidget *child,
+                                  GtkWidget *tab_label) *)
+PROCEDURE gtk_notebook_prepend_page (notebook: GtkNotebook; child: ADDRESS;
+                                     tab_label: ADDRESS) : [ INTEGER ];
+
+(* int gtk_notebook_insert_page(GtkNotebook *notebook, GtkWidget *child,
+                                 GtkWidget *tab_label, int position) *)
+PROCEDURE gtk_notebook_insert_page (notebook: GtkNotebook; child: ADDRESS;
+                                    tab_label: ADDRESS;
+                                    position: INTEGER) : [ INTEGER ];
+
+(* void gtk_notebook_remove_page(GtkNotebook *notebook, int page_num) *)
+PROCEDURE gtk_notebook_remove_page (notebook: GtkNotebook; page_num: INTEGER);
+
+(* int gtk_notebook_get_n_pages(GtkNotebook *notebook) *)
+PROCEDURE gtk_notebook_get_n_pages (notebook: GtkNotebook) : INTEGER;
+
+(* int gtk_notebook_get_current_page(GtkNotebook *notebook) *)
+PROCEDURE gtk_notebook_get_current_page (notebook: GtkNotebook) : INTEGER;
+
+(* void gtk_notebook_set_current_page(GtkNotebook *notebook, int page_num) *)
+PROCEDURE gtk_notebook_set_current_page (notebook: GtkNotebook;
+                                         page_num: INTEGER);
+
+(* void gtk_notebook_next_page(GtkNotebook *notebook) *)
+PROCEDURE gtk_notebook_next_page (notebook: GtkNotebook);
+
+(* void gtk_notebook_prev_page(GtkNotebook *notebook) *)
+PROCEDURE gtk_notebook_prev_page (notebook: GtkNotebook);
+
+(* void gtk_notebook_set_tab_pos(GtkNotebook *notebook, GtkPositionType pos) *)
+PROCEDURE gtk_notebook_set_tab_pos (notebook: GtkNotebook;
+                                    pos: GtkPositionType);
+
+(* void gtk_notebook_set_show_border(GtkNotebook *notebook, gboolean show_border) *)
+PROCEDURE gtk_notebook_set_show_border (notebook: GtkNotebook;
+                                        show_border: INTEGER);
+
+(* void gtk_notebook_set_scrollable(GtkNotebook *notebook, gboolean scrollable) *)
+PROCEDURE gtk_notebook_set_scrollable (notebook: GtkNotebook;
+                                       scrollable: INTEGER);
+
+END GtkNotebook.

+ 60 - 0
src/GtkOverlay.def

@@ -0,0 +1,60 @@
+DEFINITION MODULE FOR "C" GtkOverlay ;
+
+(*
+   m2-GTK4 - GtkOverlay: a container that stacks child widgets on top of
+   a main child.  Mapped onto <gtk/gtkoverlay.h>.
+
+   The main child is set with gtk_overlay_set_child(); extra children
+   are added with gtk_overlay_add_overlay() and positioned with the
+   per-widget margin/align helpers.  measure_overlay asks the overlay to
+   include an overlay's size in its own measurement; clip_overlay clips
+   it to the overlay allocation.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkOverlay,
+   gtk_overlay_new, gtk_overlay_set_child, gtk_overlay_get_child,
+   gtk_overlay_add_overlay, gtk_overlay_remove_overlay,
+   gtk_overlay_set_measure_overlay, gtk_overlay_get_measure_overlay,
+   gtk_overlay_set_clip_overlay, gtk_overlay_get_clip_overlay;
+
+
+TYPE
+   GtkOverlay = ADDRESS;
+
+(* GtkWidget *gtk_overlay_new(void) *)
+PROCEDURE gtk_overlay_new () : GtkOverlay;
+
+(* void gtk_overlay_set_child(GtkOverlay *overlay, GtkWidget *child) *)
+PROCEDURE gtk_overlay_set_child (overlay: GtkOverlay; child: ADDRESS);
+
+(* GtkWidget *gtk_overlay_get_child(GtkOverlay *overlay) *)
+PROCEDURE gtk_overlay_get_child (overlay: GtkOverlay) : ADDRESS;
+
+(* void gtk_overlay_add_overlay(GtkOverlay *overlay, GtkWidget *widget) *)
+PROCEDURE gtk_overlay_add_overlay (overlay: GtkOverlay; widget: ADDRESS);
+
+(* void gtk_overlay_remove_overlay(GtkOverlay *overlay, GtkWidget *widget) *)
+PROCEDURE gtk_overlay_remove_overlay (overlay: GtkOverlay; widget: ADDRESS);
+
+(* void gtk_overlay_set_measure_overlay(GtkOverlay *overlay,
+                                        GtkWidget *widget, gboolean measure) *)
+PROCEDURE gtk_overlay_set_measure_overlay (overlay: GtkOverlay;
+                                           widget: ADDRESS; measure: INTEGER);
+
+(* gboolean gtk_overlay_get_measure_overlay(GtkOverlay *overlay, GtkWidget *widget) *)
+PROCEDURE gtk_overlay_get_measure_overlay (overlay: GtkOverlay;
+                                           widget: ADDRESS) : [ INTEGER ];
+
+(* void gtk_overlay_set_clip_overlay(GtkOverlay *overlay,
+                                     GtkWidget *widget, gboolean clip) *)
+PROCEDURE gtk_overlay_set_clip_overlay (overlay: GtkOverlay;
+                                        widget: ADDRESS; clip: INTEGER);
+
+(* gboolean gtk_overlay_get_clip_overlay(GtkOverlay *overlay, GtkWidget *widget) *)
+PROCEDURE gtk_overlay_get_clip_overlay (overlay: GtkOverlay;
+                                        widget: ADDRESS) : [ INTEGER ];
+
+END GtkOverlay.

+ 61 - 0
src/GtkPaned.def

@@ -0,0 +1,61 @@
+DEFINITION MODULE FOR "C" GtkPaned ;
+
+(*
+   m2-GTK4 - GtkPaned: a two-pane container split by a draggable handle.
+   Mapped onto <gtk/gtkpaned.h>.
+
+   The two panes are "start" and "end" (orientation gives the axis).
+   The divider position is in pixels; resize/shrink flags control how
+   each pane reacts to the window being resized.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+FROM GtkEnums IMPORT GtkOrientation;
+
+EXPORT UNQUALIFIED
+   GtkPaned,
+   gtk_paned_new,
+   gtk_paned_set_start_child, gtk_paned_get_start_child,
+   gtk_paned_set_end_child, gtk_paned_get_end_child,
+   gtk_paned_set_position, gtk_paned_get_position,
+   gtk_paned_set_resize_start_child, gtk_paned_set_resize_end_child,
+   gtk_paned_set_shrink_start_child, gtk_paned_set_shrink_end_child;
+
+
+TYPE
+   GtkPaned = ADDRESS;
+
+(* GtkWidget *gtk_paned_new(GtkOrientation orientation) *)
+PROCEDURE gtk_paned_new (orientation: GtkOrientation) : GtkPaned;
+
+(* void gtk_paned_set_start_child(GtkPaned *paned, GtkWidget *child) *)
+PROCEDURE gtk_paned_set_start_child (paned: GtkPaned; child: ADDRESS);
+
+(* GtkWidget *gtk_paned_get_start_child(GtkPaned *paned) *)
+PROCEDURE gtk_paned_get_start_child (paned: GtkPaned) : ADDRESS;
+
+(* void gtk_paned_set_end_child(GtkPaned *paned, GtkWidget *child) *)
+PROCEDURE gtk_paned_set_end_child (paned: GtkPaned; child: ADDRESS);
+
+(* GtkWidget *gtk_paned_get_end_child(GtkPaned *paned) *)
+PROCEDURE gtk_paned_get_end_child (paned: GtkPaned) : ADDRESS;
+
+(* void gtk_paned_set_position(GtkPaned *paned, int position) *)
+PROCEDURE gtk_paned_set_position (paned: GtkPaned; position: INTEGER);
+
+(* int gtk_paned_get_position(GtkPaned *paned) *)
+PROCEDURE gtk_paned_get_position (paned: GtkPaned) : INTEGER;
+
+(* void gtk_paned_set_resize_start_child(GtkPaned *paned, gboolean resize) *)
+PROCEDURE gtk_paned_set_resize_start_child (paned: GtkPaned; resize: INTEGER);
+
+(* void gtk_paned_set_resize_end_child(GtkPaned *paned, gboolean resize) *)
+PROCEDURE gtk_paned_set_resize_end_child (paned: GtkPaned; resize: INTEGER);
+
+(* void gtk_paned_set_shrink_start_child(GtkPaned *paned, gboolean resize) *)
+PROCEDURE gtk_paned_set_shrink_start_child (paned: GtkPaned; shrink: INTEGER);
+
+(* void gtk_paned_set_shrink_end_child(GtkPaned *paned, gboolean resize) *)
+PROCEDURE gtk_paned_set_shrink_end_child (paned: GtkPaned; shrink: INTEGER);
+
+END GtkPaned.

+ 36 - 0
src/GtkPopoverMenuBar.def

@@ -0,0 +1,36 @@
+DEFINITION MODULE FOR "C" GtkPopoverMenuBar ;
+
+(*
+   m2-GTK4 - GtkPopoverMenuBar: the in-window menu bar for GTK4.
+   Mapped onto <gtk/gtkpopovermenubar.h>.
+
+   Build it from a GMenuModel (typically a GMenu with one submenu per
+   top-level menu):
+
+      bar := gtk_popover_menu_bar_new_from_model(menubar);
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkPopoverMenuBar,
+   gtk_popover_menu_bar_new_from_model,
+   gtk_popover_menu_bar_set_menu_model,
+   gtk_popover_menu_bar_get_menu_model;
+
+
+TYPE
+   GtkPopoverMenuBar = ADDRESS;
+
+(* GtkWidget *gtk_popover_menu_bar_new_from_model(GMenuModel *model) *)
+PROCEDURE gtk_popover_menu_bar_new_from_model (model: ADDRESS) : GtkPopoverMenuBar;
+
+(* void gtk_popover_menu_bar_set_menu_model(GtkPopoverMenuBar *bar,
+                                             GMenuModel *model) *)
+PROCEDURE gtk_popover_menu_bar_set_menu_model (bar: GtkPopoverMenuBar;
+                                               model: ADDRESS);
+
+(* GMenuModel *gtk_popover_menu_bar_get_menu_model(GtkPopoverMenuBar *bar) *)
+PROCEDURE gtk_popover_menu_bar_get_menu_model (bar: GtkPopoverMenuBar) : ADDRESS;
+
+END GtkPopoverMenuBar.

+ 35 - 0
src/GtkRange.def

@@ -0,0 +1,35 @@
+DEFINITION MODULE FOR "C" GtkRange ;
+
+(*
+   m2-GTK4 - GtkRange: the base class of value-selecting widgets
+   (GtkScale, GtkScrollbar).  Mapped onto <gtk/gtkrange.h>.
+
+   Values are C `double`, mapped here onto REAL.
+   Signal: "value-changed", handler void(GtkRange*, gpointer).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkRange,
+   gtk_range_get_value, gtk_range_set_value,
+   gtk_range_set_range, gtk_range_set_increments;
+
+
+TYPE
+   GtkRange = ADDRESS;
+
+(* double gtk_range_get_value(GtkRange *range) *)
+PROCEDURE gtk_range_get_value (range: GtkRange) : REAL;
+
+(* void gtk_range_set_value(GtkRange *range, double value) *)
+PROCEDURE gtk_range_set_value (range: GtkRange; value: REAL);
+
+(* void gtk_range_set_range(GtkRange *range, double min, double max) *)
+PROCEDURE gtk_range_set_range (range: GtkRange; min, max: REAL);
+
+(* void gtk_range_set_increments(GtkRange *range, double step, double page) *)
+PROCEDURE gtk_range_set_increments (range: GtkRange;
+                                    step, page: REAL);
+
+END GtkRange.

+ 55 - 0
src/GtkScale.def

@@ -0,0 +1,55 @@
+DEFINITION MODULE FOR "C" GtkScale ;
+
+(*
+   m2-GTK4 - GtkScale: a slider.  Mapped onto <gtk/gtkscale.h>.
+
+   GtkScale derives from GtkRange, so read/write the value with
+   gtk_range_get_value()/gtk_range_set_value() (GtkRange.def).
+
+   gtk_scale_new() takes a GtkAdjustment *; pass NIL to let the scale
+   create its own.  gtk_scale_new_with_range() is the convenient form
+   for min/max/step.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+FROM GtkEnums IMPORT GtkOrientation, GtkPositionType;
+
+EXPORT UNQUALIFIED
+   GtkScale,
+   gtk_scale_new, gtk_scale_new_with_range,
+   gtk_scale_set_digits, gtk_scale_get_digits,
+   gtk_scale_set_draw_value, gtk_scale_get_draw_value,
+   gtk_scale_set_value_pos, gtk_scale_get_value_pos;
+
+
+TYPE
+   GtkScale = ADDRESS;
+
+(* GtkWidget *gtk_scale_new(GtkOrientation orientation, GtkAdjustment *adjustment) *)
+PROCEDURE gtk_scale_new (orientation: GtkOrientation;
+                         adjustment: ADDRESS) : GtkScale;
+
+(* GtkWidget *gtk_scale_new_with_range(GtkOrientation orientation,
+                                        double min, double max, double step) *)
+PROCEDURE gtk_scale_new_with_range (orientation: GtkOrientation;
+                                    min, max, step: REAL) : GtkScale;
+
+(* void gtk_scale_set_digits(GtkScale *scale, int digits) *)
+PROCEDURE gtk_scale_set_digits (scale: GtkScale; digits: INTEGER);
+
+(* int gtk_scale_get_digits(GtkScale *scale) *)
+PROCEDURE gtk_scale_get_digits (scale: GtkScale) : INTEGER;
+
+(* void gtk_scale_set_draw_value(GtkScale *scale, gboolean draw_value) *)
+PROCEDURE gtk_scale_set_draw_value (scale: GtkScale; draw_value: INTEGER);
+
+(* gboolean gtk_scale_get_draw_value(GtkScale *scale) *)
+PROCEDURE gtk_scale_get_draw_value (scale: GtkScale) : [ INTEGER ];
+
+(* void gtk_scale_set_value_pos(GtkScale *scale, GtkPositionType pos) *)
+PROCEDURE gtk_scale_set_value_pos (scale: GtkScale; pos: GtkPositionType);
+
+(* GtkPositionType gtk_scale_get_value_pos(GtkScale *scale) *)
+PROCEDURE gtk_scale_get_value_pos (scale: GtkScale) : GtkPositionType;
+
+END GtkScale.

+ 87 - 0
src/GtkScrolledWindow.def

@@ -0,0 +1,87 @@
+DEFINITION MODULE FOR "C" GtkScrolledWindow ;
+
+(*
+   m2-GTK4 - GtkScrolledWindow: a scrollable viewport around a child.
+   Mapped onto <gtk/gtkscrolledwindow.h>.
+
+   Set the (single) child with gtk_scrolled_window_set_child(), then
+   choose scrollbar behaviour with a GtkPolicyType for each axis.
+   GtkPolicyType is declared in this header; values match the C enum.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkScrolledWindow, GtkPolicyType,
+   GtkPolicyAlways, GtkPolicyAutomatic, GtkPolicyNever, GtkPolicyExternal,
+   gtk_scrolled_window_new, gtk_scrolled_window_set_child,
+   gtk_scrolled_window_set_policy, gtk_scrolled_window_get_policy,
+   gtk_scrolled_window_set_min_content_width,
+   gtk_scrolled_window_set_min_content_height,
+   gtk_scrolled_window_set_max_content_width,
+   gtk_scrolled_window_set_max_content_height,
+   gtk_scrolled_window_set_propagate_natural_width,
+   gtk_scrolled_window_set_propagate_natural_height;
+
+
+TYPE
+   GtkScrolledWindow = ADDRESS;
+   GtkPolicyType = CARDINAL;
+
+CONST
+   GtkPolicyAlways    = 0;
+   GtkPolicyAutomatic = 1;
+   GtkPolicyNever     = 2;
+   GtkPolicyExternal  = 3;
+
+(* GtkWidget *gtk_scrolled_window_new(void) *)
+PROCEDURE gtk_scrolled_window_new () : GtkScrolledWindow;
+
+(* void gtk_scrolled_window_set_child(GtkScrolledWindow *scrolled_window,
+                                       GtkWidget *child) *)
+PROCEDURE gtk_scrolled_window_set_child (scrolled_window: GtkScrolledWindow;
+                                         child: ADDRESS);
+
+(* void gtk_scrolled_window_set_policy(GtkScrolledWindow *scrolled_window,
+                                        GtkPolicyType hscrollbar_policy,
+                                        GtkPolicyType vscrollbar_policy) *)
+PROCEDURE gtk_scrolled_window_set_policy (scrolled_window: GtkScrolledWindow;
+                                          hscroll, vscroll: GtkPolicyType);
+
+(* void gtk_scrolled_window_get_policy(GtkScrolledWindow *scrolled_window,
+                                        GtkPolicyType *hscrollbar_policy,
+                                        GtkPolicyType *vscrollbar_policy) *)
+PROCEDURE gtk_scrolled_window_get_policy (scrolled_window: GtkScrolledWindow;
+                                          VAR hscroll, vscroll: GtkPolicyType);
+
+(* void gtk_scrolled_window_set_min_content_width(GtkScrolledWindow *scrolled_window,
+                                                   int width) *)
+PROCEDURE gtk_scrolled_window_set_min_content_width (scrolled_window: GtkScrolledWindow;
+                                                     width: INTEGER);
+
+(* void gtk_scrolled_window_set_min_content_height(GtkScrolledWindow *scrolled_window,
+                                                    int height) *)
+PROCEDURE gtk_scrolled_window_set_min_content_height (scrolled_window: GtkScrolledWindow;
+                                                      height: INTEGER);
+
+(* void gtk_scrolled_window_set_max_content_width(GtkScrolledWindow *scrolled_window,
+                                                   int width) *)
+PROCEDURE gtk_scrolled_window_set_max_content_width (scrolled_window: GtkScrolledWindow;
+                                                     width: INTEGER);
+
+(* void gtk_scrolled_window_set_max_content_height(GtkScrolledWindow *scrolled_window,
+                                                    int height) *)
+PROCEDURE gtk_scrolled_window_set_max_content_height (scrolled_window: GtkScrolledWindow;
+                                                      height: INTEGER);
+
+(* void gtk_scrolled_window_set_propagate_natural_width(GtkScrolledWindow *scrolled_window,
+                                                         gboolean propagate) *)
+PROCEDURE gtk_scrolled_window_set_propagate_natural_width (scrolled_window: GtkScrolledWindow;
+                                                           propagate: INTEGER);
+
+(* void gtk_scrolled_window_set_propagate_natural_height(GtkScrolledWindow *scrolled_window,
+                                                          gboolean propagate) *)
+PROCEDURE gtk_scrolled_window_set_propagate_natural_height (scrolled_window: GtkScrolledWindow;
+                                                            propagate: INTEGER);
+
+END GtkScrolledWindow.

+ 45 - 0
src/GtkSearchEntry.def

@@ -0,0 +1,45 @@
+DEFINITION MODULE FOR "C" GtkSearchEntry ;
+
+(*
+   m2-GTK4 - GtkSearchEntry: a GtkEntry styled as a search field.
+   Mapped onto <gtk/gtksearchentry.h>.
+
+   It implements GtkEditable, so use gtk_editable_get_text() to read it.
+   Signals include "search-changed" (2-arg, like "changed") and
+   "activate".
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkSearchEntry,
+   gtk_search_entry_new,
+   gtk_search_entry_set_placeholder_text,
+   gtk_search_entry_get_placeholder_text,
+   gtk_search_entry_set_key_capture_widget,
+   gtk_search_entry_get_key_capture_widget;
+
+
+TYPE
+   GtkSearchEntry = ADDRESS;
+
+(* GtkWidget *gtk_search_entry_new(void) *)
+PROCEDURE gtk_search_entry_new () : GtkSearchEntry;
+
+(* void gtk_search_entry_set_placeholder_text(GtkSearchEntry *entry,
+                                              const char *text) *)
+PROCEDURE gtk_search_entry_set_placeholder_text (entry: GtkSearchEntry;
+                                                 text: ARRAY OF CHAR);
+
+(* const char *gtk_search_entry_get_placeholder_text(GtkSearchEntry *entry) *)
+PROCEDURE gtk_search_entry_get_placeholder_text (entry: GtkSearchEntry) : ADDRESS;
+
+(* void gtk_search_entry_set_key_capture_widget(GtkSearchEntry *entry,
+                                                 GtkWidget *widget) *)
+PROCEDURE gtk_search_entry_set_key_capture_widget (entry: GtkSearchEntry;
+                                                   widget: ADDRESS);
+
+(* GtkWidget *gtk_search_entry_get_key_capture_widget(GtkSearchEntry *entry) *)
+PROCEDURE gtk_search_entry_get_key_capture_widget (entry: GtkSearchEntry) : ADDRESS;
+
+END GtkSearchEntry.

+ 45 - 0
src/GtkSelectionModel.def

@@ -0,0 +1,45 @@
+DEFINITION MODULE FOR "C" GtkSelectionModel ;
+
+(*
+   m2-GTK4 - GtkSelectionModel: the interface a view uses to track the
+   selected items of a GListModel.  Mapped onto
+   <gtk/gtkselectionmodel.h>.
+
+   Concrete implementations: GtkSingleSelection (at most one item) and
+   GtkNoSelection (no selection - use for display-only views).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkSelectionModel,
+   gtk_selection_model_is_selected, gtk_selection_model_select_item,
+   gtk_selection_model_unselect_item,
+   gtk_selection_model_select_all, gtk_selection_model_unselect_all;
+
+
+TYPE
+   GtkSelectionModel = ADDRESS;
+
+(* gboolean gtk_selection_model_is_selected(GtkSelectionModel *model, guint position) *)
+PROCEDURE gtk_selection_model_is_selected (model: GtkSelectionModel;
+                                           position: CARDINAL) : [ INTEGER ];
+
+(* gboolean gtk_selection_model_select_item(GtkSelectionModel *model,
+                                             guint position, gboolean exclusive) *)
+PROCEDURE gtk_selection_model_select_item (model: GtkSelectionModel;
+                                           position: CARDINAL;
+                                           exclusive: INTEGER) : [ INTEGER ];
+
+(* gboolean gtk_selection_model_unselect_item(GtkSelectionModel *model,
+                                               guint position) *)
+PROCEDURE gtk_selection_model_unselect_item (model: GtkSelectionModel;
+                                             position: CARDINAL) : [ INTEGER ];
+
+(* gboolean gtk_selection_model_select_all(GtkSelectionModel *model) *)
+PROCEDURE gtk_selection_model_select_all (model: GtkSelectionModel) : [ INTEGER ];
+
+(* gboolean gtk_selection_model_unselect_all(GtkSelectionModel *model) *)
+PROCEDURE gtk_selection_model_unselect_all (model: GtkSelectionModel) : [ INTEGER ];
+
+END GtkSelectionModel.

+ 28 - 0
src/GtkSignalListItemFactory.def

@@ -0,0 +1,28 @@
+DEFINITION MODULE FOR "C" GtkSignalListItemFactory ;
+
+(*
+   m2-GTK4 - GtkSignalListItemFactory: the concrete GtkListItemFactory
+   that emits "setup", "bind", "unbind" and "teardown".  Mapped onto
+   <gtk/gtksignallistitemfactory.h>.
+
+   All four signals have the shape
+      void handler(GtkSignalListItemFactory *factory,
+                   GtkListItem *object, gpointer user_data)
+   which matches GtkClosures.Connect3.  For a GtkColumnView the object
+   passed is a GtkColumnViewCell (a GtkListItem subclass).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkSignalListItemFactory,
+   gtk_signal_list_item_factory_new;
+
+
+TYPE
+   GtkSignalListItemFactory = ADDRESS;
+
+(* GtkListItemFactory *gtk_signal_list_item_factory_new(void) *)
+PROCEDURE gtk_signal_list_item_factory_new () : GtkSignalListItemFactory;
+
+END GtkSignalListItemFactory.

+ 63 - 0
src/GtkSingleSelection.def

@@ -0,0 +1,63 @@
+DEFINITION MODULE FOR "C" GtkSingleSelection ;
+
+(*
+   m2-GTK4 - GtkSingleSelection: a GtkSelectionModel allowing zero or
+   one selected item.  Mapped onto <gtk/gtksingleselection.h>.
+
+   Feed it a GListModel (e.g. a GListStore) and hand it to a
+   GtkListView/GtkGridView/GtkColumnView.  The selected item's object
+   can be fetched with g_list_model_get_item() at the index returned by
+   gtk_single_selection_get_selected().
+
+   Signal: "notify::selected" (3-argument) when the selection changes.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkSingleSelection,
+   gtk_single_selection_new,
+   gtk_single_selection_set_model, gtk_single_selection_get_model,
+   gtk_single_selection_set_selected, gtk_single_selection_get_selected,
+   gtk_single_selection_set_autoselect, gtk_single_selection_get_autoselect,
+   gtk_single_selection_set_can_unselect,
+   gtk_single_selection_get_can_unselect;
+
+
+TYPE
+   GtkSingleSelection = ADDRESS;
+
+(* GtkSingleSelection *gtk_single_selection_new(GListModel *model) *)
+PROCEDURE gtk_single_selection_new (model: ADDRESS) : GtkSingleSelection;
+
+(* void gtk_single_selection_set_model(GtkSingleSelection *self, GListModel *model) *)
+PROCEDURE gtk_single_selection_set_model (self: GtkSingleSelection;
+                                          model: ADDRESS);
+
+(* GListModel *gtk_single_selection_get_model(GtkSingleSelection *self) *)
+PROCEDURE gtk_single_selection_get_model (self: GtkSingleSelection) : ADDRESS;
+
+(* void gtk_single_selection_set_selected(GtkSingleSelection *self, guint position) *)
+PROCEDURE gtk_single_selection_set_selected (self: GtkSingleSelection;
+                                             position: CARDINAL);
+
+(* guint gtk_single_selection_get_selected(GtkSingleSelection *self) *)
+PROCEDURE gtk_single_selection_get_selected (self: GtkSingleSelection) : CARDINAL;
+
+(* void gtk_single_selection_set_autoselect(GtkSingleSelection *self,
+                                             gboolean autoselect) *)
+PROCEDURE gtk_single_selection_set_autoselect (self: GtkSingleSelection;
+                                               autoselect: INTEGER);
+
+(* gboolean gtk_single_selection_get_autoselect(GtkSingleSelection *self) *)
+PROCEDURE gtk_single_selection_get_autoselect (self: GtkSingleSelection) : [ INTEGER ];
+
+(* void gtk_single_selection_set_can_unselect(GtkSingleSelection *self,
+                                               gboolean can_unselect) *)
+PROCEDURE gtk_single_selection_set_can_unselect (self: GtkSingleSelection;
+                                                 can_unselect: INTEGER);
+
+(* gboolean gtk_single_selection_get_can_unselect(GtkSingleSelection *self) *)
+PROCEDURE gtk_single_selection_get_can_unselect (self: GtkSingleSelection) : [ INTEGER ];
+
+END GtkSingleSelection.

+ 105 - 0
src/GtkSpinButton.def

@@ -0,0 +1,105 @@
+DEFINITION MODULE FOR "C" GtkSpinButton ;
+
+(*
+   m2-GTK4 - GtkSpinButton: a numeric entry with up/down arrows.
+   Mapped onto <gtk/gtkspinbutton.h>.
+
+   GtkSpinButton derives from GtkEntry (and thus GtkEditable), so its
+   text can be manipulated with the GtkEditable functions when needed;
+   its numeric value is a C double (REAL).
+
+   GtkSpinType (declared in this header) selects a step in spin().
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkSpinButton, GtkSpinType,
+   GtkSpinStepForward, GtkSpinStepBackward, GtkSpinPageForward,
+   GtkSpinPageBackward, GtkSpinHome, GtkSpinEnd, GtkSpinUserDefined,
+   gtk_spin_button_new, gtk_spin_button_new_with_range,
+   gtk_spin_button_get_value, gtk_spin_button_set_value,
+   gtk_spin_button_get_value_as_int,
+   gtk_spin_button_set_range, gtk_spin_button_set_increments,
+   gtk_spin_button_set_digits, gtk_spin_button_get_digits,
+   gtk_spin_button_set_wrap, gtk_spin_button_get_wrap,
+   gtk_spin_button_set_numeric, gtk_spin_button_get_numeric,
+   gtk_spin_button_set_snap_to_ticks,
+   gtk_spin_button_spin, gtk_spin_button_update;
+
+
+TYPE
+   GtkSpinButton = ADDRESS;
+   GtkSpinType = CARDINAL;
+
+CONST
+   GtkSpinStepForward  = 0;
+   GtkSpinStepBackward = 1;
+   GtkSpinPageForward  = 2;
+   GtkSpinPageBackward = 3;
+   GtkSpinHome         = 4;
+   GtkSpinEnd          = 5;
+   GtkSpinUserDefined  = 6;
+
+(* GtkWidget *gtk_spin_button_new(GtkAdjustment *adjustment,
+                                  double climb_rate, guint digits) *)
+PROCEDURE gtk_spin_button_new (adjustment: ADDRESS;
+                               climb_rate: REAL; digits: CARDINAL) : GtkSpinButton;
+
+(* GtkWidget *gtk_spin_button_new_with_range(double min, double max,
+                                              double step) *)
+PROCEDURE gtk_spin_button_new_with_range (min, max, step: REAL) : GtkSpinButton;
+
+(* double gtk_spin_button_get_value(GtkSpinButton *spin_button) *)
+PROCEDURE gtk_spin_button_get_value (spin_button: GtkSpinButton) : REAL;
+
+(* void gtk_spin_button_set_value(GtkSpinButton *spin_button, double value) *)
+PROCEDURE gtk_spin_button_set_value (spin_button: GtkSpinButton; value: REAL);
+
+(* int gtk_spin_button_get_value_as_int(GtkSpinButton *spin_button) *)
+PROCEDURE gtk_spin_button_get_value_as_int (spin_button: GtkSpinButton) : INTEGER;
+
+(* void gtk_spin_button_set_range(GtkSpinButton *spin_button,
+                                  double min, double max) *)
+PROCEDURE gtk_spin_button_set_range (spin_button: GtkSpinButton;
+                                     min, max: REAL);
+
+(* void gtk_spin_button_set_increments(GtkSpinButton *spin_button,
+                                       double step, double page) *)
+PROCEDURE gtk_spin_button_set_increments (spin_button: GtkSpinButton;
+                                          step, page: REAL);
+
+(* void gtk_spin_button_set_digits(GtkSpinButton *spin_button, guint digits) *)
+PROCEDURE gtk_spin_button_set_digits (spin_button: GtkSpinButton;
+                                      digits: CARDINAL);
+
+(* guint gtk_spin_button_get_digits(GtkSpinButton *spin_button) *)
+PROCEDURE gtk_spin_button_get_digits (spin_button: GtkSpinButton) : CARDINAL;
+
+(* void gtk_spin_button_set_wrap(GtkSpinButton *spin_button, gboolean wrap) *)
+PROCEDURE gtk_spin_button_set_wrap (spin_button: GtkSpinButton; wrap: INTEGER);
+
+(* gboolean gtk_spin_button_get_wrap(GtkSpinButton *spin_button) *)
+PROCEDURE gtk_spin_button_get_wrap (spin_button: GtkSpinButton) : [ INTEGER ];
+
+(* void gtk_spin_button_set_numeric(GtkSpinButton *spin_button, gboolean numeric) *)
+PROCEDURE gtk_spin_button_set_numeric (spin_button: GtkSpinButton;
+                                       numeric: INTEGER);
+
+(* gboolean gtk_spin_button_get_numeric(GtkSpinButton *spin_button) *)
+PROCEDURE gtk_spin_button_get_numeric (spin_button: GtkSpinButton) : [ INTEGER ];
+
+(* void gtk_spin_button_set_snap_to_ticks(GtkSpinButton *spin_button,
+                                          gboolean snap_to_ticks) *)
+PROCEDURE gtk_spin_button_set_snap_to_ticks (spin_button: GtkSpinButton;
+                                             snap_to_ticks: INTEGER);
+
+(* void gtk_spin_button_spin(GtkSpinButton *spin_button,
+                             GtkSpinType direction, double increment) *)
+PROCEDURE gtk_spin_button_spin (spin_button: GtkSpinButton;
+                                direction: GtkSpinType; increment: REAL);
+
+(* void gtk_spin_button_update(GtkSpinButton *spin_button) *)
+PROCEDURE gtk_spin_button_update (spin_button: GtkSpinButton);
+
+END GtkSpinButton.

+ 109 - 0
src/GtkStack.def

@@ -0,0 +1,109 @@
+DEFINITION MODULE FOR "C" GtkStack ;
+
+(*
+   m2-GTK4 - GtkStack: a container showing one child at a time.
+   Mapped onto <gtk/gtkstack.h>.
+
+   Children are given names (gtk_stack_add_named) or names and titles
+   (gtk_stack_add_titled, the title being what a GtkStackSwitcher
+   shows).  Switch the visible child by name or by widget pointer.
+
+   GtkStackTransitionType lives in this header; the values match the C
+   enumerators.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkStack, GtkStackTransitionType,
+   GtkStackTransitionNone, GtkStackTransitionCrossfade,
+   GtkStackTransitionSlideRight, GtkStackTransitionSlideLeft,
+   GtkStackTransitionSlideUp, GtkStackTransitionSlideDown,
+   GtkStackTransitionSlideLeftRight, GtkStackTransitionSlideUpDown,
+   GtkStackTransitionOverUp, GtkStackTransitionOverDown,
+   GtkStackTransitionOverLeft, GtkStackTransitionOverRight,
+   GtkStackTransitionUnderUp, GtkStackTransitionUnderDown,
+   GtkStackTransitionUnderLeft, GtkStackTransitionUnderRight,
+   GtkStackTransitionOverUpDown, GtkStackTransitionOverDownUp,
+   GtkStackTransitionOverLeftRight, GtkStackTransitionOverRightLeft,
+   GtkStackTransitionRotateLeft, GtkStackTransitionRotateRight,
+   GtkStackTransitionRotateLeftRight,
+   gtk_stack_new, gtk_stack_add_named, gtk_stack_add_titled,
+   gtk_stack_remove,
+   gtk_stack_set_visible_child_name, gtk_stack_get_visible_child_name,
+   gtk_stack_set_visible_child, gtk_stack_get_visible_child,
+   gtk_stack_set_transition_type, gtk_stack_get_transition_type,
+   gtk_stack_set_transition_duration;
+
+
+TYPE
+   GtkStack = ADDRESS;
+   GtkStackTransitionType = CARDINAL;
+
+CONST
+   GtkStackTransitionNone            = 0;
+   GtkStackTransitionCrossfade       = 1;
+   GtkStackTransitionSlideRight      = 2;
+   GtkStackTransitionSlideLeft       = 3;
+   GtkStackTransitionSlideUp         = 4;
+   GtkStackTransitionSlideDown       = 5;
+   GtkStackTransitionSlideLeftRight  = 6;
+   GtkStackTransitionSlideUpDown     = 7;
+   GtkStackTransitionOverUp          = 8;
+   GtkStackTransitionOverDown        = 9;
+   GtkStackTransitionOverLeft        = 10;
+   GtkStackTransitionOverRight       = 11;
+   GtkStackTransitionUnderUp         = 12;
+   GtkStackTransitionUnderDown       = 13;
+   GtkStackTransitionUnderLeft       = 14;
+   GtkStackTransitionUnderRight      = 15;
+   GtkStackTransitionOverUpDown      = 16;
+   GtkStackTransitionOverDownUp      = 17;
+   GtkStackTransitionOverLeftRight   = 18;
+   GtkStackTransitionOverRightLeft   = 19;
+   GtkStackTransitionRotateLeft      = 20;
+   GtkStackTransitionRotateRight     = 21;
+   GtkStackTransitionRotateLeftRight = 22;
+
+(* GtkWidget *gtk_stack_new(void) *)
+PROCEDURE gtk_stack_new () : GtkStack;
+
+(* GtkStackPage *gtk_stack_add_named(GtkStack *stack, GtkWidget *child,
+                                      const char *name) *)
+PROCEDURE gtk_stack_add_named (stack: GtkStack; child: ADDRESS;
+                               name: ARRAY OF CHAR) : [ ADDRESS ];
+
+(* GtkStackPage *gtk_stack_add_titled(GtkStack *stack, GtkWidget *child,
+                                       const char *name, const char *title) *)
+PROCEDURE gtk_stack_add_titled (stack: GtkStack; child: ADDRESS;
+                                name, title: ARRAY OF CHAR) : [ ADDRESS ];
+
+(* void gtk_stack_remove(GtkStack *stack, GtkWidget *child) *)
+PROCEDURE gtk_stack_remove (stack: GtkStack; child: ADDRESS);
+
+(* void gtk_stack_set_visible_child_name(GtkStack *stack, const char *name) *)
+PROCEDURE gtk_stack_set_visible_child_name (stack: GtkStack;
+                                            name: ARRAY OF CHAR);
+
+(* const char *gtk_stack_get_visible_child_name(GtkStack *stack) *)
+PROCEDURE gtk_stack_get_visible_child_name (stack: GtkStack) : ADDRESS;
+
+(* void gtk_stack_set_visible_child(GtkStack *stack, GtkWidget *child) *)
+PROCEDURE gtk_stack_set_visible_child (stack: GtkStack; child: ADDRESS);
+
+(* GtkWidget *gtk_stack_get_visible_child(GtkStack *stack) *)
+PROCEDURE gtk_stack_get_visible_child (stack: GtkStack) : ADDRESS;
+
+(* void gtk_stack_set_transition_type(GtkStack *stack,
+                                       GtkStackTransitionType transition) *)
+PROCEDURE gtk_stack_set_transition_type (stack: GtkStack;
+                                         transition: GtkStackTransitionType);
+
+(* GtkStackTransitionType gtk_stack_get_transition_type(GtkStack *stack) *)
+PROCEDURE gtk_stack_get_transition_type (stack: GtkStack) : GtkStackTransitionType;
+
+(* void gtk_stack_set_transition_duration(GtkStack *stack, guint duration) *)
+PROCEDURE gtk_stack_set_transition_duration (stack: GtkStack;
+                                             duration: CARDINAL);
+
+END GtkStack.

+ 33 - 0
src/GtkStackSwitcher.def

@@ -0,0 +1,33 @@
+DEFINITION MODULE FOR "C" GtkStackSwitcher ;
+
+(*
+   m2-GTK4 - GtkStackSwitcher: a row of buttons that switches a paired
+   GtkStack.  Mapped onto <gtk/gtkstackswitcher.h>.
+
+   It shows the titles given to the stack pages with
+   gtk_stack_add_titled().
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkStackSwitcher,
+   gtk_stack_switcher_new,
+   gtk_stack_switcher_set_stack, gtk_stack_switcher_get_stack;
+
+
+TYPE
+   GtkStackSwitcher = ADDRESS;
+
+(* GtkWidget *gtk_stack_switcher_new(void) *)
+PROCEDURE gtk_stack_switcher_new () : GtkStackSwitcher;
+
+(* void gtk_stack_switcher_set_stack(GtkStackSwitcher *switcher,
+                                      GtkStack *stack) *)
+PROCEDURE gtk_stack_switcher_set_stack (switcher: GtkStackSwitcher;
+                                        stack: ADDRESS);
+
+(* GtkStack *gtk_stack_switcher_get_stack(GtkStackSwitcher *switcher) *)
+PROCEDURE gtk_stack_switcher_get_stack (switcher: GtkStackSwitcher) : ADDRESS;
+
+END GtkStackSwitcher.

+ 36 - 0
src/GtkStringList.def

@@ -0,0 +1,36 @@
+DEFINITION MODULE FOR "C" GtkStringList ;
+
+(*
+   m2-GTK4 - GtkStringList: a simple GListModel over UTF-8 strings.
+   Mapped onto <gtk/gtkstringlist.h>.
+
+   Convenient as the model for a GtkDropDown.  Create an empty list with
+   gtk_string_list_new(NIL), append strings, then build the drop-down
+   with gtk_drop_down_new(list, NIL).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkStringList,
+   gtk_string_list_new, gtk_string_list_append,
+   gtk_string_list_remove, gtk_string_list_get_string;
+
+
+TYPE
+   GtkStringList = ADDRESS;
+
+(* GtkStringList *gtk_string_list_new(const char * const *strings) *)
+PROCEDURE gtk_string_list_new (strings: ADDRESS) : GtkStringList;
+
+(* void gtk_string_list_append(GtkStringList *self, const char *string) *)
+PROCEDURE gtk_string_list_append (self: GtkStringList; string: ARRAY OF CHAR);
+
+(* void gtk_string_list_remove(GtkStringList *self, guint position) *)
+PROCEDURE gtk_string_list_remove (self: GtkStringList; position: CARDINAL);
+
+(* const char *gtk_string_list_get_string(GtkStringList *self, guint position) *)
+PROCEDURE gtk_string_list_get_string (self: GtkStringList;
+                                      position: CARDINAL) : ADDRESS;
+
+END GtkStringList.

+ 31 - 0
src/GtkStringObject.def

@@ -0,0 +1,31 @@
+DEFINITION MODULE FOR "C" GtkStringObject ;
+
+(*
+   m2-GTK4 - GtkStringObject: an immutable GObject wrapper around a
+   string.  Mapped onto <gtk/gtkstringobject.h>.
+
+   Useful as the item type of a GListStore; the element type is
+   gtk_string_object_get_type().
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkStringObject,
+   gtk_string_object_new, gtk_string_object_get_string,
+   gtk_string_object_get_type;
+
+
+TYPE
+   GtkStringObject = ADDRESS;
+
+(* GtkStringObject *gtk_string_object_new(const char *string) *)
+PROCEDURE gtk_string_object_new (string: ARRAY OF CHAR) : GtkStringObject;
+
+(* const char *gtk_string_object_get_string(GtkStringObject *self) *)
+PROCEDURE gtk_string_object_get_string (self: GtkStringObject) : ADDRESS;
+
+(* GType gtk_string_object_get_type(void) *)
+PROCEDURE gtk_string_object_get_type () : LONGCARD;
+
+END GtkStringObject.

+ 42 - 0
src/GtkSwitch.def

@@ -0,0 +1,42 @@
+DEFINITION MODULE FOR "C" GtkSwitch ;
+
+(*
+   m2-GTK4 - GtkSwitch: an on/off slide switch.  Mapped onto
+   <gtk/gtkswitch.h>.
+
+   "active" is the requested state; "state" is the state the switch is
+   actually showing.  For non-blocking work they are usually equal.
+
+   Signals: "state-set" (handler gboolean(GtkSwitch*, gboolean state,
+   gpointer) - return FALSE to let the default handler apply the state)
+   and "notify::active" (handler void(GObject*, GParamSpec*, gpointer)).
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkSwitch,
+   gtk_switch_new,
+   gtk_switch_get_active, gtk_switch_set_active,
+   gtk_switch_get_state, gtk_switch_set_state;
+
+
+TYPE
+   GtkSwitch = ADDRESS;
+
+(* GtkWidget *gtk_switch_new(void) *)
+PROCEDURE gtk_switch_new () : GtkSwitch;
+
+(* gboolean gtk_switch_get_active(GtkSwitch *self) *)
+PROCEDURE gtk_switch_get_active (self: GtkSwitch) : [ INTEGER ];
+
+(* void gtk_switch_set_active(GtkSwitch *self, gboolean is_active) *)
+PROCEDURE gtk_switch_set_active (self: GtkSwitch; is_active: INTEGER);
+
+(* gboolean gtk_switch_get_state(GtkSwitch *self) *)
+PROCEDURE gtk_switch_get_state (self: GtkSwitch) : [ INTEGER ];
+
+(* void gtk_switch_set_state(GtkSwitch *self, gboolean state) *)
+PROCEDURE gtk_switch_set_state (self: GtkSwitch; state: INTEGER);
+
+END GtkSwitch.

+ 89 - 0
src/GtkTextBuffer.def

@@ -0,0 +1,89 @@
+DEFINITION MODULE FOR "C" GtkTextBuffer ;
+
+(*
+   m2-GTK4 - GtkTextBuffer: the text model behind GtkTextView.  Mapped
+   onto <gtk/gtktextbuffer.h>.
+
+   Iterators are supplied by the caller as VAR parameters.  For a
+   whole-buffer string use gtk_text_buffer_get_bounds() to fill the
+   start/end iterators, then gtk_text_buffer_get_text().  The string
+   that get_text() returns is newly allocated and must be freed with
+   GLib.g_free().
+
+   Signal: "changed" (2-argument), emitted whenever the text changes.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+FROM GtkTextIter IMPORT GtkTextIter;
+
+EXPORT UNQUALIFIED
+   GtkTextBuffer,
+   gtk_text_buffer_new, gtk_text_buffer_set_text, gtk_text_buffer_get_text,
+   gtk_text_buffer_insert,
+   gtk_text_buffer_get_line_count, gtk_text_buffer_get_char_count,
+   gtk_text_buffer_get_start_iter, gtk_text_buffer_get_end_iter,
+   gtk_text_buffer_get_bounds, gtk_text_buffer_get_iter_at_line,
+   gtk_text_buffer_get_modified, gtk_text_buffer_set_modified;
+
+
+TYPE
+   GtkTextBuffer = ADDRESS;
+
+(* GtkTextBuffer *gtk_text_buffer_new(GtkTextTagTable *table) *)
+PROCEDURE gtk_text_buffer_new (table: ADDRESS) : GtkTextBuffer;
+
+(* void gtk_text_buffer_set_text(GtkTextBuffer *buffer, const char *text,
+                                  int len) *)
+PROCEDURE gtk_text_buffer_set_text (buffer: GtkTextBuffer;
+                                    text: ARRAY OF CHAR; len: INTEGER);
+
+(* char *gtk_text_buffer_get_text(GtkTextBuffer *buffer,
+                                   const GtkTextIter *start,
+                                   const GtkTextIter *end,
+                                   gboolean include_hidden) *)
+PROCEDURE gtk_text_buffer_get_text (buffer: GtkTextBuffer;
+                                    VAR start, theEnd: GtkTextIter;
+                                    include_hidden: INTEGER) : ADDRESS;
+
+(* void gtk_text_buffer_insert(GtkTextBuffer *buffer, GtkTextIter *iter,
+                                const char *text, int len) *)
+PROCEDURE gtk_text_buffer_insert (buffer: GtkTextBuffer;
+                                  VAR iter: GtkTextIter;
+                                  text: ARRAY OF CHAR; len: INTEGER);
+
+(* int gtk_text_buffer_get_line_count(GtkTextBuffer *buffer) *)
+PROCEDURE gtk_text_buffer_get_line_count (buffer: GtkTextBuffer) : INTEGER;
+
+(* int gtk_text_buffer_get_char_count(GtkTextBuffer *buffer) *)
+PROCEDURE gtk_text_buffer_get_char_count (buffer: GtkTextBuffer) : INTEGER;
+
+(* void gtk_text_buffer_get_start_iter(GtkTextBuffer *buffer,
+                                        GtkTextIter *iter) *)
+PROCEDURE gtk_text_buffer_get_start_iter (buffer: GtkTextBuffer;
+                                          VAR iter: GtkTextIter);
+
+(* void gtk_text_buffer_get_end_iter(GtkTextBuffer *buffer,
+                                      GtkTextIter *iter) *)
+PROCEDURE gtk_text_buffer_get_end_iter (buffer: GtkTextBuffer;
+                                        VAR iter: GtkTextIter);
+
+(* void gtk_text_buffer_get_bounds(GtkTextBuffer *buffer,
+                                    GtkTextIter *start, GtkTextIter *end) *)
+PROCEDURE gtk_text_buffer_get_bounds (buffer: GtkTextBuffer;
+                                      VAR start, theEnd: GtkTextIter);
+
+(* gboolean gtk_text_buffer_get_iter_at_line(GtkTextBuffer *buffer,
+                                              GtkTextIter *iter,
+                                              int line_number) *)
+PROCEDURE gtk_text_buffer_get_iter_at_line (buffer: GtkTextBuffer;
+                                            VAR iter: GtkTextIter;
+                                            line_number: INTEGER) : [ INTEGER ];
+
+(* gboolean gtk_text_buffer_get_modified(GtkTextBuffer *buffer) *)
+PROCEDURE gtk_text_buffer_get_modified (buffer: GtkTextBuffer) : [ INTEGER ];
+
+(* void gtk_text_buffer_set_modified(GtkTextBuffer *buffer, gboolean setting) *)
+PROCEDURE gtk_text_buffer_set_modified (buffer: GtkTextBuffer;
+                                        setting: INTEGER);
+
+END GtkTextBuffer.

+ 27 - 0
src/GtkTextIter.def

@@ -0,0 +1,27 @@
+DEFINITION MODULE FOR "C" GtkTextIter ;
+
+(*
+   m2-GTK4 - GtkTextIter.  Declared in <gtk/gtktextiter.h>.
+
+   GtkTextIter is a large opaque struct (80 bytes on x86-64) that the
+   text API always passes by address.  Modula-2 never inspects its
+   fields, so it is modelled as an exactly sized, 8-byte aligned block
+   that can live on the Modula-2 stack:
+
+       VAR start, stop: GtkTextIter;
+       gtk_text_buffer_get_bounds(buffer, start, stop);
+
+   The array of ADDRESS words gives both the size (10 * 8 = 80) and the
+   alignment GtkTextIter expects on 64-bit targets.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED GtkTextIter;
+
+TYPE
+   GtkTextIter = RECORD
+      opaque: ARRAY [0..9] OF ADDRESS;
+   END;
+
+END GtkTextIter.

+ 100 - 0
src/GtkTextView.def

@@ -0,0 +1,100 @@
+DEFINITION MODULE FOR "C" GtkTextView ;
+
+(*
+   m2-GTK4 - GtkTextView: a multi-line text widget.  Mapped onto
+   <gtk/gtktextview.h>.
+
+   A text view is driven by a GtkTextBuffer; gtk_text_view_new() creates
+   its own, retrievable with gtk_text_view_get_buffer().  Put it inside
+   a GtkScrolledWindow for scrolling.
+
+   Signal: "buffer" / "notify::buffer" when the buffer is swapped.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+FROM GtkEnums IMPORT GtkWrapMode;
+FROM GtkTextIter IMPORT GtkTextIter;
+
+EXPORT UNQUALIFIED
+   GtkTextView,
+   gtk_text_view_new, gtk_text_view_new_with_buffer,
+   gtk_text_view_get_buffer, gtk_text_view_set_buffer,
+   gtk_text_view_set_editable, gtk_text_view_get_editable,
+   gtk_text_view_set_cursor_visible,
+   gtk_text_view_set_wrap_mode, gtk_text_view_get_wrap_mode,
+   gtk_text_view_set_monospace, gtk_text_view_get_monospace,
+   gtk_text_view_set_left_margin, gtk_text_view_set_right_margin,
+   gtk_text_view_set_top_margin, gtk_text_view_set_bottom_margin,
+   gtk_text_view_scroll_to_iter;
+
+
+TYPE
+   GtkTextView = ADDRESS;
+
+(* GtkWidget *gtk_text_view_new(void) *)
+PROCEDURE gtk_text_view_new () : GtkTextView;
+
+(* GtkWidget *gtk_text_view_new_with_buffer(GtkTextBuffer *buffer) *)
+PROCEDURE gtk_text_view_new_with_buffer (buffer: ADDRESS) : GtkTextView;
+
+(* GtkTextBuffer *gtk_text_view_get_buffer(GtkTextView *text_view) *)
+PROCEDURE gtk_text_view_get_buffer (text_view: GtkTextView) : ADDRESS;
+
+(* void gtk_text_view_set_buffer(GtkTextView *text_view,
+                                 GtkTextBuffer *buffer) *)
+PROCEDURE gtk_text_view_set_buffer (text_view: GtkTextView; buffer: ADDRESS);
+
+(* void gtk_text_view_set_editable(GtkTextView *text_view, gboolean setting) *)
+PROCEDURE gtk_text_view_set_editable (text_view: GtkTextView; setting: INTEGER);
+
+(* gboolean gtk_text_view_get_editable(GtkTextView *text_view) *)
+PROCEDURE gtk_text_view_get_editable (text_view: GtkTextView) : [ INTEGER ];
+
+(* void gtk_text_view_set_cursor_visible(GtkTextView *text_view,
+                                         gboolean setting) *)
+PROCEDURE gtk_text_view_set_cursor_visible (text_view: GtkTextView;
+                                            setting: INTEGER);
+
+(* void gtk_text_view_set_wrap_mode(GtkTextView *text_view,
+                                    GtkWrapMode wrap_mode) *)
+PROCEDURE gtk_text_view_set_wrap_mode (text_view: GtkTextView;
+                                       wrap_mode: GtkWrapMode);
+
+(* GtkWrapMode gtk_text_view_get_wrap_mode(GtkTextView *text_view) *)
+PROCEDURE gtk_text_view_get_wrap_mode (text_view: GtkTextView) : GtkWrapMode;
+
+(* void gtk_text_view_set_monospace(GtkTextView *text_view, gboolean monospace) *)
+PROCEDURE gtk_text_view_set_monospace (text_view: GtkTextView;
+                                       monospace: INTEGER);
+
+(* gboolean gtk_text_view_get_monospace(GtkTextView *text_view) *)
+PROCEDURE gtk_text_view_get_monospace (text_view: GtkTextView) : [ INTEGER ];
+
+(* void gtk_text_view_set_left_margin(GtkTextView *text_view, int margin) *)
+PROCEDURE gtk_text_view_set_left_margin (text_view: GtkTextView;
+                                         margin: INTEGER);
+
+(* void gtk_text_view_set_right_margin(GtkTextView *text_view, int margin) *)
+PROCEDURE gtk_text_view_set_right_margin (text_view: GtkTextView;
+                                          margin: INTEGER);
+
+(* void gtk_text_view_set_top_margin(GtkTextView *text_view, int margin) *)
+PROCEDURE gtk_text_view_set_top_margin (text_view: GtkTextView;
+                                        margin: INTEGER);
+
+(* void gtk_text_view_set_bottom_margin(GtkTextView *text_view, int margin) *)
+PROCEDURE gtk_text_view_set_bottom_margin (text_view: GtkTextView;
+                                           margin: INTEGER);
+
+(* gboolean gtk_text_view_scroll_to_iter(GtkTextView *text_view,
+                                          GtkTextIter *iter,
+                                          double within_margin,
+                                          gboolean use_align,
+                                          double xalign, double yalign) *)
+PROCEDURE gtk_text_view_scroll_to_iter (text_view: GtkTextView;
+                                        VAR iter: GtkTextIter;
+                                        within_margin: REAL;
+                                        use_align: INTEGER;
+                                        xalign, yalign: REAL) : [ INTEGER ];
+
+END GtkTextView.

+ 82 - 0
src/GtkWidget.def

@@ -0,0 +1,82 @@
+DEFINITION MODULE FOR "C" GtkWidget ;
+
+(*
+   m2-GTK4 - GtkWidget: the base class of every visible control.
+   Mapped onto <gtk/gtkwidget.h>.
+
+   GTK4 removed gtk_widget_show()/hide(): a widget is shown/hidden
+   with gtk_widget_set_visible().  A widget that is appended to a
+   parent is visible by default.
+
+   Layout helpers (margins, expand, alignment) are set per widget;
+   containers such as GtkBox arrange their children.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+FROM GtkEnums IMPORT GtkAlign;
+
+EXPORT UNQUALIFIED
+   GtkWidget,
+   gtk_widget_set_visible, gtk_widget_get_visible,
+   gtk_widget_set_sensitive, gtk_widget_get_sensitive,
+   gtk_widget_set_margin_top, gtk_widget_set_margin_bottom,
+   gtk_widget_set_margin_start, gtk_widget_set_margin_end,
+   gtk_widget_set_hexpand, gtk_widget_set_vexpand,
+   gtk_widget_set_halign, gtk_widget_set_valign,
+   gtk_widget_set_size_request, gtk_widget_grab_focus,
+   gtk_widget_get_width, gtk_widget_get_height;
+
+
+TYPE
+   GtkWidget = ADDRESS;
+
+(* void gtk_widget_set_visible(GtkWidget *widget, gboolean visible) *)
+PROCEDURE gtk_widget_set_visible (widget: GtkWidget; visible: INTEGER);
+
+(* gboolean gtk_widget_get_visible(GtkWidget *widget) *)
+PROCEDURE gtk_widget_get_visible (widget: GtkWidget) : [ INTEGER ];
+
+(* void gtk_widget_set_sensitive(GtkWidget *widget, gboolean sensitive) *)
+PROCEDURE gtk_widget_set_sensitive (widget: GtkWidget; sensitive: INTEGER);
+
+(* gboolean gtk_widget_get_sensitive(GtkWidget *widget) *)
+PROCEDURE gtk_widget_get_sensitive (widget: GtkWidget) : [ INTEGER ];
+
+(* void gtk_widget_set_margin_top(GtkWidget *widget, int margin) *)
+PROCEDURE gtk_widget_set_margin_top (widget: GtkWidget; margin: INTEGER);
+
+(* void gtk_widget_set_margin_bottom(GtkWidget *widget, int margin) *)
+PROCEDURE gtk_widget_set_margin_bottom (widget: GtkWidget; margin: INTEGER);
+
+(* void gtk_widget_set_margin_start(GtkWidget *widget, int margin) *)
+PROCEDURE gtk_widget_set_margin_start (widget: GtkWidget; margin: INTEGER);
+
+(* void gtk_widget_set_margin_end(GtkWidget *widget, int margin) *)
+PROCEDURE gtk_widget_set_margin_end (widget: GtkWidget; margin: INTEGER);
+
+(* void gtk_widget_set_hexpand(GtkWidget *widget, gboolean expand) *)
+PROCEDURE gtk_widget_set_hexpand (widget: GtkWidget; expand: INTEGER);
+
+(* void gtk_widget_set_vexpand(GtkWidget *widget, gboolean expand) *)
+PROCEDURE gtk_widget_set_vexpand (widget: GtkWidget; expand: INTEGER);
+
+(* void gtk_widget_set_halign(GtkWidget *widget, GtkAlign align) *)
+PROCEDURE gtk_widget_set_halign (widget: GtkWidget; align: GtkAlign);
+
+(* void gtk_widget_set_valign(GtkWidget *widget, GtkAlign align) *)
+PROCEDURE gtk_widget_set_valign (widget: GtkWidget; align: GtkAlign);
+
+(* void gtk_widget_set_size_request(GtkWidget *widget, int width, int height) *)
+PROCEDURE gtk_widget_set_size_request (widget: GtkWidget;
+                                       width, height: INTEGER);
+
+(* void gtk_widget_grab_focus(GtkWidget *widget) *)
+PROCEDURE gtk_widget_grab_focus (widget: GtkWidget);
+
+(* int gtk_widget_get_width(GtkWidget *widget) *)
+PROCEDURE gtk_widget_get_width (widget: GtkWidget) : INTEGER;
+
+(* int gtk_widget_get_height(GtkWidget *widget) *)
+PROCEDURE gtk_widget_get_height (widget: GtkWidget) : INTEGER;
+
+END GtkWidget.

+ 74 - 0
src/GtkWindow.def

@@ -0,0 +1,74 @@
+DEFINITION MODULE FOR "C" GtkWindow ;
+
+(*
+   m2-GTK4 - GtkWindow: a top-level window.  Mapped onto <gtk/gtkwindow.h>.
+
+   In GTK4 create a window with either
+     * gtk_application_window_new(app)  - preferred; ties the window to
+       the GtkApplication so the app loop stays alive while it shows, or
+     * gtk_window_new()                 - a free-standing window.
+
+   Set its single child with gtk_window_set_child() (GTK4 windows hold
+   exactly one child), then gtk_window_present() it.
+
+   The child/app parameters are ADDRESS because the concrete widget
+   type is defined in the sibling modules (GtkWidget / GtkApplication);
+   a GtkWidget * and a GtkApplication * are both plain pointers.
+*)
+
+FROM SYSTEM IMPORT ADDRESS;
+
+EXPORT UNQUALIFIED
+   GtkWindow,
+   gtk_window_new, gtk_application_window_new,
+   gtk_window_set_title, gtk_window_set_default_size,
+   gtk_window_set_child, gtk_window_set_application,
+   gtk_window_present, gtk_window_close, gtk_window_destroy,
+   gtk_window_set_resizable, gtk_window_set_decorated,
+   gtk_window_set_titlebar, gtk_window_get_titlebar;
+
+
+TYPE
+   GtkWindow = ADDRESS;
+
+(* GtkWidget *gtk_window_new(void) *)
+PROCEDURE gtk_window_new () : GtkWindow;
+
+(* GtkWidget *gtk_application_window_new(GtkApplication *application) *)
+PROCEDURE gtk_application_window_new (application: ADDRESS) : GtkWindow;
+
+(* void gtk_window_set_title(GtkWindow *window, const char *title) *)
+PROCEDURE gtk_window_set_title (window: GtkWindow; title: ARRAY OF CHAR);
+
+(* void gtk_window_set_default_size(GtkWindow *window, int width, int height) *)
+PROCEDURE gtk_window_set_default_size (window: GtkWindow;
+                                       width, height: INTEGER);
+
+(* void gtk_window_set_child(GtkWindow *window, GtkWidget *child) *)
+PROCEDURE gtk_window_set_child (window: GtkWindow; child: ADDRESS);
+
+(* void gtk_window_set_application(GtkWindow *window, GtkApplication *application) *)
+PROCEDURE gtk_window_set_application (window: GtkWindow; application: ADDRESS);
+
+(* void gtk_window_present(GtkWindow *window) *)
+PROCEDURE gtk_window_present (window: GtkWindow);
+
+(* void gtk_window_close(GtkWindow *window) *)
+PROCEDURE gtk_window_close (window: GtkWindow);
+
+(* void gtk_window_destroy(GtkWindow *window) *)
+PROCEDURE gtk_window_destroy (window: GtkWindow);
+
+(* void gtk_window_set_resizable(GtkWindow *window, gboolean resizable) *)
+PROCEDURE gtk_window_set_resizable (window: GtkWindow; resizable: INTEGER);
+
+(* void gtk_window_set_decorated(GtkWindow *window, gboolean setting) *)
+PROCEDURE gtk_window_set_decorated (window: GtkWindow; decorated: INTEGER);
+
+(* void gtk_window_set_titlebar(GtkWindow *window, GtkWidget *titlebar) *)
+PROCEDURE gtk_window_set_titlebar (window: GtkWindow; titlebar: ADDRESS);
+
+(* GtkWidget *gtk_window_get_titlebar(GtkWindow *window) *)
+PROCEDURE gtk_window_get_titlebar (window: GtkWindow) : ADDRESS;
+
+END GtkWindow.

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio