#include <gtk/gtk.h>

#define __brisk_unused__ __attribute__((unused))

/**
 * Check for clicks outside the window itself
 */
static gboolean on_button_press(GtkWidget *widget, GdkEvent *event,
                                               __brisk_unused__ gpointer udata)
{
        gint wx, wy = 0;
        gint ww, wh = 0;

        gtk_window_get_size(GTK_WINDOW(widget), &ww, &wh);
        gtk_window_get_position(GTK_WINDOW(widget), &wx, &wy);

        if ((event->button.x_root < wx || event->button.x_root > (wx + ww)) ||
            (event->button.y_root < wy || event->button.y_root > (wy + wh))) {
                gtk_widget_hide(widget);
                return GDK_EVENT_STOP;
        }
        return GDK_EVENT_PROPAGATE;
}

static void do_grab(GtkWidget *widget)
{
        GdkDisplay *display = NULL;
        GdkSeat *seat = NULL;
        GdkWindow *window = NULL;
        GdkSeatCapabilities caps = 0;
        __brisk_unused__ GdkGrabStatus st;

        display = gtk_widget_get_display(widget);
        seat = gdk_display_get_default_seat(display);
        window = gtk_widget_get_window(widget);

        if (gdk_seat_get_pointer(seat) != NULL) {
                caps |= GDK_SEAT_CAPABILITY_ALL_POINTING;
        }
        if (gdk_seat_get_keyboard(seat) != NULL) {
                caps |= GDK_SEAT_CAPABILITY_KEYBOARD;
        }

        st = gdk_seat_grab(seat, window, caps, TRUE, NULL, NULL, NULL, NULL);
}

static gboolean on_map(GtkWidget *widget, __brisk_unused__ gpointer udata)
{
        do_grab(widget);

        return GDK_EVENT_PROPAGATE;
}

static void do_ungrab(GtkWidget *widget)
{
        GdkDisplay *display = NULL;
        GdkSeat *seat = NULL;

        display = gtk_widget_get_display(widget);
        seat = gdk_display_get_default_seat(display);

        gdk_seat_ungrab(seat);
}

static gboolean on_unmap(GtkWidget *widget, __brisk_unused__ gpointer udata)
{
        do_ungrab(widget);
        g_idle_add((GSourceFunc)gtk_main_quit, NULL);

        return GDK_EVENT_PROPAGATE;
}

int main(int argc, char **argv)
{
        gtk_init(&argc, &argv);
        GtkWidget *window = NULL, *scroll = NULL;
        GtkWidget *box = NULL;


        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_window_set_modal(GTK_WINDOW(window), TRUE);
        gtk_window_stick(GTK_WINDOW(window));
        gtk_window_set_decorated(GTK_WINDOW(window), FALSE);
        gtk_window_set_skip_pager_hint(GTK_WINDOW(window), TRUE);
        gtk_window_set_skip_taskbar_hint(GTK_WINDOW(window), TRUE);
        gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_POPUP_MENU);

        scroll = gtk_scrolled_window_new(NULL, NULL);
        gtk_container_add(GTK_CONTAINER(window), scroll);
        gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
        gtk_scrolled_window_set_overlay_scrolling(GTK_SCROLLED_WINDOW(scroll), FALSE);
        g_signal_connect_after(window, "delete-event", gtk_main_quit, NULL);
        box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
        gtk_container_add(GTK_CONTAINER(scroll), box);

        for (int i = 0; i < 300; i++) {
                GtkWidget *label = gtk_button_new_with_label("I am label");
                gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 2);
        }

        /* Hook up grab-esque signals */
        g_signal_connect(window, "button-press-event", G_CALLBACK(on_button_press), NULL);
        g_signal_connect(window, "map-event", G_CALLBACK(on_map), NULL);
        g_signal_connect(window, "unmap-event", G_CALLBACK(on_unmap), NULL);

        gtk_window_set_default_size(GTK_WINDOW(window), 400, 550);
        gtk_widget_show_all(window);

        gtk_main();

        return 0;
}
