#include <gtk/gtk.h>

static gint pointer_x = -1;
static gint pointer_y = -1;

static gboolean widget_is_covered(GtkWidget *widget)
{
    GtkWidget *window = gtk_widget_get_toplevel(widget);
    gint x, y;

    return
        gtk_widget_translate_coordinates(window, widget, pointer_x, pointer_y, &x, &y) &&
        x >= 0 && x < widget->allocation.width && y >= 0 && y < widget->allocation.height;
}

static void on_leave_notify_event()
{
    pointer_x = pointer_y = -1;
}

static void on_motion_notify_event(GtkWidget *widget, GdkEventMotion *motion)
{
    pointer_x = motion->x;
    pointer_y = motion->y;
}
     
static void gtk_widget_set_sensitive_impl(GtkWidget *widget, gboolean sensitive)
{
    if (sensitive != GTK_WIDGET_IS_SENSITIVE(widget)) {
        gtk_widget_set_sensitive(widget, sensitive);

        if (GTK_IS_BUTTON(widget))
            GTK_BUTTON(widget)->in_button = widget_is_covered(widget);
    }
}

#define gtk_widget_set_sensitive gtk_widget_set_sensitive_impl

static void on_click(GtkWidget *button)
{
    gtk_widget_set_sensitive(button, FALSE);
    g_print("Clicked!\n");
    gtk_widget_set_sensitive(button, TRUE);
}

static void on_toggle(GtkWidget *toggle, GtkWidget *button)
{
    gtk_widget_set_sensitive(button,
        gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(toggle)));
}

static gboolean on_thief(GtkWidget *widget, GdkEventMotion *motion, gboolean blocker)
{
    g_debug("trying to steal motion event: %g/%g", motion->x, motion->y);
    return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(blocker));
}
     
int main(int argc, char *argv[])
{
    gtk_init(&argc, &argv);

    GtkWidget *button = gtk_button_new_with_label("Click!");

    GtkWidget *toggle = gtk_check_button_new_with_label("Sensitive?");
    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(toggle), TRUE);

    GtkWidget *blocker = gtk_check_button_new_with_label("Block it?");
    
    GtkWidget *vbox = gtk_vbox_new(FALSE, 10);
    gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), toggle, FALSE, TRUE, 0);
    gtk_box_pack_start(GTK_BOX(vbox), blocker, FALSE, TRUE, 0);

    GtkWidget *thief = gtk_event_box_new();
    gtk_widget_add_events(thief, GDK_POINTER_MOTION_MASK);
    gtk_container_add(GTK_CONTAINER(thief), vbox);
    
    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_widget_add_events(window, GDK_POINTER_MOTION_MASK);
    gtk_container_add(GTK_CONTAINER(window), thief);
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
    gtk_widget_show_all(window);

    g_object_connect(G_OBJECT(window), 
        "signal::leave-notify-event", on_leave_notify_event, NULL,
        "signal::motion-notify-event", on_motion_notify_event, NULL,
        "signal::destroy", gtk_main_quit, NULL,
        NULL);
    g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(on_click), NULL);
    g_signal_connect(G_OBJECT(toggle), "toggled", G_CALLBACK(on_toggle), button);
    g_signal_connect(G_OBJECT(thief), "motion-notify-event", G_CALLBACK(on_thief), blocker);

    gtk_main();

    return 0;
}
