Find avaible Signals for an Object

I would like to know how do I find programmatically information about which Signals are available for an Object.

For example, if I need to find out which properties are available for an object and for its child (if is the case), I use the following two functions:

g_object_class_list_properties()
gtk_container_class_list_child_properties

Putting them in some functions I have the following (lets take a GRID as example):

void list_object_properties( GObject *object )
{
    GParamSpec **list_prop;
    guint n_prop;
    guint count = 1;

    list_prop = g_object_class_list_properties( G_OBJECT_GET_CLASS( object ), &n_prop );

    for ( guint i = 0 ; i < n_prop ; i++ )
    {
        const gchar *const prop_name = g_param_spec_get_name( list_prop[i] );
        g_print( "property[%u] = %s\n", count++, prop_name );
    }
}

void list_child_properties ( GObject *object )
{
    GParamSpec **list_prop;
    guint n_prop = 0;
    guint count  = 1;

    list_prop = gtk_container_class_list_child_properties( G_OBJECT_GET_CLASS( object ), &n_prop );

    for ( guint i = 0 ; i < n_prop ; i++ )
    {
        const gchar *const prop_name = g_param_spec_get_name( list_prop[i] );
        g_print( "property[%u] = %s\n", count++, prop_name );
    }
}

And Outpus:

        Object Properties
property[1] = orientation
property[2] = name
property[3] = parent
property[4] = width-request
property[5] = height-request
property[6] = visible
property[7] = sensitive
property[8] = app-paintable
property[9] = can-focus
property[10] = has-focus
property[11] = is-focus
property[12] = focus-on-click
property[13] = can-default
property[14] = has-default
property[15] = receives-default
property[16] = composite-child
property[17] = style
property[18] = events
property[19] = no-show-all
property[20] = has-tooltip
property[21] = tooltip-markup
property[22] = tooltip-text
property[23] = window
property[24] = opacity
property[25] = double-buffered
property[26] = halign
property[27] = valign
property[28] = margin-left
property[29] = margin-right
property[30] = margin-start
property[31] = margin-end
property[32] = margin-top
property[33] = margin-bottom
property[34] = margin
property[35] = hexpand
property[36] = vexpand
property[37] = hexpand-set
property[38] = vexpand-set
property[39] = expand
property[40] = scale-factor
property[41] = border-width
property[42] = resize-mode
property[43] = child
property[44] = row-spacing
property[45] = column-spacing
property[46] = row-homogeneous
property[47] = column-homogeneous
property[48] = baseline-row

        Child Properties

property[1] = left-attach
property[2] = top-attach
property[3] = width
property[4] = height

How do I find out information about signals, which reports something like this:

        Object Signals
Signal[1] = ??????
Signal[2] = ??????
Signal[3] = ??????
Signal[4] = ??????
Signal[5] = ??????

        Child Signals

Signal[1] = ??????
Signal[2] = ??????

You will need to call g_signal_list_ids() to gather all the signal identifiers for a given GType, and then call g_signal_query() for each identifier to gather the signal metadata.

Well I was close, but it is now what I was needing:

guint n_signals;
guint *signals = g_signal_list_ids( g_type_from_name( "GtkWidget" ), &n_signals );

for ( guint i = 0 ; i < n_signals ; i++ )
{
    g_print( "Signal = %s\n", g_signal_name( signals[i] ) );
}

I will give a try, Thank you.

Remember that this will ever only work for:

  1. GTypes registered by GTK itself or
  2. GTypes that have been instantiated

If a GType hasn’t been registered yet, you won’t be able to get the type from the type name.

Yes, and I notices once that I used:

g_type_from_name( "GtkGrid" )

Or:

g_type_from_name( gtk_widget_get_name( grid ) )

Both did not worked.

I suppose this is why g_type_ensure has been exposed.

Getting the type from GtkGrid should always work after calling gtk_init() because GTK registers all its types on initialization.

This line is non-sensical. The name of the widget could be any random string, and will fall back to the type name if one isn’t set.

In general, you can only ever use g_type_from_name() when debugging and you already know what kind of types you have. You cannot rely on the type name for anything else—especially for introspection.

It seems you’re doing a lot of introspection work; why not use the introspection data provided by GTK itself, through gobject-introspection instead of reimplementing it from first principles (and probably badly)?

Kind of. We have g_type_ensure() because calling something like:

GType unused = some_class_get_type ();

or:

(void) some_class_get_type ();

will either produce a warning, or might be optimised away by the compiler.

I am doing something wrong in here, because the following does not work for grid:

guint n_signals;
guint *signals_id = g_signal_list_ids ( G_TYPE_FROM_INSTANCE ( grid ), &n_signals );

for ( guint i = 0 ; i < n_signals ; i++ )
{
    GSignalQuery query;
    g_signal_query( signals_id[i], &query );
    g_print ( "Signal[%u] = %s\n",i , query.signal_name );
}

and for “window” it returns: (with G_TYPE_FROM_INSTANCE ( window ) )

Signal[0] = keys-changed
Signal[1] = set-focus
Signal[2] = activate-focus
Signal[3] = activate-default
Signal[4] = enable-debugging

So I cannot figure out why is now working on grid.

GtkGrid doesn’t have any signal by itself, so of course you won’t get any signal from its type.

If you want to get all the signals registered by a type, including its ancestor types, you’ll have to traverse the type hierarchy.

Yes you are right, my bad explanation.

Lets put it in a different way.
The GtkGrid si derived from GtkContainer, which in terms means that it inherits its properties and signals (of GtkContainer).

What I was trying to achieve was to get those Signals as well (available for GtkContainer and so on… ).
The GtkContainer has 4 Signals ( “add, check-resize, remove, set-focus-child”) and I thought that I can get them through the GtkGrid object.

In other words GtkGrid has only 5 Properties, but avaible (because it inherits…) are 48 ( from its ancestor types) available.
I hope you understand what I am trying here to achieve.

Here is a demo of the “add” signal:

#include <gtk/gtk.h>

void child_added ( GtkGrid *grid );
void child_added ( GtkGrid *grid )
{
    g_return_if_fail ( GTK_IS_GRID ( grid ) );
    g_print ( "child added\n" );
}

int main ( void )
{
    GtkWidget *window;
    GtkWidget *grid;
    GtkWidget *button;

    /// ***
    gtk_init ( NULL, NULL );

    /// *** Create a Window
    window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );

    /// *** Create a Grid
    grid = gtk_grid_new();
    gtk_container_add ( GTK_CONTAINER ( window ), grid );

    ///  *** Catch the ADD signal from GtkContainer
    g_signal_connect_swapped ( grid, "add", G_CALLBACK ( child_added ), grid );

    /// *** Create and Add the button Child
    button = gtk_button_new_with_label( "click" );
    gtk_container_add ( GTK_CONTAINER( grid ), button );


    gtk_widget_show_all ( window );
    gtk_main ();
}

If you want to get all the signals registered by a type, including its ancestor types, you’ll have to traverse the type hierarchy

This was my Question, how do I do that? How do I find out all available Signals (including its ancestor types) which one can use them on an Object?

You can look at the GTK Inspector as an example: https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/inspector/signals-list.c

1 Like

Start from the GType you have, get the list of signals and query them.

Get the parent GType, using g_type_parent(), get the list of signals, and query them.

Continue upwards on the type hierarchy until you hit G_TYPE_OBJECT.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.