Skip to content

GtkCustomSorter compare callback receives undefined args (untyped gconstpointer not marshalled) #440

Description

@romgrk

Summary

Gtk.CustomSorter's compare callback receives undefined for both items it is supposed to compare, so the sorter can never order anything. Any GtkSortListModel driven by a CustomSorter silently keeps the model's original order.

The root cause appears to be that GtkCustomSortFunc is declared as

int (*GtkCustomSortFunc) (gconstpointer a, gconstpointer b, gpointer user_data);

i.e. the two items are untyped gconstpointers. With no GI type information for a/b, node-gtk passes undefined into the JS callback instead of wrapping the underlying GObjects.

Reproduction

const gi = require('node-gtk');
const Gtk = gi.require('Gtk', '4.0');
Gtk.init();

const list = Gtk.StringList.new(['banana', 'apple', 'cherry']);
let firstArgs = null;
const sorter = Gtk.CustomSorter.new((a, b) => {
  if (!firstArgs) firstArgs = [a, b];
  const av = a && a.getString ? a.getString() : a;
  const bv = b && b.getString ? b.getString() : b;
  return av < bv ? -1 : av > bv ? 1 : 0;
});
const sorted = Gtk.SortListModel.new(list, sorter);

console.log('callback first args:', firstArgs);
const out = [];
for (let i = 0; i < sorted.getNItems(); i++) out.push(sorted.getItem(i).getString());
console.log('result order:', out.join(', '));

Actual

callback first args: [ undefined, undefined ]
result order: banana, apple, cherry

Expected

a and b should be the GtkStringObject items being compared, and the result should be apple, banana, cherry.

Impact

CustomSorter is the only GtkSorter that takes a plain compare function; the expression-based sorters (StringSorter/NumericSorter) require a GtkExpression, and ClosureExpression.new wants a real GObject.Closure rather than a JS function. So there is currently no working way to do a custom sort (e.g. "directories first, then by name" for a file tree) from JS. The practical workaround is to sort in JS and feed a Gio.ListStore.

The same limitation presumably affects any callback whose arguments are untyped gpointer/gconstpointer (e.g. GCompareDataFunc, GtkMapListModel map funcs returning into untyped slots, etc.).

Environment

  • node-gtk 2.0.0
  • node v22.22.3
  • GTK 4.22.4, GLib 2.88.1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions