<commit_before>/*
 Copyright (C) 2009 <NAME> <<EMAIL>>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 See the file COPYING for the full license text.
*/

#include <midori/midori.h>

enum { TAB_ICON, TAB_NAME, TAB_POINTER, TAB_CELL_COUNT };

static MidoriExtension *thisExtension;
static gboolean switchEvent;

static GdkPixbuf* tab_selector_get_snapshot(MidoriView* view,
                                            gint       maxwidth,
                                            gint       maxheight)
{
    GtkWidget* web_view;
    guint width, height;
    gfloat factor;

    g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);

    web_view = midori_view_get_web_view (view);

    if(maxwidth < 0) {
        maxwidth *= -1;
    }
    if(maxheight < 0) {
        maxheight *= -1;
    }

    factor = MIN((gfloat) maxwidth / web_view->allocation.width, (gfloat) maxheight / web_view->allocation.height);
    width = (int)(factor * web_view->allocation.width);
    height = (int)(factor * web_view->allocation.height);

    return midori_view_get_snapshot(view, width, height);
}

static void tab_selector_list_foreach (GtkWidget    *view,
                                       GtkListStore *store)
{
    GtkTreeIter it;
    GdkPixbuf* icon = midori_view_get_icon (MIDORI_VIEW (view));
    const gchar *title = midori_view_get_display_title (MIDORI_VIEW (view));
    gtk_list_store_append (store, &it);
    gtk_list_store_set (store, &it, TAB_ICON, icon, -1);
    gtk_list_store_set (store, &it, TAB_NAME, title, -1);
    gtk_list_store_set (store, &it, TAB_POINTER, view, -1);
}

static GtkWidget* tab_selector_init_window (MidoriBrowser   *browser)
{
    GList *list;
    gint col_offset;
    GtkCellRenderer *renderer;
    GtkTreeViewColumn *column;
    GtkWidget *window, *treeview, *sw, *hbox;
    GtkListStore *store;
    GtkWidget *page;
    GtkWidget *image;
    GdkPixbuf *snapshot;

    window = gtk_window_new(GTK_WINDOW_POPUP);
    gtk_window_set_default_size(GTK_WINDOW(window), 320, 20);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);


    hbox = gtk_hbox_new(FALSE, 1);
    gtk_container_add(GTK_CONTAINER(window), hbox);
    gtk_container_set_border_width(GTK_CONTAINER(hbox), 1);

    sw = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
            GTK_SHADOW_ETCHED_IN);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
            GTK_POLICY_NEVER,
            GTK_POLICY_AUTOMATIC);

    gtk_box_pack_start (GTK_BOX (hbox), sw, TRUE, TRUE, 0);

    store = gtk_list_store_new(TAB_CELL_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
    treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
    g_object_set_data(G_OBJECT(window), "tab_selector_treeview", treeview);

    list = g_object_get_data(G_OBJECT(browser), "tab_selector_list");
    g_list_foreach(list, (GFunc) tab_selector_list_foreach, store);

    g_object_unref(store);
    g_object_set(treeview, "headers-visible", FALSE, NULL);

    renderer = gtk_cell_renderer_pixbuf_new();

    gtk_tree_view_insert_column_with_attributes(
            GTK_TREE_VIEW(treeview), -1, "Icon", renderer, "pixbuf", TAB_ICON, NULL);

    renderer = gtk_cell_renderer_text_new();

    col_offset = gtk_tree_view_insert_column_with_attributes(
            GTK_TREE_VIEW(treeview), -1, "Title", renderer, "text", TAB_NAME, NULL);
    column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), col_offset - 1);
    gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column),
            GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column),
            midori_extension_get_integer(thisExtension, "TitleColumnWidth"));

    gtk_container_add (GTK_CONTAINER (sw), treeview);

    page = katze_object_get_object(browser, "tab");
    snapshot = tab_selector_get_snapshot(MIDORI_VIEW(page),
            midori_extension_get_integer(thisExtension, "TabPreviewWidth"),
            midori_extension_get_integer(thisExtension, "TabPreviewHeight"));
    image = gtk_image_new_from_pixbuf (snapshot);
    gtk_box_pack_start (GTK_BOX (hbox), image, TRUE, TRUE, 0);
    g_object_set_data(G_OBJECT(window), "tab_selector_image", image);

    gtk_widget_show_all(window);

    return window;
}

static void tab_selector_window_walk (  GtkWidget       *window,
                                        GdkEventKey     *event,
                                        MidoriBrowser   *browser)
{
    gint *pindex, iindex, items;
    GtkWidget *view;
    GtkTreeIter iter;
    GtkTreePath *path;
    GtkTreeView *treeview;
    GtkTreeModel *model;
    GtkTreeViewColumn *column;

    treeview = g_object_get_data (G_OBJECT (window), "tab_selector_treeview");
    model = gtk_tree_view_get_model (treeview);
    items = gtk_tree_model_iter_n_children (model, NULL) -1;
    gtk_tree_view_get_cursor (treeview, &path, &column);
    pindex = gtk_tree_path_get_indices (path);
    if(!pindex)
        return;
    iindex = *pindex;
    gtk_tree_path_free(path);

    if (event->state & GDK_SHIFT_MASK)
        iindex = iindex == 0 ? items : iindex-1;
    else
        iindex = iindex == items ? 0 : iindex+1;

    path = gtk_tree_path_new_from_indices(iindex, -1);
    column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), 1);
    gtk_tree_view_set_cursor (GTK_TREE_VIEW (treeview), path, column, FALSE);

    gtk_tree_model_get_iter (model, &iter, path);
    gtk_tree_model_get (model, &iter, TAB_POINTER, &view, -1);

    if (midori_extension_get_boolean (thisExtension, "ShowTabInBackground")) {
        midori_browser_set_current_tab (browser, view);
    } else {
        GtkImage *image;
        GdkPixbuf *snapshot = tab_selector_get_snapshot(MIDORI_VIEW(view),
                midori_extension_get_integer(thisExtension, "TabPreviewWidth"),
                midori_extension_get_integer(thisExtension, "TabPreviewHeight"));
        image = g_object_get_data(G_OBJECT(window), "tab_selector_image");
        gtk_image_set_from_pixbuf(image, snapshot);
    }
    gtk_tree_path_free(path);
}

static gboolean tab_selector_handle_events (GtkWidget       *widget,
                                            GdkEventKey     *event,
                                            MidoriBrowser   *browser)
{
    /* tab -> 23
       ctrl -> 37 */
    gint treeitems;
    static GtkWidget *window;
    if(event->type == GDK_KEY_PRESS && event->hardware_keycode == 23 && event->state & GDK_CONTROL_MASK) {
        treeitems = gtk_notebook_get_n_pages (GTK_NOTEBOOK (
                katze_object_get_object(browser, "notebook")));
        if(treeitems > 1) {
            if(!GTK_IS_WINDOW(window)) {
                switchEvent = FALSE;
                window = tab_selector_init_window(browser);
            }
            tab_selector_window_walk(window, event, browser);
        }
        return TRUE;
    } else if(event->type == GDK_KEY_RELEASE && event->hardware_keycode == 37 && GTK_IS_WINDOW(window)) {
        switchEvent = TRUE;
        if(midori_extension_get_boolean(thisExtension, "ShowTabInBackground")) {
            GtkWidget *page;
            page = katze_object_get_object(browser, "tab");

            GList *list = g_object_get_data(G_OBJECT(browser), "tab_selector_list");
            list = g_list_remove(list, page);
            list = g_list_prepend(list, page);
            g_object_set_data(G_OBJECT(browser), "tab_selector_list", list);
        } else {
            GtkTreePath *path;
            GtkTreeViewColumn *column;
            GtkTreeIter iter;
            GtkWidget *view, *treeview;
            GtkTreeModel *model;

            treeview = g_object_get_data(G_OBJECT(window), "tab_selector_treeview");
            model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));

            gtk_tree_view_get_cursor (
                    GTK_TREE_VIEW(treeview), &path, &column);
            gtk_tree_model_get_iter (
                    model, &iter, path);
            gtk_tree_model_get (
                    model, &iter, TAB_POINTER, &view, -1);
            midori_browser_set_current_tab (browser, view);
            gtk_tree_path_free (path);
        }
        gtk_widget_destroy(window);
        window = NULL;
        return TRUE;
    }
    return FALSE;
}

static void tab_selector_switch_page (GtkNotebook     *notebook,
                                      GtkNotebookPage *page_,
                                      guint            page_num,
                                      MidoriBrowser   *browser)
{
    if(switchEvent) {
        /* Don't know why *page_ points to the wrong address */
        GtkWidget *page;
        page = katze_object_get_object(browser, "tab");

        GList *list = g_object_get_data(G_OBJECT(browser), "tab_selector_list");
        list = g_list_remove(list, page);
        list = g_list_prepend(list, page);
        g_object_set_data(G_OBJECT(browser), "tab_selector_list", list);
    }
}

static void
tab_selector_browser_add_tab_cb (MidoriBrowser      *browser,
                                 GtkWidget          *view,
                                 MidoriExtension    *extension)
{
    g_signal_connect (view, "key_press_event",
            G_CALLBACK (tab_selector_handle_events), browser);
    g_signal_connect (view, "key_release_event",
            G_CALLBACK (tab_selector_handle_events), browser);

    GList *list = g_object_get_data(G_OBJECT(browser), "tab_selector_list");
    list = g_list_append(list, view);
    g_object_set_data(G_OBJECT(browser), "tab_selector_list", list);
}

static void
tab_selector_browser_remove_tab_cb (MidoriBrowser      *browser,
                                    GtkWidget          *view,
                                    MidoriExtension    *extension)
{
    GList *list = g_object_get_data(G_OBJECT(browser), "tab_selector_list");
    list = g_list_remove(list, view);
    g_object_set_data(G_OBJECT(browser), "tab_selector_list", list);
}

static void
tab_selector_disconnect_tab_cb (GtkWidget     *view,
                                MidoriBrowser *browser)
{
    g_signal_handlers_disconnect_by_func (
        view, tab_selector_handle_events, browser);
}

static void
tab_selector_app_add_browser_cb (MidoriApp       *app,<commit_msg>Connect tab switcher to child web view key events<commit_after>/*
 Copyright (C) 2009 <NAME> <<EMAIL>>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 See the file COPYING for the full license text.
*/

#include <midori/midori.h>

enum { TAB_ICON, TAB_NAME, TAB_POINTER, TAB_CELL_COUNT };

static MidoriExtension *thisExtension;
static gboolean switchEvent;

static GdkPixbuf* tab_selector_get_snapshot(MidoriView* view,
                                            gint       maxwidth,
                                            gint       maxheight)
{
    GtkWidget* web_view;
    guint width, height;
    gfloat factor;

    g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);

    web_view = midori_view_get_web_view (view);

    if(maxwidth < 0) {
        maxwidth *= -1;
    }
    if(maxheight < 0) {
        maxheight *= -1;
    }

    factor = MIN((gfloat) maxwidth / web_view->allocation.width, (gfloat) maxheight / web_view->allocation.height);
    width = (int)(factor * web_view->allocation.width);
    height = (int)(factor * web_view->allocation.height);

    return midori_view_get_snapshot(view, width, height);
}

static void tab_selector_list_foreach (GtkWidget    *view,
                                       GtkListStore *store)
{
    GtkTreeIter it;
    GdkPixbuf* icon = midori_view_get_icon (MIDORI_VIEW (view));
    const gchar *title = midori_view_get_display_title (MIDORI_VIEW (view));
    gtk_list_store_append (store, &it);
    gtk_list_store_set (store, &it, TAB_ICON, icon, -1);
    gtk_list_store_set (store, &it, TAB_NAME, title, -1);
    gtk_list_store_set (store, &it, TAB_POINTER, view, -1);
}

static GtkWidget* tab_selector_init_window (MidoriBrowser   *browser)
{
    GList *list;
    gint col_offset;
    GtkCellRenderer *renderer;
    GtkTreeViewColumn *column;
    GtkWidget *window, *treeview, *sw, *hbox;
    GtkListStore *store;
    GtkWidget *page;
    GtkWidget *image;
    GdkPixbuf *snapshot;

    window = gtk_window_new(GTK_WINDOW_POPUP);
    gtk_window_set_default_size(GTK_WINDOW(window), 320, 20);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);


    hbox = gtk_hbox_new(FALSE, 1);
    gtk_container_add(GTK_CONTAINER(window), hbox);
    gtk_container_set_border_width(GTK_CONTAINER(hbox), 1);

    sw = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
            GTK_SHADOW_ETCHED_IN);
    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
            GTK_POLICY_NEVER,
            GTK_POLICY_AUTOMATIC);

    gtk_box_pack_start (GTK_BOX (hbox), sw, TRUE, TRUE, 0);

    store = gtk_list_store_new(TAB_CELL_COUNT, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_POINTER);
    treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
    g_object_set_data(G_OBJECT(window), "tab_selector_treeview", treeview);

    list = g_object_get_data(G_OBJECT(browser), "tab_selector_list");
    g_list_foreach(list, (GFunc) tab_selector_list_foreach, store);

    g_object_unref(store);
    g_object_set(treeview, "headers-visible", FALSE, NULL);

    renderer = gtk_cell_renderer_pixbuf_new();

    gtk_tree_view_insert_column_with_attributes(
            GTK_TREE_VIEW(treeview), -1, "Icon", renderer, "pixbuf", TAB_ICON, NULL);

    renderer = gtk_cell_renderer_text_new();

    col_offset = gtk_tree_view_insert_column_with_attributes(
            GTK_TREE_VIEW(treeview), -1, "Title", renderer, "text", TAB_NAME, NULL);
    column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), col_offset - 1);
    gtk_tree_view_column_set_sizing (GTK_TREE_VIEW_COLUMN (column),
            GTK_TREE_VIEW_COLUMN_FIXED);
    gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column),
            midori_extension_get_integer(thisExtension, "TitleColumnWidth"));

    gtk_container_add (GTK_CONTAINER (sw), treeview);

    page = katze_object_get_object(browser, "tab");
    snapshot = tab_selector_get_snapshot(MIDORI_VIEW(page),
            midori_extension_get_integer(thisExtension, "TabPreviewWidth"),
            midori_extension_get_integer(thisExtension, "TabPreviewHeight"));
    image = gtk_image_new_from_pixbuf (snapshot);
    gtk_box_pack_start (GTK_BOX (hbox), image, TRUE, TRUE, 0);
    g_object_set_data(G_OBJECT(window), "tab_selector_image", image);

    gtk_widget_show_all(window);

    return window;
}

static void tab_selector_window_walk (  GtkWidget       *window,
                                        GdkEventKey     *event,
                                        MidoriBrowser   *browser)
{
    gint *pindex, iindex, items;
    GtkWidget *view;
    GtkTreeIter iter;
    GtkTreePath *path;
    GtkTreeView *treeview;
    GtkTreeModel *model;
    GtkTreeViewColumn *column;

    treeview = g_object_get_data (G_OBJECT (window), "tab_selector_treeview");
    model = gtk_tree_view_get_model (treeview);
    items = gtk_tree_model_iter_n_children (model, NULL) -1;
    gtk_tree_view_get_cursor (treeview, &path, &column);
    pindex = gtk_tree_path_get_indices (path);
    if(!pindex)
        return;
    iindex = *pindex;
    gtk_tree_path_free(path);

    if (event->state & GDK_SHIFT_MASK)
        iindex = iindex == 0 ? items : iindex-1;
    else
        iindex = iindex == items ? 0 : iindex+1;

    path = gtk_tree_path_new_from_indices(iindex, -1);
    column = gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), 1);
    gtk_tree_view_set_cursor (GTK_TREE_VIEW (treeview), path, column, FALSE);

    gtk_tree_model_get_iter (model, &iter, path);
    gtk_tree_model_get (model, &iter, TAB_POINTER, &view, -1);

    if (midori_extension_get_boolean (thisExtension, "ShowTabInBackground")) {
        midori_browser_set_current_tab (browser, view);
    } else {
        GtkImage *image;
        GdkPixbuf *snapshot = tab_selector_get_snapshot(MIDORI_VIEW(view),
                midori_extension_get_integer(thisExtension, "TabPreviewWidth"),
                midori_extension_get_integer(thisExtension, "TabPreviewHeight"));
        image = g_object_get_data(G_OBJECT(window), "tab_selector_image");
        gtk_image_set_from_pixbuf(image, snapshot);
    }
    gtk_tree_path_free(path);
}

static gboolean tab_selector_handle_events (GtkWidget       *widget,
                                            GdkEventKey     *event,
                                            MidoriBrowser   *browser)
{
    /* tab -> 23
       ctrl -> 37 */
    gint treeitems;
    static GtkWidget *window;
    if(event->type == GDK_KEY_PRESS && event->hardware_keycode == 23 && event->state & GDK_CONTROL_MASK) {
        treeitems = gtk_notebook_get_n_pages (GTK_NOTEBOOK (
                katze_object_get_object(browser, "notebook")));
        if(treeitems > 1) {
            if(!GTK_IS_WINDOW(window)) {
                switchEvent = FALSE;
                window = tab_selector_init_window(browser);
            }
            tab_selector_window_walk(window, event, browser);
        }
        return TRUE;
    } else if(event->type == GDK_KEY_RELEASE && event->hardware_keycode == 37 && GTK_IS_WINDOW(window)) {
        switchEvent = TRUE;
        if(midori_extension_get_boolean(thisExtension, "ShowTabInBackground")) {
            GtkWidget *page;
            page = katze_object_get_object(browser, "tab");

            GList *list = g_object_get_data(G_OBJECT(browser), "tab_selector_list");
            list = g_list_remove(list, page);
            list = g_list_prepend(list, page);
            g_object_set_data(G_OBJECT(browser), "tab_selector_list", list);
        } else {
            GtkTreePath *path;
            GtkTreeViewColumn *column;
            GtkTreeIter iter;
            GtkWidget *view, *treeview;
            GtkTreeModel *model;

            treeview = g_object_get_data(G_OBJECT(window), "tab_selector_treeview");
            model = gtk_tree_view_get_model(GTK_TREE_VIEW(treeview));

            gtk_tree_view_get_cursor (
                    GTK_TREE_VIEW(treeview), &path, &column);
            gtk_tree_model_get_iter (
                    model, &iter, path);
            gtk_tree_model_get (
                    model, &iter, TAB_POINTER, &view, -1);
            midori_browser_set_current_tab (browser, view);
            gtk_tree_path_free (path);
        }
        gtk_widget_destroy(window);
        window = NULL;
        return TRUE;
    }
    return FALSE;
}

static void tab_selector_switch_page (GtkNotebook     *notebook,
                                      GtkNotebookPage *page_,
                                      guint            page_num,
                                      MidoriBrowser   *browser)
{
    if(switchEvent) {
        /* Don't know why *page_ points to the wrong address */
        GtkWidget *page;
        page = katze_object_get_object(browser, "tab");

        GList *list = g_object_get_data(G_OBJECT(browser), "tab_selector_list");
        list = g_list_remove(list, page);
        list = g_list_prepend(list, page);
        g_object_set_data(G_OBJECT(browser), "tab_selector_list", list);
    }
}

static void
tab_selector_browser_add_tab_cb (MidoriBrowser      *browser,
                                 GtkWidget          *view,
                                 MidoriExtension    *extension)
{
    GtkWidget* web_view;
    GList* list;

    g_return_if_fail (MIDORI_IS_VIEW (view));

    web_view = midori_view_get_web_view (MIDORI_VIEW(view));

    g_signal_connect (web_view, "key_press_event",
            G_CALLBACK (tab_selector_handle_events), browser);
    g_signal_connect (web_view, "key_release_event",
            G_CALLBACK (tab_selector_handle_events), browser);

    list = g_object_get_data(G_OBJECT(browser), "tab_selector_list");
    list = g_list_append(list, view);
    g_object_set_data(G_OBJECT(browser), "tab_selector_list", list);
}

static void
tab_selector_browser_remove_tab_cb (MidoriBrowser      *browser,
                                    GtkWidget          *view,
                                    MidoriExtension    *extension)
{
    GList *list = g_object_get_data(G_OBJECT(browser), "tab_selector_list");
    list = g_list_remove(list, view);
    g_object_set_data(G_OBJECT(browser), "tab_selector_list", list);
}

static void
tab_selector_disconnect_tab_cb (GtkWidget     *view,
                                MidoriBrowser *browser)
{
    g_signal_handlers_disconnect_by_func (
        view, tab_selector_handle_events, browser);
}

static void
tab_selector_app_add_browser_cb (MidoriApp       *app,
{'fraction_non_alphanumeric': 0.09296612971798385, 'fraction_numerical': 0.0040625442864566114, 'mean_word_length': 2.860320933625091, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 36, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7216172', 'n_tokens_mistral': 7108, 'n_tokens_neox': 6890, 'n_words': 1282}