NetSurf
scaffolding.c
Go to the documentation of this file.
1/*
2 * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
3 *
4 * This file is part of NetSurf, http://www.netsurf-browser.org/
5 *
6 * NetSurf is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 *
10 * NetSurf is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <gtk/gtk.h>
20#include <stdbool.h>
21#include <stdlib.h>
22#include <string.h>
23
24#include "utils/utils.h"
25#include "utils/log.h"
26#include "utils/messages.h"
27#include "utils/nsurl.h"
28#include "utils/nsoption.h"
31#include "desktop/hotlist.h"
32
33#include "gtk/compat.h"
34#include "gtk/toolbar_items.h"
35#include "gtk/menu.h"
36#include "gtk/local_history.h"
37#include "gtk/gui.h"
38#include "gtk/download.h"
39#include "gtk/window.h"
40#include "gtk/warn.h"
41#include "gtk/tabs.h"
42#include "gtk/resources.h"
43#include "gtk/scaffolding.h"
44
45
46/**
47 * menu entry context
48 */
49struct nsgtk_menu {
50 GtkWidget *main; /* main menu entry */
51 GtkWidget *burger; /* right click menu */
52 GtkWidget *popup; /* popup menu entry */
53 /**
54 * menu item handler
55 */
56 gboolean (*mhandler)(GtkMenuItem *widget, gpointer data);
57 const char *iconname; /* name of the icon to use */
58 bool sensitivity; /* menu item is sensitive */
59};
60
61/**
62 * Core scaffolding structure.
63 */
65 /** global linked list of scaffolding for gui interface adjustments */
67
68 /** currently active gui browsing context */
70
71 /** Builder object scaffold was created from */
72 GtkBuilder *builder;
73
74 /** scaffold container window */
75 GtkWindow *window;
76
77 /** tab widget holding displayed pages */
78 GtkNotebook *notebook;
79
80 /** handler id for tabs remove callback */
82
83 /** menu bar hierarchy */
85
86 /** burger menu hierarchy */
88
89 /** right click popup menu hierarchy */
91
92 /** link popup menu */
94
95 /** menu entries widgets for sensitivity adjustment */
97};
98
99/**
100 * current scaffold for model dialogue use
101 */
103
104/**
105 * global list for interface changes
106 */
107static struct nsgtk_scaffolding *scaf_list = NULL;
108
109/**
110 * holds the context data for what's under the pointer, when the
111 * contextual menu is opened.
112 */
114
115
116/**
117 * Helper to hide popup menu entries by grouping.
118 *
119 * \param menu The popup menu to modify.
120 * \param nav flag to indicate if navigation entries should be hidden.
121 * \param cnp flag to indicate if cut and paste entries should be hidden.
122 * \param custom flag to indicate if menu customisation is hidden.
123 */
124static void
125popup_menu_hide(struct nsgtk_popup_menu *menu, bool nav, bool cnp)
126{
127 if (nav) {
128 gtk_widget_hide(GTK_WIDGET(menu->back_menuitem));
129 gtk_widget_hide(GTK_WIDGET(menu->forward_menuitem));
130 gtk_widget_hide(GTK_WIDGET(menu->stop_menuitem));
131 gtk_widget_hide(GTK_WIDGET(menu->reload_menuitem));
132
133 gtk_widget_hide(menu->first_separator);
134 }
135
136 if (cnp) {
137 gtk_widget_hide(GTK_WIDGET(menu->cut_menuitem));
138 gtk_widget_hide(GTK_WIDGET(menu->copy_menuitem));
139 gtk_widget_hide(GTK_WIDGET(menu->paste_menuitem));
140
141 gtk_widget_hide(menu->second_separator);
142 }
143
144
145}
146
147
148/**
149 * Helper to show popup menu entries by grouping.
150 *
151 * \param menu The popup menu to modify.
152 * \param nav flag to indicate if navigation entries should be visible.
153 * \param cnp flag to indicate if cut and paste entries should be visible.
154 * \param custom flag to indicate if menu customisation is visible.
155 */
156static void
157popup_menu_show(struct nsgtk_popup_menu *menu, bool nav, bool cnp)
158{
159 if (nav) {
160 gtk_widget_show(GTK_WIDGET(menu->back_menuitem));
161 gtk_widget_show(GTK_WIDGET(menu->forward_menuitem));
162 gtk_widget_show(GTK_WIDGET(menu->stop_menuitem));
163 gtk_widget_show(GTK_WIDGET(menu->reload_menuitem));
164
165 gtk_widget_show(menu->first_separator);
166 }
167
168 if (cnp) {
169 gtk_widget_show(GTK_WIDGET(menu->cut_menuitem));
170 gtk_widget_show(GTK_WIDGET(menu->copy_menuitem));
171 gtk_widget_show(GTK_WIDGET(menu->paste_menuitem));
172
173 gtk_widget_show(menu->second_separator);
174 }
175
176}
177
178
179/**
180 * resource cleanup function for window destruction.
181 *
182 * gtk event called when window is being destroyed. Need to free any
183 * resources associated with this scaffold,
184 *
185 * \param widget the widget being destroyed
186 * \param data The context pointer passed when the connection was made.
187 */
188static void scaffolding_window_destroy(GtkWidget *widget, gpointer data)
189{
190 struct nsgtk_scaffolding *gs = data;
191
192 NSLOG(netsurf, INFO, "scaffold:%p", gs);
193
195
196 /* ensure scaffolding being destroyed is not current */
197 if (scaf_current == gs) {
198 scaf_current = NULL;
199 /* attempt to select nearest scaffold instead of just selecting the first */
200 if (gs->prev != NULL) {
201 scaf_current = gs->prev;
202 } else if (gs->next != NULL) {
203 scaf_current = gs->next;
204 }
205 }
206
207 /* remove scaffolding from list */
208 if (gs->prev != NULL) {
209 gs->prev->next = gs->next;
210 } else {
211 scaf_list = gs->next;
212 }
213 if (gs->next != NULL) {
214 gs->next->prev = gs->prev;
215 }
216
217 NSLOG(netsurf, INFO, "scaffold list head: %p", scaf_list);
218
219 /* ensure menu resources are freed */
224
225 g_signal_handler_disconnect(gs->notebook, gs->tabs_remove_handler_id);
226
227 free(gs);
228
229 if (scaf_list == NULL) {
230 /* no more open windows - stop the browser */
231 nsgtk_complete = true;
232 }
233}
234
235
236/**
237 * gtk event callback on window delete event.
238 *
239 * prevent window close if download is in progress
240 *
241 * \param widget The widget receiving the delete event
242 * \param event The event
243 * \param data The context pointer passed when the connection was made.
244 * \return TRUE to indicate message handled.
245 */
246static gboolean
248 GdkEvent *event,
249 gpointer data)
250{
251 struct nsgtk_scaffolding *g = data;
252
253 if (nsgtk_check_for_downloads(GTK_WINDOW(widget)) == false) {
254 gtk_widget_destroy(GTK_WIDGET(g->window));
255 }
256 return TRUE;
257}
258
259
260/**
261 * Update the scaffolding controls
262 *
263 * The button sensitivity, url bar and local history visibility are updated
264 *
265 * \param g The scaffolding context to update
266 */
268{
270
275
277
279}
280
281
282/**
283 * edit the sensitivity of focused widget
284 *
285 * \todo this needs to update toolbar sensitivity
286 *
287 * \param g The scaffolding context.
288 */
289static guint
291{
292 GtkWidget *widget = gtk_window_get_focus(g->window);
293
294 if (GTK_IS_EDITABLE(widget)) {
295 gboolean has_selection;
296 has_selection = gtk_editable_get_selection_bounds(
297 GTK_EDITABLE(widget), NULL, NULL);
298 g->menus[COPY_BUTTON].sensitivity = has_selection;
299 g->menus[CUT_BUTTON].sensitivity = has_selection;
300 g->menus[PASTE_BUTTON].sensitivity = true;
301 } else {
302 struct browser_window *bw =
304 browser_editor_flags edit_f =
306
308 edit_f & BW_EDITOR_CAN_COPY;
310 edit_f & BW_EDITOR_CAN_CUT;
312 edit_f & BW_EDITOR_CAN_PASTE;
313 }
314
316
317 return ((g->menus[COPY_BUTTON].sensitivity) |
320}
321
322
323/**
324 * make edit actions sensitive
325 *
326 * \todo toolbar sensitivity
327 *
328 * \param g The scaffolding context.
329 */
330static void
332{
333 g->menus[PASTE_BUTTON].sensitivity = true;
334 g->menus[COPY_BUTTON].sensitivity = true;
335 g->menus[CUT_BUTTON].sensitivity = true;
337
338 popup_menu_show(g->popup_menu, false, true);
339}
340
341/* signal handling functions for the toolbar, URL bar, and menu bar */
342
343/**
344 * gtk event for edit menu being show
345 *
346 * \param widget The menu widget
347 * \param g scaffolding handle
348 * \return TRUE to indicate event handled
349 */
350static gboolean
352 struct nsgtk_scaffolding *g)
353{
355
356 return TRUE;
357}
358
359/**
360 * gtk event handler for edit menu being hidden
361 *
362 * \param widget The menu widget
363 * \param g scaffolding handle
364 * \return TRUE to indicate event handled
365 */
366static gboolean
368 struct nsgtk_scaffolding *g)
369{
371
372 return TRUE;
373}
374
375
376/**
377 * gtk event handler for popup menu being hidden.
378 *
379 * \param widget The menu widget
380 * \param g scaffolding handle
381 * \return TRUE to indicate event handled
382 */
383static gboolean
385{
387 return TRUE;
388}
389
390
391/**
392 * Update the menus when the number of tabs changes.
393 *
394 * \todo toolbar sensitivity
395 * \todo next/previous tab ought to only be visible if there is such a tab
396 *
397 * \param notebook The notebook all the tabs are in
398 * \param page The newly added page container widget
399 * \param page_num The index of the newly added page
400 * \param g The scaffolding context containing the notebook
401 */
402static void
403nsgtk_window_tabs_add(GtkNotebook *notebook,
404 GtkWidget *page,
405 guint page_num,
406 struct nsgtk_scaffolding *g)
407{
408 gboolean visible = gtk_notebook_get_show_tabs(g->notebook);
409 g_object_set(g->menu_bar->view_submenu->tabs_menuitem,
410 "visible",
411 visible,
412 NULL);
413 g_object_set(g->burger_menu->view_submenu->tabs_menuitem,
414 "visible",
415 visible,
416 NULL);
417
418 g->menus[NEXTTAB_BUTTON].sensitivity = visible;
419 g->menus[PREVTAB_BUTTON].sensitivity = visible;
420 g->menus[CLOSETAB_BUTTON].sensitivity = visible;
421
423}
424
425
426/**
427 * Update the menus when the number of tabs changes.
428 *
429 * \todo toolbar sensitivity
430 *
431 * \param notebook The notebook all the tabs are in
432 * \param page The page container widget being removed
433 * \param page_num The index of the removed page
434 * \param gs The scaffolding context containing the notebook
435 */
436static void
437nsgtk_window_tabs_remove(GtkNotebook *notebook,
438 GtkWidget *page,
439 guint page_num,
440 struct nsgtk_scaffolding *gs)
441{
442 gboolean visible;
443
444 /* if the scaffold is being destroyed it is not useful to
445 * update the state, further many of the widgets may have
446 * already been destroyed.
447 */
448 if (gtk_widget_in_destruction(GTK_WIDGET(gs->window)) == TRUE) {
449 return;
450 }
451
452 /* if this is the last tab destroy the scaffold in addition */
453 if (gtk_notebook_get_n_pages(notebook) == 1) {
454 gtk_widget_destroy(GTK_WIDGET(gs->window));
455 return;
456 }
457
458 visible = gtk_notebook_get_show_tabs(gs->notebook);
459 g_object_set(gs->menu_bar->view_submenu->tabs_menuitem,
460 "visible", visible, NULL);
461 g_object_set(gs->burger_menu->view_submenu->tabs_menuitem,
462 "visible", visible, NULL);
463
464 gs->menus[NEXTTAB_BUTTON].sensitivity = visible;
465 gs->menus[PREVTAB_BUTTON].sensitivity = visible;
466 gs->menus[CLOSETAB_BUTTON].sensitivity = visible;
467
469}
470
471
472/* signal handlers for menu entries */
473
474/**
475 * handle menu activate signals by calling toolbar item activation
476 */
477#define TOOLBAR_ITEM_p(identifier, name) \
478 static gboolean \
479nsgtk_on_##name##_activate_menu(GtkMenuItem *widget, gpointer data) \
480{ \
481 struct nsgtk_scaffolding *gs = (struct nsgtk_scaffolding *)data;\
482 nsgtk_window_item_activate(gs->top_level, identifier); \
483 return TRUE; \
484}
485#define TOOLBAR_ITEM_y(identifier, name)
486#define TOOLBAR_ITEM_n(identifier, name)
487#define TOOLBAR_ITEM(identifier, name, sensitivity, clicked, activate, label, iconame) \
488 TOOLBAR_ITEM_ ## activate(identifier, name)
489#include "gtk/toolbar_items.h"
490#undef TOOLBAR_ITEM_y
491#undef TOOLBAR_ITEM_n
492#undef TOOLBAR_ITEM_p
493#undef TOOLBAR_ITEM
494
495
496static gboolean
497nsgtk_on_savelink_activate_menu(GtkMenuItem *widget, gpointer data)
498{
499 struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *) data;
500 struct gui_window *gui = g->top_level;
502 nserror err;
503
504 if (current_menu_features.link == NULL)
505 return FALSE;
506
509 NULL,
511 NULL,
512 NULL,
513 NULL);
514 if (err != NSERROR_OK) {
516 }
517
518 return TRUE;
519}
520
521
522/**
523 * Handler for opening new window from a link. attached to the popup menu.
524 */
525static gboolean
526nsgtk_on_link_openwin_activate_menu(GtkMenuItem *widget, gpointer data)
527{
528 struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *) data;
529 struct gui_window *gui = g->top_level;
531 nserror err;
532
533 if (current_menu_features.link == NULL)
534 return FALSE;
535
537 current_menu_features.link, NULL, bw, NULL);
538 if (err != NSERROR_OK) {
540 }
541
542 return TRUE;
543}
544
545
546/**
547 * Handler for opening new tab from a link. attached to the popup menu.
548 */
549static gboolean
550nsgtk_on_link_opentab_activate_menu(GtkMenuItem *widget, gpointer data)
551{
552 struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *) data;
553 struct gui_window *gui = g->top_level;
555 nserror err;
556
557 if (current_menu_features.link == NULL)
558 return FALSE;
559
563 current_menu_features.link, NULL, bw, NULL);
564 if (err != NSERROR_OK) {
566 }
567
568 return TRUE;
569}
570
571
572/**
573 * Handler for bookmarking a link. attached to the popup menu.
574 */
575static gboolean
576nsgtk_on_link_bookmark_activate_menu(GtkMenuItem *widget, gpointer data)
577{
578 if (current_menu_features.link == NULL)
579 return FALSE;
580
582
583 return TRUE;
584}
585
586
587/**
588 * Handler for copying a link. attached to the popup menu.
589 */
590static gboolean
591nsgtk_on_link_copy_activate_menu(GtkMenuItem *widget, gpointer data)
592{
593 GtkClipboard *clipboard;
594
595 if (current_menu_features.link == NULL)
596 return FALSE;
597
598 clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD);
599 gtk_clipboard_set_text(clipboard,
601
602 return TRUE;
603}
604
605
606static gboolean nsgtk_on_find_activate_menu(GtkMenuItem *widget, gpointer data)
607{
608 struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
609
611
612 return TRUE;
613}
614
615static nserror get_bar_show(bool *menu, bool *tool)
616{
617 const char *cur_bar_show;
618
619 *menu = false;
620 *tool = false;
621
622 cur_bar_show = nsoption_charp(bar_show);
623 if (cur_bar_show != NULL) {
624 if (strcmp(cur_bar_show, "menu/tool") == 0) {
625 *menu = true;
626 *tool = true;
627 } else if (strcmp(cur_bar_show, "menu") == 0) {
628 *menu = true;
629 } else if (strcmp(cur_bar_show, "tool") == 0) {
630 *tool = true;
631 }
632 }
633
634 return NSERROR_OK;
635}
636
637static nserror set_bar_show(const char *bar, bool show)
638{
639 bool menu;
640 bool tool;
641 const char *new_bar_show;
642
643 get_bar_show(&menu, &tool);
644
645 if (strcmp(bar, "menu") == 0) {
646 menu = show;
647 } else if (strcmp(bar, "tool") == 0) {
648 tool = show;
649 }
650
651 if ((menu == true) && (tool == true)) {
652 new_bar_show = "menu/tool";
653 } else if (menu == true) {
654 new_bar_show = "menu";
655 } else if (tool == true) {
656 new_bar_show = "tool";
657 } else {
658 new_bar_show = "none";
659 }
660 nsoption_set_charp(bar_show, strdup(new_bar_show));
661
662 return NSERROR_OK;
663}
664
665static gboolean
666nsgtk_on_menubar_activate_menu(GtkMenuItem *widget, gpointer data)
667{
668 struct nsgtk_scaffolding *gs = (struct nsgtk_scaffolding *)data;
669 GtkCheckMenuItem *bmcmi; /* burger menu check */
670 GtkCheckMenuItem *mbcmi; /* menu bar check */
671 GtkCheckMenuItem *tbcmi; /* popup menu check */
672
673 bmcmi = GTK_CHECK_MENU_ITEM(gs->burger_menu->view_submenu->toolbars_submenu->menubar_menuitem);
674 mbcmi = GTK_CHECK_MENU_ITEM(gs->menu_bar->view_submenu->toolbars_submenu->menubar_menuitem);
675 tbcmi = GTK_CHECK_MENU_ITEM(gs->popup_menu->toolbars_submenu->menubar_menuitem);
676
677 /* ensure menubar and burger menu checkboxes are both updated */
678 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
679 if (gtk_check_menu_item_get_active(bmcmi) == FALSE) {
680 gtk_check_menu_item_set_active(bmcmi, TRUE);
681 }
682
683 if (gtk_check_menu_item_get_active(mbcmi) == FALSE) {
684 gtk_check_menu_item_set_active(mbcmi, TRUE);
685 }
686
687 if (gtk_check_menu_item_get_active(tbcmi) == FALSE) {
688 gtk_check_menu_item_set_active(tbcmi, TRUE);
689 }
690
691 gtk_widget_show(GTK_WIDGET(gs->menu_bar->bar_menu));
692 set_bar_show("menu", true);
693 } else {
694 if (gtk_check_menu_item_get_active(bmcmi) == TRUE) {
695 gtk_check_menu_item_set_active(bmcmi, FALSE);
696 }
697
698 if (gtk_check_menu_item_get_active(mbcmi) == TRUE) {
699 gtk_check_menu_item_set_active(mbcmi, FALSE);
700 }
701
702 if (gtk_check_menu_item_get_active(tbcmi) == TRUE) {
703 gtk_check_menu_item_set_active(tbcmi, FALSE);
704 }
705
706 gtk_widget_hide(GTK_WIDGET(gs->menu_bar->bar_menu));
707 set_bar_show("menu", false);
708 }
709 return TRUE;
710}
711
712
713static gboolean
714nsgtk_on_toolbar_activate_menu(GtkMenuItem *widget, gpointer data)
715{
716 struct nsgtk_scaffolding *gs = (struct nsgtk_scaffolding *)data;
717 GtkCheckMenuItem *bmcmi; /* burger menu check */
718 GtkCheckMenuItem *mbcmi; /* menu bar check */
719 GtkCheckMenuItem *tbcmi; /* popup menu check */
720
721 bmcmi = GTK_CHECK_MENU_ITEM(gs->burger_menu->view_submenu->toolbars_submenu->toolbar_menuitem);
722 mbcmi = GTK_CHECK_MENU_ITEM(gs->menu_bar->view_submenu->toolbars_submenu->toolbar_menuitem);
723 tbcmi = GTK_CHECK_MENU_ITEM(gs->popup_menu->toolbars_submenu->toolbar_menuitem);
724
725 /* ensure menubar and burger menu checkboxes are both updated */
726 if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
727 if (gtk_check_menu_item_get_active(bmcmi) == FALSE) {
728 gtk_check_menu_item_set_active(bmcmi, TRUE);
729 }
730
731 if (gtk_check_menu_item_get_active(mbcmi) == FALSE) {
732 gtk_check_menu_item_set_active(mbcmi, TRUE);
733 }
734
735 if (gtk_check_menu_item_get_active(tbcmi) == FALSE) {
736 gtk_check_menu_item_set_active(tbcmi, TRUE);
737 }
738
740 set_bar_show("tool", true);
741 } else {
742 if (gtk_check_menu_item_get_active(bmcmi) == TRUE) {
743 gtk_check_menu_item_set_active(bmcmi, FALSE);
744 }
745
746 if (gtk_check_menu_item_get_active(mbcmi) == TRUE) {
747 gtk_check_menu_item_set_active(mbcmi, FALSE);
748 }
749
750 if (gtk_check_menu_item_get_active(tbcmi) == TRUE) {
751 gtk_check_menu_item_set_active(tbcmi, FALSE);
752 }
753
754 nsgtk_window_toolbar_show(gs, false);
755 set_bar_show("tool", false);
756 }
757 return TRUE;
758}
759
760
761static gboolean
762nsgtk_on_nexttab_activate_menu(GtkMenuItem *widget, gpointer data)
763{
764 struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
765
767
768 return TRUE;
769}
770
771
772static gboolean
773nsgtk_on_prevtab_activate_menu(GtkMenuItem *widget, gpointer data)
774{
775 struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
776
778
779 return TRUE;
780}
781
782
783/**
784 * menu signal handler for activation on close tab item
785 */
786static gboolean
787nsgtk_on_closetab_activate_menu(GtkMenuItem *widget, gpointer data)
788{
789 struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
790
792
793 return TRUE;
794}
795
796/* end of menu callback handlers */
797
798/**
799 * attach gtk signal handlers for menus
800 */
802{
803 int idx; /* item index */
804 for (idx = BACK_BUTTON; idx < PLACEHOLDER_BUTTON; idx++) {
805 if (g->menus[idx].main != NULL) {
806 g_signal_connect(g->menus[idx].main,
807 "activate",
808 G_CALLBACK(g->menus[idx].mhandler),
809 g);
810 }
811 if (g->menus[idx].burger != NULL) {
812 g_signal_connect(g->menus[idx].burger,
813 "activate",
814 G_CALLBACK(g->menus[idx].mhandler),
815 g);
816 }
817 if (g->menus[idx].popup != NULL) {
818 g_signal_connect(g->menus[idx].popup,
819 "activate",
820 G_CALLBACK(g->menus[idx].mhandler),
821 g);
822 }
823 }
824}
825
826
827/**
828 * Create and connect handlers to bar menu.
829 *
830 * \param gs scaffolding to attach popup menu to.
831 * \param group The accelerator group to use for the popup.
832 * \param showmenu if the bar menu should be shown
833 * \param showtool if the toolabar should be shown
834 * \return menu structure on success or NULL on error.
835 */
836static struct nsgtk_bar_submenu *
838 GtkAccelGroup *group,
839 bool showmenu,
840 bool showtool)
841{
842 GtkMenuShell *menushell;
843 struct nsgtk_bar_submenu *nmenu;
844
845 menushell = GTK_MENU_SHELL(gtk_builder_get_object(gs->builder,
846 "menubar"));
847
848 nmenu = nsgtk_menu_bar_create(menushell, group);
849 if (nmenu == NULL) {
850 return NULL;
851 }
852
853 /* set menu bar visibility */
854 if (showmenu) {
855 gtk_widget_show(GTK_WIDGET(nmenu->bar_menu));
856 } else {
857 gtk_widget_hide(GTK_WIDGET(nmenu->bar_menu));
858 }
859
860 /* set checks correct way on toolbar submenu */
861 gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->menubar_menuitem, showmenu);
862 gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem, showtool);
863
864 /* bar menu signal handlers for edit controls */
865 g_signal_connect(nmenu->edit_submenu->edit,
866 "show",
868 gs);
869
870 g_signal_connect(nmenu->edit_submenu->edit,
871 "hide",
873 gs);
874
875 /*
876 * attach signal handlers for menubar and toolbar visibility toggling
877 */
878 g_signal_connect(nmenu->view_submenu->toolbars_submenu->menubar_menuitem,
879 "toggled",
881 gs);
882
883 g_signal_connect(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem,
884 "toggled",
886 gs);
887
888
889 return nmenu;
890}
891
892
893/**
894 * Create and connect handlers to burger menu.
895 *
896 * \param g scaffolding to attach popup menu to.
897 * \param group The accelerator group to use for the popup.
898 * \param showbar if the bar menu should be shown
899 * \param showtool if the toolabar should be shown
900 * \return menu structure on success or NULL on error.
901 */
902static struct nsgtk_burger_menu *
904 GtkAccelGroup *group,
905 bool showbar,
906 bool showtool)
907{
908 struct nsgtk_burger_menu *nmenu;
909
910 nmenu = nsgtk_burger_menu_create(group);
911
912 if (nmenu == NULL) {
913 return NULL;
914 }
915
916 /* set checks correct way on toolbar submenu */
917 gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->menubar_menuitem, showbar);
918 gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem, showtool);
919
920 g_signal_connect(nmenu->view_submenu->toolbars_submenu->menubar_menuitem,
921 "toggled",
923 gs);
924 g_signal_connect(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem,
925 "toggled",
927 gs);
928 return nmenu;
929}
930
931
932/**
933 * Create and connect handlers to popup menu.
934 *
935 * \param gs scaffolding to attach popup menu to.
936 * \param group The accelerator group to use for the popup.
937 * \param showbar if the bar menu should be shown
938 * \param showtool if the toolabar should be shown
939 * \return menu structure on success or NULL on error.
940 */
941static struct nsgtk_popup_menu *
943 GtkAccelGroup *group,
944 bool showbar,
945 bool showtool)
946{
947 struct nsgtk_popup_menu *nmenu;
948
949 nmenu = nsgtk_popup_menu_create(group);
950
951 if (nmenu == NULL) {
952 return NULL;
953 }
954 /* set checks correct way on toolbar submenu */
955 gtk_check_menu_item_set_active(nmenu->toolbars_submenu->menubar_menuitem, showbar);
956 gtk_check_menu_item_set_active(nmenu->toolbars_submenu->toolbar_menuitem, showtool);
957
958 g_signal_connect(nmenu->popup_menu,
959 "hide",
961 gs);
962
963 g_signal_connect(nmenu->toolbars_submenu->menubar_menuitem,
964 "toggled",
966 gs);
967 g_signal_connect(nmenu->toolbars_submenu->toolbar_menuitem,
968 "toggled",
970 gs);
971
972 /* set initial popup menu visibility */
973 popup_menu_hide(nmenu, false, false);
974
975 return nmenu;
976}
977
978
979/**
980 * Create and connect handlers to link popup menu.
981 *
982 * \param g scaffolding to attach popup menu to.
983 * \param group The accelerator group to use for the popup.
984 * \return true on success or false on error.
985 */
986static struct nsgtk_link_menu *
987create_scaffolding_link_menu(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
988{
989 struct nsgtk_link_menu *nmenu;
990
991 nmenu = nsgtk_link_menu_create(group);
992
993 if (nmenu == NULL) {
994 return NULL;
995 }
996
997 g_signal_connect(nmenu->save_menuitem,
998 "activate",
1000 g);
1001
1002 g_signal_connect(nmenu->opentab_menuitem,
1003 "activate",
1005 g);
1006
1007 g_signal_connect(nmenu->openwin_menuitem,
1008 "activate",
1010 g);
1011
1012 g_signal_connect(nmenu->bookmark_menuitem,
1013 "activate",
1015 g);
1016
1017 g_signal_connect(nmenu->copy_menuitem,
1018 "activate",
1020 g);
1021
1022 return nmenu;
1023}
1024
1025
1026/**
1027 * initialiase the menu signal handlers ready for connection
1028 */
1030{
1031#define TOOLBAR_ITEM_p(identifier, name, iconame) \
1032 g->menus[identifier].mhandler = nsgtk_on_##name##_activate_menu; \
1033 g->menus[identifier].iconname = iconame;
1034#define TOOLBAR_ITEM_y(identifier, name, iconame) \
1035 g->menus[identifier].mhandler = nsgtk_on_##name##_activate_menu; \
1036 g->menus[identifier].iconname = iconame;
1037#define TOOLBAR_ITEM_n(identifier, name, iconame) \
1038 g->menus[identifier].mhandler = NULL; \
1039 g->menus[identifier].iconname = iconame;
1040#define TOOLBAR_ITEM(identifier, name, snstvty, clicked, activate, label, iconame) \
1041 g->menus[identifier].sensitivity = snstvty; \
1042 TOOLBAR_ITEM_ ## activate(identifier, name, iconame)
1043#include "gtk/toolbar_items.h"
1044#undef TOOLBAR_ITEM_y
1045#undef TOOLBAR_ITEM_n
1046#undef TOOLBAR_ITEM
1047
1048 /* items on menubar, burger */
1049#define ITEM_MB(p, q, r) \
1050 g->menus[p##_BUTTON].main = g->menu_bar->r##_submenu->q##_menuitem; \
1051 g->menus[p##_BUTTON].burger = g->burger_menu->r##_submenu->q##_menuitem
1052
1053 /* items on menubar, burger and context popup submenu */
1054#define ITEM_MBP(p, q, r) \
1055 g->menus[p##_BUTTON].main = g->menu_bar->r##_submenu->q##_menuitem; \
1056 g->menus[p##_BUTTON].burger = g->burger_menu->r##_submenu->q##_menuitem; \
1057 g->menus[p##_BUTTON].popup = g->popup_menu->r##_submenu->q##_menuitem
1058
1059 /* items on menubar, burger and context popup */
1060#define ITEM_MBp(p, q, r) \
1061 g->menus[p##_BUTTON].main = g->menu_bar->r##_submenu->q##_menuitem; \
1062 g->menus[p##_BUTTON].burger = g->burger_menu->r##_submenu->q##_menuitem; \
1063 g->menus[p##_BUTTON].popup = g->popup_menu->q##_menuitem
1064
1065
1066 /* file menu */
1067 ITEM_MB(NEWWINDOW, newwindow, file);
1068 ITEM_MB(NEWTAB, newtab, file);
1069 ITEM_MB(OPENFILE, openfile, file);
1070 ITEM_MB(CLOSEWINDOW, closewindow, file);
1071 ITEM_MB(PRINTPREVIEW, printpreview, file);
1072 ITEM_MB(PRINT, print, file);
1073 ITEM_MB(QUIT, quit, file);
1074 /* file - export submenu */
1075 ITEM_MB(SAVEPAGE, savepage, file_submenu->export);
1076 ITEM_MB(PLAINTEXT, plaintext, file_submenu->export);
1077 ITEM_MB(PDF, pdf, file_submenu->export);
1078
1079 /* edit menu */
1080 ITEM_MBp(CUT, cut, edit);
1081 ITEM_MBp(COPY, copy, edit);
1082 ITEM_MBp(PASTE, paste, edit);
1083 ITEM_MB(DELETE, delete, edit);
1084 ITEM_MB(SELECTALL, selectall, edit);
1085 ITEM_MB(FIND, find, edit);
1086 ITEM_MB(PREFERENCES, preferences, edit);
1087
1088 /* view menu */
1089 ITEM_MB(FULLSCREEN, fullscreen, view);
1090 ITEM_MB(SAVEWINDOWSIZE, savewindowsize, view);
1091 /* view - scale submenu */
1092 ITEM_MB(ZOOMPLUS, zoomplus, view_submenu->scaleview);
1093 ITEM_MB(ZOOMMINUS, zoomminus, view_submenu->scaleview);
1094 ITEM_MB(ZOOMNORMAL, zoomnormal, view_submenu->scaleview);
1095 /* view - tabs submenu */
1096 ITEM_MB(NEXTTAB, nexttab, view_submenu->tabs);
1097 ITEM_MB(PREVTAB, prevtab, view_submenu->tabs);
1098 ITEM_MB(CLOSETAB, closetab, view_submenu->tabs);
1099 /* view - toolbars submenu */
1100 ITEM_MB(CUSTOMIZE, customize, view_submenu->toolbars);
1102
1103 /* navigation menu */
1104 ITEM_MBp(BACK, back, nav);
1105 ITEM_MBp(FORWARD, forward, nav);
1106 ITEM_MBp(STOP, stop, nav);
1107 ITEM_MBp(RELOAD, reload, nav);
1108 ITEM_MB(HOME, home, nav);
1109 ITEM_MB(LOCALHISTORY, localhistory, nav);
1110 ITEM_MB(GLOBALHISTORY, globalhistory, nav);
1111 ITEM_MB(ADDBOOKMARKS, addbookmarks, nav);
1112 ITEM_MB(SHOWBOOKMARKS, showbookmarks, nav);
1113 ITEM_MB(OPENLOCATION, openlocation, nav);
1114
1115 /* tools menu */
1116 ITEM_MBP(DOWNLOADS, downloads, tools);
1117 ITEM_MBP(SHOWCOOKIES, showcookies, tools);
1118 /* tools > developer submenu */
1119 ITEM_MBP(VIEWSOURCE, viewsource, tools_submenu->developer);
1120 ITEM_MBP(TOGGLEDEBUGGING, toggledebugging, tools_submenu->developer);
1121 ITEM_MBP(SAVEBOXTREE, debugboxtree, tools_submenu->developer);
1122 ITEM_MBP(SAVEDOMTREE, debugdomtree, tools_submenu->developer);
1123
1124 /* help menu */
1125 ITEM_MB(CONTENTS, contents, help);
1126 ITEM_MB(GUIDE, guide, help);
1127 ITEM_MB(INFO, info, help);
1128 ITEM_MB(ABOUT, about, help);
1129
1130
1131#undef ITEM_MB
1132#undef ITEM_MBp
1133#undef ITEM_MBP
1134
1135 return NSERROR_OK;
1136}
1137
1138
1140{
1141
1142 for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
1143 if (g->menus[i].main != NULL) {
1144 gtk_widget_set_sensitive(GTK_WIDGET(
1145 g->menus[i].main),
1146 g->menus[i].sensitivity);
1147 }
1148 if (g->menus[i].burger != NULL) {
1149 gtk_widget_set_sensitive(GTK_WIDGET(
1150 g->menus[i].burger),
1151 g->menus[i].sensitivity);
1152 }
1153 if (g->menus[i].popup != NULL) {
1154 gtk_widget_set_sensitive(GTK_WIDGET(
1155 g->menus[i].popup),
1156 g->menus[i].sensitivity);
1157 }
1158 }
1159}
1160
1161
1162/* set menu items to have icons */
1164{
1165 GtkWidget *img;
1166 for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
1167 /* ensure there is an icon name */
1168 if (g->menus[i].iconname == NULL) {
1169 continue;
1170 }
1171
1172 if (g->menus[i].main != NULL) {
1173 img = gtk_image_new_from_icon_name(g->menus[i].iconname,
1174 GTK_ICON_SIZE_MENU);
1175 nsgtk_image_menu_item_set_image(GTK_WIDGET(g->menus[i].main), img);
1176 }
1177 if (g->menus[i].burger != NULL) {
1178 img = gtk_image_new_from_icon_name(g->menus[i].iconname,
1179 GTK_ICON_SIZE_MENU);
1180 nsgtk_image_menu_item_set_image(GTK_WIDGET(g->menus[i].burger), img);
1181 }
1182 if (g->menus[i].popup != NULL) {
1183 img = gtk_image_new_from_icon_name(g->menus[i].iconname,
1184 GTK_ICON_SIZE_MENU);
1185 nsgtk_image_menu_item_set_image(GTK_WIDGET(g->menus[i].popup), img);
1186 }
1187 }
1188}
1189
1190
1191/**
1192 * create and initialise menus
1193 *
1194 * There are four menus held by the scaffolding:
1195 *
1196 * 1. Main menubar menu.
1197 * This can be hidden which causes the right click popup context menu
1198 * to use the burger menu.
1199 * 2. Burger menu.
1200 * This can be opened from a burger icon on the toolbar.
1201 * 3. popup context menu.
1202 * This is opened by right mouse clicking on the toolbar or browser area
1203 * 4. link context menu
1204 * Opened like the other popup menu when the mouse is over a link in the
1205 * browser area
1206 *
1207 * The cut, copy, paste, delete and back, forwards, stop, reload groups of
1208 * menu entries are context sensitive and must be updated as appropriate
1209 * when a menu is opened which contains those groups.
1210 */
1212{
1213 GtkAccelGroup *group;
1214 bool showmenu; /* show menubar */
1215 bool showtool; /* show toolbar */
1216
1217 get_bar_show(&showmenu, &showtool);
1218
1219 group = gtk_accel_group_new();
1220
1221 gtk_window_add_accel_group(gs->window, group);
1222
1223 gs->menu_bar = create_scaffolding_bar_menu(gs, group, showmenu, showtool);
1224 gs->burger_menu = create_scaffolding_burger_menu(gs, group, showmenu, showtool);
1225 gs->popup_menu = create_scaffolding_popup_menu(gs, group, showmenu, showtool);
1226 gs->link_menu = create_scaffolding_link_menu(gs, group);
1227
1228 /* set up the menu signal handlers */
1233
1234 return NSERROR_OK;
1235}
1236
1237
1238/* exported function documented in gtk/scaffolding.h */
1239void nsgtk_scaffolding_set_title(struct gui_window *gw, const char *title)
1240{
1241 struct nsgtk_scaffolding *gs = nsgtk_get_scaffold(gw);
1242 int title_len;
1243 char *newtitle;
1244
1245 /* only set window title if top level window */
1246 if (gs->top_level != gw) {
1247 return;
1248 }
1249
1250 if (title == NULL || title[0] == '\0') {
1251 gtk_window_set_title(gs->window, "NetSurf");
1252 return;
1253 }
1254
1255 title_len = strlen(title) + SLEN(" - NetSurf") + 1;
1256 newtitle = malloc(title_len);
1257 if (newtitle == NULL) {
1258 return;
1259 }
1260
1261 snprintf(newtitle, title_len, "%s - NetSurf", title);
1262
1263 gtk_window_set_title(gs->window, newtitle);
1264
1265 free(newtitle);
1266
1267}
1268
1269
1270/* exported interface documented in scaffolding.h */
1272{
1273 struct nsgtk_scaffolding *gs = nsgtk_get_scaffold(gw);
1274 if (active) {
1275 gs->menus[STOP_BUTTON].sensitivity = true;
1276 gs->menus[RELOAD_BUTTON].sensitivity = false;
1277 } else {
1278 gs->menus[STOP_BUTTON].sensitivity = false;
1279 gs->menus[RELOAD_BUTTON].sensitivity = true;
1280 }
1282
1283 return NSERROR_OK;
1284}
1285
1286
1287/* exported interface documented in gtk/scaffolding.h */
1289{
1290 struct nsgtk_scaffolding *gs;
1291
1292 gs = scaf_list;
1293 assert(gs != NULL);
1294
1295 if (nsgtk_check_for_downloads(gs->window) == true) {
1296 return NSERROR_INVALID;
1297 }
1298
1299 /* iterate all scaffolding windows and destroy them */
1300 while (gs != NULL) {
1301 struct nsgtk_scaffolding *next = gs->next;
1302 gtk_widget_destroy(GTK_WIDGET(gs->window));
1303 gs = next;
1304 }
1305 return NSERROR_OK;
1306}
1307
1308
1309/* exported interface documented in gtk/scaffolding.h */
1311{
1312 return g->window;
1313}
1314
1315/* exported interface documented in gtk/scaffolding.h */
1317{
1318 return g->notebook;
1319}
1320
1321
1322/* exported interface documented in gtk/scaffolding.h */
1324{
1325 if (gs == NULL) {
1326 return NULL;
1327 }
1328 return gs->menu_bar->bar_menu;
1329}
1330
1331/* exported interface documented in gtk/scaffolding.h */
1333{
1334 if (g == NULL) {
1335 return scaf_list;
1336 }
1337 return g->next;
1338}
1339
1340
1341/* exported interface documented in gtk/scaffolding.h */
1343{
1344 return g->top_level;
1345}
1346
1347
1348/* exported interface documented in gtk/scaffolding.h */
1350{
1351 struct browser_window *bw;
1352 struct nsgtk_scaffolding *sc;
1353
1354 assert(gw != NULL);
1355
1356 bw = nsgtk_get_browser_window(gw);
1357
1358 assert(bw != NULL);
1359
1360 sc = nsgtk_get_scaffold(gw);
1361 assert(sc != NULL);
1362
1363 scaf_current = sc;
1364
1365 sc->top_level = gw;
1366
1367 /* Synchronise the history */
1369
1370 /* Ensure the window's title bar is updated */
1372}
1373
1374
1375/* exported interface documented in scaffolding.h */
1377{
1378 int i;
1379#define SENSITIVITY(q) \
1380 i = q##_BUTTON; \
1381 if (g->menus[i].main != NULL) \
1382 gtk_widget_set_sensitive(GTK_WIDGET(g->menus[i].main), \
1383 g->menus[i].sensitivity); \
1384 if (g->menus[i].burger != NULL) \
1385 gtk_widget_set_sensitive(GTK_WIDGET(g->menus[i].burger), \
1386 g->menus[i].sensitivity); \
1387 if (g->menus[i].popup != NULL) \
1388 gtk_widget_set_sensitive(GTK_WIDGET(g->menus[i].popup), \
1389 g->menus[i].sensitivity);
1390
1391 SENSITIVITY(STOP)
1392 SENSITIVITY(RELOAD)
1393 SENSITIVITY(CUT)
1394 SENSITIVITY(COPY)
1395 SENSITIVITY(PASTE)
1396 SENSITIVITY(BACK)
1397 SENSITIVITY(FORWARD)
1398 SENSITIVITY(NEXTTAB)
1399 SENSITIVITY(PREVTAB)
1400 SENSITIVITY(CLOSETAB)
1401#undef SENSITIVITY
1402
1403}
1404
1405
1406/* exported interface documented in gtk/scaffolding.h */
1408{
1409 /* set visibility for right-click popup menu */
1410 popup_menu_hide(gs->popup_menu, false, true);
1411
1413
1414 return NSERROR_OK;
1415}
1416
1417
1418/* exported interface documented in gtk/scaffolding.h */
1420{
1422
1423 return NSERROR_OK;
1424}
1425
1426
1427/* exported interface documented in gtk/scaffolding.h */
1428void
1430 gdouble x,
1431 gdouble y)
1432{
1433 GtkMenu *gtkmenu;
1434 struct browser_window *bw;
1435
1437
1438 /* update the global context menu features */
1440
1441 if (current_menu_features.link != NULL) {
1442 /* menu is opening over a link */
1443 gtkmenu = g->link_menu->link_menu;
1444 } else {
1445 gtkmenu = g->popup_menu->popup_menu;
1446
1448
1449 if (!(g->menus[COPY_BUTTON].sensitivity)) {
1450 gtk_widget_hide(GTK_WIDGET(g->popup_menu->copy_menuitem));
1451 } else {
1452 gtk_widget_show(GTK_WIDGET(g->popup_menu->copy_menuitem));
1453 }
1454
1455 if (!(g->menus[CUT_BUTTON].sensitivity)) {
1456 gtk_widget_hide(GTK_WIDGET(g->popup_menu->cut_menuitem));
1457 } else {
1458 gtk_widget_show(GTK_WIDGET(g->popup_menu->cut_menuitem));
1459 }
1460
1461 if (!(g->menus[PASTE_BUTTON].sensitivity)) {
1462 gtk_widget_hide(GTK_WIDGET(g->popup_menu->paste_menuitem));
1463 } else {
1464 gtk_widget_show(GTK_WIDGET(g->popup_menu->paste_menuitem));
1465 }
1466
1467 }
1468
1469 nsgtk_menu_popup_at_pointer(gtkmenu, NULL);
1470}
1471
1472/* exported interface documented in gtk/scaffolding.h */
1474{
1475 if (scaf_current == NULL) {
1477 }
1478 return scaf_current;
1479}
1480
1481/* exported interface documented in gtk/scaffolding.h */
1483{
1484 struct nsgtk_scaffolding *gs;
1485 gs = scaf_list;
1486 while (gs != NULL) {
1487 if (gs->notebook == notebook) {
1488 break;
1489 }
1490 gs = gs->next;
1491 }
1492 return gs;
1493}
1494
1495/* exported interface documented in gtk/scaffolding.h */
1497{
1498 nserror res;
1499 struct nsgtk_scaffolding *gs;
1500
1501 gs = calloc(1, sizeof(*gs));
1502 if (gs == NULL) {
1503 return NULL;
1504 }
1505
1506 NSLOG(netsurf, INFO,
1507 "Constructing a scaffold of %p for gui_window %p", gs, toplevel);
1508
1509 gs->top_level = toplevel;
1510
1511 /* Construct UI widgets */
1512 if (nsgtk_builder_new_from_resname("netsurf", &gs->builder) != NSERROR_OK) {
1513 free(gs);
1514 return NULL;
1515 }
1516
1517 gtk_builder_connect_signals(gs->builder, NULL);
1518
1519 /* containing window setup */
1520 gs->window = GTK_WINDOW(gtk_builder_get_object(gs->builder,
1521 "wndBrowser"));
1522
1523 /**
1524 * set this window's size and position to what's in the options, or
1525 * some sensible default if they are not set yet.
1526 */
1527 if (nsoption_int(window_width) > 0) {
1528 gtk_window_move(gs->window,
1529 nsoption_int(window_x),
1530 nsoption_int(window_y));
1531 gtk_window_resize(gs->window,
1532 nsoption_int(window_width),
1533 nsoption_int(window_height));
1534 } else {
1535 /* Set to 1000x700, so we're very likely to fit even on
1536 * 1024x768 displays, not being able to take into account
1537 * window furniture or panels.
1538 */
1539 gtk_window_set_default_size(gs->window, 1000, 700);
1540 }
1541
1542 g_signal_connect(gs->window,
1543 "delete-event",
1545 gs);
1546
1547 g_signal_connect(gs->window,
1548 "destroy",
1549 G_CALLBACK(scaffolding_window_destroy),
1550 gs);
1551
1552
1553 /* notebook */
1554 res = nsgtk_notebook_create(gs->builder, &gs->notebook);
1555 if (res != NSERROR_OK) {
1556 free(gs);
1557 return NULL;
1558 }
1559
1560 g_signal_connect_after(gs->notebook,
1561 "page-added",
1562 G_CALLBACK(nsgtk_window_tabs_add),
1563 gs);
1564 gs->tabs_remove_handler_id = g_signal_connect_after(gs->notebook,
1565 "page-removed",
1566 G_CALLBACK(nsgtk_window_tabs_remove),
1567 gs);
1568
1569
1570 res = nsgtk_menus_create(gs);
1571 if (res != NSERROR_OK) {
1572 free(gs);
1573 return NULL;
1574 }
1575
1576 /* attach to the list */
1577 if (scaf_list) {
1578 scaf_list->prev = gs;
1579 }
1580 gs->next = scaf_list;
1581 gs->prev = NULL;
1582 scaf_list = gs;
1583
1584 /* finally, show the window. */
1585 gtk_widget_show(GTK_WIDGET(gs->window));
1586
1587 NSLOG(netsurf, INFO, "creation complete");
1588
1589 return gs;
1590}
1591
1592/* exported interface documented in gtk/scaffolding.h */
1594 struct nsgtk_pi_window *win)
1595{
1597}
1598
1599/* exported interface documented in gtk/scaffolding.h */
1601{
1603}
static struct s_view view
Definition: plot.c:199
bool browser_window_history_forward_available(struct browser_window *bw)
Check whether it is pssible to go forwards in the history.
bool browser_window_history_back_available(struct browser_window *bw)
Check whether it is pssible to go back in the history.
Interface to browser history operations.
Browser window creation and manipulation interface.
nserror browser_window_get_features(struct browser_window *bw, int x, int y, struct browser_window_features *data)
Get access to any page features at the given coordinates.
nserror browser_window_navigate(struct browser_window *bw, struct nsurl *url, struct nsurl *referrer, enum browser_window_nav_flags flags, char *post_urlenc, struct fetch_multipart_data *post_multipart, struct hlcache_handle *parent)
Start fetching a page in a browser window.
browser_editor_flags
@ BW_EDITOR_CAN_PASTE
Can paste, input.
@ BW_EDITOR_CAN_CUT
Selection not read-only.
@ BW_EDITOR_CAN_COPY
Have selection.
const char * browser_window_get_title(struct browser_window *bw)
Get the title of a browser_window.
nserror browser_window_create(enum browser_window_create_flags flags, struct nsurl *url, struct nsurl *referrer, struct browser_window *existing, struct browser_window **bw)
Create and open a new root browser window with the given page.
browser_editor_flags browser_window_get_editor_flags(struct browser_window *bw)
Check whether browser window can accept a cut/copy/paste, or has a selection that could be saved.
@ BW_CREATE_HISTORY
this will form a new history node (don't set for back/reload/etc)
@ BW_CREATE_TAB
New gui_window to be tab in same window as "existing" gui_window.
@ BW_CREATE_CLONE
New gui_window to be clone of "existing" gui_window.
@ BW_NAVIGATE_DOWNLOAD
download rather than render the uri
void nsgtk_image_menu_item_set_image(GtkWidget *image_menu_item, GtkWidget *image)
Sets the image of image_menu_item to the given widget.
Definition: compat.c:553
void nsgtk_menu_popup_at_pointer(GtkMenu *menu, const GdkEvent *trigger_event)
Displays menu and makes it available for selection.
Definition: compat.c:561
Compatibility functions for older GTK versions (interface)
#define gtk_widget_in_destruction(widget)
Definition: compat.h:169
nserror hotlist_add_url(nsurl *url)
Add an entry to the hotlist for given URL.
Definition: hotlist.c:1431
nserror
Enumeration of error codes.
Definition: errors.h:29
@ NSERROR_INVALID
Invalid data.
Definition: errors.h:49
@ NSERROR_OK
No error.
Definition: errors.h:30
bool nsgtk_check_for_downloads(GtkWindow *parent)
Check with user if download is in progress they want to complete.
Definition: download.c:1033
nserror nsgtk_local_history_hide(void)
hide the local history window from being visible.
Interface to GTK local history manager.
static GtkClipboard * clipboard
Definition: selection.c:31
bool nsgtk_complete
set when no windows remain open.
Definition: gui.c:77
nserror nsgtk_warning(const char *warning, const char *detail)
Warn the user of an event.
Definition: gui.c:95
struct nsgtk_link_menu * nsgtk_link_menu_create(GtkAccelGroup *group)
Generate context sensitive link popup menu.
Definition: menu.c:582
struct nsgtk_burger_menu * nsgtk_burger_menu_create(GtkAccelGroup *group)
Generate burger menu.
Definition: menu.c:522
nserror nsgtk_menu_bar_destroy(struct nsgtk_bar_submenu *menu)
destroy bar menu
Definition: menu.c:602
nserror nsgtk_burger_menu_destroy(struct nsgtk_burger_menu *menu)
destroy burger menu
Definition: menu.c:623
struct nsgtk_popup_menu * nsgtk_popup_menu_create(GtkAccelGroup *group)
Generate right click popup menu.
Definition: menu.c:551
nserror nsgtk_popup_menu_destroy(struct nsgtk_popup_menu *menu)
destroy popup menu
Definition: menu.c:645
nserror nsgtk_link_menu_destroy(struct nsgtk_link_menu *menu)
destroy link menu
Definition: menu.c:659
struct nsgtk_bar_submenu * nsgtk_menu_bar_create(GtkMenuShell *menubar, GtkAccelGroup *group)
Generate menubar menus.
Definition: menu.c:488
nserror nsgtk_window_search_toggle(struct gui_window *gw)
toggle search visibility
Definition: window.c:1634
nserror nsgtk_window_position_local_history(struct gui_window *gw)
position local_history appropriately
Definition: window.c:1702
struct nsgtk_scaffolding * nsgtk_get_scaffold(struct gui_window *g)
get containing nsgtk scaffolding handle from gui window handle
Definition: window.c:1612
nserror nsgtk_window_position_page_info(struct gui_window *gw, struct nsgtk_pi_window *win)
position page_info appropriately
Definition: window.c:1695
nserror nsgtk_window_toolbar_show(struct nsgtk_scaffolding *gs, bool show)
Windows associated with a scaffold will have their toolbar show state set.
Definition: window.c:1671
struct browser_window * nsgtk_get_browser_window(struct gui_window *g)
get core browsing context from gui window handle
Definition: window.c:1619
struct fbtk_bitmap reload
#define NSLOG(catname, level, logmsg, args...)
Definition: log.h:116
const char * messages_get_errorcode(nserror code)
lookup of a message by errorcode from the standard Messages hash.
Definition: messages.c:248
Localised message support (interface).
NetSurf URL handling (interface).
const char * nsurl_access(const nsurl *url)
Access a NetSurf URL object as a string.
nserror nsgtk_builder_new_from_resname(const char *resname, GtkBuilder **builder_out)
Create gtk builder object for the named ui resource.
Definition: resources.c:526
Interface to gtk builtin resource handling.
void nsgtk_scaffolding_set_top_level(struct gui_window *gw)
Set the current active top level gui window.
Definition: scaffolding.c:1349
static struct nsgtk_link_menu * create_scaffolding_link_menu(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
Create and connect handlers to link popup menu.
Definition: scaffolding.c:987
static gboolean nsgtk_on_link_bookmark_activate_menu(GtkMenuItem *widget, gpointer data)
Handler for bookmarking a link.
Definition: scaffolding.c:576
nserror nsgtk_scaffolding_toolbar_context_menu(struct nsgtk_scaffolding *gs)
open the toolbar context menu
Definition: scaffolding.c:1407
static struct nsgtk_burger_menu * create_scaffolding_burger_menu(struct nsgtk_scaffolding *gs, GtkAccelGroup *group, bool showbar, bool showtool)
Create and connect handlers to burger menu.
Definition: scaffolding.c:903
static void nsgtk_window_tabs_add(GtkNotebook *notebook, GtkWidget *page, guint page_num, struct nsgtk_scaffolding *g)
Update the menus when the number of tabs changes.
Definition: scaffolding.c:403
static gboolean nsgtk_window_edit_menu_shown(GtkWidget *widget, struct nsgtk_scaffolding *g)
gtk event for edit menu being show
Definition: scaffolding.c:351
void nsgtk_scaffolding_set_title(struct gui_window *gw, const char *title)
set the title in the window
Definition: scaffolding.c:1239
static struct nsgtk_popup_menu * create_scaffolding_popup_menu(struct nsgtk_scaffolding *gs, GtkAccelGroup *group, bool showbar, bool showtool)
Create and connect handlers to popup menu.
Definition: scaffolding.c:942
#define ITEM_MBp(p, q, r)
static gboolean nsgtk_on_find_activate_menu(GtkMenuItem *widget, gpointer data)
Definition: scaffolding.c:606
struct nsgtk_scaffolding * nsgtk_new_scaffolding(struct gui_window *toplevel)
create a new scaffolding for a window.
Definition: scaffolding.c:1496
static void nsgtk_menu_set_sensitivity(struct nsgtk_scaffolding *g)
Definition: scaffolding.c:1139
static gboolean nsgtk_on_savelink_activate_menu(GtkMenuItem *widget, gpointer data)
Definition: scaffolding.c:497
static struct browser_window_features current_menu_features
holds the context data for what's under the pointer, when the contextual menu is opened.
Definition: scaffolding.c:113
static void nsgtk_window_tabs_remove(GtkNotebook *notebook, GtkWidget *page, guint page_num, struct nsgtk_scaffolding *gs)
Update the menus when the number of tabs changes.
Definition: scaffolding.c:437
static gboolean nsgtk_window_edit_menu_hidden(GtkWidget *widget, struct nsgtk_scaffolding *g)
gtk event handler for edit menu being hidden
Definition: scaffolding.c:367
static void popup_menu_hide(struct nsgtk_popup_menu *menu, bool nav, bool cnp)
Helper to hide popup menu entries by grouping.
Definition: scaffolding.c:125
static nserror nsgtk_menu_initialise(struct nsgtk_scaffolding *g)
initialiase the menu signal handlers ready for connection
Definition: scaffolding.c:1029
nserror nsgtk_scaffolding_burger_menu(struct nsgtk_scaffolding *gs)
open the burger menu
Definition: scaffolding.c:1419
GtkNotebook * nsgtk_scaffolding_notebook(struct nsgtk_scaffolding *g)
Get the gtk notebook from a scaffold.
Definition: scaffolding.c:1316
static gboolean nsgtk_on_link_copy_activate_menu(GtkMenuItem *widget, gpointer data)
Handler for copying a link.
Definition: scaffolding.c:591
static void scaffolding_window_destroy(GtkWidget *widget, gpointer data)
resource cleanup function for window destruction.
Definition: scaffolding.c:188
void nsgtk_scaffolding_set_sensitivity(struct nsgtk_scaffolding *g)
update the sensitivity of context sensitive UI elements
Definition: scaffolding.c:1376
static gboolean scaffolding_window_delete_event(GtkWidget *widget, GdkEvent *event, gpointer data)
gtk event callback on window delete event.
Definition: scaffolding.c:247
GtkMenuBar * nsgtk_scaffolding_menu_bar(struct nsgtk_scaffolding *gs)
Definition: scaffolding.c:1323
#define ITEM_MBP(p, q, r)
static gboolean nsgtk_on_link_opentab_activate_menu(GtkMenuItem *widget, gpointer data)
Handler for opening new tab from a link.
Definition: scaffolding.c:550
nserror nsgtk_scaffolding_position_local_history(struct nsgtk_scaffolding *gs)
Position the local-history popup in the right place.
Definition: scaffolding.c:1600
static gboolean nsgtk_on_prevtab_activate_menu(GtkMenuItem *widget, gpointer data)
Definition: scaffolding.c:773
static void nsgtk_menu_set_icons(struct nsgtk_scaffolding *g)
Definition: scaffolding.c:1163
#define SENSITIVITY(q)
static struct nsgtk_scaffolding * scaf_list
global list for interface changes
Definition: scaffolding.c:107
static nserror set_bar_show(const char *bar, bool show)
Definition: scaffolding.c:637
static gboolean nsgtk_on_menubar_activate_menu(GtkMenuItem *widget, gpointer data)
Definition: scaffolding.c:666
static void nsgtk_scaffolding_enable_edit_actions_sensitivity(struct nsgtk_scaffolding *g)
make edit actions sensitive
Definition: scaffolding.c:331
static guint nsgtk_scaffolding_update_edit_actions_sensitivity(struct nsgtk_scaffolding *g)
edit the sensitivity of focused widget
Definition: scaffolding.c:290
static struct nsgtk_scaffolding * scaf_current
current scaffold for model dialogue use
Definition: scaffolding.c:102
static gboolean nsgtk_on_link_openwin_activate_menu(GtkMenuItem *widget, gpointer data)
Handler for opening new window from a link.
Definition: scaffolding.c:526
static void popup_menu_show(struct nsgtk_popup_menu *menu, bool nav, bool cnp)
Helper to show popup menu entries by grouping.
Definition: scaffolding.c:157
static gboolean nsgtk_window_popup_menu_hidden(GtkWidget *widget, struct nsgtk_scaffolding *g)
gtk event handler for popup menu being hidden.
Definition: scaffolding.c:384
nserror nsgtk_scaffolding_throbber(struct gui_window *gw, bool active)
Update scaffolding window when throbber state changes.
Definition: scaffolding.c:1271
static gboolean nsgtk_on_closetab_activate_menu(GtkMenuItem *widget, gpointer data)
menu signal handler for activation on close tab item
Definition: scaffolding.c:787
struct gui_window * nsgtk_scaffolding_top_level(struct nsgtk_scaffolding *g)
Definition: scaffolding.c:1342
static struct nsgtk_bar_submenu * create_scaffolding_bar_menu(struct nsgtk_scaffolding *gs, GtkAccelGroup *group, bool showmenu, bool showtool)
Create and connect handlers to bar menu.
Definition: scaffolding.c:837
GtkWindow * nsgtk_scaffolding_window(struct nsgtk_scaffolding *g)
Get the gtk window for a scaffolding.
Definition: scaffolding.c:1310
static gboolean nsgtk_on_toolbar_activate_menu(GtkMenuItem *widget, gpointer data)
Definition: scaffolding.c:714
nserror nsgtk_scaffolding_destroy_all(void)
causes all scaffolding windows to be destroyed.
Definition: scaffolding.c:1288
nserror nsgtk_scaffolding_position_page_info(struct nsgtk_scaffolding *gs, struct nsgtk_pi_window *win)
Position the page-info popup in the right place.
Definition: scaffolding.c:1593
struct nsgtk_scaffolding * nsgtk_scaffolding_from_notebook(GtkNotebook *notebook)
find which scaffolding contains a gtk notebook
Definition: scaffolding.c:1482
static gboolean nsgtk_on_nexttab_activate_menu(GtkMenuItem *widget, gpointer data)
Definition: scaffolding.c:762
void nsgtk_scaffolding_context_menu(struct nsgtk_scaffolding *g, gdouble x, gdouble y)
Open a context sensitive menu.
Definition: scaffolding.c:1429
static nserror get_bar_show(bool *menu, bool *tool)
Definition: scaffolding.c:615
static void nsgtk_menu_connect_signals(struct nsgtk_scaffolding *g)
attach gtk signal handlers for menus
Definition: scaffolding.c:801
#define ITEM_MB(p, q, r)
static void scaffolding_update_context(struct nsgtk_scaffolding *g)
Update the scaffolding controls.
Definition: scaffolding.c:267
struct nsgtk_scaffolding * nsgtk_current_scaffolding(void)
Obtain the most recently used scaffolding element.
Definition: scaffolding.c:1473
struct nsgtk_scaffolding * nsgtk_scaffolding_iterate(struct nsgtk_scaffolding *g)
Iterate through available scaffolding.
Definition: scaffolding.c:1332
static nserror nsgtk_menus_create(struct nsgtk_scaffolding *gs)
create and initialise menus
Definition: scaffolding.c:1211
Interface to utility string handling.
Page features at a specific spatial location.
struct nsurl * link
URL of a link or NULL.
Browser window data.
int x
Window dimensions.
struct browser_window * bw
first entry in window list
Definition: gui.c:296
struct gui_window * gui
Definition: window.c:89
main menubar
Definition: menu.h:142
GtkMenuBar * bar_menu
Definition: menu.h:143
struct nsgtk_view_menu * view_submenu
Definition: menu.h:146
struct nsgtk_edit_menu * edit_submenu
Definition: menu.h:145
struct nsgtk_view_menu * view_submenu
Definition: menu.h:162
GtkMenu * burger_menu
Definition: menu.h:153
GtkMenuItem * edit
Definition: menu.h:41
menu entry context
Definition: scaffolding.c:49
GtkWidget * popup
Definition: scaffolding.c:52
GtkWidget * main
Definition: scaffolding.c:50
gboolean(* mhandler)(GtkMenuItem *widget, gpointer data)
menu item handler
Definition: scaffolding.c:56
GtkWidget * burger
Definition: scaffolding.c:51
bool sensitivity
Definition: scaffolding.c:58
const char * iconname
Definition: scaffolding.c:57
GTK certificate viewing window context.
Definition: page_info.c:47
GtkWidget * first_separator
Definition: menu.h:183
struct nsgtk_toolbars_submenu * toolbars_submenu
Definition: menu.h:193
GtkWidget * back_menuitem
Definition: menu.h:178
GtkWidget * reload_menuitem
Definition: menu.h:181
GtkWidget * copy_menuitem
Definition: menu.h:187
GtkWidget * stop_menuitem
Definition: menu.h:180
GtkWidget * cut_menuitem
Definition: menu.h:186
GtkMenu * popup_menu
Definition: menu.h:175
GtkWidget * second_separator
Definition: menu.h:190
GtkWidget * forward_menuitem
Definition: menu.h:179
GtkWidget * paste_menuitem
Definition: menu.h:188
Core scaffolding structure.
Definition: scaffolding.c:64
GtkWindow * window
scaffold container window
Definition: scaffolding.c:75
struct nsgtk_scaffolding * next
global linked list of scaffolding for gui interface adjustments
Definition: scaffolding.c:66
struct nsgtk_burger_menu * burger_menu
burger menu hierarchy
Definition: scaffolding.c:87
struct nsgtk_menu menus[PLACEHOLDER_BUTTON]
menu entries widgets for sensitivity adjustment
Definition: scaffolding.c:96
struct nsgtk_link_menu * link_menu
link popup menu
Definition: scaffolding.c:93
gulong tabs_remove_handler_id
handler id for tabs remove callback
Definition: scaffolding.c:81
struct nsgtk_scaffolding * prev
Definition: scaffolding.c:66
struct nsgtk_popup_menu * popup_menu
right click popup menu hierarchy
Definition: scaffolding.c:90
GtkBuilder * builder
Builder object scaffold was created from.
Definition: scaffolding.c:72
struct gui_window * top_level
currently active gui browsing context
Definition: scaffolding.c:69
GtkNotebook * notebook
tab widget holding displayed pages
Definition: scaffolding.c:78
struct nsgtk_bar_submenu * menu_bar
menu bar hierarchy
Definition: scaffolding.c:84
GtkWidget * customize_menuitem
Definition: menu.h:127
GtkCheckMenuItem * menubar_menuitem
Definition: menu.h:125
GtkCheckMenuItem * toolbar_menuitem
Definition: menu.h:126
struct nsgtk_toolbars_submenu * toolbars_submenu
Definition: menu.h:60
GtkWidget * tabs_menuitem
Definition: menu.h:61
nserror nsgtk_tab_next(GtkNotebook *notebook)
Definition: tabs.c:568
nserror nsgtk_notebook_create(GtkBuilder *builder, GtkNotebook **notebook_out)
create notebook
Definition: tabs.c:380
nserror nsgtk_tab_close_current(GtkNotebook *notebook)
Definition: tabs.c:527
nserror nsgtk_tab_prev(GtkNotebook *notebook)
Definition: tabs.c:560
@ CUSTOMIZE_BUTTON
Definition: toolbar_items.h:76
@ BACK_BUTTON
Definition: toolbar_items.h:23
@ NEXTTAB_BUTTON
Definition: toolbar_items.h:70
@ COPY_BUTTON
Definition: toolbar_items.h:48
@ CLOSETAB_BUTTON
Definition: toolbar_items.h:37
@ PASTE_BUTTON
Definition: toolbar_items.h:49
@ RELOAD_BUTTON
Definition: toolbar_items.h:31
@ FORWARD_BUTTON
Definition: toolbar_items.h:25
@ PLACEHOLDER_BUTTON
Definition: toolbar_items.h:77
@ CUT_BUTTON
Definition: toolbar_items.h:47
@ STOP_BUTTON
Definition: toolbar_items.h:30
@ PREVTAB_BUTTON
Definition: toolbar_items.h:71
Option reading and saving interface.
#define nsoption_charp(OPTION)
Get the value of a string option.
Definition: nsoption.h:297
#define nsoption_int(OPTION)
Get the value of an integer option.
Definition: nsoption.h:279
#define nsoption_set_charp(OPTION, VALUE)
set string option in default table
Definition: nsoption.h:338
Interface to a number of general purpose functionality.
#define SLEN(x)
Calculate length of constant C string.
Definition: utils.h:84