diff options
Diffstat (limited to 'frontends/gtk/tabs.c')
-rw-r--r-- | frontends/gtk/tabs.c | 379 |
1 files changed, 277 insertions, 102 deletions
diff --git a/frontends/gtk/tabs.c b/frontends/gtk/tabs.c index dbe9d405b..4fa109b70 100644 --- a/frontends/gtk/tabs.c +++ b/frontends/gtk/tabs.c @@ -20,11 +20,12 @@ #include <string.h> #include "utils/nsoption.h" -#include "utils/messages.h" +#include "utils/log.h" #include "netsurf/browser_window.h" #include "desktop/search.h" #include "gtk/compat.h" +#include "gtk/toolbar_items.h" #include "gtk/scaffolding.h" #include "gtk/window.h" #include "gtk/search.h" @@ -32,9 +33,15 @@ #define TAB_WIDTH_N_CHARS 15 -/** callback to update sizes when style-set gtk signal */ -static void nsgtk_tab_update_size(GtkWidget *hbox, GtkStyle *previous_style, - GtkWidget *close_button) +static gint srcpagenum; + +/** + * callback to update sizes when style-set gtk signal + */ +static void +nsgtk_tab_update_size(GtkWidget *hbox, + GtkStyle *previous_style, + GtkWidget *close_button) { PangoFontMetrics *metrics; PangoContext *context; @@ -63,63 +70,114 @@ static void nsgtk_tab_update_size(GtkWidget *hbox, GtkStyle *previous_style, gtk_widget_set_size_request(close_button, w + 4, h + 4); } -/** Create a notebook tab label */ -static GtkWidget *nsgtk_tab_label_setup(struct gui_window *window) + +/** + * gtk event handler for button release on tab hbox + */ +static gboolean +nsgtk_tab_button_release(GtkWidget *widget, + GdkEventButton *event, + gpointer user_data) +{ + GtkWidget *page; + + if ((event->type == GDK_BUTTON_RELEASE) && (event->button == 2)) { + page = (GtkWidget *)user_data; + gtk_widget_destroy(page); + return TRUE; + } + return FALSE; +} + + +/** + * Create a notebook tab label + * + * \param page The page content widget + * \param title The title of the page + * \param icon_pixbuf The icon of the page + */ +static GtkWidget * +nsgtk_tab_label_setup(GtkWidget *page, + const char *title, + GdkPixbuf *icon_pixbuf) { - GtkWidget *hbox, *label, *button, *close; + GtkWidget *ebox, *hbox, *favicon, *label, *button, *close; + + /* horizontal box */ + hbox = nsgtk_hbox_new(FALSE, 3); - hbox = nsgtk_hbox_new(FALSE, 2); + /* event box */ + ebox = gtk_event_box_new(); + gtk_widget_set_events(ebox, GDK_BUTTON_PRESS_MASK); + gtk_container_add(GTK_CONTAINER(ebox), hbox); - label = gtk_label_new(messages_get("NewTab")); + /* construct a favicon */ + favicon = gtk_image_new(); + if (icon_pixbuf != NULL) { + gtk_image_set_from_pixbuf(GTK_IMAGE(favicon), icon_pixbuf); + } + + /* construct a label */ + label = gtk_label_new(title); gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END); gtk_label_set_single_line_mode(GTK_LABEL(label), TRUE); nsgtk_widget_set_alignment(label, GTK_ALIGN_START, GTK_ALIGN_CENTER); nsgtk_widget_set_margins(label, 0, 0); gtk_widget_show(label); + /* construct a close button */ button = gtk_button_new(); close = nsgtk_image_new_from_stock(NSGTK_STOCK_CLOSE, - GTK_ICON_SIZE_MENU); + GTK_ICON_SIZE_LARGE_TOOLBAR); gtk_container_add(GTK_CONTAINER(button), close); - gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE); + nsgtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE); gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_widget_set_tooltip_text(button, "Close this tab."); -#ifdef FIXME - GtkRcStyle *rcstyle; - rcstyle = gtk_rc_style_new(); - rcstyle->xthickness = rcstyle->ythickness = 0; - gtk_widget_modify_style(button, rcstyle); - g_object_unref(rcstyle); -#endif - - g_signal_connect_swapped(button, "clicked", - G_CALLBACK(nsgtk_window_destroy_browser), window); - g_signal_connect(hbox, "style-set", - G_CALLBACK(nsgtk_tab_update_size), button); - + /* pack the widgets into the label box */ + gtk_box_pack_start(GTK_BOX(hbox), favicon, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); - g_object_set_data(G_OBJECT(hbox), "label", label); - g_object_set_data(G_OBJECT(hbox), "close-button", button); + /* make the icon and label widgets findable by name */ + g_object_set_data(G_OBJECT(ebox), "favicon", favicon); + g_object_set_data(G_OBJECT(ebox), "label", label); + /* attach signal handlers */ + g_signal_connect_swapped(button, + "clicked", + G_CALLBACK(gtk_widget_destroy), page); - gtk_widget_show_all(hbox); - return hbox; -} -#include "utils/log.h" + g_signal_connect(hbox, + "style-set", + G_CALLBACK(nsgtk_tab_update_size), + button); -/** callback when page is switched */ + g_signal_connect(ebox, + "button-release-event", + G_CALLBACK(nsgtk_tab_button_release), + page); -static gint srcpagenum; -/** The switch-page signal handler + gtk_widget_show_all(ebox); + + return ebox; +} + + +/** + * The before switch-page gtk signal handler * * This signal is handled both before and after delivery to work round * issue that setting the selected tab during the switch-page signal * fails + * + * \param notebook The notebook being changed + * \param page The notebook page being switched to + * \param selpagenum The currently selected page number + * \param user_data Unused */ static void nsgtk_tab_switch_page(GtkNotebook *notebook, @@ -130,6 +188,15 @@ nsgtk_tab_switch_page(GtkNotebook *notebook, srcpagenum = gtk_notebook_get_current_page(notebook); } + +/** + * The after switch-page gtk signal handler + * + * \param notebook The notebook being changed + * \param selpage The notebook page selected + * \param selpagenum The currently selected page number + * \param user_data Unused + */ static void nsgtk_tab_switch_page_after(GtkNotebook *notebook, GtkWidget *selpage, @@ -138,41 +205,62 @@ nsgtk_tab_switch_page_after(GtkNotebook *notebook, { GtkWidget *srcpage; GtkWidget *addpage; - struct gui_window *gw; - nserror error; + GtkMenuBar *menubar; + struct gui_window *gw = NULL; + nserror res = NSERROR_INVALID; addpage = g_object_get_data(G_OBJECT(notebook), "addtab"); - if (selpage == addpage) { - if ((srcpagenum != -1) && - (srcpagenum != (gint)selpagenum)) { - /* ensure the add tab is not actually selected */ - NSLOG(netsurf, INFO, "src %d sel %d", srcpagenum, - selpagenum); - srcpage = gtk_notebook_get_nth_page(notebook, srcpagenum); - gw = g_object_get_data(G_OBJECT(srcpage), "gui_window"); - if ((gw != NULL) && (nsgtk_get_scaffold(gw) != NULL)) { - error = nsgtk_scaffolding_new_tab(gw); - if (error != NSERROR_OK) { - NSLOG(netsurf, INFO, - "Failed to open new tab."); - } - } - } - } else { + /* check if trying to select the "add page" tab */ + if (selpage != addpage) { NSLOG(netsurf, INFO, "sel %d", selpagenum); - /* tab with page in it */ + menubar = nsgtk_scaffolding_menu_bar(nsgtk_scaffolding_from_notebook(notebook)); gw = g_object_get_data(G_OBJECT(selpage), "gui_window"); if (gw != NULL) { + /* tab with web page in it */ nsgtk_scaffolding_set_top_level(gw); + gtk_widget_show(GTK_WIDGET(addpage)); + gtk_widget_set_sensitive(GTK_WIDGET(menubar), true); + } else { + /* tab with non browser content (e.g. tb customize) */ + gtk_widget_hide(GTK_WIDGET(addpage)); + gtk_widget_set_sensitive(GTK_WIDGET(menubar), false); } + return; + } + + NSLOG(netsurf, INFO, "src %d sel %d", srcpagenum, selpagenum); + + /* ensure the add tab is not already selected */ + if ((srcpagenum == -1) || (srcpagenum == (gint)selpagenum)) { + return; + } + + srcpage = gtk_notebook_get_nth_page(notebook, srcpagenum); + + gw = g_object_get_data(G_OBJECT(srcpage), "gui_window"); + + if (gw != NULL) { + res = nsgtk_window_item_activate(gw, NEWTAB_BUTTON); + } + if (res != NSERROR_OK) { + NSLOG(netsurf, INFO, "Failed to open new tab."); } } -static void nsgtk_tab_page_reordered(GtkNotebook *notebook, - GtkWidget *child, - guint page_num, - gpointer user_data) + +/** + * The tab reordered gtk signal handler + * + * \param notebook The notebook being changed + * \param page_num The currently selected page number + * \param user_data Unused + */ +static void +nsgtk_tab_page_reordered(GtkNotebook *notebook, + GtkWidget *child, + guint page_num, + gpointer user_data) { gint pages; GtkWidget *addpage; @@ -187,6 +275,13 @@ static void nsgtk_tab_page_reordered(GtkNotebook *notebook, } } +/** + * The tab orientation signal handler + * + * \param notebook The notebook being changed + * \param page_num The currently selected page number + * \param user_data Unused + */ static void nsgtk_tab_orientation(GtkNotebook *notebook) { @@ -210,7 +305,9 @@ nsgtk_tab_orientation(GtkNotebook *notebook) } } -/** adds a "new tab" tab */ +/** + * adds a "new tab" tab + */ static GtkWidget * nsgtk_tab_add_newtab(GtkNotebook *notebook) { @@ -221,7 +318,9 @@ nsgtk_tab_add_newtab(GtkNotebook *notebook) tablabel = nsgtk_hbox_new(FALSE, 1); tabcontents = nsgtk_hbox_new(FALSE, 1); - add = nsgtk_image_new_from_stock(NSGTK_STOCK_ADD, GTK_ICON_SIZE_MENU); + add = gtk_image_new_from_icon_name(NSGTK_STOCK_ADD, + GTK_ICON_SIZE_LARGE_TOOLBAR); + gtk_widget_set_tooltip_text(add, "New Tab"); gtk_box_pack_start(GTK_BOX(tablabel), add, FALSE, FALSE, 0); @@ -238,18 +337,26 @@ nsgtk_tab_add_newtab(GtkNotebook *notebook) return tablabel; } -/** callback to alter tab visibility when pages are added or removed */ + +/** + * callback to alter tab visibility when pages are added or removed + */ static void nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child, guint page) { - gint pagec = gtk_notebook_get_n_pages(notebook); - GtkWidget *addpage = g_object_get_data(G_OBJECT(notebook), "addtab"); - - if (addpage != NULL) { - pagec--; /* skip the add tab */ - if ((gint)page == pagec) { - /* ensure the add new tab cannot be current */ - gtk_notebook_set_current_page(notebook, page - 1); + gint pagec; + GtkWidget *addpage; + + pagec = gtk_notebook_get_n_pages(notebook); + if (pagec > 1) { + addpage = g_object_get_data(G_OBJECT(notebook), "addtab"); + if (addpage != NULL) { + pagec--; /* skip the add tab */ + if ((gint)page == pagec) { + /* ensure the add new tab cannot be current */ + gtk_notebook_set_current_page(notebook, + page - 1); + } } } @@ -260,6 +367,7 @@ nsgtk_tab_visibility_update(GtkNotebook *notebook, GtkWidget *child, guint page) } } + /* exported interface documented in gtk/tabs.h */ void nsgtk_tab_options_changed(GtkNotebook *notebook) { @@ -269,48 +377,56 @@ void nsgtk_tab_options_changed(GtkNotebook *notebook) /* exported interface documented in gtk/tabs.h */ -void nsgtk_tab_init(struct nsgtk_scaffolding *gs) +nserror nsgtk_notebook_create(GtkBuilder *builder, GtkNotebook **notebook_out) { GtkNotebook *notebook; - notebook = nsgtk_scaffolding_notebook(gs); + notebook = GTK_NOTEBOOK(gtk_builder_get_object(builder, "notebook")); nsgtk_tab_add_newtab(notebook); - g_signal_connect(notebook, "switch-page", - G_CALLBACK(nsgtk_tab_switch_page), NULL); - g_signal_connect_after(notebook, "switch-page", - G_CALLBACK(nsgtk_tab_switch_page_after), NULL); + g_signal_connect(notebook, + "switch-page", + G_CALLBACK(nsgtk_tab_switch_page), + NULL); + g_signal_connect_after(notebook, + "switch-page", + G_CALLBACK(nsgtk_tab_switch_page_after), + NULL); + g_signal_connect(notebook, + "page-removed", + G_CALLBACK(nsgtk_tab_visibility_update), + NULL); + g_signal_connect(notebook, + "page-added", + G_CALLBACK(nsgtk_tab_visibility_update), + NULL); + g_signal_connect(notebook, + "page-reordered", + G_CALLBACK(nsgtk_tab_page_reordered), + NULL); - g_signal_connect(notebook, "page-removed", - G_CALLBACK(nsgtk_tab_visibility_update), NULL); - g_signal_connect(notebook, "page-added", - G_CALLBACK(nsgtk_tab_visibility_update), NULL); - g_signal_connect(notebook, "page-reordered", - G_CALLBACK(nsgtk_tab_page_reordered), NULL); + nsgtk_tab_options_changed(notebook); + *notebook_out = notebook; - nsgtk_tab_options_changed(notebook); + return NSERROR_OK; } /* exported interface documented in gtk/tabs.h */ -void nsgtk_tab_add(struct gui_window *gw, +nserror +nsgtk_tab_add_page(GtkNotebook *notebook, GtkWidget *tab_contents, - bool background) + bool background, + const char *title, + GdkPixbuf *icon_pixbuf) { - GtkNotebook *notebook; GtkWidget *tabBox; gint remember; gint pages; gint newpage; - g_object_set_data(G_OBJECT(tab_contents), "gui_window", gw); - - notebook = nsgtk_scaffolding_notebook(nsgtk_get_scaffold(gw)); - - tabBox = nsgtk_tab_label_setup(gw); - - nsgtk_window_set_tab(gw, tabBox); + tabBox = nsgtk_tab_label_setup(tab_contents, title, icon_pixbuf); remember = gtk_notebook_get_current_page(notebook); @@ -328,24 +444,83 @@ void nsgtk_tab_add(struct gui_window *gw, gtk_notebook_set_current_page(notebook, newpage); } - gtk_widget_grab_focus(GTK_WIDGET(nsgtk_scaffolding_urlbar( - nsgtk_get_scaffold(gw)))); + return NSERROR_OK; } + /* exported interface documented in gtk/tabs.h */ -void nsgtk_tab_set_title(struct gui_window *g, const char *title) +void nsgtk_tab_add(struct gui_window *gw, + GtkWidget *tab_contents, + bool background, + const char *title, + GdkPixbuf *icon_pixbuf) { - GtkWidget *label; - GtkWidget *tab; + GtkNotebook *notebook; - tab = nsgtk_window_get_tab(g); - if (tab == NULL) { - return; + g_object_set_data(G_OBJECT(tab_contents), "gui_window", gw); + + notebook = nsgtk_scaffolding_notebook(nsgtk_get_scaffold(gw)); + + nsgtk_tab_add_page(notebook, tab_contents, background, title, icon_pixbuf); + +} + + +/* exported interface documented in gtk/tabs.h */ +nserror nsgtk_tab_set_icon(GtkWidget *page, GdkPixbuf *pixbuf) +{ + GtkImage *favicon; + GtkWidget *tab_label; + GtkNotebook *notebook; + + if (pixbuf == NULL) { + return NSERROR_INVALID; + } + notebook = GTK_NOTEBOOK(gtk_widget_get_ancestor(page, GTK_TYPE_NOTEBOOK)); + if (notebook == NULL) { + return NSERROR_BAD_PARAMETER; + } + + tab_label = gtk_notebook_get_tab_label(notebook, page); + if (tab_label == NULL) { + return NSERROR_INVALID; } - label = g_object_get_data(G_OBJECT(tab), "label"); - gtk_label_set_text(GTK_LABEL(label), title); - gtk_widget_set_tooltip_text(tab, title); + favicon = GTK_IMAGE(g_object_get_data(G_OBJECT(tab_label), "favicon")); + + gtk_image_set_from_pixbuf(favicon, pixbuf); + + return NSERROR_OK; +} + + +/* exported interface documented in gtk/tabs.h */ +nserror nsgtk_tab_set_title(GtkWidget *page, const char *title) +{ + GtkLabel *label; + GtkWidget *tab_label; + GtkNotebook *notebook; + + if (title == NULL) { + return NSERROR_INVALID; + } + + notebook = GTK_NOTEBOOK(gtk_widget_get_ancestor(page, GTK_TYPE_NOTEBOOK)); + if (notebook == NULL) { + return NSERROR_BAD_PARAMETER; + } + + tab_label = gtk_notebook_get_tab_label(notebook, page); + if (tab_label == NULL) { + return NSERROR_INVALID; + } + + label = GTK_LABEL(g_object_get_data(G_OBJECT(tab_label), "label")); + + gtk_label_set_text(label, title); + gtk_widget_set_tooltip_text(tab_label, title); + + return NSERROR_OK; } /* exported interface documented in gtk/tabs.h */ |