Glib signals - How to check if a handler of an instance is already blocked?
Asked Answered
F

1

6

After a handler of an instance has been blocked with g_signal_handler_block, is it possible to check if the handler is still being blocked or has been unblocked by g_signal_handler_unblock in the meantime, apart from storing the state in a boolean variable for example?

I hoped something like that would be possible

g_signal_handler_block (selection, handler_id_row_selected);
if (g_signal_handler_is_blocked (selection, handler_id_row_selected))
  g_print ("is still blocked");

But a "g_signal_handler_is_blocked" function does not exist. g_signal_handler_is_connected is not the right function to use, since the signal handler remains connected, thus the function returns TRUE.

I have tried g_signal_handler_find (), since there is G_SIGNAL_MATCH_UNBLOCKED as one of the match types, but it has not worked yet. Even though I have rewritten my code anyway, I still would like to know if it is possible, since i use the blocking/unblocking relatively often.

Firehouse answered 21/1, 2013 at 0:15 Comment(2)
Maybe you could write that function and submit a patch in a bug report on bugzilla.gnome.org? Looking at git.gnome.org/browse/glib/tree/gobject/gsignal.c, it would be easy enough to implement...Damian
Though my mind didn't reach that far yet, there is nothing to lose with that... I'll have a look at gsignal.c, thanks for coming up with that idea.Firehouse
S
2

g_signal_handler_find here is working as expected. Here is my test case:

#include <gtk/gtk.h>

gboolean
g_signal_handlers_is_blocked_by_func(gpointer instance, GFunc func, gpointer data)
{
    return g_signal_handler_find(instance,
                                 G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA | G_SIGNAL_MATCH_UNBLOCKED,
                                 0, 0, NULL, func, data) == 0;
}

static void
handler(void)
{
    g_print("handler called\n");
}

static void
switch_blocking(GtkWidget *button)
{
    GFunc func = (GFunc) handler;

    if (g_signal_handlers_is_blocked_by_func(button, func, NULL)) {
        g_signal_handlers_unblock_by_func(button, func, NULL);
        g_print("handler unblocked\n");
    } else {
        g_signal_handlers_block_by_func(button, func, NULL);
        g_print("handler blocked\n");
    }
}

int
main(int argc, char **argv)
{
    GtkWidget *window;
    GtkWidget *button;

    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    button = gtk_button_new_with_label("Click me");

    g_signal_connect_after(button, "clicked", G_CALLBACK(switch_blocking), NULL);
    g_signal_connect(button, "clicked", G_CALLBACK(handler), NULL);

    gtk_container_add(GTK_CONTAINER(window), button);
    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}
Subtotal answered 21/1, 2013 at 22:46 Comment(4)
Thanks to your example I managed to adapt your example for my code, if (g_signal_handler_find (selection,G_SIGNAL_MATCH_UNBLOCKED, 0, 0, NULL, NULL, NULL) == 0) simply was enough. Would still be nice if there would be a simple function to handle this!Firehouse
This is what the above g_signal_handlers_is_blocked_by_func() wrapper was intended for. Also, your use of g_signal_handler_find is wrong (or, better, it does not do what you requested): it unblocks every handler bound to selection.Subtotal
Maybe I didn't state this clear enough, the simple if statement was good enough for my special case since I have only one handler bound to selection anyway. It wasn't meant to be understood as a general, easier solution than yours.Firehouse
The code snippet is a test-case, the only relevant part are lines 7-10. What I'm trying to say is g_signal_handler_find(selection, G_SIGNAL_MATCH_UNBLOCKED, 0, 0, NULL, NULL, NULL) does not filter on handler_id_row_selected, as requested by your question.Subtotal

© 2022 - 2024 — McMap. All rights reserved.