/* Even the GPL header does not want to be associated with "that". */

#include "gliv.h"
#include "dirty_gtk.h"

/*
 * This is the only way I found to build a menu with N items in O(N)
 * time instead of O(N²).
 */

#define CHILDREN(dirty_menu) GTK_MENU_SHELL((dirty_menu)->gtk_menu)->children

DirtyGtkMenu *dirty_gtk_menu_new(void)
{
    DirtyGtkMenu *menu = g_new(DirtyGtkMenu, 1);

    menu->gtk_menu = GTK_MENU(gtk_menu_new());
    menu->tearoff = GTK_TEAROFF_MENU_ITEM(gtk_tearoff_menu_item_new());

    gtk_menu_append(menu->gtk_menu, GTK_WIDGET(menu->tearoff));
    menu->last_child = g_list_last(CHILDREN(menu));

    return menu;
}

void dirty_gtk_menu_append(DirtyGtkMenu * menu, GtkWidget * item)
{
    GList *children = CHILDREN(menu);

    menu->last_child = g_list_last(menu->last_child);
    CHILDREN(menu) = menu->last_child;

    gtk_menu_shell_append(GTK_MENU_SHELL(menu->gtk_menu), item);
    CHILDREN(menu) = children;
}

GtkTearoffMenuItem *dirty_gtk_menu_get_tearoff(DirtyGtkMenu * menu)
{
    return menu->tearoff;
}

void dirty_gtk_menu_release(DirtyGtkMenu * menu)
{
    g_free(menu);
}

/*** ::grab-notify ***/

/*
 * This is borrowed from gtk+-2, without the gtk_grab_notify() calls.
 * They slow down things a lot when the images menus are built with many files.
 */
GtkWindowGroup *_gtk_window_get_group(GtkWindow * window)
{
    if (window && window->group)
        return window->group;
    else {
        static GtkWindowGroup *default_group = NULL;

        if (!default_group)
            default_group = gtk_window_group_new();

        return default_group;
    }
}

static GtkWindowGroup *gtk_main_get_window_group(GtkWidget * widget)
{
    GtkWidget *toplevel = NULL;

    if (widget)
        toplevel = gtk_widget_get_toplevel(widget);

    if (toplevel && GTK_IS_WINDOW(toplevel))
        return _gtk_window_get_group(GTK_WINDOW(toplevel));
    else
        return _gtk_window_get_group(NULL);
}

void gtk_grab_add(GtkWidget * widget)
{
    GtkWindowGroup *group;

    g_return_if_fail(widget != NULL);

    if (!GTK_WIDGET_HAS_GRAB(widget) && GTK_WIDGET_IS_SENSITIVE(widget)) {
        GTK_WIDGET_SET_FLAGS(widget, GTK_HAS_GRAB);

        group = gtk_main_get_window_group(widget);

        g_object_ref(widget);
        group->grabs = g_slist_prepend(group->grabs, widget);

/*      gtk_grab_notify (group, widget, FALSE); */
    }
}

void gtk_grab_remove(GtkWidget * widget)
{
    GtkWindowGroup *group;

    g_return_if_fail(widget != NULL);

    if (GTK_WIDGET_HAS_GRAB(widget)) {
        GTK_WIDGET_UNSET_FLAGS(widget, GTK_HAS_GRAB);

        group = gtk_main_get_window_group(widget);
        group->grabs = g_slist_remove(group->grabs, widget);

        g_object_unref(widget);

/*      gtk_grab_notify (group, widget, TRUE); */
    }
}
