From c7c89daff3f04d2ccc78905c128e7dfa938543d4 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Fri, 6 Sep 2019 20:42:23 +0100 Subject: [PATCH] allow toolbar customisation to open a tab --- frontends/gtk/scaffolding.c | 17 +++---- frontends/gtk/scaffolding.h | 3 +- frontends/gtk/tabs.c | 98 +++++++++++++++++++++++++------------ frontends/gtk/tabs.h | 17 +++++-- frontends/gtk/toolbar.c | 47 +++++++++++++++--- frontends/gtk/window.c | 41 +++++++++------- frontends/gtk/window.h | 14 ------ 7 files changed, 151 insertions(+), 86 deletions(-) diff --git a/frontends/gtk/scaffolding.c b/frontends/gtk/scaffolding.c index a2c3a7dee..8712dcd10 100644 --- a/frontends/gtk/scaffolding.c +++ b/frontends/gtk/scaffolding.c @@ -1202,23 +1202,19 @@ struct nsgtk_scaffolding *nsgtk_current_scaffolding(void) /* exported function documented in gtk/scaffolding.h */ -void nsgtk_window_set_title(struct gui_window *gw, const char *title) +void nsgtk_scaffolding_set_title(struct gui_window *gw, const char *title) { struct nsgtk_scaffolding *gs = nsgtk_get_scaffold(gw); int title_len; char *newtitle; - if ((title == NULL) || (title[0] == '\0')) { - if (gs->top_level != gw) { - gtk_window_set_title(gs->window, "NetSurf"); - } + /* only set window title if top level window */ + if (gs->top_level != gw) { return; } - nsgtk_tab_set_title(gw, title); - - if (gs->top_level != gw) { - /* not top level window so do not set window title */ + if (title == NULL || title[0] == '\0') { + gtk_window_set_title(gs->window, "NetSurf"); return; } @@ -1233,6 +1229,7 @@ void nsgtk_window_set_title(struct gui_window *gw, const char *title) gtk_window_set_title(gs->window, newtitle); free(newtitle); + } @@ -1366,7 +1363,7 @@ void nsgtk_scaffolding_set_top_level(struct gui_window *gw) browser_window_search_clear(bw); /* Ensure the window's title bar is updated */ - nsgtk_window_set_title(gw, browser_window_get_title(bw)); + nsgtk_scaffolding_set_title(gw, browser_window_get_title(bw)); } diff --git a/frontends/gtk/scaffolding.h b/frontends/gtk/scaffolding.h index 89212a351..42ae6b6be 100644 --- a/frontends/gtk/scaffolding.h +++ b/frontends/gtk/scaffolding.h @@ -145,14 +145,13 @@ void nsgtk_scaffolding_set_sensitivity(struct nsgtk_scaffolding *g); */ void nsgtk_scaffolding_context_menu(struct nsgtk_scaffolding *g, gdouble x, gdouble y); -/* core acessors */ /** * set the title in the window * * \param gw The gui window to set title on * \param title The title to set which may be NULL */ -void nsgtk_window_set_title(struct gui_window *gw, const char *title); +void nsgtk_scaffolding_set_title(struct gui_window *gw, const char *title); #endif /* NETSURF_GTK_SCAFFOLDING_H */ diff --git a/frontends/gtk/tabs.c b/frontends/gtk/tabs.c index bb4135f0b..18dec6174 100644 --- a/frontends/gtk/tabs.c +++ b/frontends/gtk/tabs.c @@ -73,9 +73,13 @@ nsgtk_tab_update_size(GtkWidget *hbox, /** * 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(struct gui_window *window, +nsgtk_tab_label_setup(GtkWidget *page, const char *title, GdkPixbuf *icon_pixbuf) { @@ -108,10 +112,13 @@ nsgtk_tab_label_setup(struct gui_window *window, gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE); gtk_widget_set_tooltip_text(button, "Close this tab."); - 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); + g_signal_connect_swapped(button, + "clicked", + G_CALLBACK(gtk_widget_destroy), page); + 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); @@ -355,25 +362,19 @@ nserror nsgtk_notebook_create(GtkBuilder *builder, GtkNotebook **notebook_out) } /* 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, 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, title, icon_pixbuf); - - nsgtk_window_set_tab(gw, tabBox); + tabBox = nsgtk_tab_label_setup(tab_contents, title, icon_pixbuf); remember = gtk_notebook_get_current_page(notebook); @@ -391,48 +392,85 @@ void nsgtk_tab_add(struct gui_window *gw, gtk_notebook_set_current_page(notebook, newpage); } + return NSERROR_OK; +} + + +/* exported interface documented in gtk/tabs.h */ +void nsgtk_tab_add(struct gui_window *gw, + GtkWidget *tab_contents, + bool background, + const char *title, + GdkPixbuf *icon_pixbuf) +{ + GtkNotebook *notebook; + + 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); + gtk_widget_grab_focus(GTK_WIDGET(nsgtk_scaffolding_urlbar( nsgtk_get_scaffold(gw)))); } /* exported interface documented in gtk/tabs.h */ -nserror nsgtk_tab_set_icon(struct gui_window *gw, GdkPixbuf *pixbuf) +nserror nsgtk_tab_set_icon(GtkWidget *page, GdkPixbuf *pixbuf) { - GtkWidget *favicon; - GtkWidget *tab; + 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 = nsgtk_window_get_tab(gw); - if (tab == NULL) { + tab_label = gtk_notebook_get_tab_label(notebook, page); + if (tab_label == NULL) { return NSERROR_INVALID; } - favicon = g_object_get_data(G_OBJECT(tab), "favicon"); + favicon = GTK_IMAGE(g_object_get_data(G_OBJECT(tab_label), "favicon")); - gtk_image_set_from_pixbuf(GTK_IMAGE(favicon), pixbuf); + gtk_image_set_from_pixbuf(favicon, pixbuf); return NSERROR_OK; } /* exported interface documented in gtk/tabs.h */ -void nsgtk_tab_set_title(struct gui_window *g, const char *title) +nserror nsgtk_tab_set_title(GtkWidget *page, const char *title) { - GtkWidget *label; - GtkWidget *tab; + GtkLabel *label; + GtkWidget *tab_label; + GtkNotebook *notebook; - tab = nsgtk_window_get_tab(g); - if (tab == NULL) { - return; + if (title == 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); + 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 */ diff --git a/frontends/gtk/tabs.h b/frontends/gtk/tabs.h index acec396ed..63edae3cc 100644 --- a/frontends/gtk/tabs.h +++ b/frontends/gtk/tabs.h @@ -34,10 +34,16 @@ struct gui_window; nserror nsgtk_notebook_create(GtkBuilder *builder, GtkNotebook **notebook_out); /** - * Add new tab to notebook. + * Add new gui window page to notebook. */ void nsgtk_tab_add(struct gui_window *window, GtkWidget *tab_contents, bool background, const char *title, GdkPixbuf *icon_pixbuf); +/** + * Add new page to a notebook + */ +nserror nsgtk_tab_add_page(GtkNotebook *notebook, GtkWidget *tab_contents, bool background, const char *title, GdkPixbuf *icon_pixbuf); + + /** * set the tab title * @@ -45,21 +51,22 @@ void nsgtk_tab_add(struct gui_window *window, GtkWidget *tab_contents, bool back * * \note currently only called from nsgtk_window_set_title() * - * \param g the gui window to set tab title for. + * \param page The page widget that was added to the notebook * \param title The title text which may not be NULL. + * \return NSERROR_OK on sucess else appropriate code. */ -void nsgtk_tab_set_title(struct gui_window *g, const char *title); +nserror nsgtk_tab_set_title(GtkWidget *page, const char *title); /** * set the tab icon * * The tab icon will be set to the \a pixbuf parameter * - * \param gw The gui window to set teh tab icon for. + * \param page The page widget that was added to the notebook * \param pixbuf The pixbuf to set the icon to. * \return NSERROR_OK on sucess else appropriate code. */ -nserror nsgtk_tab_set_icon(struct gui_window *gw, GdkPixbuf *pixbuf); +nserror nsgtk_tab_set_icon(GtkWidget *page, GdkPixbuf *pixbuf); void nsgtk_tab_options_changed(GtkNotebook *notebook); nserror nsgtk_tab_close_current(GtkNotebook *notebook); diff --git a/frontends/gtk/toolbar.c b/frontends/gtk/toolbar.c index dadddc27d..339263b72 100644 --- a/frontends/gtk/toolbar.c +++ b/frontends/gtk/toolbar.c @@ -148,9 +148,10 @@ struct nsgtk_toolbar_customization { struct nsgtk_toolbar toolbar; /** - * toolbar gtk builder + * The top level container (tabBox) */ - GtkBuilder *builder; + GtkWidget *container; + }; /** @@ -1530,16 +1531,34 @@ static gboolean cutomize_button_clicked_cb(GtkWidget *widget, gpointer data) struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data; struct nsgtk_toolbar_customization *tbc; nserror res; + GtkBuilder *builder; + GtkNotebook *notebook; + struct gui_window *gw; + + /* create builder */ + res = nsgtk_builder_new_from_resname("toolbar", &builder); + if (res != NSERROR_OK) { + NSLOG(netsurf, INFO, "Toolbar UI builder init failed"); + return TRUE; + } + gtk_builder_connect_signals(builder, NULL); + /* create nsgtk_toolbar_customization which has nsgtk_toolbar * at the front so we can reuse functions that take * nsgtk_toolbar */ tbc = calloc(1, sizeof(struct nsgtk_toolbar_customization)); + if (tbc == NULL) { + g_object_unref(builder); + return TRUE; + } - /* create builder*/ - res = nsgtk_builder_new_from_resname("toolbar", &tbc->builder); - if (res != NSERROR_OK) { - NSLOG(netsurf, INFO, "Toolbar UI builder init failed"); + /* get container box widget which forms a page of the tabs */ + tbc->container = GTK_WIDGET(gtk_builder_get_object(builder, "tabBox")); + if (tbc->container == NULL) { + free(tbc); + g_object_unref(builder); + NSLOG(netsurf, ERROR, "dammit"); return TRUE; } @@ -1550,6 +1569,22 @@ static gboolean cutomize_button_clicked_cb(GtkWidget *widget, gpointer data) /* save and update on apply button then discard */ /* discard button causes destruction */ /* close and cleanup on destroy signal */ + + + gw = tb->get_ctx; /** \todo stop assuming the context is a gui window */ + notebook = nsgtk_scaffolding_notebook(nsgtk_get_scaffold(gw)); + + nsgtk_tab_add_page(notebook, + tbc->container, + false, + messages_get("gtkCustomizeToolbarTitle"), + favicon_pixbuf); + + /* safe to drop the reference to the builder as the container is + * referenced by the notebook now. + */ + g_object_unref(builder); + return TRUE; } diff --git a/frontends/gtk/window.c b/frontends/gtk/window.c index f0eb7431f..76e9863ee 100644 --- a/frontends/gtk/window.c +++ b/frontends/gtk/window.c @@ -31,11 +31,13 @@ #include #include -#include "netsurf/inttypes.h" +#include "utils/utils.h" #include "utils/log.h" #include "utils/utf8.h" #include "utils/nsoption.h" #include "utils/messages.h" +#include "utils/nsurl.h" +#include "netsurf/inttypes.h" #include "netsurf/content.h" #include "netsurf/browser_window.h" #include "netsurf/mouse.h" @@ -45,7 +47,6 @@ #include "netsurf/keypress.h" #include "desktop/searchweb.h" #include "desktop/textinput.h" -#include "utils/nsurl.h" #include "gtk/selection.h" #include "gtk/warn.h" @@ -940,7 +941,7 @@ gui_window_set_icon(struct gui_window *gw, struct hlcache_handle *icon) gw->icon = favicon_pixbuf; } - nsgtk_tab_set_icon(gw, gw->icon); + nsgtk_tab_set_icon(gw->container, gw->icon); } @@ -1377,6 +1378,22 @@ static nserror gui_window_set_url(struct gui_window *gw, nsurl *url) } +/** + * GTK window UI callback when core changes the current title + * + * \param gw The gui window on which the url has been set. + * \param url The new url. + */ +static void gui_window_set_title(struct gui_window *gw, const char *title) +{ + + if ((title != NULL) && (title[0] != '\0')) { + nsgtk_tab_set_title(gw->container, title); + } + nsgtk_scaffolding_set_title(gw, title); +} + + /** * GTK UI callback when search provider details are updated. * @@ -1425,6 +1442,7 @@ static struct gui_window_table window_table = { .event = gui_window_event, .set_icon = gui_window_set_icon, + .set_title = gui_window_set_title, .set_status = gui_window_set_status, .set_pointer = gui_window_set_pointer, .place_caret = gui_window_place_caret, @@ -1432,8 +1450,7 @@ static struct gui_window_table window_table = { .file_gadget_open = gui_window_file_gadget_open, .set_url = gui_window_set_url, - /* from scaffold */ - .set_title = nsgtk_window_set_title, + }; struct gui_window_table *nsgtk_window_table = &window_table; @@ -1467,20 +1484,6 @@ GtkLayout *nsgtk_window_get_layout(struct gui_window *g) } -/* exported interface documented in window.h */ -GtkWidget *nsgtk_window_get_tab(struct gui_window *g) -{ - return g->tab; -} - - -/* exported interface documented in window.h */ -void nsgtk_window_set_tab(struct gui_window *g, GtkWidget *w) -{ - g->tab = w; -} - - /* exported interface documented in window.h */ nserror nsgtk_window_item_activate(struct gui_window *gw, nsgtk_toolbar_button itemid) diff --git a/frontends/gtk/window.h b/frontends/gtk/window.h index ae3dae16f..1b3c8aa24 100644 --- a/frontends/gtk/window.h +++ b/frontends/gtk/window.h @@ -87,20 +87,6 @@ unsigned long nsgtk_window_get_signalhandler(struct gui_window *gw, int i); */ GtkLayout *nsgtk_window_get_layout(struct gui_window *gw); -/** - * get tab widget from gui window handle - * - * \param gw gui window handle - */ -GtkWidget *nsgtk_window_get_tab(struct gui_window *gw); - -/** - * set tab widget associated with gui window handle - * - * \param gw gui window handle - * \param w gtk widget to associate - */ -void nsgtk_window_set_tab(struct gui_window *gw, GtkWidget *w); /** * activate the handler for a item in a toolbar of a gui window