summaryrefslogtreecommitdiff
path: root/frontends/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/gtk')
-rw-r--r--frontends/gtk/Makefile49
-rw-r--r--frontends/gtk/Makefile.tools16
-rw-r--r--frontends/gtk/bitmap.c278
-rw-r--r--frontends/gtk/bitmap.h2
-rw-r--r--frontends/gtk/compat.c55
-rw-r--r--frontends/gtk/compat.h47
-rw-r--r--frontends/gtk/completion.c55
-rw-r--r--frontends/gtk/completion.h9
-rw-r--r--frontends/gtk/cookies.c7
-rw-r--r--frontends/gtk/cookies.h2
-rw-r--r--frontends/gtk/corewindow.c116
-rw-r--r--frontends/gtk/download.c856
-rw-r--r--frontends/gtk/download.h27
-rw-r--r--frontends/gtk/fetch.c11
-rw-r--r--frontends/gtk/fetch.h2
-rw-r--r--frontends/gtk/gdk.c5
-rw-r--r--frontends/gtk/global_history.c6
-rw-r--r--frontends/gtk/gui.c1333
-rw-r--r--frontends/gtk/gui.h3
-rw-r--r--frontends/gtk/hotlist.c2
-rw-r--r--frontends/gtk/layout_pango.c2
-rw-r--r--frontends/gtk/local_history.c37
-rw-r--r--frontends/gtk/local_history.h5
-rw-r--r--frontends/gtk/login.c232
-rw-r--r--frontends/gtk/menu.c231
-rw-r--r--frontends/gtk/menu.h240
-rw-r--r--frontends/gtk/misc.c192
-rw-r--r--frontends/gtk/misc.h (renamed from frontends/gtk/login.h)15
-rw-r--r--frontends/gtk/options.h15
-rw-r--r--frontends/gtk/page_info.c258
-rw-r--r--frontends/gtk/page_info.h (renamed from frontends/gtk/ssl_cert.h)29
-rw-r--r--frontends/gtk/plotters.c37
-rw-r--r--frontends/gtk/preferences.c41
-rw-r--r--frontends/gtk/print.c32
-rw-r--r--frontends/gtk/res/arrow_down_8x32.pngbin206 -> 0 bytes
l---------frontends/gtk/res/en/maps.html1
l---------frontends/gtk/res/fr/credits.html1
l---------frontends/gtk/res/fr/licence.html1
l---------frontends/gtk/res/fr/welcome.html1
-rw-r--r--frontends/gtk/res/gtk2/cookies.ui (renamed from frontends/gtk/res/cookies.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/downloads.ui (renamed from frontends/gtk/res/downloads.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/globalhistory.ui (renamed from frontends/gtk/res/globalhistory.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/hotlist.ui (renamed from frontends/gtk/res/hotlist.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/localhistory.ui (renamed from frontends/gtk/res/localhistory.gtk2.ui)1
-rw-r--r--frontends/gtk/res/gtk2/netsurf.ui90
-rw-r--r--frontends/gtk/res/gtk2/options.ui (renamed from frontends/gtk/res/options.gtk2.ui)83
-rw-r--r--frontends/gtk/res/gtk2/pageinfo.ui16
-rw-r--r--frontends/gtk/res/gtk2/password.ui (renamed from frontends/gtk/res/password.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/tabcontents.ui229
-rw-r--r--frontends/gtk/res/gtk2/toolbar.ui120
-rw-r--r--frontends/gtk/res/gtk2/viewdata.ui (renamed from frontends/gtk/res/viewdata.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/warning.ui (renamed from frontends/gtk/res/warning.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk3/cookies.ui (renamed from frontends/gtk/res/cookies.gtk3.ui)2
-rw-r--r--frontends/gtk/res/gtk3/downloads.ui (renamed from frontends/gtk/res/downloads.gtk3.ui)0
-rw-r--r--frontends/gtk/res/gtk3/globalhistory.ui (renamed from frontends/gtk/res/globalhistory.gtk3.ui)2
-rw-r--r--frontends/gtk/res/gtk3/hotlist.ui (renamed from frontends/gtk/res/hotlist.gtk3.ui)2
-rw-r--r--frontends/gtk/res/gtk3/localhistory.ui (renamed from frontends/gtk/res/localhistory.gtk3.ui)3
-rw-r--r--frontends/gtk/res/gtk3/netsurf.ui61
-rw-r--r--frontends/gtk/res/gtk3/options.ui (renamed from frontends/gtk/res/options.gtk3.ui)216
-rw-r--r--frontends/gtk/res/gtk3/pageinfo.ui22
-rw-r--r--frontends/gtk/res/gtk3/password.ui (renamed from frontends/gtk/res/password.gtk3.ui)0
-rw-r--r--frontends/gtk/res/gtk3/tabcontents.ui229
-rw-r--r--frontends/gtk/res/gtk3/toolbar.ui126
-rw-r--r--frontends/gtk/res/gtk3/viewdata.ui (renamed from frontends/gtk/res/viewdata.gtk3.ui)0
-rw-r--r--frontends/gtk/res/gtk3/warning.ui (renamed from frontends/gtk/res/warning.gtk3.ui)0
-rw-r--r--frontends/gtk/res/login.gtk2.ui223
-rw-r--r--frontends/gtk/res/login.gtk3.ui223
l---------frontends/gtk/res/maps.html1
-rw-r--r--frontends/gtk/res/messages.gresource.xml1
-rw-r--r--frontends/gtk/res/netsurf.gresource.xml48
-rw-r--r--frontends/gtk/res/netsurf.gtk2.ui212
-rw-r--r--frontends/gtk/res/netsurf.gtk3.ui207
-rw-r--r--frontends/gtk/res/ssl.gtk2.ui202
-rw-r--r--frontends/gtk/res/ssl.gtk3.ui181
-rw-r--r--frontends/gtk/res/tabcontents.gtk2.ui92
-rw-r--r--frontends/gtk/res/tabcontents.gtk3.ui92
-rw-r--r--frontends/gtk/res/toolbar.gtk2.ui172
-rw-r--r--frontends/gtk/res/toolbar.gtk3.ui137
-rw-r--r--frontends/gtk/res/ui.gresource.xml18
l---------frontends/gtk/res/zh_CN/credits.html1
l---------frontends/gtk/res/zh_CN/licence.html1
l---------frontends/gtk/res/zh_CN/welcome.html1
-rw-r--r--frontends/gtk/resources.c24
-rw-r--r--frontends/gtk/scaffolding.c2873
-rw-r--r--frontends/gtk/scaffolding.h176
-rw-r--r--frontends/gtk/schedule.c52
-rw-r--r--frontends/gtk/search.c418
-rw-r--r--frontends/gtk/search.h49
-rw-r--r--frontends/gtk/selection.c1
-rw-r--r--frontends/gtk/selection.h2
-rw-r--r--frontends/gtk/ssl_cert.c259
-rw-r--r--frontends/gtk/tabs.c379
-rw-r--r--frontends/gtk/tabs.h48
-rw-r--r--frontends/gtk/throbber.c48
-rw-r--r--frontends/gtk/throbber.h33
-rw-r--r--frontends/gtk/toolbar.c4564
-rw-r--r--frontends/gtk/toolbar.h184
-rw-r--r--frontends/gtk/toolbar_items.h159
-rw-r--r--frontends/gtk/viewsource.c15
-rw-r--r--frontends/gtk/window.c715
-rw-r--r--frontends/gtk/window.h110
101 files changed, 9410 insertions, 7964 deletions
diff --git a/frontends/gtk/Makefile b/frontends/gtk/Makefile
index ec60ce70c..64a0872ba 100644
--- a/frontends/gtk/Makefile
+++ b/frontends/gtk/Makefile
@@ -11,6 +11,8 @@
NETSURF_FEATURE_RSVG_CFLAGS := -DWITH_RSVG
NETSURF_FEATURE_VIDEO_CFLAGS := -DWITH_VIDEO
+# determine if the rsvg library API version
+RSVG_API := $(shell $(PKG_CONFIG) --atleast-version=2.46 librsvg-2.0 && echo 246)
$(eval $(call pkg_config_find_and_add_enabled,RSVG,librsvg-2.0,SVG))
$(eval $(call pkg_config_find_and_add_enabled,VIDEO,gstreamer-0.10,Video))
@@ -32,13 +34,19 @@ ifeq ($(NETSURF_GTK_MAJOR),2)
GTKDEPFLAGS += -DGTK_DISABLE_DEPRECATED
endif
+# C library API control
+ifeq ($(HOST),FreeBSD)
+CAPIFLAGS :=
+else
+CAPIFLAGS := -D_XOPEN_SOURCE=700 \
+ -D_POSIX_C_SOURCE=200809L
+endif
GTKCFLAGS := -std=c99 -Dgtk -Dnsgtk -g \
$(GTKDEPFLAGS) \
+ $(CAPIFLAGS) \
-D_BSD_SOURCE \
-D_DEFAULT_SOURCE \
- -D_XOPEN_SOURCE=600 \
- -D_POSIX_C_SOURCE=200809L \
-D_NETBSD_SOURCE \
-DGTK_RESPATH=\"$(NETSURF_GTK_RES_PATH)\"
@@ -59,13 +67,7 @@ LDFLAGS += -lm
NSGTK_RESOURCES_DIR := $(FRONTEND_RESOURCES_DIR)
# The gtk binary target.
-ifeq ($(NETSURF_GTK_MAJOR),2)
- # gtk2 builds have no major suffix
- EXETARGET := nsgtk
-else
- # gtk3 and later builds use the major version suffix
- EXETARGET := nsgtk$(NETSURF_GTK_MAJOR)
-endif
+EXETARGET := nsgtk$(NETSURF_GTK_MAJOR)
# The filter and target for split messages
MESSAGES_FILTER=gtk
@@ -109,6 +111,7 @@ GLIB_COMPILE_RESOURCES := glib-compile-resources
CFLAGS += -DWITH_GRESOURCE
NETSURF_GRESOURCE_XML := $(NSGTK_RESOURCES_DIR)/netsurf.gresource.xml
+UI_GRESOURCE_XML := $(NSGTK_RESOURCES_DIR)/ui.gresource.xml
MESSAGES_GRESOURCE_XML := $(NSGTK_RESOURCES_DIR)/messages.gresource.xml
# generate the netsurf gresource source files
@@ -118,6 +121,13 @@ $(OBJROOT)/netsurf_gresource.c: $(NETSURF_GRESOURCE_XML) $(shell $(GLIB_COMPILE_
S_RESOURCE += $(OBJROOT)/netsurf_gresource.c
+# generate the ui gresource source files
+$(OBJROOT)/ui_gresource.c: $(UI_GRESOURCE_XML) $(shell $(GLIB_COMPILE_RESOURCES) --sourcedir $(NSGTK_RESOURCES_DIR)/gtk$(NETSURF_GTK_MAJOR) --generate-dependencies $(UI_GRESOURCE_XML))
+ $(VQ)echo "GRESORCE: $<"
+ $(Q)$(GLIB_COMPILE_RESOURCES) --generate-source --sourcedir $(NSGTK_RESOURCES_DIR)/gtk$(NETSURF_GTK_MAJOR) --target=$@ $<
+
+S_RESOURCE += $(OBJROOT)/ui_gresource.c
+
# generate the messages gresource source file
$(OBJROOT)/messages_gresource.c: $(MESSAGES_GRESOURCE_XML) $(addsuffix /Messages,$(addprefix $(MESSAGES_TARGET)/,$(MESSAGES_LANGUAGES)))
$(VQ)echo "GRESORCE: $<"
@@ -164,12 +174,12 @@ endif
# ----------------------------------------------------------------------------
# S_FRONTEND are sources purely for the GTK frontend
-S_FRONTEND := gui.c schedule.c layout_pango.c bitmap.c plotters.c \
- scaffolding.c gdk.c completion.c login.c throbber.c accelerator.c \
- selection.c window.c fetch.c download.c menu.c print.c \
- search.c tabs.c toolbar.c gettext.c compat.c viewdata.c \
- viewsource.c preferences.c about.c resources.c corewindow.c \
- local_history.c global_history.c cookies.c hotlist.c ssl_cert.c
+S_FRONTEND := gui.c misc.c schedule.c layout_pango.c bitmap.c plotters.c \
+ scaffolding.c gdk.c completion.c throbber.c accelerator.c \
+ selection.c window.c fetch.c download.c menu.c print.c \
+ search.c tabs.c toolbar.c gettext.c compat.c viewdata.c \
+ viewsource.c preferences.c about.c resources.c corewindow.c \
+ local_history.c global_history.c cookies.c hotlist.c page_info.c
# This is the final source build list
# Note this is deliberately *not* expanded here as common and image
@@ -183,16 +193,15 @@ SOURCES = $(S_COMMON) $(S_IMAGE) $(S_BROWSER) $(S_RESOURCE) $(S_FRONTEND)
GTK_RESOURCES_LIST := \
languages SearchEngines ca-bundle.txt \
default.css adblock.css quirks.css internal.css \
- credits.html licence.html welcome.html maps.html Messages \
- default.ico favicon.png netsurf.png netsurf.xpm netsurf-16x16.xpm \
- arrow_down_8x32.png
+ credits.html licence.html welcome.html Messages \
+ default.ico favicon.png netsurf.png netsurf.xpm netsurf-16x16.xpm
GTK_RESOURCES_LIST := \
$(addprefix $(NSGTK_RESOURCES_DIR)/, $(GTK_RESOURCES_LIST)) \
- $(wildcard $(NSGTK_RESOURCES_DIR)/*.gtk$(NETSURF_GTK_MAJOR).ui)
+ $(wildcard $(NSGTK_RESOURCES_DIR)/gtk$(NETSURF_GTK_MAJOR)/*.ui)
# translations with more than just Messages files
-GTK_TRANSLATIONS_HTML := de en fr it ja nl
+GTK_TRANSLATIONS_HTML := de en fr it ja nl zh_CN
# destination for installed resources is the first entry in the gtk resource path
NSGTK_RESOURCES_DESTDIR := $(DESTDIR)$(word 1,$(subst :, ,$(NETSURF_GTK_RES_PATH)))
diff --git a/frontends/gtk/Makefile.tools b/frontends/gtk/Makefile.tools
new file mode 100644
index 000000000..5331dcc71
--- /dev/null
+++ b/frontends/gtk/Makefile.tools
@@ -0,0 +1,16 @@
+# -*- mode: makefile-gmake -*-
+##
+## tool setup for the gtk target
+##
+
+# use native package config
+PKG_CONFIG := pkg-config
+
+# gtk target processing
+ifeq ($(SUBTARGET),3)
+ override NETSURF_GTK_MAJOR := 3
+endif
+
+ifeq ($(SUBTARGET),2)
+ override NETSURF_GTK_MAJOR := 2
+endif
diff --git a/frontends/gtk/bitmap.c b/frontends/gtk/bitmap.c
index 36b614cf9..a995a9e28 100644
--- a/frontends/gtk/bitmap.c
+++ b/frontends/gtk/bitmap.c
@@ -45,22 +45,25 @@
* Create a bitmap.
*
* \param width width of image in pixels
- * \param height width of image in pixels
- * \param state a flag word indicating the initial state
+ * \param height height of image in pixels
+ * \param flags flags for bitmap creation
* \return an opaque struct bitmap, or NULL on memory exhaustion
*/
-static void *bitmap_create(int width, int height, unsigned int state)
+static void *bitmap_create(int width, int height, enum gui_bitmap_flags flags)
{
struct bitmap *gbitmap;
+ if (width == 0 || height == 0) {
+ return NULL;
+ }
+
gbitmap = calloc(1, sizeof(struct bitmap));
if (gbitmap != NULL) {
- if ((state & BITMAP_OPAQUE) != 0) {
- gbitmap->surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, width, height);
- } else {
- gbitmap->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+ if (flags & BITMAP_OPAQUE) {
+ gbitmap->opaque = true;
}
+ gbitmap->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
if (cairo_surface_status(gbitmap->surface) != CAIRO_STATUS_SUCCESS) {
cairo_surface_destroy(gbitmap->surface);
free(gbitmap);
@@ -81,76 +84,8 @@ static void *bitmap_create(int width, int height, unsigned int state)
static void bitmap_set_opaque(void *vbitmap, bool opaque)
{
struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- cairo_format_t fmt;
- cairo_surface_t *nsurface = NULL;
-
- assert(gbitmap);
-
- fmt = cairo_image_surface_get_format(gbitmap->surface);
- if (fmt == CAIRO_FORMAT_RGB24) {
- if (opaque == false) {
- /* opaque to transparent */
- nsurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- cairo_image_surface_get_width(gbitmap->surface),
- cairo_image_surface_get_height(gbitmap->surface));
-
- }
-
- } else {
- if (opaque == true) {
- /* transparent to opaque */
- nsurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
- cairo_image_surface_get_width(gbitmap->surface),
- cairo_image_surface_get_height(gbitmap->surface));
-
- }
- }
-
- if (nsurface != NULL) {
- if (cairo_surface_status(nsurface) != CAIRO_STATUS_SUCCESS) {
- cairo_surface_destroy(nsurface);
- } else {
- memcpy(cairo_image_surface_get_data(nsurface),
- cairo_image_surface_get_data(gbitmap->surface),
- cairo_image_surface_get_stride(gbitmap->surface) * cairo_image_surface_get_height(gbitmap->surface));
- cairo_surface_destroy(gbitmap->surface);
- gbitmap->surface = nsurface;
-
- cairo_surface_mark_dirty(gbitmap->surface);
-
- }
-
- }
-}
-
-
-/**
- * Tests whether a bitmap has an opaque alpha channel
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \return whether the bitmap is opaque
- */
-static bool bitmap_test_opaque(void *vbitmap)
-{
- struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- unsigned char *pixels;
- int pcount;
- int ploop;
-
- assert(gbitmap);
-
- pixels = cairo_image_surface_get_data(gbitmap->surface);
-
- pcount = cairo_image_surface_get_stride(gbitmap->surface) *
- cairo_image_surface_get_height(gbitmap->surface);
-
- for (ploop = 3; ploop < pcount; ploop += 4) {
- if (pixels[ploop] != 0xff) {
- return false;
- }
- }
- return true;
+ gbitmap->opaque = opaque;
}
@@ -162,16 +97,8 @@ static bool bitmap_test_opaque(void *vbitmap)
static bool bitmap_get_opaque(void *vbitmap)
{
struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- cairo_format_t fmt;
- assert(gbitmap);
-
- fmt = cairo_image_surface_get_format(gbitmap->surface);
- if (fmt == CAIRO_FORMAT_RGB24) {
- return true;
- }
-
- return false;
+ return gbitmap->opaque;
}
@@ -187,83 +114,13 @@ static bool bitmap_get_opaque(void *vbitmap)
static unsigned char *bitmap_get_buffer(void *vbitmap)
{
struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- int pixel_loop;
- int pixel_count;
uint8_t *pixels;
- uint32_t t, r, g, b;
- cairo_format_t fmt;
assert(gbitmap);
cairo_surface_flush(gbitmap->surface);
pixels = cairo_image_surface_get_data(gbitmap->surface);
- if (!gbitmap->converted)
- return pixels;
-
- fmt = cairo_image_surface_get_format(gbitmap->surface);
- pixel_count = cairo_image_surface_get_width(gbitmap->surface) *
- cairo_image_surface_get_height(gbitmap->surface);
-
- if (fmt == CAIRO_FORMAT_RGB24) {
- /* Opaque image */
- for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) {
- /* Cairo surface is ARGB, written in native endian */
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- b = pixels[4 * pixel_loop + 0];
- g = pixels[4 * pixel_loop + 1];
- r = pixels[4 * pixel_loop + 2];
- t = pixels[4 * pixel_loop + 3];
-#else
- t = pixels[4 * pixel_loop + 0];
- r = pixels[4 * pixel_loop + 1];
- g = pixels[4 * pixel_loop + 2];
- b = pixels[4 * pixel_loop + 3];
-#endif
-
- /* Core bitmaps always have a component order of rgba,
- * regardless of system endianness */
- pixels[4 * pixel_loop + 0] = r;
- pixels[4 * pixel_loop + 1] = g;
- pixels[4 * pixel_loop + 2] = b;
- pixels[4 * pixel_loop + 3] = t;
- }
- } else {
- /* Alpha image: de-multiply alpha */
- for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) {
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- b = pixels[4 * pixel_loop + 0];
- g = pixels[4 * pixel_loop + 1];
- r = pixels[4 * pixel_loop + 2];
- t = pixels[4 * pixel_loop + 3];
-#else
- t = pixels[4 * pixel_loop + 0];
- r = pixels[4 * pixel_loop + 1];
- g = pixels[4 * pixel_loop + 2];
- b = pixels[4 * pixel_loop + 3];
-#endif
-
- if (t != 0) {
- r = (r << 8) / t;
- g = (g << 8) / t;
- b = (b << 8) / t;
-
- r = (r > 255) ? 255 : r;
- g = (g > 255) ? 255 : g;
- b = (b > 255) ? 255 : b;
- } else {
- r = g = b = 0;
- }
-
- pixels[4 * pixel_loop + 0] = r;
- pixels[4 * pixel_loop + 1] = g;
- pixels[4 * pixel_loop + 2] = b;
- pixels[4 * pixel_loop + 3] = t;
- }
- }
-
- gbitmap->converted = false;
-
return (unsigned char *) pixels;
}
@@ -284,22 +141,6 @@ static size_t bitmap_get_rowstride(void *vbitmap)
/**
- * Find the bytes per pixel of a bitmap
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \return bytes per pixel
- */
-static size_t bitmap_get_bpp(void *vbitmap)
-{
- struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- assert(gbitmap);
-
- return 4;
-}
-
-
-
-/**
* Free a bitmap.
*
* \param vbitmap a bitmap, as returned by bitmap_create()
@@ -320,23 +161,6 @@ static void bitmap_destroy(void *vbitmap)
/**
- * Save a bitmap in the platform's native format.
- *
- * \param vbitmap a bitmap, as returned by bitmap_create()
- * \param path pathname for file
- * \param flags modify the behaviour of the save
- * \return true on success, false on error and error reported
- */
-static bool bitmap_save(void *vbitmap, const char *path, unsigned flags)
-{
- struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- assert(gbitmap);
-
- return false;
-}
-
-
-/**
* The bitmap image has changed, so flush any persistant cache.
*
* \param vbitmap a bitmap, as returned by bitmap_create()
@@ -344,81 +168,10 @@ static bool bitmap_save(void *vbitmap, const char *path, unsigned flags)
static void bitmap_modified(void *vbitmap)
{
struct bitmap *gbitmap = (struct bitmap *)vbitmap;
- int pixel_loop;
- int pixel_count;
- uint8_t *pixels;
- uint32_t t, r, g, b;
- cairo_format_t fmt;
assert(gbitmap);
- fmt = cairo_image_surface_get_format(gbitmap->surface);
-
- pixel_count = cairo_image_surface_get_width(gbitmap->surface) *
- cairo_image_surface_get_height(gbitmap->surface);
- pixels = cairo_image_surface_get_data(gbitmap->surface);
-
- if (gbitmap->converted) {
- cairo_surface_mark_dirty(gbitmap->surface);
- return;
- }
-
- if (fmt == CAIRO_FORMAT_RGB24) {
- /* Opaque image */
- for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) {
- /* Core bitmaps always have a component order of rgba,
- * regardless of system endianness */
- r = pixels[4 * pixel_loop + 0];
- g = pixels[4 * pixel_loop + 1];
- b = pixels[4 * pixel_loop + 2];
- t = pixels[4 * pixel_loop + 3];
-
- /* Cairo surface is ARGB, written in native endian */
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- pixels[4 * pixel_loop + 0] = b;
- pixels[4 * pixel_loop + 1] = g;
- pixels[4 * pixel_loop + 2] = r;
- pixels[4 * pixel_loop + 3] = t;
-#else
- pixels[4 * pixel_loop + 0] = t;
- pixels[4 * pixel_loop + 1] = r;
- pixels[4 * pixel_loop + 2] = g;
- pixels[4 * pixel_loop + 3] = b;
-#endif
- }
- } else {
- /* Alpha image: pre-multiply alpha */
- for (pixel_loop=0; pixel_loop < pixel_count; pixel_loop++) {
- r = pixels[4 * pixel_loop + 0];
- g = pixels[4 * pixel_loop + 1];
- b = pixels[4 * pixel_loop + 2];
- t = pixels[4 * pixel_loop + 3];
-
- if (t != 0) {
- r = ((r * (t + 1)) >> 8) & 0xff;
- g = ((g * (t + 1)) >> 8) & 0xff;
- b = ((b * (t + 1)) >> 8) & 0xff;
- } else {
- r = g = b = 0;
- }
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
- pixels[4 * pixel_loop + 0] = b;
- pixels[4 * pixel_loop + 1] = g;
- pixels[4 * pixel_loop + 2] = r;
- pixels[4 * pixel_loop + 3] = t;
-#else
- pixels[4 * pixel_loop + 0] = t;
- pixels[4 * pixel_loop + 1] = r;
- pixels[4 * pixel_loop + 2] = g;
- pixels[4 * pixel_loop + 3] = b;
-#endif
- }
- }
-
cairo_surface_mark_dirty(gbitmap->surface);
-
- gbitmap->converted = true;
}
/* exported interface documented in gtk/bitmap.h */
@@ -478,6 +231,10 @@ bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
* aspect ratio of the required thumbnail. */
cheight = ((cwidth * dheight) + (dwidth / 2)) / dwidth;
+ /* At this point, we MUST have decided to render something non-zero sized */
+ assert(cwidth > 0);
+ assert(cheight > 0);
+
/* Create surface to render into */
surface = cairo_surface_create_similar(dsurface, CAIRO_CONTENT_COLOR_ALPHA, cwidth, cheight);
@@ -526,13 +283,10 @@ static struct gui_bitmap_table bitmap_table = {
.destroy = bitmap_destroy,
.set_opaque = bitmap_set_opaque,
.get_opaque = bitmap_get_opaque,
- .test_opaque = bitmap_test_opaque,
.get_buffer = bitmap_get_buffer,
.get_rowstride = bitmap_get_rowstride,
.get_width = nsgtk_bitmap_get_width,
.get_height = nsgtk_bitmap_get_height,
- .get_bpp = bitmap_get_bpp,
- .save = bitmap_save,
.modified = bitmap_modified,
.render = bitmap_render,
};
diff --git a/frontends/gtk/bitmap.h b/frontends/gtk/bitmap.h
index 0f46d19a8..80a0e7a3a 100644
--- a/frontends/gtk/bitmap.h
+++ b/frontends/gtk/bitmap.h
@@ -26,7 +26,7 @@ extern struct gui_bitmap_table *nsgtk_bitmap_table;
struct bitmap {
cairo_surface_t *surface; /* original cairo surface */
cairo_surface_t *scsurface; /* scaled surface */
- bool converted; /** set if the surface data has been converted */
+ bool opaque;
};
int nsgtk_bitmap_get_width(void *vbitmap);
diff --git a/frontends/gtk/compat.c b/frontends/gtk/compat.c
index 4c5524b0e..bd3f46ee5 100644
--- a/frontends/gtk/compat.c
+++ b/frontends/gtk/compat.c
@@ -170,18 +170,18 @@ void nsgtk_entry_set_icon_from_pixbuf(GtkWidget *entry,
/* exported interface documented in gtk/compat.h */
-void nsgtk_entry_set_icon_from_stock(GtkWidget *entry,
- GtkEntryIconPosition icon_pos,
- const gchar *id)
+void nsgtk_entry_set_icon_from_icon_name(GtkWidget *entry,
+ GtkEntryIconPosition icon_pos,
+ const gchar *id)
{
#ifdef NSGTK_USE_ICON_NAME
gtk_entry_set_icon_from_icon_name(GTK_ENTRY(entry), icon_pos, id);
#else
#if GTK_CHECK_VERSION(2,16,0)
- gtk_entry_set_icon_from_stock(GTK_ENTRY(entry), icon_pos, id);
+ gtk_entry_set_icon_from_icon_name(GTK_ENTRY(entry), icon_pos, id);
#else
- GtkImage *image = GTK_IMAGE(gtk_image_new_from_stock(id,
- GTK_ICON_SIZE_LARGE_TOOLBAR));
+ GtkImage *image;
+ image = GTK_IMAGE(gtk_image_new_from_stock(id, GTK_ICON_SIZE_LARGE_TOOLBAR));
if (image != NULL) {
sexy_icon_entry_set_icon(SEXY_ICON_ENTRY(entry),
@@ -216,6 +216,17 @@ GtkWidget *nsgtk_button_new_from_stock(const gchar *stock_id)
}
/* exported interface documented in gtk/compat.h */
+void nsgtk_button_set_focus_on_click(GtkButton *button, gboolean focus_on_click)
+{
+#if GTK_CHECK_VERSION(3,20,0)
+ gtk_widget_set_focus_on_click(GTK_WIDGET(button), focus_on_click);
+#else
+ gtk_button_set_focus_on_click(button, focus_on_click);
+#endif
+}
+
+
+/* exported interface documented in gtk/compat.h */
gboolean nsgtk_stock_lookup(const gchar *stock_id, GtkStockItem *item)
{
#ifdef NSGTK_USE_ICON_NAME
@@ -234,12 +245,17 @@ void nsgtk_widget_override_background_color(GtkWidget *widget,
uint16_t b)
{
#if GTK_CHECK_VERSION(3,0,0)
+#if GTK_CHECK_VERSION(3,16,0)
+ /* do nothing - deprecated - must use css styling */
+ return;
+#else
GdkRGBA colour;
colour.alpha = (double)a / 0xffff;
colour.red = (double)r / 0xffff;
colour.green = (double)g / 0xffff;
colour.blue = (double)b / 0xffff;
gtk_widget_override_background_color(widget, state, &colour);
+#endif
#else
GdkColor colour;
colour.pixel = a;
@@ -403,15 +419,25 @@ GtkWidget *nsgtk_dialog_get_content_area(GtkDialog *dialog)
#endif
}
+#if GTK_CHECK_VERSION(3,22,0)
+#include "gtk/scaffolding.h"
+#endif
+
gboolean nsgtk_show_uri(GdkScreen *screen,
const gchar *uri,
guint32 timestamp,
GError **error)
{
#if GTK_CHECK_VERSION(2,14,0)
+#if GTK_CHECK_VERSION(3,22,0)
+ GtkWindow *parent;
+ parent = nsgtk_scaffolding_window(nsgtk_current_scaffolding());
+ return gtk_show_uri_on_window(parent, uri, timestamp,error);
+#else
return gtk_show_uri(screen, uri, timestamp, error);
+#endif
#else
- return FALSE; /* FIXME */
+ return FALSE; /** \todo add uri opening for before gtk 2.14 */
#endif
}
@@ -532,6 +558,17 @@ void nsgtk_image_menu_item_set_image(GtkWidget *image_menu_item, GtkWidget *imag
}
/* exported interface documented in gtk/compat.h */
+void nsgtk_menu_popup_at_pointer(GtkMenu *menu, const GdkEvent *trigger_event)
+{
+#if GTK_CHECK_VERSION(3,22,0)
+ gtk_menu_popup_at_pointer(menu, trigger_event);
+#else
+ gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0,
+ gtk_get_current_event_time());
+#endif
+}
+
+/* exported interface documented in gtk/compat.h */
gboolean nsgtk_icon_size_lookup_for_settings(GtkSettings *settings,
GtkIconSize size,
gint *width,
@@ -598,7 +635,9 @@ void nsgtk_widget_set_margins(GtkWidget *widget, gint hmargin, gint vmargin)
gtk_widget_set_margin_top(widget, vmargin);
gtk_widget_set_margin_bottom(widget, vmargin);
#else
- gtk_misc_set_padding(GTK_MISC(widget), hmargin, vmargin);
+ if (GTK_IS_MISC(widget)) {
+ gtk_misc_set_padding(GTK_MISC(widget), hmargin, vmargin);
+ }
#endif
}
diff --git a/frontends/gtk/compat.h b/frontends/gtk/compat.h
index 9554b0cba..3b2f55094 100644
--- a/frontends/gtk/compat.h
+++ b/frontends/gtk/compat.h
@@ -16,7 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
+/**
+ * \file
* Compatibility functions for older GTK versions (interface)
*/
@@ -40,9 +41,6 @@
#define NSGTK_STOCK_CANCEL "_Cancel"
#define NSGTK_STOCK_CLEAR "edit-clear"
#define NSGTK_STOCK_CLOSE "window-close"
-#define NSGTK_STOCK_FIND "edit-find"
-#define NSGTK_STOCK_GO_BACK "go-previous"
-#define NSGTK_STOCK_GO_FORWARD "go-next"
#define NSGTK_STOCK_HOME "go-home"
#define NSGTK_STOCK_INFO "dialog-information"
#define NSGTK_STOCK_REFRESH "view-refresh"
@@ -51,14 +49,12 @@
#define NSGTK_STOCK_STOP "process-stop"
#define NSGTK_STOCK_OK "_OK"
#define NSGTK_STOCK_OPEN "_Open"
+#define NSGTK_STOCK_OPEN_MENU "open-menu"
#else
#define NSGTK_STOCK_ADD GTK_STOCK_ADD
#define NSGTK_STOCK_CANCEL GTK_STOCK_CANCEL
#define NSGTK_STOCK_CLEAR GTK_STOCK_CLEAR
#define NSGTK_STOCK_CLOSE GTK_STOCK_CLOSE
-#define NSGTK_STOCK_FIND GTK_STOCK_FIND
-#define NSGTK_STOCK_GO_BACK GTK_STOCK_GO_BACK
-#define NSGTK_STOCK_GO_FORWARD GTK_STOCK_GO_FORWARD
#define NSGTK_STOCK_HOME GTK_STOCK_HOME
#define NSGTK_STOCK_INFO GTK_STOCK_INFO
#define NSGTK_STOCK_REFRESH GTK_STOCK_REFRESH
@@ -67,6 +63,7 @@
#define NSGTK_STOCK_STOP GTK_STOCK_STOP
#define NSGTK_STOCK_OK GTK_STOCK_OK
#define NSGTK_STOCK_OPEN GTK_STOCK_OPEN
+#define NSGTK_STOCK_OPEN_MENU GTK_STOCK_JUSTIFY_FILL
#endif
/* widget alignment only available since 3.0 */
@@ -80,6 +77,12 @@ typedef enum {
} GtkAlign;
#endif
+/* value init since gtk 2.30 */
+#ifndef G_VALUE_INIT
+#define G_VALUE_INIT { 0, { { 0 } } }
+#endif
+
+
/**
* Set the alignment of a widget.
*
@@ -153,6 +156,9 @@ GtkStateType nsgtk_widget_get_state(GtkWidget *widget);
typedef GtkStateType GtkStateFlags;
typedef GtkStyle GtkStyleContext;
+/* gtk 3 changed the enum name for the state flags */
+#define GTK_STATE_FLAG_NORMAL GTK_STATE_NORMAL
+
#if GTK_CHECK_VERSION(2,22,0)
enum {
GTK_IN_DESTRUCTION = 1 << 0,
@@ -167,16 +173,16 @@ enum {
/**
- * Sets the icon shown in the entry at the specified position from a
- * stock image.
+ * Sets the icon shown in the entry at the specified position from an
+ * icon name.
*
- * Compatability interface for original deprecated in GTK 3.10
+ * Compatability interface for original introduced in 2.16
*
* \param entry The entry widget to set the icon on.
* \param icon_pos The position of the icon.
* \param stock_id the name of the stock item.
*/
-void nsgtk_entry_set_icon_from_stock(GtkWidget *entry, GtkEntryIconPosition icon_pos, const gchar *stock_id);
+void nsgtk_entry_set_icon_from_icon_name(GtkWidget *entry, GtkEntryIconPosition icon_pos, const gchar *stock_id);
/**
* Creates a GtkImage displaying a stock icon.
@@ -209,6 +215,16 @@ GtkWidget *nsgtk_button_new_from_stock(const gchar *stock_id);
*/
gboolean nsgtk_stock_lookup(const gchar *stock_id, GtkStockItem *item);
+/**
+ * Sets whether the button will grab focus when it is clicked with the mouse.
+ *
+ * Compatability interface for original deprecated in GTK 3.20
+ *
+ * \param button The button alter
+ * \param focus_on_click whether the button grabs focus when clicked with the mouse
+ */
+void nsgtk_button_set_focus_on_click(GtkButton *button, gboolean focus_on_click);
+
void nsgtk_window_set_opacity(GtkWindow *window, gdouble opacity);
void nsgtk_scrolled_window_add_with_viewport(GtkScrolledWindow *window, GtkWidget *child);
@@ -268,6 +284,15 @@ GtkWidget *nsgtk_image_menu_item_new_with_mnemonic(const gchar *label);
*/
void nsgtk_image_menu_item_set_image(GtkWidget *image_menu_item, GtkWidget *image);
+/**
+ * Displays menu and makes it available for selection
+ *
+ * Compatability interface for gtk_menu_popup deprecated in GTK 3.22.
+ *
+ * \param image_menu_item The image menu entry item.
+ * \param trigger_event the GdkEvent that initiated this request or NULL if it's the current event.
+ */
+void nsgtk_menu_popup_at_pointer(GtkMenu *menu, const GdkEvent *trigger_event);
/**
* Parses a resource file containing a GtkBuilder UI definition and
diff --git a/frontends/gtk/completion.c b/frontends/gtk/completion.c
index eea0a789f..585a9e511 100644
--- a/frontends/gtk/completion.c
+++ b/frontends/gtk/completion.c
@@ -21,7 +21,7 @@
* Implementation of url entry completion.
*/
-#include <gtk/gtk.h>
+#include <stdlib.h>
#include "utils/log.h"
#include "utils/messages.h"
@@ -31,13 +31,27 @@
#include "netsurf/browser_window.h"
#include "desktop/searchweb.h"
+#include "gtk/compat.h"
#include "gtk/warn.h"
#include "gtk/scaffolding.h"
+#include "gtk/toolbar_items.h"
#include "gtk/window.h"
#include "gtk/completion.h"
GtkListStore *nsgtk_completion_list;
+struct nsgtk_completion_ctx {
+ /**
+ * callback to obtain a browser window for navigation
+ */
+ struct browser_window *(*get_bw)(void *ctx);
+
+ /**
+ * context passed to get_bw function
+ */
+ void *get_bw_ctx;
+};
+
/**
* completion row matcher
*/
@@ -51,7 +65,6 @@ static gboolean nsgtk_completion_match(GtkEntryCompletion *completion,
* are in the list should be shown.
*/
return TRUE;
-
}
@@ -78,14 +91,17 @@ static gboolean
nsgtk_completion_match_select(GtkEntryCompletion *widget,
GtkTreeModel *model,
GtkTreeIter *iter,
- gpointer user_data)
+ gpointer data)
{
- GValue value = {0, };
- struct nsgtk_scaffolding *g = user_data;
- struct browser_window *bw = nsgtk_get_browser_window(nsgtk_scaffolding_top_level(g));
+ struct nsgtk_completion_ctx *cb_ctx;
+ GValue value = G_VALUE_INIT;
+ struct browser_window *bw;
nserror ret;
nsurl *url;
+ cb_ctx = data;
+ bw = cb_ctx->get_bw(cb_ctx->get_bw_ctx);
+
gtk_tree_model_get_value(model, iter, 0, &value);
ret = search_web_omni(g_value_get_string(&value),
@@ -128,11 +144,20 @@ gboolean nsgtk_completion_update(GtkEntry *entry)
}
/* exported interface documented in completion.h */
-GtkEntryCompletion *nsgtk_url_entry_completion_new(struct nsgtk_scaffolding *gs)
+nserror
+nsgtk_completion_connect_signals(GtkEntry *entry,
+ struct browser_window *(*get_bw)(void *ctx),
+ void *get_bw_ctx)
{
GtkEntryCompletion *completion;
+ struct nsgtk_completion_ctx *cb_ctx;
+
+ cb_ctx = calloc(1, sizeof(struct nsgtk_completion_ctx));
+ cb_ctx->get_bw = get_bw;
+ cb_ctx->get_bw_ctx = get_bw_ctx;
+
+ completion = gtk_entry_get_completion(entry);
- completion = gtk_entry_completion_new();
gtk_entry_completion_set_match_func(completion,
nsgtk_completion_match, NULL, NULL);
@@ -147,13 +172,15 @@ GtkEntryCompletion *nsgtk_url_entry_completion_new(struct nsgtk_scaffolding *gs)
gtk_entry_completion_set_popup_completion(completion, TRUE);
/* when selected callback */
- g_signal_connect(G_OBJECT(completion), "match-selected",
- G_CALLBACK(nsgtk_completion_match_select), gs);
+ g_signal_connect(G_OBJECT(completion),
+ "match-selected",
+ G_CALLBACK(nsgtk_completion_match_select),
+ cb_ctx);
g_object_set(G_OBJECT(completion),
- "popup-set-width", TRUE,
- "popup-single-match", TRUE,
- NULL);
+ "popup-set-width", TRUE,
+ "popup-single-match", TRUE,
+ NULL);
- return completion;
+ return NSERROR_OK;
}
diff --git a/frontends/gtk/completion.h b/frontends/gtk/completion.h
index 9a1db293d..a81f1301a 100644
--- a/frontends/gtk/completion.h
+++ b/frontends/gtk/completion.h
@@ -37,10 +37,11 @@ void nsgtk_completion_init(void);
gboolean nsgtk_completion_update(GtkEntry *entry);
/**
- * create a new entry completion on a scaffold.
- *
- * \param gs The scaffoliding which the url entry is in.
+ * connect signals on entry completion
*/
-GtkEntryCompletion *nsgtk_url_entry_completion_new(struct nsgtk_scaffolding *gs);
+nserror
+nsgtk_completion_connect_signals(GtkEntry *entry,
+ struct browser_window *(*get_bw)(void *ctx),
+ void *get_bw_ctx);
#endif
diff --git a/frontends/gtk/cookies.c b/frontends/gtk/cookies.c
index 1f7833cca..0df9719cb 100644
--- a/frontends/gtk/cookies.c
+++ b/frontends/gtk/cookies.c
@@ -98,6 +98,8 @@ MENUHANDLER(delete_selected)
MENUHANDLER(delete_all)
{
+ cookie_manager_keypress(NS_KEY_ESCAPE);
+ cookie_manager_keypress(NS_KEY_ESCAPE);
cookie_manager_keypress(NS_KEY_SELECT_ALL);
cookie_manager_keypress(NS_KEY_DELETE_LEFT);
return TRUE;
@@ -105,6 +107,8 @@ MENUHANDLER(delete_all)
MENUHANDLER(select_all)
{
+ cookie_manager_keypress(NS_KEY_ESCAPE);
+ cookie_manager_keypress(NS_KEY_ESCAPE);
cookie_manager_keypress(NS_KEY_SELECT_ALL);
return TRUE;
}
@@ -305,13 +309,14 @@ static nserror nsgtk_cookies_init(void)
/* exported function documented gtk/cookies.h */
-nserror nsgtk_cookies_present(void)
+nserror nsgtk_cookies_present(const char *search_term)
{
nserror res;
res = nsgtk_cookies_init();
if (res == NSERROR_OK) {
gtk_window_present(cookie_window->wnd);
+ res = cookie_manager_set_search_string(search_term);
}
return res;
}
diff --git a/frontends/gtk/cookies.h b/frontends/gtk/cookies.h
index c1a68b7f9..b8fc9aba2 100644
--- a/frontends/gtk/cookies.h
+++ b/frontends/gtk/cookies.h
@@ -28,7 +28,7 @@
*
* \return NSERROR_OK on success else appropriate error code on faliure.
*/
-nserror nsgtk_cookies_present(void);
+nserror nsgtk_cookies_present(const char *search_term);
/**
* Free any resources allocated for the cookie window.
diff --git a/frontends/gtk/corewindow.c b/frontends/gtk/corewindow.c
index 6ca5d228f..baa4cf155 100644
--- a/frontends/gtk/corewindow.c
+++ b/frontends/gtk/corewindow.c
@@ -87,6 +87,7 @@ static browser_mouse_state nsgtk_cw_gdkbutton_to_nsstate(GdkEventButton *event)
}
if (event->state & GDK_MOD1_MASK) {
+ /* usually alt */
ms |= BROWSER_MOUSE_MOD_3;
}
@@ -224,6 +225,10 @@ nsgtk_cw_motion_notify_event(GtkWidget *widget,
struct nsgtk_corewindow_mouse *mouse = &nsgtk_cw->mouse_state;
if (mouse->pressed == false) {
+ nsgtk_cw->mouse(nsgtk_cw,
+ BROWSER_MOUSE_HOVER,
+ event->x,
+ event->y);
return TRUE;
}
@@ -304,7 +309,7 @@ nsgtk_cw_motion_notify_event(GtkWidget *widget,
*/
static nserror nsgtk_cw_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
{
- double value;
+ double value = 0;
GtkAdjustment *vscroll;
GtkAdjustment *hscroll;
GtkAdjustment *scroll = NULL;
@@ -588,13 +593,15 @@ nsgtk_cw_invalidate_area(struct core_window *cw, const struct rect *rect)
* \param width New widget width.
* \param height New widget height.
*/
-static void
+static nserror
nsgtk_cw_update_size(struct core_window *cw, int width, int height)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
gtk_widget_set_size_request(GTK_WIDGET(nsgtk_cw->drawing_area),
width, height);
+
+ return NSERROR_OK;
}
@@ -604,30 +611,56 @@ nsgtk_cw_update_size(struct core_window *cw, int width, int height)
* \param cw core window handle.
* \param r rectangle that needs scrolling.
*/
-static void
-nsgtk_cw_scroll_visible(struct core_window *cw, const struct rect *r)
+static nserror
+nsgtk_cw_set_scroll(struct core_window *cw, int x, int y)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
- int y = 0, height = 0, y0, y1;
- gdouble page;
- GtkAdjustment *vadj;
- vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
+ if (nsgtk_cw->scrolled != NULL) {
+ GtkAdjustment *vadj;
+ GtkAdjustment *hadj;
+
+ vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
+ hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
+
+ assert(vadj != NULL);
+ assert(hadj != NULL);
+
+ gtk_adjustment_set_value(vadj, y);
+ gtk_adjustment_set_value(hadj, x);
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * scroll window core window callback
+ *
+ * \param cw core window handle.
+ * \param r rectangle that needs scrolling.
+ */
+static nserror
+nsgtk_cw_get_scroll(const struct core_window *cw, int *x, int *y)
+{
+ struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
- assert(vadj);
+ if (nsgtk_cw->scrolled != NULL) {
+ GtkAdjustment *vadj;
+ GtkAdjustment *hadj;
- g_object_get(vadj, "page-size", &page, NULL);
+ vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
+ hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
- y0 = (int)(gtk_adjustment_get_value(vadj));
- y1 = y0 + page;
+ assert(vadj != NULL);
+ assert(hadj != NULL);
- if ((y >= y0) && (y + height <= y1))
- return;
- if (y + height > y1)
- y0 = y0 + (y + height - y1);
- if (y < y0)
- y0 = y;
- gtk_adjustment_set_value(vadj, y0);
+ *y = (int)(gtk_adjustment_get_value(vadj));
+ *x = (int)(gtk_adjustment_get_value(hadj));
+ } else {
+ *x = 0;
+ *y = 0;
+ }
+ return NSERROR_OK;
}
@@ -638,21 +671,31 @@ nsgtk_cw_scroll_visible(struct core_window *cw, const struct rect *r)
* \param[out] width to be set to viewport width in px
* \param[out] height to be set to viewport height in px
*/
-static void
-nsgtk_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
+static nserror
+nsgtk_cw_get_window_dimensions(const struct core_window *cw,
+ int *width, int *height)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
- GtkAdjustment *vadj;
- GtkAdjustment *hadj;
- gdouble page;
-
- hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
- g_object_get(hadj, "page-size", &page, NULL);
- *width = page;
-
- vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
- g_object_get(vadj, "page-size", &page, NULL);
- *height = page;
+ if (nsgtk_cw->scrolled != NULL) {
+ GtkAdjustment *vadj;
+ GtkAdjustment *hadj;
+ gdouble page;
+
+ hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
+ g_object_get(hadj, "page-size", &page, NULL);
+ *width = page;
+
+ vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
+ g_object_get(vadj, "page-size", &page, NULL);
+ *height = page;
+ } else {
+ GtkAllocation allocation;
+ gtk_widget_get_allocation(GTK_WIDGET(nsgtk_cw->drawing_area),
+ &allocation);
+ *width = allocation.width;
+ *height = allocation.height;
+ }
+ return NSERROR_OK;
}
@@ -662,11 +705,13 @@ nsgtk_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
* \param cw core window handle.
* \param ds The new drag status.
*/
-static void
+static nserror
nsgtk_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
nsgtk_cw->drag_status = ds;
+
+ return NSERROR_OK;
}
@@ -676,7 +721,8 @@ nsgtk_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
static struct core_window_callback_table nsgtk_cw_cb_table = {
.invalidate = nsgtk_cw_invalidate_area,
.update_size = nsgtk_cw_update_size,
- .scroll_visible = nsgtk_cw_scroll_visible,
+ .set_scroll = nsgtk_cw_set_scroll,
+ .get_scroll = nsgtk_cw_get_scroll,
.get_window_dimensions = nsgtk_cw_get_window_dimensions,
.drag_status = nsgtk_cw_drag_status
};
@@ -730,7 +776,7 @@ nserror nsgtk_corewindow_init(struct nsgtk_corewindow *nsgtk_cw)
nsgtk_widget_override_background_color(
GTK_WIDGET(nsgtk_cw->drawing_area),
- GTK_STATE_NORMAL,
+ GTK_STATE_FLAG_NORMAL,
0, 0xffff, 0xffff, 0xffff);
return NSERROR_OK;
diff --git a/frontends/gtk/download.c b/frontends/gtk/download.c
index d11036ea8..d1231634d 100644
--- a/frontends/gtk/download.c
+++ b/frontends/gtk/download.c
@@ -34,6 +34,7 @@
#include "gtk/warn.h"
#include "gtk/scaffolding.h"
+#include "gtk/toolbar_items.h"
#include "gtk/window.h"
#include "gtk/compat.h"
#include "gtk/resources.h"
@@ -64,12 +65,23 @@ typedef enum {
} nsgtk_download_status;
typedef enum {
- NSGTK_DOWNLOAD_PAUSE = 1 << 0,
+ NSGTK_DOWNLOAD_PAUSE = 1 << 0,
NSGTK_DOWNLOAD_RESUME = 1 << 1,
- NSGTK_DOWNLOAD_CANCEL = 1 << 2,
- NSGTK_DOWNLOAD_CLEAR = 1 << 3
+ NSGTK_DOWNLOAD_CANCEL = 1 << 2,
+ NSGTK_DOWNLOAD_CLEAR = 1 << 3
} nsgtk_download_actions;
+static const gchar* status_messages[] = {
+ NULL,
+ "gtkWorking",
+ "gtkError",
+ "gtkComplete",
+ "gtkCanceled"
+};
+
+/**
+ * context for each download.
+ */
struct gui_download_window {
struct download_context *ctx;
nsgtk_download_actions sensitivity;
@@ -77,8 +89,8 @@ struct gui_download_window {
GString *name;
GString *time_left;
- gint size_total;
- gint size_downloaded;
+ unsigned long long int size_total;
+ unsigned long long int size_downloaded;
gint progress;
gfloat time_remaining;
gfloat start_time;
@@ -89,26 +101,37 @@ struct gui_download_window {
GError *error;
};
-typedef void (*nsgtk_download_selection_action)(struct gui_download_window *dl);
+typedef void (*nsgtk_download_selection_action)(struct gui_download_window *dl,
+ void *user_data);
-static GtkWindow *nsgtk_download_window, *nsgtk_download_parent;
-static GtkProgressBar *nsgtk_download_progress_bar;
+/**
+ * context for a nsgtk download window.
+ */
+struct download_window_ctx {
+ GtkWindow *window;
+ GtkWindow *parent;
+
+ GtkProgressBar *progress;
+
+ GtkTreeView *tree;
+ GtkListStore *store;
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
-static GtkTreeView *nsgtk_download_tree;
-static GtkListStore *nsgtk_download_store;
-static GtkTreeSelection *nsgtk_download_selection;
-static GtkTreeIter nsgtk_download_iter;
+ GTimer *timer;
+ GList *list;
+ GtkButton *pause;
+ GtkButton *clear;
+ GtkButton *cancel;
+ GtkButton *resume;
-static GTimer *nsgtk_downloads_timer;
-static GList *nsgtk_downloads_list;
-static GtkButton *nsgtk_download_button_pause;
-static GtkButton *nsgtk_download_button_clear;
-static GtkButton *nsgtk_download_button_cancel;
-static GtkButton *nsgtk_download_button_resume;
-static gint nsgtk_downloads_num_active;
-static const gchar* status_messages[] = { NULL, "gtkWorking", "gtkError",
- "gtkComplete", "gtkCanceled" };
+ gint num_active;
+};
+/**
+ * global instance of the download window
+ */
+static struct download_window_ctx dl_ctx;
static GtkTreeView* nsgtk_download_tree_view_new(GtkBuilder *gladeFile)
@@ -116,40 +139,66 @@ static GtkTreeView* nsgtk_download_tree_view_new(GtkBuilder *gladeFile)
GtkTreeView *treeview;
GtkCellRenderer *renderer;
- treeview = GTK_TREE_VIEW(gtk_builder_get_object(gladeFile, "treeDownloads"));
+ treeview = GTK_TREE_VIEW(gtk_builder_get_object(gladeFile,
+ "treeDownloads"));
/* Progress column */
renderer = gtk_cell_renderer_progress_new();
- gtk_tree_view_insert_column_with_attributes (treeview, -1,
- messages_get("gtkProgress"), renderer, "value",
- NSGTK_DOWNLOAD_PROGRESS, "pulse", NSGTK_DOWNLOAD_PULSE,
- "text", NSGTK_DOWNLOAD_STATUS, NULL);
+ gtk_tree_view_insert_column_with_attributes(treeview,
+ -1,
+ messages_get("gtkProgress"),
+ renderer,
+ "value",
+ NSGTK_DOWNLOAD_PROGRESS,
+ "pulse",
+ NSGTK_DOWNLOAD_PULSE,
+ "text",
+ NSGTK_DOWNLOAD_STATUS,
+ NULL);
/* Information column */
renderer = gtk_cell_renderer_text_new();
- g_object_set(G_OBJECT(renderer), "wrap-mode", PANGO_WRAP_WORD_CHAR,
- "wrap-width", 300, NULL);
- gtk_tree_view_insert_column_with_attributes (treeview, -1,
- messages_get("gtkDetails"), renderer, "text",
- NSGTK_DOWNLOAD_INFO, NULL);
- gtk_tree_view_column_set_expand(gtk_tree_view_get_column(treeview,
- NSGTK_DOWNLOAD_INFO), TRUE);
+ g_object_set(G_OBJECT(renderer),
+ "wrap-mode",
+ PANGO_WRAP_WORD_CHAR,
+ "wrap-width",
+ 300,
+ NULL);
+ gtk_tree_view_insert_column_with_attributes(treeview,
+ -1,
+ messages_get("gtkDetails"),
+ renderer,
+ "text",
+ NSGTK_DOWNLOAD_INFO,
+ NULL);
+ gtk_tree_view_column_set_expand(
+ gtk_tree_view_get_column(treeview,
+ NSGTK_DOWNLOAD_INFO), TRUE);
/* Time remaining column */
renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes (treeview, -1,
- messages_get("gtkRemaining"), renderer, "text",
- NSGTK_DOWNLOAD_REMAINING, NULL);
+ gtk_tree_view_insert_column_with_attributes(treeview,
+ -1,
+ messages_get("gtkRemaining"),
+ renderer,
+ "text",
+ NSGTK_DOWNLOAD_REMAINING,
+ NULL);
/* Speed column */
renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_insert_column_with_attributes (treeview, -1,
- messages_get("gtkSpeed"), renderer, "text",
- NSGTK_DOWNLOAD_SPEED, NULL);
+ gtk_tree_view_insert_column_with_attributes(treeview,
+ -1,
+ messages_get("gtkSpeed"),
+ renderer,
+ "text",
+ NSGTK_DOWNLOAD_SPEED,
+ NULL);
return treeview;
}
+
static gint
nsgtk_download_sort(GtkTreeModel *model,
GtkTreeIter *a,
@@ -164,43 +213,52 @@ nsgtk_download_sort(GtkTreeModel *model,
return dl1->status - dl2->status;
}
+
static void
nsgtk_download_sensitivity_update_buttons(nsgtk_download_actions sensitivity)
{
/* Glade seems to pack the buttons in an arbitrary order */
enum { PAUSE_BUTTON, CLEAR_BUTTON, CANCEL_BUTTON, RESUME_BUTTON };
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_download_button_pause),
+ gtk_widget_set_sensitive(GTK_WIDGET(dl_ctx.pause),
sensitivity & NSGTK_DOWNLOAD_PAUSE);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_download_button_clear),
+ gtk_widget_set_sensitive(GTK_WIDGET(dl_ctx.clear),
sensitivity & NSGTK_DOWNLOAD_CLEAR);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_download_button_cancel),
+ gtk_widget_set_sensitive(GTK_WIDGET(dl_ctx.cancel),
sensitivity & NSGTK_DOWNLOAD_CANCEL);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_download_button_resume),
+ gtk_widget_set_sensitive(GTK_WIDGET(dl_ctx.resume),
sensitivity & NSGTK_DOWNLOAD_RESUME);
}
+
static void nsgtk_download_sensitivity_evaluate(GtkTreeSelection *selection)
{
GtkTreeIter iter;
GList *rows;
- gboolean selected = gtk_tree_selection_count_selected_rows(selection);
- GtkTreeModel *model = GTK_TREE_MODEL(nsgtk_download_store);
+ gboolean selected;
+ GtkTreeModel *model;
nsgtk_download_actions sensitivity = 0;
struct gui_download_window *dl;
+ model = GTK_TREE_MODEL(dl_ctx.store);
+
+ selected = gtk_tree_selection_count_selected_rows(selection);
if (selected) {
rows = gtk_tree_selection_get_selected_rows(selection, &model);
while (rows != NULL) {
- gtk_tree_model_get_iter(model, &iter,
+ gtk_tree_model_get_iter(model,
+ &iter,
(GtkTreePath*)rows->data);
- gtk_tree_model_get(model, &iter, NSGTK_DOWNLOAD,
- &dl, -1);
+ gtk_tree_model_get(model,
+ &iter,
+ NSGTK_DOWNLOAD,
+ &dl,
+ -1);
sensitivity |= dl->sensitivity;
rows = rows->next;
}
} else {
- rows = nsgtk_downloads_list;
+ rows = dl_ctx.list;
while (rows != NULL) {
dl = rows->data;
sensitivity |= (dl->sensitivity & NSGTK_DOWNLOAD_CLEAR);
@@ -208,83 +266,121 @@ static void nsgtk_download_sensitivity_evaluate(GtkTreeSelection *selection)
}
}
-
nsgtk_download_sensitivity_update_buttons(sensitivity);
}
+
+/**
+ * Wrapper to GFunc-ify gtk_tree_path_free for g_list_foreach.
+ */
+static void
+nsgtk_download_gfunc__gtk_tree_path_free(gpointer data, gpointer user_data)
+{
+ gtk_tree_path_free(data);
+}
+
+
+/**
+ * Wrapper to GFunc-ify g_free for g_list_foreach.
+ */
+static void
+nsgtk_download_gfunc__g_free(gpointer data, gpointer user_data)
+{
+ g_free(data);
+}
+
+
static void nsgtk_download_do(nsgtk_download_selection_action action)
{
GList *rows, *dls = NULL;
- GtkTreeModel *model = GTK_TREE_MODEL(nsgtk_download_store);
- gboolean selection_exists = gtk_tree_selection_count_selected_rows(
- nsgtk_download_selection);
+ GtkTreeModel *model;
+
+ if (gtk_tree_selection_count_selected_rows(dl_ctx.selection)) {
+ model = GTK_TREE_MODEL(dl_ctx.store);
- if (selection_exists) {
- rows = gtk_tree_selection_get_selected_rows(
- nsgtk_download_selection, &model);
+ rows = gtk_tree_selection_get_selected_rows(dl_ctx.selection,
+ &model);
while (rows != NULL) {
struct gui_download_window *dl;
- gtk_tree_model_get_iter(GTK_TREE_MODEL(
- nsgtk_download_store),
- &nsgtk_download_iter,
+
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter,
(GtkTreePath*)rows->data);
- gtk_tree_model_get(GTK_TREE_MODEL(nsgtk_download_store),
- &nsgtk_download_iter, NSGTK_DOWNLOAD,
- &dl, -1);
+
+ gtk_tree_model_get(GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter,
+ NSGTK_DOWNLOAD,
+ &dl,
+ -1);
+
dls = g_list_prepend(dls, dl);
rows = rows->next;
}
- g_list_foreach(rows, (GFunc)gtk_tree_path_free, NULL);
- g_list_foreach(rows, (GFunc)g_free, NULL);
+ g_list_foreach(rows,
+ nsgtk_download_gfunc__gtk_tree_path_free,
+ NULL);
+ g_list_foreach(rows,
+ nsgtk_download_gfunc__g_free,
+ NULL);
g_list_free(rows);
- } else
- dls = g_list_copy(nsgtk_downloads_list);
+ } else {
+ dls = g_list_copy(dl_ctx.list);
+ }
g_list_foreach(dls, (GFunc)action, NULL);
g_list_free(dls);
}
+
static gchar* nsgtk_download_info_to_string(struct gui_download_window *dl)
{
- gchar *size_info = g_strdup_printf(messages_get("gtkSizeInfo"),
- human_friendly_bytesize(dl->size_downloaded),
- dl->size_total == 0 ? messages_get("gtkUnknownSize") :
- human_friendly_bytesize(dl->size_total));
-
+ gchar *size_info;
gchar *r;
- if (dl->status != NSGTK_DOWNLOAD_ERROR)
+ size_info = g_strdup_printf(messages_get("gtkSizeInfo"),
+ human_friendly_bytesize(dl->size_downloaded),
+ dl->size_total == 0 ?
+ messages_get("gtkUnknownSize") :
+ human_friendly_bytesize(dl->size_total));
+
+ if (dl->status != NSGTK_DOWNLOAD_ERROR) {
r = g_strdup_printf("%s\n%s", dl->name->str, size_info);
- else
- r = g_strdup_printf("%s\n%s", dl->name->str,
- dl->error->message);
+ } else {
+ r = g_strdup_printf("%s\n%s", dl->name->str, dl->error->message);
+ }
g_free(size_info);
return r;
}
+
static gchar* nsgtk_download_time_to_string(gint seconds)
{
gint hours, minutes;
- if (seconds < 0)
+ if (seconds < 0) {
return g_strdup("-");
+ }
hours = seconds / 3600;
seconds -= hours * 3600;
minutes = seconds / 60;
seconds -= minutes * 60;
- if (hours > 0)
- return g_strdup_printf("%u:%02u:%02u", hours, minutes,
+ if (hours > 0) {
+ return g_strdup_printf("%u:%02u:%02u",
+ hours,
+ minutes,
seconds);
- else
+ } else {
return g_strdup_printf("%u:%02u", minutes, seconds);
+ }
}
-static void nsgtk_download_store_update_item (struct gui_download_window *dl)
+
+static void nsgtk_download_store_update_item(struct gui_download_window *dl)
{
gchar *info = nsgtk_download_info_to_string(dl);
char *human = human_friendly_bytesize(dl->speed);
@@ -294,11 +390,11 @@ static void nsgtk_download_store_update_item (struct gui_download_window *dl)
gboolean pulse = dl->status == NSGTK_DOWNLOAD_WORKING;
/* Updates iter (which is needed to set and get data) with the dl row */
- gtk_tree_model_get_iter(GTK_TREE_MODEL(nsgtk_download_store),
- &nsgtk_download_iter,
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter,
gtk_tree_row_reference_get_path(dl->row));
- gtk_list_store_set(nsgtk_download_store, &nsgtk_download_iter,
+ gtk_list_store_set(dl_ctx.store, &dl_ctx.iter,
NSGTK_DOWNLOAD_PULSE, pulse ? dl->progress : -1,
NSGTK_DOWNLOAD_PROGRESS, pulse ? 0 : dl->progress,
NSGTK_DOWNLOAD_INFO, info,
@@ -311,27 +407,32 @@ static void nsgtk_download_store_update_item (struct gui_download_window *dl)
g_free(time);
}
+
static gboolean nsgtk_download_update(gboolean force_update)
{
/* Be sure we need to update */
- if (!nsgtk_widget_get_visible(GTK_WIDGET(nsgtk_download_window)))
+ if (!nsgtk_widget_get_visible(GTK_WIDGET(dl_ctx.window))) {
return TRUE;
+ }
GList *list;
gchar *text;
gboolean update, pulse_mode = FALSE;
- gint downloaded = 0, total = 0, dls = 0;
- gfloat percent, elapsed = g_timer_elapsed(nsgtk_downloads_timer, NULL);
- nsgtk_downloads_num_active = 0;
+ unsigned long long int downloaded = 0;
+ unsigned long long int total = 0;
+ gint dls = 0;
+ gfloat percent, elapsed = g_timer_elapsed(dl_ctx.timer, NULL);
- for (list = nsgtk_downloads_list; list != NULL; list = list->next) {
+ dl_ctx.num_active = 0;
+
+ for (list = dl_ctx.list; list != NULL; list = list->next) {
struct gui_download_window *dl = list->data;
update = force_update;
switch (dl->status) {
case NSGTK_DOWNLOAD_WORKING:
pulse_mode = TRUE;
- /* Fall through */
+ fallthrough;
case NSGTK_DOWNLOAD_NONE:
dl->speed = dl->size_downloaded /
@@ -340,77 +441,86 @@ static gboolean nsgtk_download_update(gboolean force_update)
dl->time_remaining = (dl->size_total -
dl->size_downloaded)/
dl->speed;
- dl->progress = (gfloat)
- dl->size_downloaded /
- dl->size_total * 100;
- } else
+ dl->progress = (double)dl->size_downloaded /
+ (double)dl->size_total * 100;
+ } else {
dl->progress++;
+ }
- nsgtk_downloads_num_active++;
+ dl_ctx.num_active++;
update = TRUE;
- /* Fall through */
+ fallthrough;
case NSGTK_DOWNLOAD_COMPLETE:
downloaded += dl->size_downloaded;
total += dl->size_total;
dls++;
+ fallthrough;
default:
;//Do nothing
}
- if (update)
+ if (update) {
nsgtk_download_store_update_item(dl);
+ }
}
if (pulse_mode) {
text = g_strdup_printf(
- messages_get(nsgtk_downloads_num_active > 1 ?
+ messages_get(dl_ctx.num_active > 1 ?
"gtkProgressBarPulse" :
"gtkProgressBarPulseSingle"),
- nsgtk_downloads_num_active);
- gtk_progress_bar_pulse(nsgtk_download_progress_bar);
- gtk_progress_bar_set_text(nsgtk_download_progress_bar, text);
+ dl_ctx.num_active);
+ gtk_progress_bar_pulse(dl_ctx.progress);
+ gtk_progress_bar_set_text(dl_ctx.progress, text);
} else {
- percent = total != 0 ? (gfloat)downloaded / total : 0;
+ percent = total != 0 ? (double)downloaded / (double)total : 0;
text = g_strdup_printf(messages_get("gtkProgressBar"),
- floor(percent*100), dls);
- gtk_progress_bar_set_fraction(nsgtk_download_progress_bar,
+ floor(percent * 100), dls);
+ gtk_progress_bar_set_fraction(dl_ctx.progress,
percent);
- gtk_progress_bar_set_text(nsgtk_download_progress_bar, text);
+ gtk_progress_bar_set_text(dl_ctx.progress, text);
}
g_free(text);
- if (nsgtk_downloads_num_active == 0)
+ if (dl_ctx.num_active == 0) {
return FALSE; /* Returning FALSE here cancels the g_timeout */
- else
+ } else {
return TRUE;
+ }
}
-static void nsgtk_download_store_clear_item(struct gui_download_window *dl)
+
+static void
+nsgtk_download_store_clear_item(struct gui_download_window *dl, void *user_data)
{
if (dl->sensitivity & NSGTK_DOWNLOAD_CLEAR) {
- nsgtk_downloads_list = g_list_remove(nsgtk_downloads_list, dl);
+ dl_ctx.list = g_list_remove(dl_ctx.list, dl);
- gtk_tree_model_get_iter(GTK_TREE_MODEL(nsgtk_download_store),
- &nsgtk_download_iter,
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter,
gtk_tree_row_reference_get_path(dl->row));
- gtk_list_store_remove(nsgtk_download_store,
- &nsgtk_download_iter);
+ gtk_list_store_remove(dl_ctx.store,
+ &dl_ctx.iter);
download_context_destroy(dl->ctx);
g_string_free(dl->name, TRUE);
g_string_free(dl->time_left, TRUE);
g_free(dl);
- nsgtk_download_sensitivity_evaluate(nsgtk_download_selection);
+ nsgtk_download_sensitivity_evaluate(dl_ctx.selection);
nsgtk_download_update(FALSE);
}
}
-static void nsgtk_download_tree_view_row_activated(GtkTreeView *tree,
- GtkTreePath *path, GtkTreeViewColumn *column, gpointer data)
+
+static void
+nsgtk_download_tree_view_row_activated(GtkTreeView *tree,
+ GtkTreePath *path,
+ GtkTreeViewColumn *column,
+ gpointer data)
{
GtkTreeModel *model;
GtkTreeIter iter;
@@ -423,29 +533,36 @@ static void nsgtk_download_tree_view_row_activated(GtkTreeView *tree,
}
}
-static void nsgtk_download_change_sensitivity(struct gui_download_window *dl,
- nsgtk_download_actions sensitivity)
+
+static void
+nsgtk_download_change_sensitivity(struct gui_download_window *dl,
+ nsgtk_download_actions sensitivity)
{
dl->sensitivity = sensitivity;
- nsgtk_download_sensitivity_evaluate(nsgtk_download_selection);
+ nsgtk_download_sensitivity_evaluate(dl_ctx.selection);
}
-static void nsgtk_download_change_status (
- struct gui_download_window *dl, nsgtk_download_status status)
+
+static void
+nsgtk_download_change_status(struct gui_download_window *dl,
+ nsgtk_download_status status)
{
dl->status = status;
if (status != NSGTK_DOWNLOAD_NONE) {
- gtk_tree_model_get_iter(GTK_TREE_MODEL(nsgtk_download_store),
- &nsgtk_download_iter,
+ gtk_tree_model_get_iter(GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter,
gtk_tree_row_reference_get_path(dl->row));
- gtk_list_store_set(nsgtk_download_store, &nsgtk_download_iter,
+ gtk_list_store_set(dl_ctx.store, &dl_ctx.iter,
NSGTK_DOWNLOAD_STATUS,
messages_get(status_messages[status]), -1);
}
}
-static void nsgtk_download_store_cancel_item (struct gui_download_window *dl)
+
+static void
+nsgtk_download_store_cancel_item(struct gui_download_window *dl,
+ void *user_data)
{
if (dl->sensitivity & NSGTK_DOWNLOAD_CANCEL) {
dl->speed = 0;
@@ -463,148 +580,49 @@ static void nsgtk_download_store_cancel_item (struct gui_download_window *dl)
}
}
+
static gboolean nsgtk_download_hide(GtkWidget *window)
{
gtk_widget_hide(window);
return TRUE;
}
-/* exported interface documented in gtk/download.h */
-nserror nsgtk_download_init(void)
-{
- GtkBuilder* builder;
- nserror res;
-
- res = nsgtk_builder_new_from_resname("downloads", &builder);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Download UI builder init failed");
- return res;
- }
-
- gtk_builder_connect_signals(builder, NULL);
-
- nsgtk_download_button_pause = GTK_BUTTON(gtk_builder_get_object(builder, "buttonPause"));
- nsgtk_download_button_clear = GTK_BUTTON(gtk_builder_get_object(builder, "buttonClear"));
- nsgtk_download_button_cancel = GTK_BUTTON(gtk_builder_get_object(builder, "buttonCancel"));
- nsgtk_download_button_resume = GTK_BUTTON(gtk_builder_get_object(builder, "buttonPlay"));
-
- nsgtk_download_progress_bar = GTK_PROGRESS_BAR(gtk_builder_get_object(builder, "progressBar"));
- nsgtk_download_window = GTK_WINDOW(gtk_builder_get_object(builder, "wndDownloads"));
- nsgtk_download_parent = NULL;
-
- gtk_window_set_transient_for(GTK_WINDOW(nsgtk_download_window),
- nsgtk_download_parent);
- gtk_window_set_destroy_with_parent(GTK_WINDOW(nsgtk_download_window),
- FALSE);
-
- nsgtk_downloads_timer = g_timer_new();
-
- nsgtk_download_tree = nsgtk_download_tree_view_new(builder);
-
- nsgtk_download_store = gtk_list_store_new(NSGTK_DOWNLOAD_N_COLUMNS,
- G_TYPE_INT, /* % complete */
- G_TYPE_STRING, /* Description */
- G_TYPE_STRING, /* Time remaining */
- G_TYPE_STRING, /* Speed */
- G_TYPE_INT, /* Pulse */
- G_TYPE_STRING, /* Status */
- G_TYPE_POINTER /* Download structure */
- );
-
-
- gtk_tree_view_set_model(nsgtk_download_tree,
- GTK_TREE_MODEL(nsgtk_download_store));
-
- gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(nsgtk_download_store),
- NSGTK_DOWNLOAD_STATUS,
- (GtkTreeIterCompareFunc) nsgtk_download_sort, NULL, NULL);
- gtk_tree_sortable_set_sort_column_id(
- GTK_TREE_SORTABLE(nsgtk_download_store),
- NSGTK_DOWNLOAD_STATUS, GTK_SORT_ASCENDING);
-
- g_object_unref(nsgtk_download_store);
-
- nsgtk_download_selection =
- gtk_tree_view_get_selection(nsgtk_download_tree);
- gtk_tree_selection_set_mode(nsgtk_download_selection,
- GTK_SELECTION_MULTIPLE);
-
- g_signal_connect(G_OBJECT(nsgtk_download_selection), "changed",
- G_CALLBACK(nsgtk_download_sensitivity_evaluate), NULL);
- g_signal_connect(nsgtk_download_tree, "row-activated",
- G_CALLBACK(nsgtk_download_tree_view_row_activated),
- NULL);
- g_signal_connect_swapped(gtk_builder_get_object(builder, "buttonClear"),
- "clicked",
- G_CALLBACK(nsgtk_download_do),
- nsgtk_download_store_clear_item);
- g_signal_connect_swapped(gtk_builder_get_object(builder, "buttonCancel"),
- "clicked",
- G_CALLBACK(nsgtk_download_do),
- nsgtk_download_store_cancel_item);
- g_signal_connect(G_OBJECT(nsgtk_download_window), "delete-event",
- G_CALLBACK(nsgtk_download_hide), NULL);
-
- return NSERROR_OK;
-}
-
-void nsgtk_download_destroy ()
-{
- nsgtk_download_do(nsgtk_download_store_cancel_item);
-}
-
-bool nsgtk_check_for_downloads (GtkWindow *parent)
-{
- if (nsgtk_downloads_num_active != 0) {
- GtkWidget *dialog;
- dialog = gtk_message_dialog_new_with_markup(parent,
- GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING,
- GTK_BUTTONS_NONE,
- "<big><b>%s</b></big>\n\n"
- "<small>%s</small>", messages_get("gtkQuit"),
- messages_get("gtkDownloadsRunning"));
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), "gtk-cancel",
- GTK_RESPONSE_CANCEL, "gtk-quit",
- GTK_RESPONSE_CLOSE, NULL);
-
- gint response = gtk_dialog_run(GTK_DIALOG(dialog));
- gtk_widget_destroy(dialog);
-
- if (response == GTK_RESPONSE_CANCEL)
- return true;
- }
-
- return false;
-}
-
-void nsgtk_download_show(GtkWindow *parent)
-{
- gtk_window_set_transient_for(nsgtk_download_window,
- nsgtk_download_parent);
- gtk_window_present(nsgtk_download_window);
-}
-static gchar* nsgtk_download_dialog_show (const gchar *filename, const gchar *domain,
- const gchar *size)
+/**
+ * Prompt user for downloaded file name
+ *
+ * \param filename The original name of the file
+ * \param domain the domain the file is being downloaded from
+ * \param size The size of the file being downloaded
+ */
+static gchar*
+nsgtk_download_dialog_show(const gchar *filename,
+ const gchar *domain,
+ const gchar *size)
{
enum { GTK_RESPONSE_DOWNLOAD, GTK_RESPONSE_SAVE_AS };
GtkWidget *dialog;
char *destination = NULL;
- gchar *message = g_strdup(messages_get("gtkStartDownload"));
- gchar *info = g_strdup_printf(messages_get("gtkInfo"), filename,
- domain, size);
-
- dialog = gtk_message_dialog_new_with_markup(nsgtk_download_parent,
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
- "<span size=\"x-large\" weight=\"ultrabold\">%s</span>"
- "\n\n<small>%s</small>",
- message, info);
-
- gtk_dialog_add_buttons(GTK_DIALOG(dialog), NSGTK_STOCK_SAVE,
- GTK_RESPONSE_DOWNLOAD, NSGTK_STOCK_CANCEL,
- GTK_RESPONSE_CANCEL, NSGTK_STOCK_SAVE_AS,
- GTK_RESPONSE_SAVE_AS, NULL);
+ gchar *message;
+ gchar *info;
+
+ message = g_strdup(messages_get("gtkStartDownload"));
+ info = g_strdup_printf(messages_get("gtkInfo"), filename, domain, size);
+
+ dialog = gtk_message_dialog_new_with_markup(
+ dl_ctx.parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
+ "<span size=\"x-large\" weight=\"ultrabold\">%s</span>"
+ "\n\n<small>%s</small>",
+ message,
+ info);
+
+ gtk_dialog_add_buttons(GTK_DIALOG(dialog),
+ NSGTK_STOCK_SAVE, GTK_RESPONSE_DOWNLOAD,
+ NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NSGTK_STOCK_SAVE_AS, GTK_RESPONSE_SAVE_AS,
+ NULL);
gint result = gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
@@ -613,13 +631,13 @@ static gchar* nsgtk_download_dialog_show (const gchar *filename, const gchar *do
switch (result) {
case GTK_RESPONSE_SAVE_AS: {
- dialog = gtk_file_chooser_dialog_new
- (messages_get("gtkSave"),
- nsgtk_download_parent,
- GTK_FILE_CHOOSER_ACTION_SAVE,
- NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NSGTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
+ dialog = gtk_file_chooser_dialog_new(
+ messages_get("gtkSave"),
+ dl_ctx.parent,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NSGTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+ NULL);
gtk_file_chooser_set_current_name
(GTK_FILE_CHOOSER(dialog), filename);
gtk_file_chooser_set_current_folder
@@ -649,30 +667,32 @@ static gchar* nsgtk_download_dialog_show (const gchar *filename, const gchar *do
* confirmation if needed */
if (g_file_test(destination, G_FILE_TEST_EXISTS) &&
nsoption_bool(request_overwrite)) {
- message = g_strdup_printf(messages_get(
- "gtkOverwrite"), filename);
- info = g_strdup_printf(messages_get(
- "gtkOverwriteInfo"),
+ GtkWidget *button;
+
+ message = g_strdup_printf(messages_get("gtkOverwrite"),
+ filename);
+ info = g_strdup_printf(messages_get("gtkOverwriteInfo"),
nsoption_charp(downloads_directory));
dialog = gtk_message_dialog_new_with_markup(
- nsgtk_download_parent,
- GTK_DIALOG_DESTROY_WITH_PARENT,
- GTK_MESSAGE_QUESTION,
- GTK_BUTTONS_CANCEL,
- "<b>%s</b>",message);
+ dl_ctx.parent,
+ GTK_DIALOG_DESTROY_WITH_PARENT,
+ GTK_MESSAGE_QUESTION,
+ GTK_BUTTONS_CANCEL,
+ "<b>%s</b>",
+ message);
gtk_message_dialog_format_secondary_markup(
- GTK_MESSAGE_DIALOG(dialog),
- "%s", info);
+ GTK_MESSAGE_DIALOG(dialog),
+ "%s",
+ info);
- GtkWidget *button = gtk_dialog_add_button(
- GTK_DIALOG(dialog),
- "_Replace",
- GTK_RESPONSE_DOWNLOAD);
+ button = gtk_dialog_add_button(GTK_DIALOG(dialog),
+ "_Replace",
+ GTK_RESPONSE_DOWNLOAD);
gtk_button_set_image(GTK_BUTTON(button),
nsgtk_image_new_from_stock(
- NSGTK_STOCK_SAVE,
- GTK_ICON_SIZE_BUTTON));
+ NSGTK_STOCK_SAVE,
+ GTK_ICON_SIZE_BUTTON));
gint result = gtk_dialog_run(GTK_DIALOG(dialog));
if (result == GTK_RESPONSE_CANCEL)
@@ -689,20 +709,24 @@ static gchar* nsgtk_download_dialog_show (const gchar *filename, const gchar *do
}
-static gboolean nsgtk_download_handle_error (GError *error)
+static gboolean nsgtk_download_handle_error(GError *error)
{
+ GtkWidget*dialog;
+ gchar *message;
+
if (error != NULL) {
- GtkWidget*dialog;
- gchar *message = g_strdup_printf(messages_get("gtkFileError"),
- error->message);
-
- dialog = gtk_message_dialog_new_with_markup
- (nsgtk_download_parent,
- GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR,
- GTK_BUTTONS_OK,
- "<big><b>%s</b></big>\n\n"
- "<small>%s</small>", messages_get("gtkFailed"),
- message);
+ message = g_strdup_printf(messages_get("gtkFileError"),
+ error->message);
+
+ dialog = gtk_message_dialog_new_with_markup(
+ dl_ctx.parent,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_ERROR,
+ GTK_BUTTONS_OK,
+ "<big><b>%s</b></big>\n\n"
+ "<small>%s</small>",
+ messages_get("gtkFailed"),
+ message);
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
@@ -711,30 +735,53 @@ static gboolean nsgtk_download_handle_error (GError *error)
return FALSE;
}
-static void nsgtk_download_store_create_item (struct gui_download_window *dl)
+
+static void nsgtk_download_store_create_item(struct gui_download_window *dl)
{
nsgtk_download_store_update_item(dl);
/* The iter has already been updated to this row */
- gtk_list_store_set(nsgtk_download_store, &nsgtk_download_iter,
- NSGTK_DOWNLOAD, dl, -1);
+ gtk_list_store_set(dl_ctx.store,
+ &dl_ctx.iter,
+ NSGTK_DOWNLOAD,
+ dl,
+ -1);
}
+
+/**
+ * Wrapper to GSourceFunc-ify nsgtk_download_update.
+ */
+static gboolean
+nsgtk_download_gsourcefunc__nsgtk_download_update(gpointer user_data)
+{
+ return nsgtk_download_update(FALSE);
+}
+
+
+/**
+ * core callback on creating a new download
+ */
static struct gui_download_window *
gui_download_window_create(download_context *ctx, struct gui_window *gui)
{
- nsurl *url = download_context_get_url(ctx);
- unsigned long total_size = download_context_get_total_length(ctx);
+ nsurl *url;
+ unsigned long long int total_size;
gchar *domain;
gchar *destination;
- gboolean unknown_size = total_size == 0;
- const char *size = (total_size == 0 ?
- messages_get("gtkUnknownSize") :
- human_friendly_bytesize(total_size));
+ gboolean unknown_size;
+ struct gui_download_window *download;
+ const char *size;
+
+ url = download_context_get_url(ctx);
+ total_size = download_context_get_total_length(ctx);
+ unknown_size = total_size == 0;
+ size = (total_size == 0 ?
+ messages_get("gtkUnknownSize") :
+ human_friendly_bytesize(total_size));
- nsgtk_download_parent =
- nsgtk_scaffolding_window(nsgtk_get_scaffold(gui));
+ dl_ctx.parent = nsgtk_scaffolding_window(nsgtk_get_scaffold(gui));
- struct gui_download_window *download = malloc(sizeof *download);
+ download = malloc(sizeof *download);
if (download == NULL) {
return NULL;
}
@@ -761,12 +808,12 @@ gui_download_window_create(download_context *ctx, struct gui_window *gui)
/* Add the new row and store the reference to it (which keeps track of
* the tree changes) */
- gtk_list_store_prepend(nsgtk_download_store, &nsgtk_download_iter);
+ gtk_list_store_prepend(dl_ctx.store, &dl_ctx.iter);
download->row = gtk_tree_row_reference_new(
- GTK_TREE_MODEL(nsgtk_download_store),
- gtk_tree_model_get_path(
- GTK_TREE_MODEL(nsgtk_download_store),
- &nsgtk_download_iter));
+ GTK_TREE_MODEL(dl_ctx.store),
+ gtk_tree_model_get_path(
+ GTK_TREE_MODEL(dl_ctx.store),
+ &dl_ctx.iter));
download->ctx = ctx;
download->name = g_string_new(download_context_get_filename(ctx));
@@ -774,13 +821,14 @@ gui_download_window_create(download_context *ctx, struct gui_window *gui)
download->size_total = total_size;
download->size_downloaded = 0;
download->speed = 0;
- download->start_time = g_timer_elapsed(nsgtk_downloads_timer, NULL);
+ download->start_time = g_timer_elapsed(dl_ctx.timer, NULL);
download->time_remaining = -1;
download->status = NSGTK_DOWNLOAD_NONE;
download->progress = 0;
download->error = NULL;
- download->write =
- g_io_channel_new_file(destination, "w", &download->error);
+ download->write = g_io_channel_new_file(destination,
+ "w",
+ &download->error);
if (nsgtk_download_handle_error(download->error)) {
g_string_free(download->name, TRUE);
@@ -793,24 +841,32 @@ gui_download_window_create(download_context *ctx, struct gui_window *gui)
nsgtk_download_change_sensitivity(download, NSGTK_DOWNLOAD_CANCEL);
nsgtk_download_store_create_item(download);
- nsgtk_download_show(nsgtk_download_parent);
+ nsgtk_download_show(dl_ctx.parent);
- if (unknown_size)
+ if (unknown_size) {
nsgtk_download_change_status(download, NSGTK_DOWNLOAD_WORKING);
+ }
- if (nsgtk_downloads_num_active == 0) {
- g_timeout_add(UPDATE_RATE,
- (GSourceFunc) nsgtk_download_update, FALSE);
+ if (dl_ctx.num_active == 0) {
+ g_timeout_add(
+ UPDATE_RATE,
+ nsgtk_download_gsourcefunc__nsgtk_download_update,
+ NULL);
}
- nsgtk_downloads_list = g_list_prepend(nsgtk_downloads_list, download);
+ dl_ctx.list = g_list_prepend(dl_ctx.list, download);
return download;
}
-static nserror gui_download_window_data(struct gui_download_window *dw,
- const char *data, unsigned int size)
+/**
+ * core callback on receipt of data
+ */
+static nserror
+gui_download_window_data(struct gui_download_window *dw,
+ const char *data,
+ unsigned int size)
{
g_io_channel_write_chars(dw->write, data, size, NULL, &dw->error);
if (dw->error != NULL) {
@@ -822,7 +878,7 @@ static nserror gui_download_window_data(struct gui_download_window *dw,
nsgtk_download_update(TRUE);
- gtk_window_present(nsgtk_download_window);
+ gtk_window_present(dl_ctx.window);
return NSERROR_SAVE_FAILED;
}
@@ -832,12 +888,18 @@ static nserror gui_download_window_data(struct gui_download_window *dw,
}
-static void gui_download_window_error(struct gui_download_window *dw,
- const char *error_msg)
+/**
+ * core callback on error
+ */
+static void
+gui_download_window_error(struct gui_download_window *dw, const char *error_msg)
{
}
+/**
+ * core callback when core download is complete
+ */
static void gui_download_window_done(struct gui_download_window *dw)
{
g_io_channel_shutdown(dw->write, TRUE, &dw->error);
@@ -850,10 +912,11 @@ static void gui_download_window_done(struct gui_download_window *dw)
nsgtk_download_change_sensitivity(dw, NSGTK_DOWNLOAD_CLEAR);
nsgtk_download_change_status(dw, NSGTK_DOWNLOAD_COMPLETE);
- if (nsoption_bool(downloads_clear))
- nsgtk_download_store_clear_item(dw);
- else
+ if (nsoption_bool(downloads_clear)) {
+ nsgtk_download_store_clear_item(dw, NULL);
+ } else {
nsgtk_download_update(TRUE);
+ }
}
@@ -865,3 +928,146 @@ static struct gui_download_table download_table = {
};
struct gui_download_table *nsgtk_download_table = &download_table;
+
+
+/* exported interface documented in gtk/download.h */
+nserror nsgtk_download_init(void)
+{
+ GtkBuilder* builder;
+ nserror res;
+
+ res = nsgtk_builder_new_from_resname("downloads", &builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Download UI builder init failed");
+ return res;
+ }
+
+ gtk_builder_connect_signals(builder, NULL);
+
+ dl_ctx.pause = GTK_BUTTON(gtk_builder_get_object(builder,
+ "buttonPause"));
+ dl_ctx.clear = GTK_BUTTON(gtk_builder_get_object(builder,
+ "buttonClear"));
+ dl_ctx.cancel = GTK_BUTTON(gtk_builder_get_object(builder,
+ "buttonCancel"));
+ dl_ctx.resume = GTK_BUTTON(gtk_builder_get_object(builder,
+ "buttonPlay"));
+
+ dl_ctx.progress = GTK_PROGRESS_BAR(gtk_builder_get_object(builder,
+ "progressBar"));
+ dl_ctx.window = GTK_WINDOW(gtk_builder_get_object(builder,
+ "wndDownloads"));
+ dl_ctx.parent = NULL;
+
+ gtk_window_set_transient_for(GTK_WINDOW(dl_ctx.window),
+ dl_ctx.parent);
+ gtk_window_set_destroy_with_parent(GTK_WINDOW(dl_ctx.window),
+ FALSE);
+
+ dl_ctx.timer = g_timer_new();
+
+ dl_ctx.tree = nsgtk_download_tree_view_new(builder);
+
+ dl_ctx.store = gtk_list_store_new(NSGTK_DOWNLOAD_N_COLUMNS,
+ G_TYPE_INT, /* % complete */
+ G_TYPE_STRING, /* Description */
+ G_TYPE_STRING, /* Time remaining */
+ G_TYPE_STRING, /* Speed */
+ G_TYPE_INT, /* Pulse */
+ G_TYPE_STRING, /* Status */
+ G_TYPE_POINTER /* Download structure */
+ );
+
+
+ gtk_tree_view_set_model(dl_ctx.tree, GTK_TREE_MODEL(dl_ctx.store));
+
+ gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(dl_ctx.store),
+ NSGTK_DOWNLOAD_STATUS,
+ (GtkTreeIterCompareFunc)nsgtk_download_sort, NULL, NULL);
+ gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(dl_ctx.store),
+ NSGTK_DOWNLOAD_STATUS,
+ GTK_SORT_ASCENDING);
+
+ g_object_unref(dl_ctx.store);
+
+ dl_ctx.selection = gtk_tree_view_get_selection(dl_ctx.tree);
+ gtk_tree_selection_set_mode(dl_ctx.selection, GTK_SELECTION_MULTIPLE);
+
+ g_signal_connect(G_OBJECT(dl_ctx.selection),
+ "changed",
+ G_CALLBACK(nsgtk_download_sensitivity_evaluate),
+ NULL);
+
+ g_signal_connect(dl_ctx.tree,
+ "row-activated",
+ G_CALLBACK(nsgtk_download_tree_view_row_activated),
+ NULL);
+
+ g_signal_connect_swapped(gtk_builder_get_object(builder, "buttonClear"),
+ "clicked",
+ G_CALLBACK(nsgtk_download_do),
+ nsgtk_download_store_clear_item);
+
+ g_signal_connect_swapped(gtk_builder_get_object(builder, "buttonCancel"),
+ "clicked",
+ G_CALLBACK(nsgtk_download_do),
+ nsgtk_download_store_cancel_item);
+
+ g_signal_connect(G_OBJECT(dl_ctx.window),
+ "delete-event",
+ G_CALLBACK(nsgtk_download_hide),
+ NULL);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in gtk/download.h */
+void nsgtk_download_destroy(void)
+{
+ nsgtk_download_do(nsgtk_download_store_cancel_item);
+}
+
+
+/* exported interface documented in gtk/download.h */
+bool nsgtk_check_for_downloads(GtkWindow *parent)
+{
+ GtkWidget *dialog;
+ gint response;
+
+ if (dl_ctx.num_active == 0) {
+ return false;
+ }
+
+ dialog = gtk_message_dialog_new_with_markup(
+ parent,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_NONE,
+ "<big><b>%s</b></big>\n\n"
+ "<small>%s</small>",
+ messages_get("gtkQuit"),
+ messages_get("gtkDownloadsRunning"));
+
+ gtk_dialog_add_buttons(GTK_DIALOG(dialog),
+ "gtk-cancel", GTK_RESPONSE_CANCEL,
+ "gtk-quit", GTK_RESPONSE_CLOSE,
+ NULL);
+
+ response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_widget_destroy(dialog);
+
+ if (response == GTK_RESPONSE_CANCEL) {
+ return true;
+ }
+
+ return false;
+}
+
+
+/* exported interface documented in gtk/download.h */
+void nsgtk_download_show(GtkWindow *parent)
+{
+ gtk_window_set_transient_for(dl_ctx.window, dl_ctx.parent);
+ gtk_window_present(dl_ctx.window);
+}
diff --git a/frontends/gtk/download.h b/frontends/gtk/download.h
index 0b1097655..c6dc187e7 100644
--- a/frontends/gtk/download.h
+++ b/frontends/gtk/download.h
@@ -19,12 +19,11 @@
#ifndef GTK_DOWNLOAD_H
#define GTK_DOWNLOAD_H
-#include <gtk/gtk.h>
-
/**
* download operation table for gtk
*/
-struct gui_download_table *nsgtk_download_table;
+extern struct gui_download_table *nsgtk_download_table;
+
/**
* Initialise download window ready for use.
@@ -33,9 +32,27 @@ struct gui_download_table *nsgtk_download_table;
*/
nserror nsgtk_download_init(void);
-void nsgtk_download_destroy (void);
+
+/**
+ * Destroy download window
+ */
+void nsgtk_download_destroy(void);
+
+
+/**
+ * Check with user if download is in progress they want to complete
+ *
+ * \param parent The parent window for the prompt dialog.
+ * \return true if the user wants to continue else false.
+ */
bool nsgtk_check_for_downloads(GtkWindow *parent);
+
+
+/**
+ * Show the download window
+ *
+ * \param parent The parent window to use for the shown window
+ */
void nsgtk_download_show(GtkWindow *parent);
-void nsgtk_download_add(gchar *url, gchar *destination);
#endif
diff --git a/frontends/gtk/fetch.c b/frontends/gtk/fetch.c
index b05c1bd95..d77073a63 100644
--- a/frontends/gtk/fetch.c
+++ b/frontends/gtk/fetch.c
@@ -75,6 +75,7 @@ void gtk_fetch_filetype_init(const char *mimefile)
hash_add(mime_hash, "html", "text/html");
hash_add(mime_hash, "jpg", "image/jpeg");
hash_add(mime_hash, "jpeg", "image/jpeg");
+ hash_add(mime_hash, "jxl", "image/jxl");
hash_add(mime_hash, "gif", "image/gif");
hash_add(mime_hash, "png", "image/png");
hash_add(mime_hash, "jng", "image/jng");
@@ -117,11 +118,9 @@ void gtk_fetch_filetype_init(const char *mimefile)
type = ptr;
- /* search for the first non-whitespace char or NUL or
+ /* search for the first whitespace char or NUL or
* NL */
- while (*ptr &&
- (!ascii_is_space(*ptr)) &&
- *ptr != '\n') {
+ while (*ptr && (!ascii_is_space(*ptr))) {
ptr++;
}
@@ -146,9 +145,7 @@ void gtk_fetch_filetype_init(const char *mimefile)
/* search for the first whitespace char or
* NUL or NL which is the end of the ext.
*/
- while (*ptr &&
- (!ascii_is_space(*ptr)) &&
- *ptr != '\n') {
+ while (*ptr && (!ascii_is_space(*ptr))) {
ptr++;
}
diff --git a/frontends/gtk/fetch.h b/frontends/gtk/fetch.h
index a095adbf9..9175ccdf2 100644
--- a/frontends/gtk/fetch.h
+++ b/frontends/gtk/fetch.h
@@ -19,7 +19,7 @@
#ifndef NETSURF_GTK_FETCH_H
#define NETSURF_GTK_FETCH_H
-struct gui_fetch_table *nsgtk_fetch_table;
+extern struct gui_fetch_table *nsgtk_fetch_table;
void gtk_fetch_filetype_init(const char *mimefile);
void gtk_fetch_filetype_fin(void);
diff --git a/frontends/gtk/gdk.c b/frontends/gtk/gdk.c
index fd82af5b2..fe9a0791c 100644
--- a/frontends/gtk/gdk.c
+++ b/frontends/gtk/gdk.c
@@ -33,7 +33,8 @@ convert_alpha(guchar *dest_data,
int x, y;
for (y = 0; y < height; y++) {
- guint32 *src = (guint32 *) src_data;
+ /* this cast is safe, the buffer is appropriately aligned */
+ guint32 *src = (void *) src_data;
for (x = 0; x < width; x++) {
guint alpha = src[x] >> 24;
@@ -72,7 +73,7 @@ nsgdk_pixbuf_get_from_surface(cairo_surface_t *surface, int scwidth, int scheigh
memset(gdk_pixbuf_get_pixels(pixbuf),
0xff,
- gdk_pixbuf_get_rowstride(pixbuf) * scheight);
+ gdk_pixbuf_get_rowstride(pixbuf) * (size_t)scheight);
/* scale cairo surface into new surface the target size */
cairo_surface_flush(surface); /* ensure source surface is ready */
diff --git a/frontends/gtk/global_history.c b/frontends/gtk/global_history.c
index f204168d0..33032e567 100644
--- a/frontends/gtk/global_history.c
+++ b/frontends/gtk/global_history.c
@@ -107,6 +107,8 @@ MENUHANDLER(delete_selected)
MENUHANDLER(delete_all)
{
+ global_history_keypress(NS_KEY_ESCAPE);
+ global_history_keypress(NS_KEY_ESCAPE);
global_history_keypress(NS_KEY_SELECT_ALL);
global_history_keypress(NS_KEY_DELETE_LEFT);
return TRUE;
@@ -114,12 +116,16 @@ MENUHANDLER(delete_all)
MENUHANDLER(select_all)
{
+ global_history_keypress(NS_KEY_ESCAPE);
+ global_history_keypress(NS_KEY_ESCAPE);
global_history_keypress(NS_KEY_SELECT_ALL);
return TRUE;
}
MENUHANDLER(clear_selection)
{
+ global_history_keypress(NS_KEY_ESCAPE);
+ global_history_keypress(NS_KEY_ESCAPE);
global_history_keypress(NS_KEY_CLEAR_SELECTION);
return TRUE;
}
diff --git a/frontends/gtk/gui.c b/frontends/gtk/gui.c
index 3163be16d..661176ded 100644
--- a/frontends/gtk/gui.c
+++ b/frontends/gtk/gui.c
@@ -41,13 +41,13 @@
#include "netsurf/keypress.h"
#include "netsurf/url_db.h"
#include "netsurf/cookie_db.h"
+#include "netsurf/browser.h"
#include "netsurf/browser_window.h"
-#include "netsurf/misc.h"
#include "netsurf/netsurf.h"
+#include "netsurf/bitmap.h"
#include "content/fetch.h"
#include "content/backing_store.h"
#include "desktop/save_complete.h"
-#include "desktop/save_pdf.h"
#include "desktop/searchweb.h"
#include "desktop/hotlist.h"
@@ -62,446 +62,34 @@
#include "gtk/global_history.h"
#include "gtk/hotlist.h"
#include "gtk/throbber.h"
+#include "gtk/toolbar_items.h"
#include "gtk/scaffolding.h"
#include "gtk/window.h"
#include "gtk/schedule.h"
#include "gtk/selection.h"
#include "gtk/search.h"
-#include "gtk/ssl_cert.h"
#include "gtk/bitmap.h"
+#include "gtk/misc.h"
#include "gtk/resources.h"
-#include "gtk/login.h"
#include "gtk/layout_pango.h"
#include "gtk/accelerator.h"
bool nsgtk_complete = false;
-char *nsgtk_config_home; /* exported global defined in gtk/gui.h */
+/* exported global defined in gtk/gui.h */
+char *nsgtk_config_home;
-GdkPixbuf *favicon_pixbuf; /** favicon default pixbuf */
-GdkPixbuf *win_default_icon_pixbuf; /** default window icon pixbuf */
-GdkPixbuf *arrow_down_pixbuf; /** arrow down pixbuf */
+/** favicon default pixbuf */
+GdkPixbuf *favicon_pixbuf;
-GtkBuilder *warning_builder;
-
-char **respaths; /** resource search path vector */
-
-/**
- * Cause an abnormal program termination.
- *
- * \note This never returns and is intended to terminate without any cleanup.
- *
- * \param error The message to display to the user.
- */
-static void die(const char * const error)
-{
- fprintf(stderr, "%s", error);
- exit(EXIT_FAILURE);
-}
-
-/**
- * Create an array of valid paths to search for resources.
- *
- * The idea is that all the complex path computation to find resources
- * is performed here, once, rather than every time a resource is
- * searched for.
- */
-static char **
-nsgtk_init_resource_path(const char *config_home)
-{
- char *resource_path;
- int resource_path_len;
- const gchar * const *langv;
- char **pathv; /* resource path string vector */
- char **respath; /* resource paths vector */
-
- if (config_home != NULL) {
- resource_path_len = snprintf(NULL, 0,
- "%s:${NETSURFRES}:%s",
- config_home,
- GTK_RESPATH);
- resource_path = malloc(resource_path_len + 1);
- if (resource_path == NULL) {
- return NULL;
- }
- snprintf(resource_path, resource_path_len + 1,
- "%s:${NETSURFRES}:%s",
- config_home,
- GTK_RESPATH);
- } else {
- resource_path_len = snprintf(NULL, 0,
- "${NETSURFRES}:%s",
- GTK_RESPATH);
- resource_path = malloc(resource_path_len + 1);
- if (resource_path == NULL) {
- return NULL;
- }
- snprintf(resource_path,
- resource_path_len + 1,
- "${NETSURFRES}:%s",
- GTK_RESPATH);
- }
-
- pathv = filepath_path_to_strvec(resource_path);
-
- langv = g_get_language_names();
-
- respath = filepath_generate(pathv, langv);
-
- filepath_free_strvec(pathv);
-
- free(resource_path);
-
- return respath;
-}
-
-
-/**
- * Set option defaults for gtk frontend.
- *
- * @param defaults The option table to update.
- * @return error status.
- */
-static nserror set_defaults(struct nsoption_s *defaults)
-{
- char *fname;
-
- /* cookie file default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
- if (fname != NULL) {
- nsoption_setnull_charp(cookie_file, fname);
- }
-
- /* cookie jar default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
- if (fname != NULL) {
- nsoption_setnull_charp(cookie_jar, fname);
- }
-
- /* url database default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "URLs");
- if (fname != NULL) {
- nsoption_setnull_charp(url_file, fname);
- }
-
- /* bookmark database default */
- fname = NULL;
- netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Hotlist");
- if (fname != NULL) {
- nsoption_setnull_charp(hotlist_path, fname);
- }
-
- /* download directory default */
- fname = getenv("HOME");
- if (fname != NULL) {
- nsoption_setnull_charp(downloads_directory, strdup(fname));
- }
-
- /* default path to certificates */
- nsoption_setnull_charp(ca_path, strdup("/etc/ssl/certs"));
-
- if ((nsoption_charp(cookie_file) == NULL) ||
- (nsoption_charp(cookie_jar) == NULL) ||
- (nsoption_charp(url_file) == NULL) ||
- (nsoption_charp(hotlist_path) == NULL) ||
- (nsoption_charp(downloads_directory) == NULL) ||
- (nsoption_charp(ca_path) == NULL)) {
- NSLOG(netsurf, INFO,
- "Failed initialising default resource paths");
- return NSERROR_BAD_PARAMETER;
- }
-
- /* set default font names */
- nsoption_set_charp(font_sans, strdup("Sans"));
- nsoption_set_charp(font_serif, strdup("Serif"));
- nsoption_set_charp(font_mono, strdup("Monospace"));
- nsoption_set_charp(font_cursive, strdup("Serif"));
- nsoption_set_charp(font_fantasy, strdup("Serif"));
-
- return NSERROR_OK;
-}
-
-
-
-
-/**
- * Initialize GTK specific parts of the browser.
- *
- * \param argc The number of arguments on the command line
- * \param argv A string vector of command line arguments.
- * \respath A string vector of the path elements of resources
- */
-static nserror nsgtk_init(int argc, char** argv, char **respath)
-{
- char buf[PATH_MAX];
- char *resource_filename;
- char *addr = NULL;
- nsurl *url;
- nserror res;
-
- /* Initialise gtk accelerator table */
- res = nsgtk_accelerator_init(respaths);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to load gtk accelerator configuration");
- /* not fatal if this does not load */
- }
-
- /* initialise warning dialog */
- res = nsgtk_builder_new_from_resname("warning", &warning_builder);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise warning dialog");
- return res;
- }
-
- gtk_builder_connect_signals(warning_builder, NULL);
-
- /* set default icon if its available */
- res = nsgdk_pixbuf_new_from_resname("netsurf.xpm",
- &win_default_icon_pixbuf);
- if (res == NSERROR_OK) {
- NSLOG(netsurf, INFO, "Seting default window icon");
- gtk_window_set_default_icon(win_default_icon_pixbuf);
- }
-
- /* Search engine sources */
- resource_filename = filepath_find(respath, "SearchEngines");
- search_web_init(resource_filename);
- if (resource_filename != NULL) {
- NSLOG(netsurf, INFO, "Using '%s' as Search Engines file",
- resource_filename);
- free(resource_filename);
- }
-
- /* Default favicon */
- res = nsgdk_pixbuf_new_from_resname("favicon.png", &favicon_pixbuf);
- if (res != NSERROR_OK) {
- favicon_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
- false, 8, 16, 16);
- }
-
- /* arrow down icon */
- res = nsgdk_pixbuf_new_from_resname("arrow_down_8x32.png",
- &arrow_down_pixbuf);
- if (res != NSERROR_OK) {
- arrow_down_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
- false, 8, 8, 32);
- }
-
- /* initialise throbber */
- res = nsgtk_throbber_init();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise throbber.");
- return res;
- }
-
- /* Initialise completions - cannot fail */
- nsgtk_completion_init();
-
- /* The tree view system needs to know the screen's DPI, so we
- * find that out here, rather than when we create a first browser
- * window.
- */
- browser_set_dpi(gdk_screen_get_resolution(gdk_screen_get_default()));
- NSLOG(netsurf, INFO, "Set CSS DPI to %d", browser_get_dpi());
-
- filepath_sfinddef(respath, buf, "mime.types", "/etc/");
- gtk_fetch_filetype_init(buf);
-
- save_complete_init();
-
- urldb_load(nsoption_charp(url_file));
- urldb_load_cookies(nsoption_charp(cookie_file));
- hotlist_init(nsoption_charp(hotlist_path),
- nsoption_charp(hotlist_path));
-
- /* Initialise top level UI elements */
- res = nsgtk_download_init();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise download window.");
- return res;
- }
-
- /* If there is a url specified on the command line use it */
- if (argc > 1) {
- struct stat fs;
- if (stat(argv[1], &fs) == 0) {
- size_t addrlen;
- char *rp = realpath(argv[1], NULL);
- assert(rp != NULL);
-
- /* calculate file url length including terminator */
- addrlen = SLEN("file://") + strlen(rp) + 1;
- addr = malloc(addrlen);
- assert(addr != NULL);
- snprintf(addr, addrlen, "file://%s", rp);
- free(rp);
- } else {
- addr = strdup(argv[1]);
- }
- }
- if (addr != NULL) {
- /* managed to set up based on local launch */
- } else if (nsoption_charp(homepage_url) != NULL) {
- addr = strdup(nsoption_charp(homepage_url));
- } else {
- addr = strdup(NETSURF_HOMEPAGE);
- }
-
- /* create an initial browser window */
- res = nsurl_create(addr, &url);
- if (res == NSERROR_OK) {
- res = browser_window_create(BW_CREATE_HISTORY,
- url,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
- }
-
- free(addr);
-
- return res;
-}
-
-
-
-/**
- * Ensures output logging stream is correctly configured
- */
-static bool nslog_stream_configure(FILE *fptr)
-{
- /* set log stream to be non-buffering */
- setbuf(fptr, NULL);
-
- return true;
-}
-
-
-/**
- * Run the gtk event loop.
- *
- * The same as the standard gtk_main loop except this ensures active
- * FD are added to the gtk poll event set.
- */
-static void nsgtk_main(void)
-{
- fd_set read_fd_set, write_fd_set, exc_fd_set;
- int max_fd;
- GPollFD *fd_list[1000];
- unsigned int fd_count;
-
- while (!nsgtk_complete) {
- max_fd = -1;
- fd_count = 0;
- FD_ZERO(&read_fd_set);
- FD_ZERO(&write_fd_set);
- FD_ZERO(&exc_fd_set);
-
- fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
- for (int i = 0; i <= max_fd; i++) {
- if (FD_ISSET(i, &read_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
- if (FD_ISSET(i, &write_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_OUT | G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
- if (FD_ISSET(i, &exc_fd_set)) {
- GPollFD *fd = malloc(sizeof *fd);
- fd->fd = i;
- fd->events = G_IO_ERR;
- g_main_context_add_poll(0, fd, 0);
- fd_list[fd_count++] = fd;
- }
- }
-
- schedule_run();
+/** default window icon pixbuf */
+GdkPixbuf *win_default_icon_pixbuf;
- gtk_main_iteration();
-
- for (unsigned int i = 0; i != fd_count; i++) {
- g_main_context_remove_poll(0, fd_list[i]);
- free(fd_list[i]);
- }
- }
-}
-
-
-static void gui_quit(void)
-{
- nserror res;
-
- NSLOG(netsurf, INFO, "Quitting GUI");
-
- /* Ensure all scaffoldings are destroyed before we go into exit */
- nsgtk_download_destroy();
- urldb_save_cookies(nsoption_charp(cookie_jar));
- urldb_save(nsoption_charp(url_file));
-
- res = nsgtk_cookies_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising cookie viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = nsgtk_local_history_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Error finalising local history viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = nsgtk_global_history_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Error finalising global history viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = nsgtk_hotlist_destroy();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising hotlist viewer: %s",
- messages_get_errorcode(res));
- }
-
- res = hotlist_fini();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Error finalising hotlist: %s",
- messages_get_errorcode(res));
- }
-
- free(nsgtk_config_home);
-
- gtk_fetch_filetype_fin();
-}
-
-static nserror gui_launch_url(struct nsurl *url)
-{
- gboolean ok;
- GError *error = NULL;
+GtkBuilder *warning_builder;
- ok = nsgtk_show_uri(NULL, nsurl_access(url), GDK_CURRENT_TIME, &error);
- if (ok == TRUE) {
- return NSERROR_OK;
- }
+/** resource search path vector */
+char **respaths;
- if (error) {
- nsgtk_warning(messages_get("URIOpenError"), error->message);
- g_error_free(error);
- }
- return NSERROR_NO_FETCH_HANDLER;
-}
/* exported function documented in gtk/warn.h */
nserror nsgtk_warning(const char *warning, const char *detail)
@@ -518,7 +106,7 @@ nserror nsgtk_warning(const char *warning, const char *detail)
"labelWarning"));
snprintf(buf, sizeof(buf), "%s %s", messages_get(warning),
- detail ? detail : "");
+ detail ? detail : "");
buf[sizeof(buf) - 1] = 0;
gtk_label_set_text(WarningLabel, buf);
@@ -529,129 +117,7 @@ nserror nsgtk_warning(const char *warning, const char *detail)
}
-static void nsgtk_PDF_set_pass(GtkButton *w, gpointer data)
-{
- char **owner_pass = ((void **)data)[0];
- char **user_pass = ((void **)data)[1];
- GtkWindow *wnd = ((void **)data)[2];
- GtkBuilder *password_builder = ((void **)data)[3];
- char *path = ((void **)data)[4];
-
- char *op, *op1;
- char *up, *up1;
-
- op = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFOwnerPassword"))));
- op1 = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFOwnerPassword1"))));
- up = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFUserPassword"))));
- up1 = strdup(gtk_entry_get_text(
- GTK_ENTRY(gtk_builder_get_object(password_builder,
- "entryPDFUserPassword1"))));
-
-
- if (op[0] == '\0') {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")),
- "Owner password must be at least 1 character long:");
- free(op);
- free(up);
- } else if (!strcmp(op, up)) {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")),
- "User and owner passwords must be different:");
- free(op);
- free(up);
- } else if (!strcmp(op, op1) && !strcmp(up, up1)) {
-
- *owner_pass = op;
- if (up[0] == '\0')
- free(up);
- else
- *user_pass = up;
-
- free(data);
- gtk_widget_destroy(GTK_WIDGET(wnd));
- g_object_unref(G_OBJECT(password_builder));
-
- save_pdf(path);
-
- free(path);
- } else {
- gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
- "labelInfo")), "Passwords not confirmed:");
- free(op);
- free(up);
- }
-
- free(op1);
- free(up1);
-}
-
-static void nsgtk_PDF_no_pass(GtkButton *w, gpointer data)
-{
- GtkWindow *wnd = ((void **)data)[2];
- GtkBuilder *password_builder = ((void **)data)[3];
- char *path = ((void **)data)[4];
-
- free(data);
-
- gtk_widget_destroy(GTK_WIDGET(wnd));
- g_object_unref(G_OBJECT(password_builder));
-
- save_pdf(path);
-
- free(path);
-}
-
-static void nsgtk_pdf_password(char **owner_pass, char **user_pass, char *path)
-{
- GtkButton *ok, *no;
- GtkWindow *wnd;
- void **data;
- GtkBuilder *password_builder;
- nserror res;
-
- res = nsgtk_builder_new_from_resname("password", &password_builder);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Password UI builder init failed");
- return;
- }
-
- gtk_builder_connect_signals(password_builder, NULL);
-
- wnd = GTK_WINDOW(gtk_builder_get_object(password_builder,
- "wndPDFPassword"));
-
- data = malloc(5 * sizeof(void *));
-
- *owner_pass = NULL;
- *user_pass = NULL;
-
- data[0] = owner_pass;
- data[1] = user_pass;
- data[2] = wnd;
- data[3] = password_builder;
- data[4] = path;
-
- ok = GTK_BUTTON(gtk_builder_get_object(password_builder,
- "buttonPDFSetPassword"));
- no = GTK_BUTTON(gtk_builder_get_object(password_builder,
- "buttonPDFNoPassword"));
-
- g_signal_connect(G_OBJECT(ok), "clicked",
- G_CALLBACK(nsgtk_PDF_set_pass), (gpointer)data);
- g_signal_connect(G_OBJECT(no), "clicked",
- G_CALLBACK(nsgtk_PDF_no_pass), (gpointer)data);
-
- gtk_widget_show(GTK_WIDGET(wnd));
-}
-
-
+/* exported interface documented in gtk/gui.h */
uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
{
/* this function will need to become much more complex to support
@@ -666,12 +132,16 @@ uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
case GDK_KEY(BackSpace):
if (key->state & GDK_SHIFT_MASK)
return NS_KEY_DELETE_LINE_START;
+ else if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_DELETE_WORD_LEFT;
else
return NS_KEY_DELETE_LEFT;
case GDK_KEY(Delete):
if (key->state & GDK_SHIFT_MASK)
return NS_KEY_DELETE_LINE_END;
+ else if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_DELETE_WORD_RIGHT;
else
return NS_KEY_DELETE_RIGHT;
@@ -683,10 +153,14 @@ uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
case GDK_KEY(Left):
case GDK_KEY(KP_Left):
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_WORD_LEFT;
return NS_KEY_LEFT;
case GDK_KEY(Right):
case GDK_KEY(KP_Right):
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_WORD_RIGHT;
return NS_KEY_RIGHT;
case GDK_KEY(Up):
@@ -781,6 +255,63 @@ uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
/**
+ * Create an array of valid paths to search for resources.
+ *
+ * The idea is that all the complex path computation to find resources
+ * is performed here, once, rather than every time a resource is
+ * searched for.
+ */
+static char **
+nsgtk_init_resource_path(const char *config_home)
+{
+ char *resource_path;
+ int resource_path_len;
+ const gchar * const *langv;
+ char **pathv; /* resource path string vector */
+ char **respath; /* resource paths vector */
+
+ if (config_home != NULL) {
+ resource_path_len = snprintf(NULL, 0,
+ "%s:${NETSURFRES}:%s",
+ config_home,
+ GTK_RESPATH);
+ resource_path = malloc(resource_path_len + 1);
+ if (resource_path == NULL) {
+ return NULL;
+ }
+ snprintf(resource_path, resource_path_len + 1,
+ "%s:${NETSURFRES}:%s",
+ config_home,
+ GTK_RESPATH);
+ } else {
+ resource_path_len = snprintf(NULL, 0,
+ "${NETSURFRES}:%s",
+ GTK_RESPATH);
+ resource_path = malloc(resource_path_len + 1);
+ if (resource_path == NULL) {
+ return NULL;
+ }
+ snprintf(resource_path,
+ resource_path_len + 1,
+ "${NETSURFRES}:%s",
+ GTK_RESPATH);
+ }
+
+ pathv = filepath_path_to_strvec(resource_path);
+
+ langv = g_get_language_names();
+
+ respath = filepath_generate(pathv, langv);
+
+ filepath_free_strvec(pathv);
+
+ free(resource_path);
+
+ return respath;
+}
+
+
+/**
* create directory name and check it is acessible and a directory.
*/
static nserror
@@ -818,6 +349,7 @@ check_dirname(const char *path, const char *leaf, char **dirname_out)
return ret;
}
+
/**
* Get the path to the config directory.
*
@@ -885,6 +417,7 @@ static nserror get_config_home(char **config_home_out)
return NSERROR_OK;
}
+
static nserror create_config_home(char **config_home_out)
{
char *config_home = NULL;
@@ -935,6 +468,192 @@ static nserror create_config_home(char **config_home_out)
return NSERROR_OK;
}
+
+/**
+ * Ensures output logging stream is correctly configured
+ */
+static bool nslog_stream_configure(FILE *fptr)
+{
+ /* set log stream to be non-buffering */
+ setbuf(fptr, NULL);
+
+ return true;
+}
+
+
+/**
+ * Set option defaults for gtk frontend.
+ *
+ * \param defaults The option table to update.
+ * \return error status.
+ */
+static nserror set_defaults(struct nsoption_s *defaults)
+{
+ char *fname;
+ GtkSettings *settings;
+ GtkIconSize tooliconsize;
+ GtkToolbarStyle toolbarstyle;
+
+ /* cookie file default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
+ if (fname != NULL) {
+ nsoption_setnull_charp(cookie_file, fname);
+ }
+
+ /* cookie jar default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Cookies");
+ if (fname != NULL) {
+ nsoption_setnull_charp(cookie_jar, fname);
+ }
+
+ /* url database default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "URLs");
+ if (fname != NULL) {
+ nsoption_setnull_charp(url_file, fname);
+ }
+
+ /* bookmark database default */
+ fname = NULL;
+ netsurf_mkpath(&fname, NULL, 2, nsgtk_config_home, "Hotlist");
+ if (fname != NULL) {
+ nsoption_setnull_charp(hotlist_path, fname);
+ }
+
+ /* download directory default */
+ fname = getenv("HOME");
+ if (fname != NULL) {
+ nsoption_setnull_charp(downloads_directory, strdup(fname));
+ }
+
+ if ((nsoption_charp(cookie_file) == NULL) ||
+ (nsoption_charp(cookie_jar) == NULL) ||
+ (nsoption_charp(url_file) == NULL) ||
+ (nsoption_charp(hotlist_path) == NULL) ||
+ (nsoption_charp(downloads_directory) == NULL)) {
+ NSLOG(netsurf, INFO,
+ "Failed initialising default resource paths");
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ /* set default font names */
+ nsoption_set_charp(font_sans, strdup("Sans"));
+ nsoption_set_charp(font_serif, strdup("Serif"));
+ nsoption_set_charp(font_mono, strdup("Monospace"));
+ nsoption_set_charp(font_cursive, strdup("Serif"));
+ nsoption_set_charp(font_fantasy, strdup("Serif"));
+
+ /* Default toolbar button type to system defaults */
+
+ settings = gtk_settings_get_default();
+ g_object_get(settings,
+ "gtk-toolbar-icon-size", &tooliconsize,
+ "gtk-toolbar-style", &toolbarstyle, NULL);
+
+ switch (toolbarstyle) {
+ case GTK_TOOLBAR_ICONS:
+ if (tooliconsize == GTK_ICON_SIZE_SMALL_TOOLBAR) {
+ nsoption_set_int(button_type, 1);
+ } else {
+ nsoption_set_int(button_type, 2);
+ }
+ break;
+
+ case GTK_TOOLBAR_TEXT:
+ nsoption_set_int(button_type, 4);
+ break;
+
+ case GTK_TOOLBAR_BOTH:
+ case GTK_TOOLBAR_BOTH_HORIZ:
+ /* no labels in default configuration */
+ default:
+ /* No system default, so use large icons */
+ nsoption_set_int(button_type, 2);
+ break;
+ }
+
+ /* set default items in toolbar */
+ nsoption_set_charp(toolbar_items,
+ strdup("back/history/forward/reloadstop/url_bar/websearch/openmenu"));
+
+ /* set default for menu and tool bar visibility */
+ nsoption_set_charp(bar_show, strdup("tool"));
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Initialise user options
+ *
+ * Initialise the browser configuration options. These are set by:
+ * - set generic defaults suitable for the gtk frontend
+ * - user choices loaded from Choices file
+ * - command line parameters
+ */
+static nserror nsgtk_option_init(int *pargc, char** argv)
+{
+ nserror ret;
+ char *choices = NULL;
+
+ /* user options setup */
+ ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ /* Attempt to load the user choices */
+ ret = netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
+ if (ret == NSERROR_OK) {
+ nsoption_read(choices, nsoptions);
+ free(choices);
+ }
+
+ /* overide loaded options with those from commandline */
+ nsoption_commandline(pargc, argv, nsoptions);
+
+ /* ensure all options fall within sensible bounds */
+
+ /* Attempt to handle nonsense status bar widths. These may exist
+ * in people's Choices as the GTK front end used to abuse the
+ * status bar width option by using it for an absolute value in px.
+ * The GTK front end now correctly uses it as a proportion of window
+ * width. Here we assume that a value of less than 15% is wrong
+ * and set to the default two thirds. */
+ if (nsoption_int(toolbar_status_size) < 1500) {
+ nsoption_set_int(toolbar_status_size, 6667);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * initialise message translation
+ */
+static nserror nsgtk_messages_init(char **respaths)
+{
+ const char *messages;
+ nserror ret;
+ const uint8_t *data;
+ size_t data_size;
+
+ ret = nsgtk_data_from_resname("Messages", &data, &data_size);
+ if (ret == NSERROR_OK) {
+ ret = messages_add_from_inline(data, data_size);
+ } else {
+ /* Obtain path to messages */
+ ret = nsgtk_path_from_resname("Messages", &messages);
+ if (ret == NSERROR_OK) {
+ ret = messages_add_from_file(messages);
+ }
+ }
+ return ret;
+}
+
+
/**
* Get the path to the cache directory.
*
@@ -983,6 +702,10 @@ static nserror get_cache_home(char **cache_home_out)
return NSERROR_OK;
}
+
+/**
+ * create a cache directory
+ */
static nserror create_cache_home(char **cache_home_out)
{
char *cache_home = NULL;
@@ -990,7 +713,7 @@ static nserror create_cache_home(char **cache_home_out)
char *xdg_cache_dir;
nserror ret;
- NSLOG(netsurf, INFO, "Attempting to create configuration directory");
+ NSLOG(netsurf, INFO, "Attempting to create cache directory");
/* $XDG_CACHE_HOME defines the base directory
* relative to which user specific cache files
@@ -1033,98 +756,13 @@ static nserror create_cache_home(char **cache_home_out)
return NSERROR_OK;
}
-static nserror nsgtk_option_init(int *pargc, char** argv)
-{
- nserror ret;
- char *choices = NULL;
-
- /* user options setup */
- ret = nsoption_init(set_defaults, &nsoptions, &nsoptions_default);
- if (ret != NSERROR_OK) {
- return ret;
- }
-
- /* Attempt to load the user choices */
- ret = netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
- if (ret == NSERROR_OK) {
- nsoption_read(choices, nsoptions);
- free(choices);
- }
-
- /* overide loaded options with those from commandline */
- nsoption_commandline(pargc, argv, nsoptions);
-
- /* ensure all options fall within sensible bounds */
-
- /* Attempt to handle nonsense status bar widths. These may exist
- * in people's Choices as the GTK front end used to abuse the
- * status bar width option by using it for an absolute value in px.
- * The GTK front end now correctly uses it as a proportion of window
- * width. Here we assume that a value of less than 15% is wrong
- * and set to the default two thirds. */
- if (nsoption_int(toolbar_status_size) < 1500) {
- nsoption_set_int(toolbar_status_size, 6667);
- }
-
- return NSERROR_OK;
-}
-
-static struct gui_misc_table nsgtk_misc_table = {
- .schedule = nsgtk_schedule,
- .warning = nsgtk_warning,
-
- .quit = gui_quit,
- .launch_url = gui_launch_url,
- .cert_verify = gtk_cert_verify,
- .login = gui_401login_open,
- .pdf_password = nsgtk_pdf_password,
-};
-
-
-static nserror nsgtk_messages_init(char **respaths)
-{
- const char *messages;
- nserror ret;
- const uint8_t *data;
- size_t data_size;
-
- ret = nsgtk_data_from_resname("Messages", &data, &data_size);
- if (ret == NSERROR_OK) {
- ret = messages_add_from_inline(data, data_size);
- } else {
- /* Obtain path to messages */
- ret = nsgtk_path_from_resname("Messages", &messages);
- if (ret == NSERROR_OK) {
- ret = messages_add_from_file(messages);
- }
- }
- return ret;
-}
/**
- * Main entry point from OS.
+ * GTK specific initialisation
*/
-int main(int argc, char** argv)
+static nserror nsgtk_init(int *pargc, char ***pargv, char **cache_home)
{
- char *cache_home = NULL;
nserror ret;
- struct netsurf_table nsgtk_table = {
- .misc = &nsgtk_misc_table,
- .window = nsgtk_window_table,
- .clipboard = nsgtk_clipboard_table,
- .download = nsgtk_download_table,
- .fetch = nsgtk_fetch_table,
- .llcache = filesystem_llcache_table,
- .search = nsgtk_search_table,
- .search_web = nsgtk_search_web_table,
- .bitmap = nsgtk_bitmap_table,
- .layout = nsgtk_layout_table,
- };
-
- ret = netsurf_register(&nsgtk_table);
- if (ret != NSERROR_OK) {
- die("NetSurf operation table failed registration\n");
- }
/* Locate the correct user configuration directory path */
ret = get_config_home(&nsgtk_config_home);
@@ -1139,12 +777,12 @@ int main(int argc, char** argv)
}
/* Initialise gtk */
- gtk_init(&argc, &argv);
+ gtk_init(pargc, pargv);
/* initialise logging. Not fatal if it fails but not much we
* can do about it either.
*/
- nslog_init(nslog_stream_configure, &argc, argv);
+ nslog_init(nslog_stream_configure, pargc, *pargv);
/* build the common resource path list */
respaths = nsgtk_init_resource_path(nsgtk_config_home);
@@ -1158,15 +796,15 @@ int main(int argc, char** argv)
if (ret != NSERROR_OK) {
fprintf(stderr, "GTK resources failed to initialise (%s)\n",
messages_get_errorcode(ret));
- return 1;
+ return ret;
}
/* Initialise user options */
- ret = nsgtk_option_init(&argc, argv);
+ ret = nsgtk_option_init(pargc, *pargv);
if (ret != NSERROR_OK) {
fprintf(stderr, "Options failed to initialise (%s)\n",
messages_get_errorcode(ret));
- return 1;
+ return ret;
}
/* Initialise translated messages */
@@ -1177,35 +815,353 @@ int main(int argc, char** argv)
NSLOG(netsurf, INFO, "Unable to load translated messages");
/** \todo decide if message load faliure should be fatal */
}
-
+
/* Locate the correct user cache directory path */
- ret = get_cache_home(&cache_home);
+ ret = get_cache_home(cache_home);
if (ret == NSERROR_NOT_FOUND) {
/* no cache directory exists yet so try to create one */
- ret = create_cache_home(&cache_home);
+ ret = create_cache_home(cache_home);
}
if (ret != NSERROR_OK) {
NSLOG(netsurf, INFO, "Unable to locate a cache directory.");
}
- /* core initialisation */
- ret = netsurf_init(cache_home);
- free(cache_home);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "NetSurf core failed to initialise (%s)\n",
- messages_get_errorcode(ret));
- return 1;
+
+ return NSERROR_OK;
+}
+
+
+#if GTK_CHECK_VERSION(3,14,0)
+
+/**
+ * adds named icons into gtk theme
+ */
+static nserror nsgtk_add_named_icons_to_theme(void)
+{
+ gtk_icon_theme_add_resource_path(gtk_icon_theme_get_default(),
+ "/org/netsurf/icons");
+ return NSERROR_OK;
+}
+
+#else
+
+static nserror
+add_builtin_icon(const char *prefix, const char *name, int x, int y)
+{
+ GdkPixbuf *pixbuf;
+ nserror res;
+ char *resname;
+ int resnamelen;
+
+ /* resource name string length allowing for / .png and termination */
+ resnamelen = strlen(prefix) + strlen(name) + 5 + 1 + 4 + 1;
+ resname = malloc(resnamelen);
+ if (resname == NULL) {
+ return NSERROR_NOMEM;
}
+ snprintf(resname, resnamelen, "icons%s/%s.png", prefix, name);
- /* gtk specific initalisation and main run loop */
- ret = nsgtk_init(argc, argv, respaths);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "NetSurf gtk initialise failed (%s)\n",
- messages_get_errorcode(ret));
+ res = nsgdk_pixbuf_new_from_resname(resname, &pixbuf);
+ NSLOG(netsurf, DEEPDEBUG, "%d %s", res, resname);
+ free(resname);
+ if (res != NSERROR_OK) {
+ pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, x, y);
+ }
+ gtk_icon_theme_add_builtin_icon(name, y, pixbuf);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * adds named icons into gtk theme
+ */
+static nserror nsgtk_add_named_icons_to_theme(void)
+{
+ /* these must also be in gtk/resources.c pixbuf_resource *and*
+ * gtk/res/netsurf.gresource.xml
+ */
+ add_builtin_icon("", "local-history", 8, 32);
+ add_builtin_icon("", "show-cookie", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-insecure", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-internal", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-local", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-secure", 24, 24);
+ add_builtin_icon("/24x24/actions", "page-info-warning", 24, 24);
+ add_builtin_icon("/48x48/actions", "page-info-insecure", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-internal", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-local", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-secure", 48, 48);
+ add_builtin_icon("/48x48/actions", "page-info-warning", 48, 48);
+
+ return NSERROR_OK;
+}
+
+#endif
+
+
+/**
+ * setup GTK specific parts of the browser.
+ *
+ * \param argc The number of arguments on the command line
+ * \param argv A string vector of command line arguments.
+ * \respath A string vector of the path elements of resources
+ */
+static nserror nsgtk_setup(int argc, char** argv, char **respath)
+{
+ char buf[PATH_MAX];
+ char *resource_filename;
+ char *addr = NULL;
+ nsurl *url;
+ nserror res;
+
+ /* Initialise gtk accelerator table */
+ res = nsgtk_accelerator_init(respaths);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to load gtk accelerator configuration");
+ /* not fatal if this does not load */
+ }
+
+ /* initialise warning dialog */
+ res = nsgtk_builder_new_from_resname("warning", &warning_builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise warning dialog");
+ return res;
+ }
+
+ gtk_builder_connect_signals(warning_builder, NULL);
+
+ /* set default icon if its available */
+ res = nsgdk_pixbuf_new_from_resname("netsurf.xpm",
+ &win_default_icon_pixbuf);
+ if (res == NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Seting default window icon");
+ gtk_window_set_default_icon(win_default_icon_pixbuf);
+ }
+
+ /* Search engine sources */
+ resource_filename = filepath_find(respath, "SearchEngines");
+ search_web_init(resource_filename);
+ if (resource_filename != NULL) {
+ NSLOG(netsurf, INFO, "Using '%s' as Search Engines file",
+ resource_filename);
+ free(resource_filename);
+ }
+ search_web_select_provider(nsoption_int(search_provider));
+
+ /* Default favicon */
+ res = nsgdk_pixbuf_new_from_resname("favicon.png", &favicon_pixbuf);
+ if (res != NSERROR_OK) {
+ favicon_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB,
+ false, 8, 16, 16);
+ }
+
+ /* add named icons to gtk theme */
+ res = nsgtk_add_named_icons_to_theme();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to add named icons to GTK theme.");
+ return res;
+ }
+
+ /* initialise throbber */
+ res = nsgtk_throbber_init();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise throbber.");
+ return res;
+ }
+
+ /* Initialise completions - cannot fail */
+ nsgtk_completion_init();
+
+ /* The tree view system needs to know the screen's DPI, so we
+ * find that out here, rather than when we create a first browser
+ * window.
+ */
+ browser_set_dpi(gdk_screen_get_resolution(gdk_screen_get_default()));
+ NSLOG(netsurf, INFO, "Set CSS DPI to %d", browser_get_dpi());
+
+ bitmap_set_format(&(bitmap_fmt_t) {
+ .layout = BITMAP_LAYOUT_ARGB8888,
+ .pma = true,
+ });
+
+ filepath_sfinddef(respath, buf, "mime.types", "/etc/");
+ gtk_fetch_filetype_init(buf);
+
+ save_complete_init();
+
+ urldb_load(nsoption_charp(url_file));
+ urldb_load_cookies(nsoption_charp(cookie_file));
+ hotlist_init(nsoption_charp(hotlist_path),
+ nsoption_charp(hotlist_path));
+
+ /* Initialise top level UI elements */
+ res = nsgtk_download_init();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise download window.");
+ return res;
+ }
+
+ /* If there is a url specified on the command line use it */
+ if (argc > 1) {
+ struct stat fs;
+ if (stat(argv[1], &fs) == 0) {
+ size_t addrlen;
+ char *rp = realpath(argv[1], NULL);
+ assert(rp != NULL);
+
+ /* calculate file url length including terminator */
+ addrlen = SLEN("file://") + strlen(rp) + 1;
+ addr = malloc(addrlen);
+ assert(addr != NULL);
+ snprintf(addr, addrlen, "file://%s", rp);
+ free(rp);
+ } else {
+ addr = strdup(argv[1]);
+ }
+ }
+ if (addr != NULL) {
+ /* managed to set up based on local launch */
+ } else if (nsoption_charp(homepage_url) != NULL) {
+ addr = strdup(nsoption_charp(homepage_url));
} else {
- nsgtk_main();
+ addr = strdup(NETSURF_HOMEPAGE);
+ }
+
+ /* create an initial browser window */
+ res = nsurl_create(addr, &url);
+ if (res == NSERROR_OK) {
+ res = browser_window_create(BW_CREATE_HISTORY,
+ url,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+
+ free(addr);
+
+ return res;
+}
+
+
+/**
+ * Run the gtk event loop.
+ *
+ * The same as the standard gtk_main loop except this ensures active
+ * FD are added to the gtk poll event set.
+ */
+static void nsgtk_main(void)
+{
+ fd_set read_fd_set, write_fd_set, exc_fd_set;
+ int max_fd;
+ GPollFD *fd_list[1000];
+ unsigned int fd_count;
+
+ while (!nsgtk_complete) {
+ max_fd = -1;
+ fd_count = 0;
+ FD_ZERO(&read_fd_set);
+ FD_ZERO(&write_fd_set);
+ FD_ZERO(&exc_fd_set);
+
+ while (gtk_events_pending())
+ gtk_main_iteration_do(TRUE);
+
+ schedule_run();
+
+ fetch_fdset(&read_fd_set, &write_fd_set, &exc_fd_set, &max_fd);
+ for (int i = 0; i <= max_fd; i++) {
+ if (FD_ISSET(i, &read_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ if (FD_ISSET(i, &write_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_OUT | G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ if (FD_ISSET(i, &exc_fd_set)) {
+ GPollFD *fd = malloc(sizeof *fd);
+ fd->fd = i;
+ fd->events = G_IO_ERR;
+ g_main_context_add_poll(0, fd, 0);
+ fd_list[fd_count++] = fd;
+ }
+ }
+
+ gtk_main_iteration();
+
+ for (unsigned int i = 0; i != fd_count; i++) {
+ g_main_context_remove_poll(0, fd_list[i]);
+ free(fd_list[i]);
+ }
+ }
+}
+
+
+/**
+ * finalise the browser
+ */
+static void nsgtk_finalise(void)
+{
+ nserror res;
+
+ NSLOG(netsurf, INFO, "Quitting GUI");
+
+ /* Ensure all scaffoldings are destroyed before we go into exit */
+ nsgtk_download_destroy();
+ urldb_save_cookies(nsoption_charp(cookie_jar));
+ urldb_save(nsoption_charp(url_file));
+
+ res = nsgtk_cookies_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising cookie viewer: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = nsgtk_local_history_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Error finalising local history viewer: %s",
+ messages_get_errorcode(res));
}
+ res = nsgtk_global_history_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Error finalising global history viewer: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = nsgtk_hotlist_destroy();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising hotlist viewer: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = hotlist_fini();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising hotlist: %s",
+ messages_get_errorcode(res));
+ }
+
+ res = save_complete_finalise();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Error finalising save complete: %s",
+ messages_get_errorcode(res));
+ }
+
+ free(nsgtk_config_home);
+
+ gtk_fetch_filetype_fin();
+
/* common finalisation */
netsurf_exit();
@@ -1215,5 +1171,66 @@ int main(int argc, char** argv)
/* finalise logging */
nslog_finalise();
+}
+
+
+/**
+ * Main entry point from OS.
+ */
+int main(int argc, char** argv)
+{
+ nserror res;
+ char *cache_home = NULL;
+ struct netsurf_table nsgtk_table = {
+ .misc = nsgtk_misc_table,
+ .window = nsgtk_window_table,
+ .clipboard = nsgtk_clipboard_table,
+ .download = nsgtk_download_table,
+ .fetch = nsgtk_fetch_table,
+ .llcache = filesystem_llcache_table,
+ .search = nsgtk_search_table,
+ .search_web = nsgtk_search_web_table,
+ .bitmap = nsgtk_bitmap_table,
+ .layout = nsgtk_layout_table,
+ };
+
+ res = netsurf_register(&nsgtk_table);
+ if (res != NSERROR_OK) {
+ fprintf(stderr,
+ "NetSurf operation table failed registration (%s)\n",
+ messages_get_errorcode(res));
+ return 1;
+ }
+
+ /* gtk specific initialisation */
+ res = nsgtk_init(&argc, &argv, &cache_home);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf gtk failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return 2;
+ }
+
+ /* core initialisation */
+ res = netsurf_init(cache_home);
+ free(cache_home);
+ if (res != NSERROR_OK) {
+ fprintf(stderr, "NetSurf core failed to initialise (%s)\n",
+ messages_get_errorcode(res));
+ return 3;
+ }
+
+ /* gtk specific initalisation and main run loop */
+ res = nsgtk_setup(argc, argv, respaths);
+ if (res != NSERROR_OK) {
+ nsgtk_finalise();
+ fprintf(stderr, "NetSurf gtk setup failed (%s)\n",
+ messages_get_errorcode(res));
+ return 4;
+ }
+
+ nsgtk_main();
+
+ nsgtk_finalise();
+
return 0;
}
diff --git a/frontends/gtk/gui.h b/frontends/gtk/gui.h
index 53e732437..ee82e7a6f 100644
--- a/frontends/gtk/gui.h
+++ b/frontends/gtk/gui.h
@@ -27,9 +27,6 @@ extern char *nsgtk_config_home;
/** favicon default pixbuf */
extern GdkPixbuf *favicon_pixbuf;
-/** arrow down pixbuf */
-extern GdkPixbuf *arrow_down_pixbuf;
-
/** resource search path vector */
extern char **respaths;
diff --git a/frontends/gtk/hotlist.c b/frontends/gtk/hotlist.c
index 843e47736..b047dc65f 100644
--- a/frontends/gtk/hotlist.c
+++ b/frontends/gtk/hotlist.c
@@ -170,6 +170,8 @@ MENUHANDLER(delete_selected)
MENUHANDLER(select_all)
{
+ hotlist_keypress(NS_KEY_ESCAPE);
+ hotlist_keypress(NS_KEY_ESCAPE);
hotlist_keypress(NS_KEY_SELECT_ALL);
return TRUE;
}
diff --git a/frontends/gtk/layout_pango.c b/frontends/gtk/layout_pango.c
index a5964eb37..9e8e94d48 100644
--- a/frontends/gtk/layout_pango.c
+++ b/frontends/gtk/layout_pango.c
@@ -277,7 +277,7 @@ nsfont_style_to_description(const plot_font_style_t *fstyle)
break;
}
- size = (fstyle->size * PANGO_SCALE) / FONT_SIZE_SCALE;
+ size = (fstyle->size * PANGO_SCALE) / PLOT_STYLE_SCALE;
if (fstyle->flags & FONTF_ITALIC)
style = PANGO_STYLE_ITALIC;
diff --git a/frontends/gtk/local_history.c b/frontends/gtk/local_history.c
index 35b7a4ad6..0d59c468a 100644
--- a/frontends/gtk/local_history.c
+++ b/frontends/gtk/local_history.c
@@ -35,6 +35,7 @@
#include "gtk/resources.h"
#include "gtk/corewindow.h"
#include "gtk/local_history.h"
+#include "gtk/scaffolding.h"
struct nsgtk_local_history_window {
struct nsgtk_corewindow core;
@@ -158,6 +159,12 @@ nsgtk_local_history_init(struct browser_window *bw,
ncwin->wnd = GTK_WINDOW(gtk_builder_get_object(ncwin->builder,
"wndHistory"));
+ /* Configure for transient behaviour */
+ gtk_window_set_type_hint(GTK_WINDOW(ncwin->wnd),
+ GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU);
+ gtk_window_set_modal(GTK_WINDOW(ncwin->wnd), TRUE);
+
+
ncwin->core.scrolled = GTK_SCROLLED_WINDOW(
gtk_builder_get_object(ncwin->builder,
"HistoryScrolled"));
@@ -171,6 +178,16 @@ nsgtk_local_history_init(struct browser_window *bw,
"delete_event",
G_CALLBACK(gtk_widget_hide_on_delete),
NULL);
+ /* Ditto if we lose the grab */
+ g_signal_connect(G_OBJECT(ncwin->wnd),
+ "grab-broken-event",
+ G_CALLBACK(gtk_widget_hide_on_delete),
+ ncwin);
+ /* Handle button press events */
+ g_signal_connect(G_OBJECT(ncwin->wnd),
+ "button-press-event",
+ G_CALLBACK(gtk_widget_hide_on_delete),
+ ncwin);
ncwin->core.draw = nsgtk_local_history_draw;
ncwin->core.key = nsgtk_local_history_key;
@@ -206,7 +223,11 @@ nserror nsgtk_local_history_present(GtkWindow *parent,
int width, height;
res = nsgtk_local_history_init(bw, &local_history_window);
if (res == NSERROR_OK) {
+ gtk_window_group_add_window(gtk_window_get_group(parent),
+ local_history_window->wnd);
gtk_window_set_transient_for(local_history_window->wnd, parent);
+ gtk_window_set_screen(local_history_window->wnd,
+ gtk_widget_get_screen(GTK_WIDGET(parent)));
gtk_window_get_size(parent, &prnt_width, &prnt_height);
@@ -224,7 +245,13 @@ nserror nsgtk_local_history_present(GtkWindow *parent,
}
gtk_window_resize(local_history_window->wnd, width, height);
- gtk_window_present(local_history_window->wnd);
+ /* Attempt to place the window in the right place */
+ nsgtk_scaffolding_position_local_history(nsgtk_current_scaffolding());
+
+ gtk_widget_show(GTK_WIDGET(local_history_window->wnd));
+ gtk_widget_grab_focus(GTK_WIDGET(local_history_window->wnd));
+
+ local_history_scroll_to_cursor(local_history_window->session);
}
return res;
@@ -267,3 +294,11 @@ nserror nsgtk_local_history_destroy(void)
return res;
}
+
+/* exported function documented gtk/history.h */
+void nsgtk_local_history_set_position(int x, int y)
+{
+ NSLOG(netsurf, INFO, "x=%d y=%d", x, y);
+
+ gtk_window_move(local_history_window->wnd, x, y);
+}
diff --git a/frontends/gtk/local_history.h b/frontends/gtk/local_history.h
index 605405ddf..c5b447194 100644
--- a/frontends/gtk/local_history.h
+++ b/frontends/gtk/local_history.h
@@ -34,6 +34,11 @@ struct browser_window;
nserror nsgtk_local_history_present(GtkWindow *parent, struct browser_window *bw);
/**
+ * set the local history window position.
+ */
+void nsgtk_local_history_set_position(int x, int y);
+
+/**
* hide the local history window from being visible.
*
* \return NSERROR_OK on success else appropriate error code on faliure.
diff --git a/frontends/gtk/login.c b/frontends/gtk/login.c
deleted file mode 100644
index 91d8b37f0..000000000
--- a/frontends/gtk/login.c
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright 2006 Rob Kendrick <rjek@rjek.com>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <gtk/gtk.h>
-
-#include "utils/log.h"
-#include "utils/nsurl.h"
-#include "netsurf/url_db.h"
-
-#include "gtk/resources.h"
-#include "gtk/login.h"
-
-/** login window session data */
-struct session_401 {
- nsurl *url; /**< URL being fetched */
- lwc_string *host; /**< Host for user display */
- char *realm; /**< Authentication realm */
- nserror (*cb)(bool proceed, void *pw); /**< Continuation callback */
- void *cbpw; /**< Continuation data */
- GtkBuilder *x; /**< Our builder windows */
- GtkWindow *wnd; /**< The login window itself */
- GtkEntry *user; /**< Widget with username */
- GtkEntry *pass; /**< Widget with password */
-};
-
-/**
- * Destroy login window and free all associated resources
- *
- * \param session The login window session to destroy.
- */
-static void destroy_login_window(struct session_401 *session)
-{
- nsurl_unref(session->url);
- lwc_string_unref(session->host);
- free(session->realm);
- gtk_widget_destroy(GTK_WIDGET(session->wnd));
- g_object_unref(G_OBJECT(session->x));
- free(session);
-}
-
-
-/**
- * process next signal in entry widgets.
- *
- * \param w current widget
- * \param data next widget
- */
-static void nsgtk_login_next(GtkWidget *w, gpointer data)
-{
- gtk_widget_grab_focus(GTK_WIDGET(data));
-}
-
-
-/**
- * handler called when navigation is continued
- *
- * \param w current widget
- * \param data login window session
- */
-static void nsgtk_login_ok_clicked(GtkButton *w, gpointer data)
-{
- /* close the window and destroy it, having continued the fetch
- * assoicated with it.
- */
-
- struct session_401 *session = (struct session_401 *)data;
- const gchar *user = gtk_entry_get_text(session->user);
- const gchar *pass = gtk_entry_get_text(session->pass);
- char *auth;
-
- auth = malloc(strlen(user) + strlen(pass) + 2);
- sprintf(auth, "%s:%s", user, pass);
- urldb_set_auth_details(session->url, session->realm, auth);
- free(auth);
-
- session->cb(true, session->cbpw);
-
- destroy_login_window(session);
-}
-
-
-/**
- * handler called when navigation is cancelled
- *
- * \param w widget
- * \param data login window session
- */
-static void nsgtk_login_cancel_clicked(GtkButton *w, gpointer data)
-{
- struct session_401 *session = (struct session_401 *) data;
-
- session->cb(false, session->cbpw);
-
- /* close and destroy the window */
- destroy_login_window(session);
-}
-
-
-/**
- * create a new instance of the login window
- *
- * creates login window and handles to all the widgets we're
- * interested in.
- *
- * \param url The url causing the login.
- * \param host the host being logged into
- * \param realm realmm the login relates to
- * \param cb callback when complete
- * \param cbpw data to pass to callback
- * \return NSERROR_OK on sucessful window creation or error code on faliure.
- */
-static nserror
-create_login_window(nsurl *url,
- lwc_string *host,
- const char *realm,
- nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
-{
- struct session_401 *session;
- GtkWindow *wnd;
- GtkLabel *lhost, *lrealm;
- GtkEntry *euser, *epass;
- GtkButton *bok, *bcan;
- GtkBuilder* builder;
- nserror res;
-
- session = calloc(1, sizeof(struct session_401));
- if (session == NULL) {
- return NSERROR_NOMEM;
- }
-
- res = nsgtk_builder_new_from_resname("login", &builder);
- if (res != NSERROR_OK) {
- free(session);
- return res;
- }
-
- gtk_builder_connect_signals(builder, NULL);
-
- wnd = GTK_WINDOW(gtk_builder_get_object(builder, "wndLogin"));
- lhost = GTK_LABEL(gtk_builder_get_object(builder, "labelLoginHost"));
- lrealm = GTK_LABEL(gtk_builder_get_object(builder, "labelLoginRealm"));
- euser = GTK_ENTRY(gtk_builder_get_object(builder, "entryLoginUser"));
- epass = GTK_ENTRY(gtk_builder_get_object(builder, "entryLoginPass"));
- bok = GTK_BUTTON(gtk_builder_get_object(builder, "buttonLoginOK"));
- bcan = GTK_BUTTON(gtk_builder_get_object(builder, "buttonLoginCan"));
-
- /* create and fill in our session structure */
- session->url = nsurl_ref(url);
- session->host = lwc_string_ref(host);
- session->realm = strdup(realm ? realm : "Secure Area");
- session->cb = cb;
- session->cbpw = cbpw;
- session->x = builder;
- session->wnd = wnd;
- session->user = euser;
- session->pass = epass;
-
- /* fill in our new login window */
-
- gtk_label_set_text(GTK_LABEL(lhost), lwc_string_data(host));
- gtk_label_set_text(lrealm, realm);
- gtk_entry_set_text(euser, "");
- gtk_entry_set_text(epass, "");
-
- /* attach signal handlers to the Login and Cancel buttons in our new
- * window to call functions in this file to process the login
- */
- g_signal_connect(G_OBJECT(bok), "clicked",
- G_CALLBACK(nsgtk_login_ok_clicked), (gpointer)session);
- g_signal_connect(G_OBJECT(bcan), "clicked",
- G_CALLBACK(nsgtk_login_cancel_clicked),
- (gpointer)session);
-
- /* attach signal handlers to the entry boxes such that pressing
- * enter in one progresses the focus onto the next widget.
- */
-
- g_signal_connect(G_OBJECT(euser), "activate",
- G_CALLBACK(nsgtk_login_next), (gpointer)epass);
- g_signal_connect(G_OBJECT(epass), "activate",
- G_CALLBACK(nsgtk_login_next), (gpointer)bok);
-
- /* make sure the username entry box currently has the focus */
- gtk_widget_grab_focus(GTK_WIDGET(euser));
-
- /* finally, show the window */
- gtk_widget_show(GTK_WIDGET(wnd));
-
- return NSERROR_OK;
-}
-
-
-/* exported function documented in gtk/login.h */
-void gui_401login_open(nsurl *url,
- const char *realm,
- nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
-{
- lwc_string *host;
- nserror res;
-
- host = nsurl_get_component(url, NSURL_HOST);
- assert(host != NULL);
-
- res = create_login_window(url, host, realm, cb, cbpw);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Login init failed");
-
- /* creating login failed so cancel navigation */
- cb(false, cbpw);
- }
-
- lwc_string_unref(host);
-}
diff --git a/frontends/gtk/menu.c b/frontends/gtk/menu.c
index 6a6033231..03056d2a8 100644
--- a/frontends/gtk/menu.c
+++ b/frontends/gtk/menu.c
@@ -49,12 +49,12 @@ nsgtk_menu_add_image_item(GtkMenu *menu,
GdkModifierType mod;
GtkWidget *item;
const char *accelerator_desc; /* accelerator key description */
-
+
item = nsgtk_image_menu_item_new_with_mnemonic(messages_get(message));
if (item == NULL) {
return false;
}
-
+
accelerator_desc = nsgtk_accelerator_get_desc(message);
if (accelerator_desc != NULL) {
gtk_accelerator_parse(accelerator_desc, &key, &mod);
@@ -85,15 +85,17 @@ nsgtk_menu_add_image_item(GtkMenu *menu,
#define IMAGE_ITEM(p, q, r, s, t)\
nsgtk_menu_add_image_item(s->p##_menu, &(s->q##_menuitem), #r, t)
-#define CHECK_ITEM(p, q, r, s)\
- s->q##_menuitem = GTK_CHECK_MENU_ITEM(\
+#define CHECK_ITEM(p, q, r, s) \
+ do { \
+ s->q##_menuitem = GTK_CHECK_MENU_ITEM( \
gtk_check_menu_item_new_with_mnemonic(\
messages_get(#r)));\
- if ((s->q##_menuitem != NULL) && (s->p##_menu != NULL)) {\
- gtk_menu_shell_append(GTK_MENU_SHELL(s->p##_menu),\
- GTK_WIDGET(s->q##_menuitem));\
- gtk_widget_show(GTK_WIDGET(s->q##_menuitem));\
- }
+ if ((s->q##_menuitem != NULL) && (s->p##_menu != NULL)) { \
+ gtk_menu_shell_append(GTK_MENU_SHELL(s->p##_menu), \
+ GTK_WIDGET(s->q##_menuitem)); \
+ gtk_widget_show(GTK_WIDGET(s->q##_menuitem)); \
+ } \
+ } while(0)
#define SET_SUBMENU(q, r) \
do { \
@@ -142,21 +144,23 @@ nsgtk_menu_add_image_item(GtkMenu *menu,
static struct nsgtk_export_submenu *
nsgtk_menu_export_submenu(GtkAccelGroup *group)
{
- struct nsgtk_export_submenu *ret = malloc(sizeof(struct
- nsgtk_export_submenu));
+ struct nsgtk_export_submenu *ret;
+ ret = malloc(sizeof(struct nsgtk_export_submenu));
+
if (ret == NULL) {
nsgtk_warning(messages_get("NoMemory"), 0);
return NULL;
}
+
ret->export_menu = GTK_MENU(gtk_menu_new());
if (ret->export_menu == NULL) {
nsgtk_warning(messages_get("NoMemory"), 0);
free(ret);
return NULL;
}
+
+ IMAGE_ITEM(export, savepage, gtkSavePage, ret, group);
IMAGE_ITEM(export, plaintext, gtkPlainText, ret, group);
- IMAGE_ITEM(export, drawfile, gtkDrawFile, ret, group);
- IMAGE_ITEM(export, postscript, gtkPostScript, ret, group);
IMAGE_ITEM(export, pdf, gtkPDF, ret, group);
return ret;
}
@@ -213,57 +217,45 @@ static struct nsgtk_tabs_submenu *nsgtk_menu_tabs_submenu(GtkAccelGroup *group)
return ret;
}
-/**
-* creates an images submenu
-* \param group the 'global' in a gtk sense accelerator reference
-*/
-static struct nsgtk_images_submenu *nsgtk_menu_images_submenu(GtkAccelGroup *group)
+/**
+ * creates a toolbars submenu
+ *
+ * \param group the 'global' in a gtk sense accelerator reference
+ */
+static struct nsgtk_toolbars_submenu *
+nsgtk_menu_toolbars_submenu(GtkAccelGroup *group)
{
- struct nsgtk_images_submenu *ret =
- malloc(sizeof(struct nsgtk_images_submenu));
- if (ret == NULL) {
+ struct nsgtk_toolbars_submenu *tmenu;
+
+ tmenu = malloc(sizeof(struct nsgtk_toolbars_submenu));
+ if (tmenu == NULL) {
nsgtk_warning(messages_get("NoMemory"), 0);
return NULL;
}
- ret->images_menu = GTK_MENU(gtk_menu_new());
- if (ret->images_menu == NULL) {
+
+ tmenu->toolbars_menu = GTK_MENU(gtk_menu_new());
+ if (tmenu->toolbars_menu == NULL) {
nsgtk_warning(messages_get("NoMemory"), 0);
- free(ret);
+ free(tmenu);
return NULL;
}
- CHECK_ITEM(images, foregroundimages, gtkForegroundImages, ret)
- CHECK_ITEM(images, backgroundimages, gtkBackgroundImages, ret)
- return ret;
-}
-
-/**
-* creates a toolbars submenu
-* \param group the 'global' in a gtk sense accelerator reference
-*/
-static struct nsgtk_toolbars_submenu *nsgtk_menu_toolbars_submenu(
- GtkAccelGroup *group)
-{
- struct nsgtk_toolbars_submenu *ret =
- malloc(sizeof(struct nsgtk_toolbars_submenu));
- if (ret == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- return NULL;
+ CHECK_ITEM(toolbars, menubar, gtkMenuBar, tmenu);
+ if (tmenu->menubar_menuitem != NULL) {
+ gtk_check_menu_item_set_active(tmenu->menubar_menuitem, TRUE);
}
- ret->toolbars_menu = GTK_MENU(gtk_menu_new());
- if (ret->toolbars_menu == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- free(ret);
- return NULL;
+
+ CHECK_ITEM(toolbars, toolbar, gtkToolBar, tmenu);
+ if (tmenu->toolbar_menuitem != NULL) {
+ gtk_check_menu_item_set_active(tmenu->toolbar_menuitem, TRUE);
}
- CHECK_ITEM(toolbars, menubar, gtkMenuBar, ret)
- if (ret->menubar_menuitem != NULL)
- gtk_check_menu_item_set_active(ret->menubar_menuitem, TRUE);
- CHECK_ITEM(toolbars, toolbar, gtkToolBar, ret)
- if (ret->toolbar_menuitem != NULL)
- gtk_check_menu_item_set_active(ret->toolbar_menuitem, TRUE);
- return ret;
+
+ ADD_SEP(toolbars, tmenu);
+
+ IMAGE_ITEM(toolbars, customize, gtkCustomize, tmenu, group);
+
+ return tmenu;
}
/**
@@ -271,8 +263,8 @@ static struct nsgtk_toolbars_submenu *nsgtk_menu_toolbars_submenu(
* \param group the 'global' in a gtk sense accelerator reference
*/
-static struct nsgtk_developer_submenu *nsgtk_menu_developer_submenu(
- GtkAccelGroup *group)
+static struct nsgtk_developer_submenu *
+nsgtk_menu_developer_submenu(GtkAccelGroup *group)
{
struct nsgtk_developer_submenu *dmenu =
malloc(sizeof(struct nsgtk_developer_submenu));
@@ -323,7 +315,6 @@ static struct nsgtk_file_menu *nsgtk_menu_file_submenu(GtkAccelGroup *group)
IMAGE_ITEM(file, openfile, gtkOpenFile, fmenu, group);
IMAGE_ITEM(file, closewindow, gtkCloseWindow, fmenu, group);
ADD_SEP(file, fmenu);
- IMAGE_ITEM(file, savepage, gtkSavePage, fmenu, group);
IMAGE_ITEM(file, export, gtkExport, fmenu, group);
ADD_SEP(file, fmenu);
IMAGE_ITEM(file, printpreview, gtkPrintPreview, fmenu, group);
@@ -385,22 +376,16 @@ static struct nsgtk_view_menu *nsgtk_menu_view_submenu(GtkAccelGroup *group)
free(ret);
return NULL;
}
- IMAGE_ITEM(view, stop, gtkStop, ret, group);
- IMAGE_ITEM(view, reload, gtkReload, ret, group);
- ADD_SEP(view, ret);
IMAGE_ITEM(view, scaleview, gtkScaleView, ret, group);
+ SET_SUBMENU(scaleview, ret);
IMAGE_ITEM(view, fullscreen, gtkFullScreen, ret, group);
ADD_SEP(view, ret);
- IMAGE_ITEM(view, images, gtkImages, ret, group);
IMAGE_ITEM(view, toolbars, gtkToolbars, ret, group);
+ SET_SUBMENU(toolbars, ret);
IMAGE_ITEM(view, tabs, gtkTabs, ret, group);
+ SET_SUBMENU(tabs, ret);
ADD_SEP(view, ret);
IMAGE_ITEM(view, savewindowsize, gtkSaveWindowSize, ret, group);
- SET_SUBMENU(scaleview, ret);
- SET_SUBMENU(images, ret);
- SET_SUBMENU(toolbars, ret);
- SET_SUBMENU(tabs, ret);
-
return ret;
}
@@ -426,6 +411,8 @@ static struct nsgtk_nav_menu *nsgtk_menu_nav_submenu(GtkAccelGroup *group)
IMAGE_ITEM(nav, back, gtkBack, ret, group);
IMAGE_ITEM(nav, forward, gtkForward, ret, group);
+ IMAGE_ITEM(nav, stop, gtkStop, ret, group);
+ IMAGE_ITEM(nav, reload, gtkReload, ret, group);
IMAGE_ITEM(nav, home, gtkHome, ret, group);
ADD_SEP(nav, ret);
IMAGE_ITEM(nav, localhistory, gtkLocalHistory, ret, group);
@@ -436,7 +423,6 @@ static struct nsgtk_nav_menu *nsgtk_menu_nav_submenu(GtkAccelGroup *group)
ADD_SEP(nav, ret);
IMAGE_ITEM(nav, openlocation, gtkOpenLocation, ret, group);
-
return ret;
}
@@ -531,44 +517,61 @@ nsgtk_menu_bar_create(GtkMenuShell *menubar, GtkAccelGroup *group)
return nmenu;
}
+
/* exported function documented in gtk/menu.h */
-struct nsgtk_popup_menu *nsgtk_popup_menu_create(GtkAccelGroup *group)
+struct nsgtk_burger_menu *nsgtk_burger_menu_create(GtkAccelGroup *group)
{
- struct nsgtk_popup_menu *nmenu;
+ struct nsgtk_burger_menu *nmenu;
- NEW_MENU(nmenu, popup);
+ NEW_MENU(nmenu, burger);
- IMAGE_ITEM(popup, file, gtkFile, nmenu, group);
+ IMAGE_ITEM(burger, file, gtkFile, nmenu, group);
SET_SUBMENU(file, nmenu);
- IMAGE_ITEM(popup, edit, gtkEdit, nmenu, group);
+ IMAGE_ITEM(burger, edit, gtkEdit, nmenu, group);
SET_SUBMENU(edit, nmenu);
- IMAGE_ITEM(popup, view, gtkView, nmenu, group);
+ IMAGE_ITEM(burger, view, gtkView, nmenu, group);
SET_SUBMENU(view, nmenu);
- IMAGE_ITEM(popup, nav, gtkNavigate, nmenu, group);
+ IMAGE_ITEM(burger, nav, gtkNavigate, nmenu, group);
SET_SUBMENU(nav, nmenu);
- IMAGE_ITEM(popup, tools, gtkTools, nmenu, group);
+ IMAGE_ITEM(burger, tools, gtkTools, nmenu, group);
SET_SUBMENU(tools, nmenu);
- IMAGE_ITEM(popup, help, gtkHelp, nmenu, group);
+ IMAGE_ITEM(burger, help, gtkHelp, nmenu, group);
SET_SUBMENU(help, nmenu);
- ADD_NAMED_SEP(popup, first, nmenu);
+ return nmenu;
+}
- IMAGE_ITEM(popup, back, gtkBack, nmenu, group);
- IMAGE_ITEM(popup, forward, gtkForward, nmenu, group);
- ADD_NAMED_SEP(popup, third, nmenu);
+/* exported function documented in gtk/menu.h */
+struct nsgtk_popup_menu *nsgtk_popup_menu_create(GtkAccelGroup *group)
+{
+ struct nsgtk_popup_menu *nmenu;
+
+ NEW_MENU(nmenu, popup);
+ IMAGE_ITEM(popup, back, gtkBack, nmenu, group);
+ IMAGE_ITEM(popup, forward, gtkForward, nmenu, group);
IMAGE_ITEM(popup, stop, gtkStop, nmenu, group);
IMAGE_ITEM(popup, reload, gtkReload, nmenu, group);
+
+ ADD_NAMED_SEP(popup, first, nmenu);
+
IMAGE_ITEM(popup, cut, gtkCut, nmenu, group);
IMAGE_ITEM(popup, copy, gtkCopy, nmenu, group);
IMAGE_ITEM(popup, paste, gtkPaste, nmenu, group);
- IMAGE_ITEM(popup, customize, gtkCustomize, nmenu, group);
+
+ ADD_NAMED_SEP(popup, second, nmenu);
+
+ IMAGE_ITEM(popup, toolbars, gtkToolbars, nmenu, group);
+ SET_SUBMENU(toolbars, nmenu);
+
+ IMAGE_ITEM(popup, tools, gtkTools, nmenu, group);
+ SET_SUBMENU(tools, nmenu);
return nmenu;
}
@@ -593,3 +596,71 @@ nsgtk_link_menu_create(GtkAccelGroup *group)
return nmenu;
}
+
+
+/* exported function documented in gtk/menu.h */
+nserror nsgtk_menu_bar_destroy(struct nsgtk_bar_submenu *menu)
+{
+ gtk_widget_destroy(GTK_WIDGET(menu->bar_menu));
+
+ free(menu->file_submenu->export_submenu);
+ free(menu->file_submenu);
+ free(menu->edit_submenu);
+ free(menu->view_submenu->tabs_submenu);
+ free(menu->view_submenu->toolbars_submenu);
+ free(menu->view_submenu->scaleview_submenu);
+ free(menu->view_submenu);
+ free(menu->nav_submenu);
+ free(menu->tools_submenu->developer_submenu);
+ free(menu->tools_submenu);
+ free(menu->help_submenu);
+ free(menu);
+
+ return NSERROR_OK;
+}
+
+/* exported function documented in gtk/menu.h */
+nserror nsgtk_burger_menu_destroy(struct nsgtk_burger_menu *menu)
+{
+ gtk_widget_destroy(GTK_WIDGET(menu->burger_menu));
+
+ free(menu->file_submenu->export_submenu);
+ free(menu->file_submenu);
+ free(menu->edit_submenu);
+ free(menu->view_submenu->tabs_submenu);
+ free(menu->view_submenu->toolbars_submenu);
+ free(menu->view_submenu->scaleview_submenu);
+ free(menu->view_submenu);
+ free(menu->nav_submenu);
+ free(menu->tools_submenu->developer_submenu);
+ free(menu->tools_submenu);
+ free(menu->help_submenu);
+ free(menu);
+
+ return NSERROR_OK;
+}
+
+
+/* exported function documented in gtk/menu.h */
+nserror nsgtk_popup_menu_destroy(struct nsgtk_popup_menu *menu)
+{
+ gtk_widget_destroy(GTK_WIDGET(menu->popup_menu));
+
+ free(menu->toolbars_submenu);
+ free(menu->tools_submenu->developer_submenu);
+ free(menu->tools_submenu);
+ free(menu);
+
+ return NSERROR_OK;
+}
+
+
+/* exported function documented in gtk/menu.h */
+nserror nsgtk_link_menu_destroy(struct nsgtk_link_menu *menu)
+{
+ gtk_widget_destroy(GTK_WIDGET(menu->link_menu));
+
+ free(menu);
+
+ return NSERROR_OK;
+}
diff --git a/frontends/gtk/menu.h b/frontends/gtk/menu.h
index 5da5cb1b2..cf63b334a 100644
--- a/frontends/gtk/menu.h
+++ b/frontends/gtk/menu.h
@@ -15,66 +15,68 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_GTK_MENU_H_
-#define _NETSURF_GTK_MENU_H_
+#ifndef NETSURF_GTK_MENU_H_
+#define NETSURF_GTK_MENU_H_
#include <gtk/gtk.h>
+/**
+ * File menu item on menubar
+ */
struct nsgtk_file_menu {
- GtkMenuItem *file; /* File menu item on menubar */
- GtkMenu *file_menu;
- GtkWidget *newwindow_menuitem;
- GtkWidget *newtab_menuitem;
- GtkWidget *openfile_menuitem;
- GtkWidget *closewindow_menuitem;
- GtkWidget *savepage_menuitem;
- GtkWidget *export_menuitem;
- struct nsgtk_export_submenu *export_submenu;
- GtkWidget *printpreview_menuitem;
- GtkWidget *print_menuitem;
- GtkWidget *quit_menuitem;
+ GtkMenuItem *file;
+ GtkMenu *file_menu;
+ GtkWidget *newwindow_menuitem;
+ GtkWidget *newtab_menuitem;
+ GtkWidget *openfile_menuitem;
+ GtkWidget *closewindow_menuitem;
+ GtkWidget *export_menuitem;
+ struct nsgtk_export_submenu *export_submenu;
+ GtkWidget *printpreview_menuitem;
+ GtkWidget *print_menuitem;
+ GtkWidget *quit_menuitem;
};
struct nsgtk_edit_menu {
- GtkMenuItem *edit; /* Edit menu item on menubar */
- GtkMenu *edit_menu;
- GtkWidget *cut_menuitem;
- GtkWidget *copy_menuitem;
- GtkWidget *paste_menuitem;
- GtkWidget *delete_menuitem;
- GtkWidget *selectall_menuitem;
- GtkWidget *find_menuitem;
- GtkWidget *preferences_menuitem;
+ GtkMenuItem *edit; /* Edit menu item on menubar */
+ GtkMenu *edit_menu;
+ GtkWidget *cut_menuitem;
+ GtkWidget *copy_menuitem;
+ GtkWidget *paste_menuitem;
+ GtkWidget *delete_menuitem;
+ GtkWidget *selectall_menuitem;
+ GtkWidget *find_menuitem;
+ GtkWidget *preferences_menuitem;
};
struct nsgtk_view_menu {
- GtkMenuItem *view; /* View menu item on menubar */
- GtkMenu *view_menu; /* gtk menu attached to menu item */
- GtkWidget *stop_menuitem;
- GtkWidget *reload_menuitem;
- GtkWidget *scaleview_menuitem;
+ GtkMenuItem *view; /* View menu item on menubar */
+ GtkMenu *view_menu; /* gtk menu attached to menu item */
+
+ GtkWidget *scaleview_menuitem;
struct nsgtk_scaleview_submenu *scaleview_submenu;
- GtkWidget *fullscreen_menuitem;
- GtkWidget *images_menuitem;
- struct nsgtk_images_submenu *images_submenu;
- GtkWidget *toolbars_menuitem;
- struct nsgtk_toolbars_submenu *toolbars_submenu;
- GtkWidget *tabs_menuitem;
- struct nsgtk_tabs_submenu *tabs_submenu;
- GtkWidget *savewindowsize_menuitem;
+ GtkWidget *fullscreen_menuitem;
+ GtkWidget *toolbars_menuitem;
+ struct nsgtk_toolbars_submenu *toolbars_submenu;
+ GtkWidget *tabs_menuitem;
+ struct nsgtk_tabs_submenu *tabs_submenu;
+ GtkWidget *savewindowsize_menuitem;
};
struct nsgtk_nav_menu {
- GtkMenuItem *nav; /* Nav menu item on menubar */
- GtkMenu *nav_menu;
- GtkWidget *back_menuitem;
- GtkWidget *forward_menuitem;
- GtkWidget *home_menuitem;
- GtkWidget *localhistory_menuitem;
- GtkWidget *globalhistory_menuitem;
- GtkWidget *addbookmarks_menuitem;
- GtkWidget *showbookmarks_menuitem;
- GtkWidget *openlocation_menuitem;
+ GtkMenuItem *nav; /* Nav menu item on menubar */
+ GtkMenu *nav_menu;
+
+ GtkWidget *back_menuitem;
+ GtkWidget *forward_menuitem;
+ GtkWidget *stop_menuitem;
+ GtkWidget *reload_menuitem;
+ GtkWidget *home_menuitem;
+ GtkWidget *localhistory_menuitem;
+ GtkWidget *globalhistory_menuitem;
+ GtkWidget *addbookmarks_menuitem;
+ GtkWidget *showbookmarks_menuitem;
+ GtkWidget *openlocation_menuitem;
};
struct nsgtk_tools_menu {
@@ -88,47 +90,41 @@ struct nsgtk_tools_menu {
};
struct nsgtk_help_menu {
- GtkMenuItem *help; /* Help menu item on menubar */
- GtkMenu *help_menu;
- GtkWidget *contents_menuitem;
- GtkWidget *guide_menuitem;
- GtkWidget *info_menuitem;
- GtkWidget *about_menuitem;
+ GtkMenuItem *help; /* Help menu item on menubar */
+ GtkMenu *help_menu;
+ GtkWidget *contents_menuitem;
+ GtkWidget *guide_menuitem;
+ GtkWidget *info_menuitem;
+ GtkWidget *about_menuitem;
};
struct nsgtk_export_submenu {
- GtkMenu *export_menu;
- GtkWidget *plaintext_menuitem;
- GtkWidget *drawfile_menuitem;
- GtkWidget *postscript_menuitem;
- GtkWidget *pdf_menuitem;
+ GtkMenu *export_menu;
+ GtkWidget *savepage_menuitem;
+ GtkWidget *plaintext_menuitem;
+ GtkWidget *pdf_menuitem;
};
struct nsgtk_scaleview_submenu {
- GtkMenu *scaleview_menu;
- GtkWidget *zoomplus_menuitem;
- GtkWidget *zoomminus_menuitem;
- GtkWidget *zoomnormal_menuitem;
+ GtkMenu *scaleview_menu;
+ GtkWidget *zoomplus_menuitem;
+ GtkWidget *zoomminus_menuitem;
+ GtkWidget *zoomnormal_menuitem;
};
struct nsgtk_tabs_submenu {
- GtkMenu *tabs_menu;
- GtkWidget *nexttab_menuitem;
- GtkWidget *prevtab_menuitem;
- GtkWidget *closetab_menuitem;
-};
-
-struct nsgtk_images_submenu {
- GtkMenu *images_menu;
- GtkCheckMenuItem *foregroundimages_menuitem;
- GtkCheckMenuItem *backgroundimages_menuitem;
+ GtkMenu *tabs_menu;
+ GtkWidget *nexttab_menuitem;
+ GtkWidget *prevtab_menuitem;
+ GtkWidget *closetab_menuitem;
};
struct nsgtk_toolbars_submenu {
- GtkMenu *toolbars_menu;
- GtkCheckMenuItem *menubar_menuitem;
- GtkCheckMenuItem *toolbar_menuitem;
+ GtkMenu *toolbars_menu;
+ GtkCheckMenuItem *menubar_menuitem;
+ GtkCheckMenuItem *toolbar_menuitem;
+ GtkWidget *customize_menuitem;
};
struct nsgtk_developer_submenu {
@@ -140,20 +136,21 @@ struct nsgtk_developer_submenu {
GtkWidget *debugdomtree_menuitem;
};
-
+/**
+ * main menubar
+ */
struct nsgtk_bar_submenu {
GtkMenuBar *bar_menu;
struct nsgtk_file_menu *file_submenu;
struct nsgtk_edit_menu *edit_submenu;
struct nsgtk_view_menu *view_submenu;
struct nsgtk_nav_menu *nav_submenu;
- struct nsgtk_tabs_submenu *tabs_submenu;
struct nsgtk_tools_menu *tools_submenu;
struct nsgtk_help_menu *help_submenu;
};
-struct nsgtk_popup_menu {
- GtkMenu *popup_menu;
+struct nsgtk_burger_menu {
+ GtkMenu *burger_menu;
GtkWidget *file_menuitem;
struct nsgtk_file_menu *file_submenu;
@@ -167,32 +164,35 @@ struct nsgtk_popup_menu {
GtkWidget *nav_menuitem;
struct nsgtk_nav_menu *nav_submenu;
- GtkWidget *tabs_menuitem;
- struct nsgtk_tabs_submenu *tabs_submenu;
-
GtkWidget *tools_menuitem;
struct nsgtk_tools_menu *tools_submenu;
GtkWidget *help_menuitem;
struct nsgtk_help_menu *help_submenu;
+};
- GtkWidget *first_separator;
+struct nsgtk_popup_menu {
+ GtkMenu *popup_menu;
/* navigation entries */
GtkWidget *back_menuitem;
GtkWidget *forward_menuitem;
-
- GtkWidget *third_separator;
-
- /* view entries */
GtkWidget *stop_menuitem;
GtkWidget *reload_menuitem;
+ GtkWidget *first_separator;
+
+ /* edit entries */
GtkWidget *cut_menuitem;
GtkWidget *copy_menuitem;
GtkWidget *paste_menuitem;
- GtkWidget *customize_menuitem;
+ GtkWidget *second_separator;
+
+ GtkWidget *toolbars_menuitem;
+ struct nsgtk_toolbars_submenu *toolbars_submenu;
+ GtkWidget *tools_menuitem;
+ struct nsgtk_tools_menu *tools_submenu;
};
struct nsgtk_link_menu {
@@ -206,22 +206,82 @@ struct nsgtk_link_menu {
GtkWidget *copy_menuitem;
};
+
/**
- * Create main menu bar.
+ * Create main menubar menu.
*/
struct nsgtk_bar_submenu *nsgtk_menu_bar_create(GtkMenuShell *menubar, GtkAccelGroup *group);
+
+/**
+ * Generate burger menu.
+ *
+ * \param accelerator group to use with menu
+ * \return new menu structure or NULL on error
+ */
+struct nsgtk_burger_menu *nsgtk_burger_menu_create(GtkAccelGroup *group);
+
+
/**
- * Generate right click menu menu.
+ * Generate right click popup menu.
*
+ * \param accelerator group to use with menu
+ * \return new menu structure or NULL on error
*/
struct nsgtk_popup_menu *nsgtk_popup_menu_create(GtkAccelGroup *group);
+
/**
- * Generate context sensitive popup menu for link.
+ * Generate context sensitive link popup menu.
*
+ * \param accelerator group to use with menu
+ * \return new menu structure or NULL on error
*/
struct nsgtk_link_menu *nsgtk_link_menu_create(GtkAccelGroup *group);
+/**
+ * destroy bar menu
+ *
+ * destroys the gtk widgets associated with menu and frees all storage.
+ *
+ * \param menu menu to destroy
+ * \return NSERROR_OK and menu destroyed on success else error code
+ */
+nserror nsgtk_menu_bar_destroy(struct nsgtk_bar_submenu *menu);
+
+
+/**
+ * destroy burger menu
+ *
+ * destroys the gtk widgets associated with menu and frees all storage.
+ *
+ * \param menu menu to destroy
+ * \return NSERROR_OK and menu destroyed on success else error code
+ */
+nserror nsgtk_burger_menu_destroy(struct nsgtk_burger_menu *menu);
+
+
+/**
+ * destroy popup menu
+ *
+ * destroys the gtk widgets associated with menu and frees all storage.
+ *
+ * \param menu menu to destroy
+ * \return NSERROR_OK and menu destroyed on success else error code
+ */
+nserror nsgtk_popup_menu_destroy(struct nsgtk_popup_menu *menu);
+
+
+/**
+ * destroy link menu
+ *
+ * destroys the gtk widgets associated with menu and frees all storage.
+ *
+ * \param menu menu to destroy
+ * \return NSERROR_OK and menu destroyed on success else error code
+ */
+nserror nsgtk_link_menu_destroy(struct nsgtk_link_menu *menu);
+
+
#endif
diff --git a/frontends/gtk/misc.c b/frontends/gtk/misc.c
new file mode 100644
index 000000000..8ab1d914c
--- /dev/null
+++ b/frontends/gtk/misc.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2021 Vincemt Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of netsurf miscellaneous operations table
+ */
+
+#include <string.h>
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+#include "utils/config.h"
+#include "utils/errors.h"
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "utils/nsurl.h"
+#include "netsurf/misc.h"
+#include "desktop/save_pdf.h"
+
+#include "gtk/compat.h"
+#include "gtk/warn.h"
+#include "gtk/schedule.h"
+#include "gtk/resources.h"
+#include "gtk/cookies.h"
+#include "gtk/misc.h"
+
+
+static nserror gui_launch_url(struct nsurl *url)
+{
+ gboolean ok;
+ GError *error = NULL;
+
+ ok = nsgtk_show_uri(NULL, nsurl_access(url), GDK_CURRENT_TIME, &error);
+ if (ok == TRUE) {
+ return NSERROR_OK;
+ }
+
+ if (error) {
+ nsgtk_warning(messages_get("URIOpenError"), error->message);
+ g_error_free(error);
+ }
+ return NSERROR_NO_FETCH_HANDLER;
+}
+
+static void nsgtk_PDF_set_pass(GtkButton *w, gpointer data)
+{
+ char **owner_pass = ((void **)data)[0];
+ char **user_pass = ((void **)data)[1];
+ GtkWindow *wnd = ((void **)data)[2];
+ GtkBuilder *password_builder = ((void **)data)[3];
+ char *path = ((void **)data)[4];
+
+ char *op, *op1;
+ char *up, *up1;
+
+ op = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFOwnerPassword"))));
+ op1 = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFOwnerPassword1"))));
+ up = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFUserPassword"))));
+ up1 = strdup(gtk_entry_get_text(
+ GTK_ENTRY(gtk_builder_get_object(password_builder,
+ "entryPDFUserPassword1"))));
+
+
+ if (op[0] == '\0') {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")),
+ "Owner password must be at least 1 character long:");
+ free(op);
+ free(up);
+ } else if (!strcmp(op, up)) {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")),
+ "User and owner passwords must be different:");
+ free(op);
+ free(up);
+ } else if (!strcmp(op, op1) && !strcmp(up, up1)) {
+
+ *owner_pass = op;
+ if (up[0] == '\0')
+ free(up);
+ else
+ *user_pass = up;
+
+ free(data);
+ gtk_widget_destroy(GTK_WIDGET(wnd));
+ g_object_unref(G_OBJECT(password_builder));
+
+ save_pdf(path);
+
+ free(path);
+ } else {
+ gtk_label_set_text(GTK_LABEL(gtk_builder_get_object(password_builder,
+ "labelInfo")), "Passwords not confirmed:");
+ free(op);
+ free(up);
+ }
+
+ free(op1);
+ free(up1);
+}
+
+static void nsgtk_PDF_no_pass(GtkButton *w, gpointer data)
+{
+ GtkWindow *wnd = ((void **)data)[2];
+ GtkBuilder *password_builder = ((void **)data)[3];
+ char *path = ((void **)data)[4];
+
+ free(data);
+
+ gtk_widget_destroy(GTK_WIDGET(wnd));
+ g_object_unref(G_OBJECT(password_builder));
+
+ save_pdf(path);
+
+ free(path);
+}
+
+static void nsgtk_pdf_password(char **owner_pass, char **user_pass, char *path)
+{
+ GtkButton *ok, *no;
+ GtkWindow *wnd;
+ void **data;
+ GtkBuilder *password_builder;
+ nserror res;
+
+ res = nsgtk_builder_new_from_resname("password", &password_builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Password UI builder init failed");
+ return;
+ }
+
+ gtk_builder_connect_signals(password_builder, NULL);
+
+ wnd = GTK_WINDOW(gtk_builder_get_object(password_builder,
+ "wndPDFPassword"));
+
+ data = malloc(5 * sizeof(void *));
+
+ *owner_pass = NULL;
+ *user_pass = NULL;
+
+ data[0] = owner_pass;
+ data[1] = user_pass;
+ data[2] = wnd;
+ data[3] = password_builder;
+ data[4] = path;
+
+ ok = GTK_BUTTON(gtk_builder_get_object(password_builder,
+ "buttonPDFSetPassword"));
+ no = GTK_BUTTON(gtk_builder_get_object(password_builder,
+ "buttonPDFNoPassword"));
+
+ g_signal_connect(G_OBJECT(ok), "clicked",
+ G_CALLBACK(nsgtk_PDF_set_pass), (gpointer)data);
+ g_signal_connect(G_OBJECT(no), "clicked",
+ G_CALLBACK(nsgtk_PDF_no_pass), (gpointer)data);
+
+ gtk_widget_show(GTK_WIDGET(wnd));
+}
+
+
+static struct gui_misc_table misc_table = {
+ .schedule = nsgtk_schedule,
+
+ .launch_url = gui_launch_url,
+ .pdf_password = nsgtk_pdf_password,
+ .present_cookies = nsgtk_cookies_present,
+};
+
+struct gui_misc_table *nsgtk_misc_table = &misc_table;
diff --git a/frontends/gtk/login.h b/frontends/gtk/misc.h
index 00c29000c..3a02c2254 100644
--- a/frontends/gtk/login.h
+++ b/frontends/gtk/misc.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
+ * Copyright 2021 Vincemt Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,16 +16,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-/** \file
- * Login interfaces.
- */
-
-#ifndef __NSGTK_LOGIN_H__
-#define __NSGTK_LOGIN_H__
+#ifndef NETSURF_GTK_MISC_H
+#define NETSURF_GTK_MISC_H 1
-/**
- * login window request.
- */
-extern void gui_401login_open(struct nsurl *url, const char *realm, nserror (*cb)(bool proceed, void *pw), void *cbpw);
+extern struct gui_misc_table *nsgtk_misc_table;
#endif
diff --git a/frontends/gtk/options.h b/frontends/gtk/options.h
index 018a448be..7fd79d7c5 100644
--- a/frontends/gtk/options.h
+++ b/frontends/gtk/options.h
@@ -16,16 +16,13 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_GTK_OPTIONS_H_
-#define _NETSURF_GTK_OPTIONS_H_
+#ifndef NETSURF_GTK_OPTIONS_H_
+#define NETSURF_GTK_OPTIONS_H_
/* currently nothing here */
#endif
-/* High quality image scaling */
-NSOPTION_BOOL(render_resample, true)
-
/* clear downloads */
NSOPTION_BOOL(downloads_clear, false)
@@ -47,9 +44,6 @@ NSOPTION_INTEGER(button_type, 0)
/* disallow popup windows */
NSOPTION_BOOL(disable_popups, false)
-/* disable content plugins */
-NSOPTION_BOOL(disable_plugins, false)
-
/* number of days to keep history data */
NSOPTION_INTEGER(history_age, 0)
@@ -72,4 +66,7 @@ NSOPTION_INTEGER(developer_view, 0)
NSOPTION_INTEGER(position_tab, 0)
/* Toolbar customisation */
-NSOPTION_STRING(toolbar_order, NULL)
+NSOPTION_STRING(toolbar_items, NULL)
+
+/* The menu and tool bars that are shown */
+NSOPTION_STRING(bar_show, NULL)
diff --git a/frontends/gtk/page_info.c b/frontends/gtk/page_info.c
new file mode 100644
index 000000000..0d76a2f71
--- /dev/null
+++ b/frontends/gtk/page_info.c
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * \file
+ * Implementation of gtk certificate viewing using gtk core windows.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <gtk/gtk.h>
+
+#include "utils/log.h"
+#include "utils/messages.h"
+#include "netsurf/keypress.h"
+#include "netsurf/plotters.h"
+#include "netsurf/misc.h"
+#include "netsurf/browser_window.h"
+#include "desktop/page-info.h"
+#include "desktop/gui_internal.h"
+
+#include "gtk/plotters.h"
+#include "gtk/scaffolding.h"
+#include "gtk/resources.h"
+#include "gtk/page_info.h"
+#include "gtk/corewindow.h"
+
+
+/**
+ * GTK certificate viewing window context
+ */
+struct nsgtk_pi_window {
+ /** GTK core window context */
+ struct nsgtk_corewindow core;
+ /** GTK builder for window */
+ GtkBuilder *builder;
+ /** GTK window being shown */
+ GtkWindow *dlg;
+ /** Core page-info window */
+ struct page_info *pi;
+};
+
+
+/**
+ * destroy a previously created page information window
+ */
+static gboolean
+nsgtk_pi_delete_event(GtkWidget *w, GdkEvent *event, gpointer data)
+{
+ struct nsgtk_pi_window *pi_win;
+ pi_win = (struct nsgtk_pi_window *)data;
+
+ page_info_destroy(pi_win->pi);
+
+ nsgtk_corewindow_fini(&pi_win->core);
+ gtk_widget_destroy(GTK_WIDGET(pi_win->dlg));
+ g_object_unref(G_OBJECT(pi_win->builder));
+ free(pi_win);
+
+ return FALSE;
+}
+
+/**
+ * Called to cause the page-info window to close cleanly
+ */
+static void
+nsgtk_pi_close_callback(void *pw)
+{
+ nsgtk_pi_delete_event(NULL, NULL, pw);
+}
+
+/**
+ * callback for mouse action for certificate verify on core window
+ *
+ * \param nsgtk_cw The nsgtk core window structure.
+ * \param mouse_state netsurf mouse state on event
+ * \param x location of event
+ * \param y location of event
+ * \return NSERROR_OK on success otherwise appropriate error code
+ */
+static nserror
+nsgtk_pi_mouse(struct nsgtk_corewindow *nsgtk_cw,
+ browser_mouse_state mouse_state,
+ int x, int y)
+{
+ struct nsgtk_pi_window *pi_win;
+ bool did_something = false;
+ /* technically degenerate container of */
+ pi_win = (struct nsgtk_pi_window *)nsgtk_cw;
+
+ if (page_info_mouse_action(pi_win->pi, mouse_state, x, y, &did_something) == NSERROR_OK) {
+ if (did_something == true) {
+ /* Something happened so we need to close ourselves */
+ guit->misc->schedule(0, nsgtk_pi_close_callback, pi_win);
+ }
+ }
+
+ return NSERROR_OK;
+}
+
+/**
+ * callback for keypress for certificate verify on core window
+ *
+ * \param nsgtk_cw The nsgtk core window structure.
+ * \param nskey The netsurf key code
+ * \return NSERROR_OK on success otherwise appropriate error code
+ */
+static nserror
+nsgtk_pi_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
+{
+ struct nsgtk_pi_window *pi_win;
+
+ /* technically degenerate container of */
+ pi_win = (struct nsgtk_pi_window *)nsgtk_cw;
+
+ if (page_info_keypress(pi_win->pi, nskey)) {
+ return NSERROR_OK;
+ }
+ return NSERROR_NOT_IMPLEMENTED;
+}
+
+/**
+ * callback on draw event for certificate verify on core window
+ *
+ * \param nsgtk_cw The nsgtk core window structure.
+ * \param r The rectangle of the window that needs updating.
+ * \return NSERROR_OK on success otherwise appropriate error code
+ */
+static nserror
+nsgtk_pi_draw(struct nsgtk_corewindow *nsgtk_cw, struct rect *r)
+{
+ struct redraw_context ctx = {
+ .interactive = true,
+ .background_images = true,
+ .plot = &nsgtk_plotters
+ };
+ struct nsgtk_pi_window *pi_win;
+
+ /* technically degenerate container of */
+ pi_win = (struct nsgtk_pi_window *)nsgtk_cw;
+
+ page_info_redraw(pi_win->pi, 0, 0, r, &ctx);
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in gtk/page_info.h */
+nserror nsgtk_page_info(struct browser_window *bw)
+{
+ struct nsgtk_pi_window *ncwin;
+ nserror res;
+ GtkWindow *scaffwin = nsgtk_scaffolding_window(nsgtk_current_scaffolding());
+
+ ncwin = calloc(1, sizeof(struct nsgtk_pi_window));
+ if (ncwin == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ res = nsgtk_builder_new_from_resname("pageinfo", &ncwin->builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, CRITICAL, "Page Info UI builder init failed %s", messages_get_errorcode(res));
+ free(ncwin);
+ return res;
+ }
+
+ gtk_builder_connect_signals(ncwin->builder, NULL);
+
+ ncwin->dlg = GTK_WINDOW(gtk_builder_get_object(ncwin->builder,
+ "PGIWindow"));
+
+ /* Configure for transient behaviour */
+ gtk_window_set_type_hint(GTK_WINDOW(ncwin->dlg),
+ GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU);
+
+ gtk_window_set_modal(GTK_WINDOW(ncwin->dlg), TRUE);
+
+ gtk_window_group_add_window(gtk_window_get_group(scaffwin),
+ GTK_WINDOW(ncwin->dlg));
+
+ gtk_window_set_transient_for(GTK_WINDOW(ncwin->dlg), scaffwin);
+
+ gtk_window_set_screen(GTK_WINDOW(ncwin->dlg),
+ gtk_widget_get_screen(GTK_WIDGET(scaffwin)));
+
+ /* Attempt to place the window in the right place */
+ nsgtk_scaffolding_position_page_info(nsgtk_current_scaffolding(),
+ ncwin);
+
+ ncwin->core.drawing_area = GTK_DRAWING_AREA(
+ gtk_builder_get_object(ncwin->builder, "PGIDrawingArea"));
+
+ /* make the delete event call our destructor */
+ g_signal_connect(G_OBJECT(ncwin->dlg),
+ "delete_event",
+ G_CALLBACK(nsgtk_pi_delete_event),
+ ncwin);
+ /* Ditto if we lose the grab */
+ g_signal_connect(G_OBJECT(ncwin->dlg),
+ "grab-broken-event",
+ G_CALLBACK(nsgtk_pi_delete_event),
+ ncwin);
+ /* Handle button press events */
+ g_signal_connect(G_OBJECT(ncwin->dlg),
+ "button-press-event",
+ G_CALLBACK(nsgtk_pi_delete_event),
+ ncwin);
+
+ /* initialise GTK core window */
+ ncwin->core.draw = nsgtk_pi_draw;
+ ncwin->core.key = nsgtk_pi_key;
+ ncwin->core.mouse = nsgtk_pi_mouse;
+
+ res = nsgtk_corewindow_init(&ncwin->core);
+ if (res != NSERROR_OK) {
+ g_object_unref(G_OBJECT(ncwin->dlg));
+ free(ncwin);
+ return res;
+ }
+
+ res = page_info_create(ncwin->core.cb_table,
+ (struct core_window *)ncwin,
+ bw, &ncwin->pi);
+ if (res != NSERROR_OK) {
+ g_object_unref(G_OBJECT(ncwin->dlg));
+ free(ncwin);
+ return res;
+ }
+
+ gtk_widget_show(GTK_WIDGET(ncwin->dlg));
+
+ gtk_widget_grab_focus(GTK_WIDGET(ncwin->dlg));
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in gtk/page_info.h */
+void
+nsgtk_page_info_set_position(struct nsgtk_pi_window *win, int x, int y)
+{
+ NSLOG(netsurf, INFO, "win=%p x=%d y=%d", win, x, y);
+
+ gtk_window_move(GTK_WINDOW(win->dlg), x, y);
+}
diff --git a/frontends/gtk/ssl_cert.h b/frontends/gtk/page_info.h
index 1712756e9..23e1e348c 100644
--- a/frontends/gtk/ssl_cert.h
+++ b/frontends/gtk/page_info.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 James Bursa <bursa@users.sourceforge.net>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,22 +16,25 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef NETSURF_GTK_SSL_CERT_H
-#define NETSURF_GTK_SSL_CERT_H 1
-
-struct nsurl;
-struct ssl_cert_info;
+#ifndef NETSURF_GTK_PAGE_INFO_H
+#define NETSURF_GTK_PAGE_INFO_H 1
/**
- * Prompt the user to verify a certificate with issuse.
+ * Page information window
*
- * \param url The URL being verified.
- * \param certs The certificate to be verified
- * \param num The number of certificates to be verified.
- * \param cb Callback upon user decision.
- * \param cbpw Context pointer passed to cb
+ * \param bw the browser window to get page information for
* \return NSERROR_OK or error code if prompt creation failed.
*/
-nserror gtk_cert_verify(struct nsurl *url, const struct ssl_cert_info *certs, unsigned long num, nserror (*cb)(bool proceed, void *pw), void *cbpw);
+nserror nsgtk_page_info(struct browser_window *bw);
+
+/**
+ * Position the given page information window at the given
+ * coordinates.
+ *
+ * \param pi the page info window to position
+ * \param x the X coordinate for the top left of the window
+ * \param y the Y coordinate for the top left of the window
+ */
+void nsgtk_page_info_set_position(struct nsgtk_pi_window *pi, int x, int y);
#endif
diff --git a/frontends/gtk/plotters.c b/frontends/gtk/plotters.c
index 88e7760c6..110dcffc5 100644
--- a/frontends/gtk/plotters.c
+++ b/frontends/gtk/plotters.c
@@ -89,6 +89,20 @@ static inline void nsgtk_set_dashed(void)
/**
+ * Set cairo context line width.
+ */
+static inline void nsgtk_set_line_width(plot_style_fixed width)
+{
+ if (width == 0) {
+ cairo_set_line_width(current_cr, 1);
+ } else {
+ cairo_set_line_width(current_cr,
+ plot_style_fixed_to_double(width));
+ }
+}
+
+
+/**
* \brief Sets a clip rectangle for subsequent plot operations.
*
* \param ctx The current redraw context.
@@ -191,10 +205,7 @@ nsgtk_plot_disc(const struct redraw_context *ctx,
break;
}
- if (style->stroke_width == 0)
- cairo_set_line_width(current_cr, 1);
- else
- cairo_set_line_width(current_cr, style->stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
cairo_arc(current_cr, x, y, radius, 0, M_PI * 2);
@@ -242,10 +253,7 @@ nsgtk_plot_line(const struct redraw_context *ctx,
nsgtk_set_colour(style->stroke_colour);
}
- if (style->stroke_width == 0)
- cairo_set_line_width(current_cr, 1);
- else
- cairo_set_line_width(current_cr, style->stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
/* core expects horizontal and vertical lines to be on pixels, not
* between pixels
@@ -331,10 +339,7 @@ nsgtk_plot_rectangle(const struct redraw_context *ctx,
break;
}
- if (style->stroke_width == 0)
- cairo_set_line_width(current_cr, 1);
- else
- cairo_set_line_width(current_cr, style->stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
cairo_rectangle(current_cr,
rect->x0 + 0.5,
@@ -394,7 +399,6 @@ nsgtk_plot_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -403,7 +407,6 @@ nsgtk_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
unsigned int i;
@@ -421,7 +424,7 @@ nsgtk_plot_path(const struct redraw_context *ctx,
cairo_get_matrix(current_cr, &old_ctm);
/* Set up line style and width */
- cairo_set_line_width(current_cr, 1);
+ nsgtk_set_line_width(pstyle->stroke_width);
nsgtk_set_solid();
/* Load new CTM */
@@ -429,8 +432,8 @@ nsgtk_plot_path(const struct redraw_context *ctx,
n_ctm.yx = transform[1];
n_ctm.xy = transform[2];
n_ctm.yy = transform[3];
- n_ctm.x0 = transform[4];
- n_ctm.y0 = transform[5];
+ n_ctm.x0 = transform[4] + old_ctm.x0;
+ n_ctm.y0 = transform[5] + old_ctm.y0;
cairo_set_matrix(current_cr, &n_ctm);
diff --git a/frontends/gtk/preferences.c b/frontends/gtk/preferences.c
index 65f41ed27..a44e7241e 100644
--- a/frontends/gtk/preferences.c
+++ b/frontends/gtk/preferences.c
@@ -30,6 +30,7 @@
#include "desktop/searchweb.h"
#include "gtk/compat.h"
+#include "gtk/toolbar_items.h"
#include "gtk/window.h"
#include "gtk/gui.h"
#include "gtk/scaffolding.h"
@@ -411,12 +412,6 @@ TOGGLEBUTTON_SIGNALS(checkHideAdverts, block_advertisements)
/* enable javascript */
TOGGLEBUTTON_SIGNALS(checkEnableJavascript, enable_javascript)
-/* disable plugins */
-TOGGLEBUTTON_SIGNALS(checkDisablePlugins, disable_plugins)
-
-/* high quality image scaling */
-TOGGLEBUTTON_SIGNALS(checkResampleImages, render_resample)
-
/* load and display of images */
G_MODULE_EXPORT void
nsgtk_preferences_comboboxLoadImages_changed(GtkComboBox *combo,
@@ -480,9 +475,6 @@ nsgtk_preferences_comboboxLoadImages_realize(GtkWidget *widget,
/* enable animation */
TOGGLEBUTTON_SIGNALS(checkEnableAnimations, animate_images)
-/* frame time */
-SPINBUTTON_SIGNALS(spinAnimationSpeed, minimum_gif_delay, 100.0)
-
/* Fonts */
/* default font */
@@ -511,7 +503,7 @@ SPINBUTTON_SIGNALS(spinDefaultSize, font_size, 10.0)
G_MODULE_EXPORT void
nsgtk_preferences_fontPreview_clicked(GtkButton *button, struct ppref *priv)
{
- nsgtk_reflow_all_windows();
+ nsgtk_window_update_all();
}
@@ -713,7 +705,7 @@ nsgtk_preferences_checkShowSingleTab_toggled(GtkToggleButton *togglebutton,
{
nsoption_set_bool(show_single_tab,
gtk_toggle_button_get_active(togglebutton));
- nsgtk_reflow_all_windows();
+ nsgtk_window_update_all();
}
G_MODULE_EXPORT void
@@ -735,20 +727,11 @@ G_MODULE_EXPORT void
nsgtk_preferences_comboTabPosition_changed(GtkComboBox *widget,
struct ppref *priv)
{
- struct nsgtk_scaffolding *current;
-
/* set the option */
nsoption_set_int(position_tab, gtk_combo_box_get_active(widget));
- /* update all notebooks in all scaffolds */
- current = nsgtk_scaffolding_iterate(NULL);
- while (current) {
- nsgtk_scaffolding_reset_offset(current);
-
- nsgtk_reflow_all_windows();
-
- current = nsgtk_scaffolding_iterate(current);
- }
+ /* update all windows */
+ nsgtk_window_update_all();
}
G_MODULE_EXPORT void
@@ -791,18 +774,10 @@ G_MODULE_EXPORT void
nsgtk_preferences_comboButtonType_changed(GtkComboBox *widget,
struct ppref *priv)
{
- struct nsgtk_scaffolding *current;
-
nsoption_set_int(button_type, gtk_combo_box_get_active(widget) + 1);
- current = nsgtk_scaffolding_iterate(NULL);
- while (current != NULL) {
- nsgtk_scaffolding_reset_offset(current);
-
- nsgtk_scaffolding_toolbars(current, nsoption_int(button_type));
-
- current = nsgtk_scaffolding_iterate(current);
- }
+ /* update all windows to adopt change */
+ nsgtk_window_update_all();
}
G_MODULE_EXPORT void
@@ -826,7 +801,7 @@ ENTRY_SIGNALS(entryHomePageURL, homepage_url)
G_MODULE_EXPORT void
nsgtk_preferences_setCurrentPage_clicked(GtkButton *button, struct ppref *priv)
{
- const gchar *url = nsurl_access(browser_window_get_url(priv->bw));
+ const gchar *url = nsurl_access(browser_window_access_url(priv->bw));
if (priv->entryHomePageURL != NULL) {
gtk_entry_set_text(GTK_ENTRY(priv->entryHomePageURL), url);
diff --git a/frontends/gtk/print.c b/frontends/gtk/print.c
index 8f71230a6..c4f1b0f7a 100644
--- a/frontends/gtk/print.c
+++ b/frontends/gtk/print.c
@@ -133,6 +133,17 @@ static inline void nsgtk_print_set_dashed(void)
cairo_set_dash(gtk_print_current_cr, cdashes, 1, 0);
}
+/** Set cairo context line width. */
+static inline void nsgtk_set_line_width(plot_style_fixed width)
+{
+ if (width == 0) {
+ cairo_set_line_width(gtk_print_current_cr, 1);
+ } else {
+ cairo_set_line_width(gtk_print_current_cr,
+ plot_style_fixed_to_double(width));
+ }
+}
+
/**
* \brief Sets a clip rectangle for subsequent plot operations.
@@ -248,10 +259,7 @@ nsgtk_print_plot_disc(const struct redraw_context *ctx,
break;
}
- if (style->stroke_width == 0)
- cairo_set_line_width(gtk_print_current_cr, 1);
- else
- cairo_set_line_width(gtk_print_current_cr, style->stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
cairo_arc(gtk_print_current_cr, x, y, radius, 0, M_PI * 2);
@@ -294,10 +302,7 @@ nsgtk_print_plot_line(const struct redraw_context *ctx,
break;
}
- if (style->stroke_width == 0)
- cairo_set_line_width(gtk_print_current_cr, 1);
- else
- cairo_set_line_width(gtk_print_current_cr, style->stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
cairo_move_to(gtk_print_current_cr, line->x0 + 0.5, line->y0 + 0.5);
cairo_line_to(gtk_print_current_cr, line->x1 + 0.5, line->y1 + 0.5);
@@ -350,13 +355,6 @@ nsgtk_print_plot_rectangle(const struct redraw_context *ctx,
}
if (style->stroke_type != PLOT_OP_TYPE_NONE) {
- int stroke_width;
-
- /* ensure minimum stroke width */
- stroke_width = style->stroke_width;
- if (stroke_width == 0) {
- stroke_width = 1;
- }
nsgtk_print_set_colour(style->stroke_colour);
@@ -375,7 +373,7 @@ nsgtk_print_plot_rectangle(const struct redraw_context *ctx,
break;
}
- cairo_set_line_width(gtk_print_current_cr, stroke_width);
+ nsgtk_set_line_width(style->stroke_width);
cairo_rectangle(gtk_print_current_cr,
rect->x0, rect->y0,
@@ -429,7 +427,6 @@ nsgtk_print_plot_polygon(const struct redraw_context *ctx,
* \param pstyle Style controlling the path plot.
* \param p elements of path
* \param n nunber of elements on path
- * \param width The width of the path
* \param transform A transform to apply to the path.
* \return NSERROR_OK on success else error code.
*/
@@ -438,7 +435,6 @@ nsgtk_print_plot_path(const struct redraw_context *ctx,
const plot_style_t *pstyle,
const float *p,
unsigned int n,
- float width,
const float transform[6])
{
/* Only the internal SVG renderer uses this plot call currently,
diff --git a/frontends/gtk/res/arrow_down_8x32.png b/frontends/gtk/res/arrow_down_8x32.png
deleted file mode 100644
index 475b4ff61..000000000
--- a/frontends/gtk/res/arrow_down_8x32.png
+++ /dev/null
Binary files differ
diff --git a/frontends/gtk/res/en/maps.html b/frontends/gtk/res/en/maps.html
deleted file mode 120000
index 507a4b248..000000000
--- a/frontends/gtk/res/en/maps.html
+++ /dev/null
@@ -1 +0,0 @@
-../../../../resources/en/maps.html \ No newline at end of file
diff --git a/frontends/gtk/res/fr/credits.html b/frontends/gtk/res/fr/credits.html
new file mode 120000
index 000000000..47da488e8
--- /dev/null
+++ b/frontends/gtk/res/fr/credits.html
@@ -0,0 +1 @@
+../../../../resources/fr/credits.html \ No newline at end of file
diff --git a/frontends/gtk/res/fr/licence.html b/frontends/gtk/res/fr/licence.html
new file mode 120000
index 000000000..2fd247ba8
--- /dev/null
+++ b/frontends/gtk/res/fr/licence.html
@@ -0,0 +1 @@
+../../../../resources/fr/licence.html \ No newline at end of file
diff --git a/frontends/gtk/res/fr/welcome.html b/frontends/gtk/res/fr/welcome.html
new file mode 120000
index 000000000..a7a2023ea
--- /dev/null
+++ b/frontends/gtk/res/fr/welcome.html
@@ -0,0 +1 @@
+../../../../resources/fr/welcome.html \ No newline at end of file
diff --git a/frontends/gtk/res/cookies.gtk2.ui b/frontends/gtk/res/gtk2/cookies.ui
index 86f15c765..86f15c765 100644
--- a/frontends/gtk/res/cookies.gtk2.ui
+++ b/frontends/gtk/res/gtk2/cookies.ui
diff --git a/frontends/gtk/res/downloads.gtk2.ui b/frontends/gtk/res/gtk2/downloads.ui
index 1e71328a4..1e71328a4 100644
--- a/frontends/gtk/res/downloads.gtk2.ui
+++ b/frontends/gtk/res/gtk2/downloads.ui
diff --git a/frontends/gtk/res/globalhistory.gtk2.ui b/frontends/gtk/res/gtk2/globalhistory.ui
index 2b89ecb4b..2b89ecb4b 100644
--- a/frontends/gtk/res/globalhistory.gtk2.ui
+++ b/frontends/gtk/res/gtk2/globalhistory.ui
diff --git a/frontends/gtk/res/hotlist.gtk2.ui b/frontends/gtk/res/gtk2/hotlist.ui
index af0fd5696..af0fd5696 100644
--- a/frontends/gtk/res/hotlist.gtk2.ui
+++ b/frontends/gtk/res/gtk2/hotlist.ui
diff --git a/frontends/gtk/res/localhistory.gtk2.ui b/frontends/gtk/res/gtk2/localhistory.ui
index 9512b6289..2003ed69a 100644
--- a/frontends/gtk/res/localhistory.gtk2.ui
+++ b/frontends/gtk/res/gtk2/localhistory.ui
@@ -2,6 +2,7 @@
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkWindow" id="wndHistory">
+ <property name="type">GTK_WINDOW_POPUP</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">NetSurf Local History</property>
<property name="window_position">center</property>
diff --git a/frontends/gtk/res/gtk2/netsurf.ui b/frontends/gtk/res/gtk2/netsurf.ui
new file mode 100644
index 000000000..adca54001
--- /dev/null
+++ b/frontends/gtk/res/gtk2/netsurf.ui
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 2.12 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkAdjustment" id="adjustment1">
+ <property name="upper">100</property>
+ <property name="value">0.5357142857142857</property>
+ <property name="step_increment">26</property>
+ <property name="page_increment">10</property>
+ <property name="page_size">10</property>
+ </object>
+ <object class="GtkAdjustment" id="adjustment2">
+ <property name="upper">100</property>
+ <property name="step_increment">26</property>
+ <property name="page_increment">10</property>
+ <property name="page_size">10</property>
+ </object>
+ <object class="GtkWindow" id="wndBrowser">
+ <property name="can_focus">False</property>
+ <property name="title" translatable="yes">NetSurf</property>
+ <property name="window_position">center</property>
+ <child>
+ <object class="GtkVBox" id="vbox14">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkMenuBar" id="menubar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <property name="scrollable">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/options.gtk2.ui b/frontends/gtk/res/gtk2/options.ui
index a1162585d..907d0b511 100644
--- a/frontends/gtk/res/options.gtk2.ui
+++ b/frontends/gtk/res/gtk2/options.ui
@@ -1143,38 +1143,6 @@
</packing>
</child>
<child>
- <object class="GtkCheckButton" id="checkDisablePlugins">
- <property name="label" translatable="yes">preferencesControlDisable</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="nsgtk_preferences_checkDisablePlugins_toggled" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_checkDisablePlugins_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <object class="GtkCheckButton" id="checkResampleImages">
- <property name="label" translatable="yes">preferencesControlHigh</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="nsgtk_preferences_checkResampleImages_toggled" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_checkResampleImages_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">4</property>
- </packing>
- </child>
- <child>
<object class="GtkHBox" id="hbox8">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -1215,7 +1183,7 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">5</property>
+ <property name="position">3</property>
</packing>
</child>
</object>
@@ -1272,55 +1240,6 @@
<property name="position">0</property>
</packing>
</child>
- <child>
- <object class="GtkHBox" id="hbox9">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkLabel" id="label19">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">preferencesAnimationMinimum</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton" id="spinAnimationSpeed">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_tooltip">True</property>
- <property name="tooltip_text" translatable="yes">preferencesAnimationMinimumTooltip</property>
- <property name="invisible_char">●</property>
- <property name="primary_icon_activatable">False</property>
- <property name="secondary_icon_activatable">False</property>
- <property name="primary_icon_sensitive">True</property>
- <property name="secondary_icon_sensitive">True</property>
- <property name="adjustment">adjustment_animation_time</property>
- <property name="climb_rate">1</property>
- <property name="digits">1</property>
- <property name="numeric">True</property>
- <property name="update_policy">if-valid</property>
- <signal name="value-changed" handler="nsgtk_preferences_spinAnimationSpeed_valuechanged" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_spinAnimationSpeed_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
</object>
</child>
</object>
diff --git a/frontends/gtk/res/gtk2/pageinfo.ui b/frontends/gtk/res/gtk2/pageinfo.ui
new file mode 100644
index 000000000..3d541d653
--- /dev/null
+++ b/frontends/gtk/res/gtk2/pageinfo.ui
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="2.24"/>
+ <!-- interface-naming-policy project-wide -->
+ <object class="GtkWindow" id="PGIWindow">
+ <property name="type">GTK_WINDOW_POPUP</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkDrawingArea" id="PGIDrawingArea">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/password.gtk2.ui b/frontends/gtk/res/gtk2/password.ui
index eb51e4f8f..eb51e4f8f 100644
--- a/frontends/gtk/res/password.gtk2.ui
+++ b/frontends/gtk/res/gtk2/password.ui
diff --git a/frontends/gtk/res/gtk2/tabcontents.ui b/frontends/gtk/res/gtk2/tabcontents.ui
new file mode 100644
index 000000000..c47e6a2ef
--- /dev/null
+++ b/frontends/gtk/res/gtk2/tabcontents.ui
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 2.12 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkAdjustment" id="layouthadjustment">
+ <property name="upper">100</property>
+ <property name="step_increment">30</property>
+ <property name="page_increment">10</property>
+ <property name="page_size">10</property>
+ </object>
+ <object class="GtkAdjustment" id="layoutvadjustment">
+ <property name="upper">100</property>
+ <property name="step_increment">30</property>
+ <property name="page_increment">10</property>
+ <property name="page_size">10</property>
+ </object>
+ <object class="GtkVBox" id="tabBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkToolbar" id="toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="toolbar_style">both-horiz</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolbar" id="findbar">
+ <property name="can_focus">False</property>
+ <property name="toolbar_style">both</property>
+ <child>
+ <object class="GtkToolItem" id="toolitemFind">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkEntry" id="Find">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="primary_icon_activatable">False</property>
+ <property name="secondary_icon_activatable">False</property>
+ <property name="primary_icon_sensitive">True</property>
+ <property name="secondary_icon_sensitive">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindBack">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">gtkFindBack</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">go-up</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindForward">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">gtkFindForward</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">go-down</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem" id="toolitemFindHighlightAll">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="FindHighlightAll">
+ <property name="label" translatable="yes">gtkFindHighlightAll</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">show all matches</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem" id="toolitemFindMatchCase">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="FindMatchCase">
+ <property name="label" translatable="yes">gtkFindMatchCase</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="tooltip_text" translatable="yes">Match case when searching</property>
+ <property name="relief">none</property>
+ <property name="use_underline">True</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindClose">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">gtkFindClose</property>
+ <property name="icon_name">window-close</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkTable" id="tabContents">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="n_rows">2</property>
+ <property name="n_columns">2</property>
+ <child>
+ <object class="GtkLayout" id="layout">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
+ <property name="hadjustment">layouthadjustment</property>
+ <property name="vadjustment">layoutvadjustment</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkStatusbar" id="resizer">
+ <property name="height_request">1</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">2</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="x_options">GTK_FILL</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHPaned" id="hpaned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <child>
+ <object class="GtkLabel" id="status_bar">
+ <property name="width_request">1</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="xpad">4</property>
+ <property name="label" translatable="yes">Status</property>
+ </object>
+ <packing>
+ <property name="resize">False</property>
+ <property name="shrink">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHScrollbar" id="hscrollbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="adjustment">layouthadjustment</property>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="top_attach">1</property>
+ <property name="bottom_attach">2</property>
+ <property name="y_options">GTK_FILL</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkVScrollbar" id="vscrollbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="adjustment">layoutvadjustment</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="right_attach">2</property>
+ <property name="x_options"/>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/gtk2/toolbar.ui b/frontends/gtk/res/gtk2/toolbar.ui
new file mode 100644
index 000000000..61723065b
--- /dev/null
+++ b/frontends/gtk/res/gtk2/toolbar.ui
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 2.12 -->
+ <!-- interface-naming-policy toplevel-contextual -->
+ <object class="GtkVBox" id="customisation">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkToolbar" id="toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0</property>
+ <property name="xpad">6</property>
+ <property name="label" translatable="yes">gtkCustomizeToolbarInstructions</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">6</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow" id="scrolledwindow1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hscrollbar_policy">automatic</property>
+ <property name="vscrollbar_policy">automatic</property>
+ <child>
+ <object class="GtkViewport" id="viewport1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkVBox" id="toolbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkHButtonBox" id="hbuttonbox1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes">Reset to defaults</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="discard">
+ <property name="label">gtk-discard</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="apply">
+ <property name="label">gtk-apply</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">6</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/viewdata.gtk2.ui b/frontends/gtk/res/gtk2/viewdata.ui
index 7589022ca..7589022ca 100644
--- a/frontends/gtk/res/viewdata.gtk2.ui
+++ b/frontends/gtk/res/gtk2/viewdata.ui
diff --git a/frontends/gtk/res/warning.gtk2.ui b/frontends/gtk/res/gtk2/warning.ui
index e4fb4e662..e4fb4e662 100644
--- a/frontends/gtk/res/warning.gtk2.ui
+++ b/frontends/gtk/res/gtk2/warning.ui
diff --git a/frontends/gtk/res/cookies.gtk3.ui b/frontends/gtk/res/gtk3/cookies.ui
index 44dcb80b8..85f9aae76 100644
--- a/frontends/gtk/res/cookies.gtk3.ui
+++ b/frontends/gtk/res/gtk3/cookies.ui
@@ -187,7 +187,7 @@
<object class="GtkDrawingArea" id="cookiesDrawingArea">
<property name="visible">True</property>
<property name="app_paintable">True</property>
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
</object>
</child>
diff --git a/frontends/gtk/res/downloads.gtk3.ui b/frontends/gtk/res/gtk3/downloads.ui
index 1e71328a4..1e71328a4 100644
--- a/frontends/gtk/res/downloads.gtk3.ui
+++ b/frontends/gtk/res/gtk3/downloads.ui
diff --git a/frontends/gtk/res/globalhistory.gtk3.ui b/frontends/gtk/res/gtk3/globalhistory.ui
index 7fa598f1e..c0496964f 100644
--- a/frontends/gtk/res/globalhistory.gtk3.ui
+++ b/frontends/gtk/res/gtk3/globalhistory.ui
@@ -219,7 +219,7 @@
<child>
<object class="GtkDrawingArea" id="globalHistoryDrawingArea">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
</object>
</child>
diff --git a/frontends/gtk/res/hotlist.gtk3.ui b/frontends/gtk/res/gtk3/hotlist.ui
index b0e075c4b..ccd193637 100644
--- a/frontends/gtk/res/hotlist.gtk3.ui
+++ b/frontends/gtk/res/gtk3/hotlist.ui
@@ -236,7 +236,7 @@
<child>
<object class="GtkDrawingArea" id="hotlistDrawingArea">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
</object>
</child>
diff --git a/frontends/gtk/res/localhistory.gtk3.ui b/frontends/gtk/res/gtk3/localhistory.ui
index 1a4b9004d..9a36a91a7 100644
--- a/frontends/gtk/res/localhistory.gtk3.ui
+++ b/frontends/gtk/res/gtk3/localhistory.ui
@@ -2,6 +2,7 @@
<interface>
<!-- interface-requires gtk+ 3.0 -->
<object class="GtkWindow" id="wndHistory">
+ <property name="type">GTK_WINDOW_POPUP</property>
<property name="can_focus">False</property>
<property name="title" translatable="yes">NetSurf Local History</property>
<property name="window_position">center</property>
@@ -26,7 +27,7 @@
<child>
<object class="GtkDrawingArea" id="HistoryDrawingArea">
<property name="visible">True</property>
- <property name="can_focus">False</property>
+ <property name="can_focus">True</property>
<property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
</object>
</child>
diff --git a/frontends/gtk/res/gtk3/netsurf.ui b/frontends/gtk/res/gtk3/netsurf.ui
new file mode 100644
index 000000000..6ea8f07a7
--- /dev/null
+++ b/frontends/gtk/res/gtk3/netsurf.ui
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <object class="GtkWindow" id="wndBrowser">
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkBox" id="box1">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkMenuBar" id="menubar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkNotebook" id="notebook">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="show_tabs">False</property>
+ <property name="show_border">False</property>
+ <property name="scrollable">True</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child type="tab">
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/options.gtk3.ui b/frontends/gtk/res/gtk3/options.ui
index 2a3516f09..82a3e175a 100644
--- a/frontends/gtk/res/options.gtk3.ui
+++ b/frontends/gtk/res/gtk3/options.ui
@@ -143,9 +143,10 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<child>
- <object class="GtkVBox" id="vbox_main">
+ <object class="GtkBox" id="vbox_main">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="valign">start</property>
<property name="spacing">6</property>
<child>
@@ -162,14 +163,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox2">
+ <object class="GtkBox" id="vbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox1">
+ <object class="GtkBox" id="hbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label_startup_page">
@@ -207,9 +210,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox2">
+ <object class="GtkBox" id="hbox2">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<placeholder/>
@@ -289,9 +293,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox3">
+ <object class="GtkBox" id="vbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkUrlSearch">
@@ -314,9 +319,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox3">
+ <object class="GtkBox" id="hbox3">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label5">
@@ -393,9 +399,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox4">
+ <object class="GtkBox" id="vbox4">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkClearDownloads">
@@ -438,9 +445,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox4">
+ <object class="GtkBox" id="hbox4">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label8">
@@ -510,9 +518,10 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox_appearance">
+ <object class="GtkBox" id="vbox_appearance">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="valign">start</property>
<property name="spacing">6</property>
<child>
@@ -529,9 +538,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox5">
+ <object class="GtkBox" id="vbox5">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkShowSingleTab">
@@ -594,9 +604,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox5">
+ <object class="GtkBox" id="hbox5">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label9">
@@ -672,14 +683,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox1">
+ <object class="GtkBox" id="vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox6">
+ <object class="GtkBox" id="hbox6">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label13">
@@ -755,9 +768,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox7">
+ <object class="GtkBox" id="vbox7">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkDisplayRecentURLs">
@@ -813,14 +827,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox8">
+ <object class="GtkBox" id="vbox8">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox7">
+ <object class="GtkBox" id="hbox7">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label16">
@@ -899,10 +915,11 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox_content">
+ <object class="GtkBox" id="vbox_content">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFrame" id="frame_content_control">
@@ -918,9 +935,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox6">
+ <object class="GtkBox" id="vbox6">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkDisablePopups">
@@ -983,49 +1001,10 @@
</packing>
</child>
<child>
- <object class="GtkCheckButton" id="checkDisablePlugins">
- <property name="label" translatable="yes">preferencesControlDisable</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="halign">start</property>
- <property name="use_action_appearance">False</property>
- <property name="xalign">0.5</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="nsgtk_preferences_checkDisablePlugins_toggled" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_checkDisablePlugins_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <object class="GtkCheckButton" id="checkResampleImages">
- <property name="label" translatable="yes">preferencesControlHigh</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="halign">start</property>
- <property name="use_action_appearance">False</property>
- <property name="xalign">0.5</property>
- <property name="draw_indicator">True</property>
- <signal name="toggled" handler="nsgtk_preferences_checkResampleImages_toggled" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_checkResampleImages_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">4</property>
- </packing>
- </child>
- <child>
- <object class="GtkHBox" id="hbox8">
+ <object class="GtkBox" id="hbox8">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label17">
@@ -1064,7 +1043,7 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">5</property>
+ <property name="position">3</property>
</packing>
</child>
</object>
@@ -1101,9 +1080,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox9">
+ <object class="GtkBox" id="vbox9">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkEnableAnimations">
@@ -1125,51 +1105,6 @@
<property name="position">0</property>
</packing>
</child>
- <child>
- <object class="GtkHBox" id="hbox9">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">12</property>
- <child>
- <object class="GtkLabel" id="label19">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">preferencesAnimationMinimum</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkSpinButton" id="spinAnimationSpeed">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_tooltip">True</property>
- <property name="tooltip_text" translatable="yes">preferencesAnimationMinimumTooltip</property>
- <property name="invisible_char">●</property>
- <property name="adjustment">adjustment_animation_time</property>
- <property name="climb_rate">1</property>
- <property name="digits">1</property>
- <property name="numeric">True</property>
- <property name="update_policy">if-valid</property>
- <signal name="value-changed" handler="nsgtk_preferences_spinAnimationSpeed_valuechanged" swapped="no"/>
- <signal name="realize" handler="nsgtk_preferences_spinAnimationSpeed_realize" swapped="no"/>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
</object>
</child>
</object>
@@ -1204,14 +1139,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkHBox" id="hbox11">
+ <object class="GtkBox" id="hbox11">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
- <object class="GtkHBox" id="hbox12">
+ <object class="GtkBox" id="hbox12">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label26">
@@ -1253,9 +1190,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox13">
+ <object class="GtkBox" id="hbox13">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label27">
@@ -1349,14 +1287,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox10">
+ <object class="GtkBox" id="vbox10">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox10">
+ <object class="GtkBox" id="hbox10">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label21">
@@ -1446,10 +1386,11 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox_privacy">
+ <object class="GtkBox" id="vbox_privacy">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFrame" id="frame_privacy_general">
@@ -1465,9 +1406,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox15">
+ <object class="GtkBox" id="vbox15">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkSendReferer">
@@ -1543,9 +1485,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox11">
+ <object class="GtkBox" id="vbox11">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkHoverURLs">
@@ -1568,9 +1511,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox14">
+ <object class="GtkBox" id="hbox14">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label28">
@@ -1657,9 +1601,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox12">
+ <object class="GtkBox" id="vbox12">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkTable" id="table3">
@@ -1815,9 +1760,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox17">
+ <object class="GtkBox" id="hbox17">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<child>
<placeholder/>
</child>
@@ -1881,10 +1827,11 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox_network">
+ <object class="GtkBox" id="vbox_network">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFrame" id="frame_network_proxy">
@@ -1979,9 +1926,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox19">
+ <object class="GtkBox" id="hbox19">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkEntry" id="entryProxyHost">
@@ -2285,10 +2233,11 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox_pdfexport">
+ <object class="GtkBox" id="vbox_pdfexport">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkFrame" id="frame_pdfexport_appearance">
@@ -2304,9 +2253,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox13">
+ <object class="GtkBox" id="vbox13">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkCheckButton" id="checkSuppressImages">
@@ -2369,9 +2319,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox15">
+ <object class="GtkBox" id="hbox15">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label59">
@@ -2458,14 +2409,16 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox16">
+ <object class="GtkBox" id="vbox16">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkHBox" id="hbox22">
+ <object class="GtkBox" id="hbox22">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<child>
<object class="GtkLabel" id="label62">
<property name="visible">True</property>
@@ -2504,9 +2457,10 @@
<placeholder/>
</child>
<child>
- <object class="GtkHBox" id="hbox16">
+ <object class="GtkBox" id="hbox16">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label51">
@@ -2548,9 +2502,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox18">
+ <object class="GtkBox" id="hbox18">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label52">
@@ -2593,9 +2548,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox20">
+ <object class="GtkBox" id="hbox20">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label53">
@@ -2639,9 +2595,10 @@
</packing>
</child>
<child>
- <object class="GtkHBox" id="hbox21">
+ <object class="GtkBox" id="hbox21">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">horizontal</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="label54">
@@ -2746,9 +2703,10 @@
<property name="left_padding">12</property>
<property name="right_padding">12</property>
<child>
- <object class="GtkVBox" id="vbox14">
+ <object class="GtkBox" id="vbox14">
<property name="visible">True</property>
<property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
<property name="spacing">7</property>
<child>
<object class="GtkCheckButton" id="checkCompressPDF">
diff --git a/frontends/gtk/res/gtk3/pageinfo.ui b/frontends/gtk/res/gtk3/pageinfo.ui
new file mode 100644
index 000000000..fdee5ac8d
--- /dev/null
+++ b/frontends/gtk/res/gtk3/pageinfo.ui
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.20"/>
+ <object class="GtkWindow" id="PGIWindow">
+ <property name="type">GTK_WINDOW_POPUP</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_STRUCTURE_MASK</property>
+ <property name="resizable">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <object class="GtkDrawingArea" id="PGIDrawingArea">
+ <property name="name">PGIDrawingArea</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+ </object>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/password.gtk3.ui b/frontends/gtk/res/gtk3/password.ui
index eb51e4f8f..eb51e4f8f 100644
--- a/frontends/gtk/res/password.gtk3.ui
+++ b/frontends/gtk/res/gtk3/password.ui
diff --git a/frontends/gtk/res/gtk3/tabcontents.ui b/frontends/gtk/res/gtk3/tabcontents.ui
new file mode 100644
index 000000000..b07cf92e0
--- /dev/null
+++ b/frontends/gtk/res/gtk3/tabcontents.ui
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <object class="GtkAdjustment" id="layouthadjustment">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkAdjustment" id="layoutvadjustment">
+ <property name="upper">100</property>
+ <property name="step_increment">1</property>
+ <property name="page_increment">10</property>
+ </object>
+ <object class="GtkBox" id="tabBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkToolbar" id="toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="toolbar_style">both</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolbar" id="findbar">
+ <property name="can_focus">False</property>
+ <property name="toolbar_style">both</property>
+ <child>
+ <object class="GtkToolItem">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkEntry" id="Find">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="invisible_char">●</property>
+ <property name="placeholder_text" translatable="yes">gtkFindPlaceholder</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindBack">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">gtkFindBack</property>
+ <property name="label" translatable="yes">gtkFindBack</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-go-up</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindForward">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">gtkFindForward</property>
+ <property name="label" translatable="yes">gtkFindForward</property>
+ <property name="use_underline">True</property>
+ <property name="stock_id">gtk-go-down</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="FindHighlightAll">
+ <property name="label" translatable="yes">gtkFindHighlightAll</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkCheckButton" id="FindMatchCase">
+ <property name="label" translatable="yes">gtkFindMatchCase</property>
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">False</property>
+ <property name="xalign">0</property>
+ <property name="draw_indicator">True</property>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">False</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolButton" id="FindClose">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">gtkFindClose</property>
+ <property name="label" translatable="yes">gtkFindClose</property>
+ <property name="stock_id">gtk-close</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkGrid" id="tabContents">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="row_spacing">2</property>
+ <property name="column_spacing">2</property>
+ <child>
+ <object class="GtkLayout" id="layout">
+ <property name="visible">True</property>
+ <property name="app_paintable">True</property>
+ <property name="can_focus">False</property>
+ <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
+ <property name="hadjustment">layouthadjustment</property>
+ <property name="vadjustment">layoutvadjustment</property>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrollbar" id="vscrollbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="vexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="adjustment">layoutvadjustment</property>
+ </object>
+ <packing>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkPaned" id="hpaned1">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="hexpand">True</property>
+ <child>
+ <object class="GtkLabel" id="status_bar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xpad">4</property>
+ <property name="label" translatable="yes">Status</property>
+ <property name="single_line_mode">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="resize">False</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrollbar" id="hscrollbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="adjustment">layouthadjustment</property>
+ </object>
+ <packing>
+ <property name="resize">True</property>
+ <property name="shrink">True</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/gtk3/toolbar.ui b/frontends/gtk/res/gtk3/toolbar.ui
new file mode 100644
index 000000000..60452f472
--- /dev/null
+++ b/frontends/gtk/res/gtk3/toolbar.ui
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
+<!--*- mode: xml -*-->
+<interface>
+ <requires lib="gtk+" version="3.0"/>
+ <object class="GtkImage" id="image2">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="stock">gtk-refresh</property>
+ </object>
+ <object class="GtkBox" id="customisation">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkToolbar" id="toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xpad">6</property>
+ <property name="label" translatable="yes">gtkCustomizeToolbarInstructions</property>
+ <property name="wrap">True</property>
+ <property name="xalign">0</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="padding">6</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkScrolledWindow">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="shadow_type">in</property>
+ <child>
+ <object class="GtkViewport">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <object class="GtkBox" id="toolbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ </child>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButtonBox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="layout_style">end</property>
+ <child>
+ <object class="GtkButton" id="reset">
+ <property name="label" translatable="yes">Reset</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="image">image2</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="discard">
+ <property name="label">gtk-discard</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="apply">
+ <property name="label">gtk-apply</property>
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="receives_default">True</property>
+ <property name="use_stock">True</property>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">False</property>
+ <property name="padding">6</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/frontends/gtk/res/viewdata.gtk3.ui b/frontends/gtk/res/gtk3/viewdata.ui
index b742d5f6b..b742d5f6b 100644
--- a/frontends/gtk/res/viewdata.gtk3.ui
+++ b/frontends/gtk/res/gtk3/viewdata.ui
diff --git a/frontends/gtk/res/warning.gtk3.ui b/frontends/gtk/res/gtk3/warning.ui
index e4fb4e662..e4fb4e662 100644
--- a/frontends/gtk/res/warning.gtk3.ui
+++ b/frontends/gtk/res/gtk3/warning.ui
diff --git a/frontends/gtk/res/login.gtk2.ui b/frontends/gtk/res/login.gtk2.ui
deleted file mode 100644
index 552b173ed..000000000
--- a/frontends/gtk/res/login.gtk2.ui
+++ /dev/null
@@ -1,223 +0,0 @@
-<?xml version="1.0"?>
-<!--*- mode: xml -*-->
-<interface>
- <object class="GtkDialog" id="wndLogin">
- <property name="title" translatable="yes">Site Authentication</property>
- <property name="window_position">GTK_WIN_POS_CENTER_ALWAYS</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
- <child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox2">
- <property name="visible">True</property>
- <child>
- <object class="GtkHBox" id="hbox12">
- <property name="visible">True</property>
- <property name="border_width">3</property>
- <child>
- <object class="GtkImage" id="image3">
- <property name="visible">True</property>
- <property name="yalign">0.10000000149011612</property>
- <property name="xpad">12</property>
- <property name="icon_size">6</property>
- <property name="icon_name">gtk-dialog-authentication</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkTable" id="table5">
- <property name="visible">True</property>
- <property name="border_width">1</property>
- <property name="n_rows">4</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">11</property>
- <property name="row_spacing">10</property>
- <child>
- <object class="GtkLabel" id="labelLoginHost">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">moo.yoo.com</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label57">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Password</property>
- </object>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label56">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Username</property>
- </object>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label54">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Host</property>
- </object>
- <packing>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label55">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Realm</property>
- </object>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="labelLoginRealm">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">my sekr3t area</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entryLoginPass">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="visibility">False</property>
- <property name="activates_default">True</property>
- <property name="text" translatable="yes">opensesame</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="y_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entryLoginUser">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_focus">True</property>
- <property name="text" translatable="yes">sesame</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options"/>
- </packing>
- </child>
- </object>
- <packing>
- <property name="padding">1</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="dialog-action_area2">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
- <child>
- <object class="GtkButton" id="buttonLoginCan">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label">gtk-cancel</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- <child>
- <object class="GtkButton" id="buttonLoginOK">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <child>
- <object class="GtkAlignment" id="alignment14">
- <property name="visible">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
- <child>
- <object class="GtkHBox" id="hbox11">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="stock">gtk-ok</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label49">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Login</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="-6">buttonLoginCan</action-widget>
- <action-widget response="-5">buttonLoginOK</action-widget>
- </action-widgets>
- </object>
-</interface>
diff --git a/frontends/gtk/res/login.gtk3.ui b/frontends/gtk/res/login.gtk3.ui
deleted file mode 100644
index 552b173ed..000000000
--- a/frontends/gtk/res/login.gtk3.ui
+++ /dev/null
@@ -1,223 +0,0 @@
-<?xml version="1.0"?>
-<!--*- mode: xml -*-->
-<interface>
- <object class="GtkDialog" id="wndLogin">
- <property name="title" translatable="yes">Site Authentication</property>
- <property name="window_position">GTK_WIN_POS_CENTER_ALWAYS</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
- <child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox2">
- <property name="visible">True</property>
- <child>
- <object class="GtkHBox" id="hbox12">
- <property name="visible">True</property>
- <property name="border_width">3</property>
- <child>
- <object class="GtkImage" id="image3">
- <property name="visible">True</property>
- <property name="yalign">0.10000000149011612</property>
- <property name="xpad">12</property>
- <property name="icon_size">6</property>
- <property name="icon_name">gtk-dialog-authentication</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkTable" id="table5">
- <property name="visible">True</property>
- <property name="border_width">1</property>
- <property name="n_rows">4</property>
- <property name="n_columns">2</property>
- <property name="column_spacing">11</property>
- <property name="row_spacing">10</property>
- <child>
- <object class="GtkLabel" id="labelLoginHost">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">moo.yoo.com</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label57">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Password</property>
- </object>
- <packing>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label56">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Username</property>
- </object>
- <packing>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label54">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Host</property>
- </object>
- <packing>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label55">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">Realm</property>
- </object>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="labelLoginRealm">
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="label" translatable="yes">my sekr3t area</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entryLoginPass">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="visibility">False</property>
- <property name="activates_default">True</property>
- <property name="text" translatable="yes">opensesame</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">3</property>
- <property name="bottom_attach">4</property>
- <property name="y_options"/>
- </packing>
- </child>
- <child>
- <object class="GtkEntry" id="entryLoginUser">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="has_focus">True</property>
- <property name="text" translatable="yes">sesame</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">2</property>
- <property name="bottom_attach">3</property>
- <property name="y_options"/>
- </packing>
- </child>
- </object>
- <packing>
- <property name="padding">1</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="dialog-action_area2">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
- <child>
- <object class="GtkButton" id="buttonLoginCan">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="label">gtk-cancel</property>
- <property name="use_stock">True</property>
- </object>
- </child>
- <child>
- <object class="GtkButton" id="buttonLoginOK">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <child>
- <object class="GtkAlignment" id="alignment14">
- <property name="visible">True</property>
- <property name="can_default">True</property>
- <property name="has_default">True</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
- <child>
- <object class="GtkHBox" id="hbox11">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="stock">gtk-ok</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label49">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Login</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="-6">buttonLoginCan</action-widget>
- <action-widget response="-5">buttonLoginOK</action-widget>
- </action-widgets>
- </object>
-</interface>
diff --git a/frontends/gtk/res/maps.html b/frontends/gtk/res/maps.html
deleted file mode 120000
index a32f725fb..000000000
--- a/frontends/gtk/res/maps.html
+++ /dev/null
@@ -1 +0,0 @@
-en/maps.html \ No newline at end of file
diff --git a/frontends/gtk/res/messages.gresource.xml b/frontends/gtk/res/messages.gresource.xml
index 684a10862..6da406245 100644
--- a/frontends/gtk/res/messages.gresource.xml
+++ b/frontends/gtk/res/messages.gresource.xml
@@ -6,5 +6,6 @@
<file>de/Messages</file>
<file>fr/Messages</file>
<file>it/Messages</file>
+ <file>zh_CN/Messages</file>
</gresource>
</gresources>
diff --git a/frontends/gtk/res/netsurf.gresource.xml b/frontends/gtk/res/netsurf.gresource.xml
index e8243254a..21a2e7723 100644
--- a/frontends/gtk/res/netsurf.gresource.xml
+++ b/frontends/gtk/res/netsurf.gresource.xml
@@ -1,34 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/netsurf">
- <file>cookies.gtk2.ui</file>
- <file>globalhistory.gtk3.ui</file>
- <file>localhistory.gtk3.ui</file>
- <file>netsurf.gtk2.ui</file>
- <file>password.gtk3.ui</file>
- <file>toolbar.gtk2.ui</file>
- <file>warning.gtk3.ui</file>
- <file>cookies.gtk3.ui</file>
- <file>hotlist.gtk2.ui</file>
- <file>netsurf.gtk3.ui</file>
- <file>ssl.gtk2.ui</file>
- <file>toolbar.gtk3.ui</file>
- <file>downloads.gtk2.ui</file>
- <file>hotlist.gtk3.ui</file>
- <file>options.gtk2.ui</file>
- <file>ssl.gtk3.ui</file>
- <file>viewdata.gtk2.ui</file>
- <file>downloads.gtk3.ui</file>
- <file>login.gtk2.ui</file>
- <file>options.gtk3.ui</file>
- <file>tabcontents.gtk2.ui</file>
- <file>viewdata.gtk3.ui</file>
- <file>localhistory.gtk2.ui</file>
- <file>globalhistory.gtk2.ui</file>
- <file>login.gtk3.ui</file>
- <file>password.gtk2.ui</file>
- <file>tabcontents.gtk3.ui</file>
- <file>warning.gtk2.ui</file>
<file preprocess="to-pixdata">favicon.png</file>
<file preprocess="to-pixdata">netsurf.xpm</file>
<file preprocess="to-pixdata">menu_cursor.png</file>
@@ -42,24 +14,30 @@
<file preprocess="to-pixdata">throbber/throbber7.png</file>
<file preprocess="to-pixdata">throbber/throbber8.png</file>
<file>credits.html</file>
+ <file>fr/credits.html</file>
<file>it/credits.html</file>
<file>nl/credits.html</file>
+ <file>zh_CN/credits.html</file>
<file>licence.html</file>
+ <file>fr/licence.html</file>
<file>it/licence.html</file>
<file>nl/licence.html</file>
+ <file>zh_CN/licence.html</file>
<file>welcome.html</file>
<file>de/welcome.html</file>
+ <file>fr/welcome.html</file>
<file>it/welcome.html</file>
<file>ja/welcome.html</file>
<file>nl/welcome.html</file>
- <file>maps.html</file>
+ <file>zh_CN/welcome.html</file>
<file>adblock.css</file>
<file>default.css</file>
<file>internal.css</file>
<file>quirks.css</file>
<file>netsurf.png</file>
<file>default.ico</file>
- <file>arrow_down_8x32.png</file>
+ <file>icons/show-cookie.png</file>
+ <file>icons/local-history.png</file>
<file>icons/arrow-l.png</file>
<file>icons/content.png</file>
<file>icons/directory2.png</file>
@@ -67,6 +45,16 @@
<file>icons/hotlist-add.png</file>
<file>icons/hotlist-rmv.png</file>
<file>icons/search.png</file>
+ <file>icons/24x24/actions/page-info-insecure.png</file>
+ <file>icons/24x24/actions/page-info-internal.png</file>
+ <file>icons/24x24/actions/page-info-local.png</file>
+ <file>icons/24x24/actions/page-info-secure.png</file>
+ <file>icons/24x24/actions/page-info-warning.png</file>
+ <file>icons/48x48/actions/page-info-insecure.png</file>
+ <file>icons/48x48/actions/page-info-internal.png</file>
+ <file>icons/48x48/actions/page-info-local.png</file>
+ <file>icons/48x48/actions/page-info-secure.png</file>
+ <file>icons/48x48/actions/page-info-warning.png</file>
<file>languages</file>
<file>accelerators</file>
</gresource>
diff --git a/frontends/gtk/res/netsurf.gtk2.ui b/frontends/gtk/res/netsurf.gtk2.ui
deleted file mode 100644
index 68812b364..000000000
--- a/frontends/gtk/res/netsurf.gtk2.ui
+++ /dev/null
@@ -1,212 +0,0 @@
-<?xml version="1.0"?>
-<!--Generated with glade3 3.4.5 on Wed Apr 7 17:10:28 2010 -->
-<interface>
- <object class="GtkAdjustment" id="adjustment1">
- <property name="upper">100</property>
- <property name="lower">0</property>
- <property name="page_increment">10</property>
- <property name="step_increment">26</property>
- <property name="page_size">10</property>
- <property name="value">0.5357142857142857</property>
- </object>
- <object class="GtkAdjustment" id="adjustment2">
- <property name="upper">100</property>
- <property name="lower">0</property>
- <property name="page_increment">10</property>
- <property name="step_increment">26</property>
- <property name="page_size">10</property>
- <property name="value">0</property>
- </object>
- <object class="GtkUIManager" id="uimanager1">
- <ui>
- <menubar name="menubar"/>
- </ui>
- </object>
- <object class="GtkWindow" id="wndBrowser">
- <property name="title" translatable="yes">NetSurf</property>
- <property name="window_position">GTK_WIN_POS_CENTER</property>
- <child>
- <object class="GtkVBox" id="vbox14">
- <property name="visible">True</property>
- <child>
- <object class="GtkMenuBar" constructor="uimanager1" id="menubar">
- <property name="visible">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="toolbar">
- <property name="visible">True</property>
- <property name="toolbar_style">GTK_TOOLBAR_BOTH_HORIZ</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="searchbar">
- <property name="toolbar_style">GTK_TOOLBAR_BOTH</property>
- <child>
- <object class="GtkToolButton" id="closeSearchButton">
- <property name="visible">True</property>
- <property name="stock_id">gtk-close</property>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="searchLabelItem">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="searchlabel">
- <property name="visible">True</property>
- <property name="xpad">4</property>
- <property name="label" translatable="yes">Match</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="toolSearch">
- <property name="visible">True</property>
- <child>
- <object class="GtkEntry" id="searchEntry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolButton" id="searchBackButton">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Search _Back</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-go-back</property>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolButton" id="searchForwardButton">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Search _Forward</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-go-forward</property>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="checkAllSearchItem">
- <property name="visible">True</property>
- <child>
- <object class="GtkCheckButton" id="checkAllSearch">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="tooltip-text" translatable="yes">show all matches</property>
- <property name="label" translatable="yes">All </property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="caseSensItem">
- <property name="visible">True</property>
- <child>
- <object class="GtkCheckButton" id="caseSensButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="tooltip-text" translatable="yes">Match case when searching</property>
- <property name="label" translatable="yes">Case</property>
- <property name="relief">GTK_RELIEF_NONE</property>
- <property name="use_underline">True</property>
- <property name="draw_indicator">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">False</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkNotebook" id="notebook">
- <property name="visible">True</property>
- <property name="show_tabs">False</property>
- <property name="show_border">False</property>
- <property name="scrollable">True</property>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="position">3</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
-</interface>
diff --git a/frontends/gtk/res/netsurf.gtk3.ui b/frontends/gtk/res/netsurf.gtk3.ui
deleted file mode 100644
index ce47c6370..000000000
--- a/frontends/gtk/res/netsurf.gtk3.ui
+++ /dev/null
@@ -1,207 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
- <!-- interface-requires gtk+ 3.0 -->
- <object class="GtkWindow" id="wndBrowser">
- <property name="can_focus">False</property>
- <child>
- <object class="GtkBox" id="box1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkMenuBar" id="menubar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="toolbar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="toolbar_style">both</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolbar" id="searchbar">
- <property name="can_focus">False</property>
- <property name="toolbar_style">both</property>
- <child>
- <object class="GtkToolButton" id="closeSearchButton">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <property name="label" translatable="yes">gtk-close</property>
- <property name="stock_id">gtk-close</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="searchLabelItem">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <child>
- <object class="GtkLabel" id="searchlabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xpad">4</property>
- <property name="label" translatable="yes">Match</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="toolSearch">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <child>
- <object class="GtkEntry" id="searchEntry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">●</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolButton" id="searchBackButton">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <property name="label" translatable="yes">Search _Back</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-go-back</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolButton" id="searchForwardButton">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <property name="label" translatable="yes">Search _Forward</property>
- <property name="use_underline">True</property>
- <property name="stock_id">gtk-go-forward</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="homogeneous">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="checkAllSearchItem">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <child>
- <object class="GtkCheckButton" id="checkAllSearch">
- <property name="label" translatable="yes">All</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkToolItem" id="caseSensItem">
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="use_action_appearance">False</property>
- <child>
- <object class="GtkCheckButton" id="caseSensButton">
- <property name="label" translatable="yes">Case</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_action_appearance">False</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkNotebook" id="notebook">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="show_tabs">False</property>
- <property name="show_border">False</property>
- <property name="scrollable">True</property>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- <child>
- <placeholder/>
- </child>
- <child type="tab">
- <placeholder/>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">3</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
-</interface>
diff --git a/frontends/gtk/res/ssl.gtk2.ui b/frontends/gtk/res/ssl.gtk2.ui
deleted file mode 100644
index 90f449ddd..000000000
--- a/frontends/gtk/res/ssl.gtk2.ui
+++ /dev/null
@@ -1,202 +0,0 @@
-<?xml version="1.0"?>
-<!--*- mode: xml -*-->
-<interface>
- <object class="GtkDialog" id="wndSSLProblem">
- <property name="border_width">1</property>
- <property name="title" translatable="yes">SSL certificate problem</property>
- <property name="modal">True</property>
- <property name="default_width">500</property>
- <property name="default_height">250</property>
- <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
- <child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox3">
- <property name="visible">True</property>
- <child>
- <object class="GtkHBox" id="hbox15">
- <property name="visible">True</property>
- <child>
- <object class="GtkImage" id="image6">
- <property name="visible">True</property>
- <property name="yalign">0</property>
- <property name="icon_size">6</property>
- <property name="icon_name">gtk-dialog-warning</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkVBox" id="vbox13">
- <property name="visible">True</property>
- <child>
- <object class="GtkLabel" id="label62">
- <property name="visible">True</property>
- <property name="label" translatable="yes">NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below.</property>
- <property name="justify">GTK_JUSTIFY_CENTER</property>
- <property name="wrap">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame" id="frame13">
- <property name="visible">True</property>
- <property name="border_width">5</property>
- <property name="label_xalign">0</property>
- <child>
- <object class="GtkAlignment" id="alignment17">
- <property name="visible">True</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkScrolledWindow" id="SSLScrolled">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="shadow_type">GTK_SHADOW_IN</property>
- <child>
- <object class="GtkViewport" id="SSLViewport">
- <property name="visible">True</property>
- <property name="resize_mode">GTK_RESIZE_QUEUE</property>
- <child>
- <object class="GtkDrawingArea" id="SSLDrawingArea">
- <property name="visible">True</property>
- <property name="app_paintable">True</property>
- <property name="can_focus">True</property>
- <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label63">
- <property name="visible">True</property>
- <property name="label" translatable="yes">&lt;b&gt;Certificate chain&lt;/b&gt;</property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="position">2</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="dialog-action_area3">
- <property name="visible">True</property>
- <property name="layout_style">GTK_BUTTONBOX_END</property>
- <child>
- <object class="GtkButton" id="sslreject">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <child>
- <object class="GtkAlignment" id="alignment16">
- <property name="visible">True</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
- <child>
- <object class="GtkHBox" id="hbox14">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkImage" id="image5">
- <property name="visible">True</property>
- <property name="stock">gtk-cancel</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label61">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Reject</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child>
- <object class="GtkButton" id="sslaccept">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="can_default">True</property>
- <child>
- <object class="GtkAlignment" id="alignment15">
- <property name="visible">True</property>
- <property name="xscale">0</property>
- <property name="yscale">0</property>
- <child>
- <object class="GtkHBox" id="hbox13">
- <property name="visible">True</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkImage" id="image4">
- <property name="visible">True</property>
- <property name="stock">gtk-apply</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label60">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Accept</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="pack_type">GTK_PACK_END</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="-6">sslreject</action-widget>
- <action-widget response="-5">sslaccept</action-widget>
- </action-widgets>
- </object>
-</interface>
diff --git a/frontends/gtk/res/ssl.gtk3.ui b/frontends/gtk/res/ssl.gtk3.ui
deleted file mode 100644
index dace2a49e..000000000
--- a/frontends/gtk/res/ssl.gtk3.ui
+++ /dev/null
@@ -1,181 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
- <!-- interface-requires gtk+ 3.0 -->
- <object class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="stock">gtk-apply</property>
- </object>
- <object class="GtkImage" id="image3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="stock">gtk-cancel</property>
- </object>
- <object class="GtkDialog" id="wndSSLProblem">
- <property name="can_focus">False</property>
- <property name="border_width">5</property>
- <property name="default_width">440</property>
- <property name="default_height">260</property>
- <property name="destroy_with_parent">True</property>
- <property name="type_hint">dialog</property>
- <child internal-child="vbox">
- <object class="GtkBox" id="dialog-vbox1">
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="spacing">2</property>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="dialog-action_area1">
- <property name="can_focus">False</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="sslreject">
- <property name="label" translatable="yes">_Reject</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_action_appearance">False</property>
- <property name="image">image3</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="sslaccept">
- <property name="label" translatable="yes">_Accept</property>
- <property name="use_action_appearance">False</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_action_appearance">False</property>
- <property name="image">image2</property>
- <property name="use_underline">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="box1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <child>
- <object class="GtkBox" id="box2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="margin_right">8</property>
- <property name="stock">gtk-dialog-warning</property>
- <property name="icon-size">6</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">NetSurf failed to verify the authenticity of an SSL certificate. Please verify the details presented below.</property>
- <property name="wrap">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkFrame" id="frame1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label_xalign">0</property>
- <property name="shadow_type">none</property>
- <child>
- <object class="GtkAlignment" id="alignment1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="left_padding">12</property>
- <child>
- <object class="GtkScrolledWindow" id="SSLScrolled">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="shadow_type">in</property>
- <child>
- <object class="GtkViewport" id="SSLViewport">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkDrawingArea" id="SSLDrawingArea">
- <property name="visible">True</property>
- <property name="app_paintable">True</property>
- <property name="can_focus">True</property>
- <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK</property>
- <property name="valign">start</property>
- <property name="hexpand">True</property>
- <property name="vexpand">True</property>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- </child>
- <child type="label">
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">&lt;b&gt;Certificate Chain&lt;/b&gt;</property>
- <property name="use_markup">True</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="-6">sslreject</action-widget>
- <action-widget response="-5">sslaccept</action-widget>
- </action-widgets>
- </object>
-</interface>
diff --git a/frontends/gtk/res/tabcontents.gtk2.ui b/frontends/gtk/res/tabcontents.gtk2.ui
deleted file mode 100644
index 63e290e8b..000000000
--- a/frontends/gtk/res/tabcontents.gtk2.ui
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0"?>
-<interface>
- <!-- interface-requires gtk+ 2.12 -->
- <!-- interface-naming-policy toplevel-contextual -->
- <object class="GtkTable" id="tabContents">
- <property name="visible">True</property>
- <property name="n_rows">2</property>
- <property name="n_columns">2</property>
- <child>
- <object class="GtkLayout" id="layout">
- <property name="visible">True</property>
- <property name="app_paintable">True</property>
- <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
- <property name="hadjustment">layouthadjustment</property>
- <property name="vadjustment">layoutvadjustment</property>
- </object>
- </child>
- <child>
- <object class="GtkStatusbar" id="resizer">
- <property name="height_request">1</property>
- <property name="visible">True</property>
- <property name="spacing">2</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="x_options">GTK_FILL</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkHPaned" id="hpaned1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <child>
- <object class="GtkLabel" id="status_bar">
- <property name="width_request">1</property>
- <property name="visible">True</property>
- <property name="xalign">0</property>
- <property name="xpad">4</property>
- <property name="label" translatable="yes">Status</property>
- </object>
- <packing>
- <property name="resize">False</property>
- <property name="shrink">False</property>
- </packing>
- </child>
- <child>
- <object class="GtkHScrollbar" id="hscrollbar">
- <property name="visible">True</property>
- <property name="adjustment">layouthadjustment</property>
- </object>
- <packing>
- <property name="resize">True</property>
- <property name="shrink">True</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="top_attach">1</property>
- <property name="bottom_attach">2</property>
- <property name="y_options">GTK_FILL</property>
- </packing>
- </child>
- <child>
- <object class="GtkVScrollbar" id="vscrollbar">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <property name="adjustment">layoutvadjustment</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="right_attach">2</property>
- <property name="x_options"></property>
- </packing>
- </child>
- </object>
- <object class="GtkAdjustment" id="layouthadjustment">
- <property name="upper">100</property>
- <property name="step_increment">30</property>
- <property name="page_increment">10</property>
- <property name="page_size">10</property>
- </object>
- <object class="GtkAdjustment" id="layoutvadjustment">
- <property name="upper">100</property>
- <property name="step_increment">30</property>
- <property name="page_increment">10</property>
- <property name="page_size">10</property>
- </object>
-</interface>
diff --git a/frontends/gtk/res/tabcontents.gtk3.ui b/frontends/gtk/res/tabcontents.gtk3.ui
deleted file mode 100644
index 23328b3b7..000000000
--- a/frontends/gtk/res/tabcontents.gtk3.ui
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
- <!-- interface-requires gtk+ 3.0 -->
- <object class="GtkAdjustment" id="layouthadjustment">
- <property name="upper">100</property>
- <property name="step_increment">1</property>
- <property name="page_increment">10</property>
- </object>
- <object class="GtkAdjustment" id="layoutvadjustment">
- <property name="upper">100</property>
- <property name="step_increment">1</property>
- <property name="page_increment">10</property>
- </object>
- <object class="GtkGrid" id="tabContents">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="row_spacing">2</property>
- <property name="column_spacing">2</property>
- <child>
- <object class="GtkLayout" id="layout">
- <property name="visible">True</property>
- <property name="app_paintable">True</property>
- <property name="can_focus">False</property>
- <property name="events">GDK_EXPOSURE_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK</property>
- <property name="hadjustment">layouthadjustment</property>
- <property name="vadjustment">layoutvadjustment</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrollbar" id="vscrollbar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="vexpand">True</property>
- <property name="orientation">vertical</property>
- <property name="adjustment">layoutvadjustment</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkPaned" id="hpaned1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hexpand">True</property>
- <child>
- <object class="GtkLabel" id="status_bar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="xalign">0</property>
- <property name="xpad">4</property>
- <property name="label" translatable="yes">Status</property>
- <property name="single_line_mode">True</property>
- </object>
- <packing>
- <property name="resize">False</property>
- <property name="shrink">True</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrollbar" id="hscrollbar">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="adjustment">layouthadjustment</property>
- </object>
- <packing>
- <property name="resize">True</property>
- <property name="shrink">True</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">1</property>
- <property name="width">1</property>
- <property name="height">1</property>
- </packing>
- </child>
- <child>
- <placeholder/>
- </child>
- </object>
-</interface>
diff --git a/frontends/gtk/res/toolbar.gtk2.ui b/frontends/gtk/res/toolbar.gtk2.ui
deleted file mode 100644
index 4e8805a6f..000000000
--- a/frontends/gtk/res/toolbar.gtk2.ui
+++ /dev/null
@@ -1,172 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<interface>
- <!-- interface-requires gtk+ 2.12 -->
- <!-- interface-naming-policy toplevel-contextual -->
- <object class="GtkDialog" id="dialogToolbar">
- <property name="width_request">700</property>
- <property name="height_request">450</property>
- <property name="can_focus">False</property>
- <property name="border_width">5</property>
- <property name="title" translatable="yes">gtkToolBarTitle</property>
- <property name="window_position">center-on-parent</property>
- <property name="destroy_with_parent">True</property>
- <property name="type_hint">dialog</property>
- <child internal-child="vbox">
- <object class="GtkVBox" id="dialog-vbox1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">2</property>
- <child>
- <object class="GtkHBox" id="hbox1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="homogeneous">True</property>
- <child>
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Move items from store to toolbar</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Rearrange items in toolbar</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Move items from toolbar to store</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">2</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <child>
- <object class="GtkViewport" id="viewport1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkVBox" id="widgetvbox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <placeholder/>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child internal-child="action_area">
- <object class="GtkHButtonBox" id="dialog-action_area1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="reset">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <child>
- <object class="GtkHBox" id="button1hbox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="stock">gtk-refresh</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="refreshbuttonlabel">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Reset to defaults</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="padding">10</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="close">
- <property name="label">gtk-close</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- </child>
- <action-widgets>
- <action-widget response="0">reset</action-widget>
- <action-widget response="0">close</action-widget>
- </action-widgets>
- </object>
-</interface>
diff --git a/frontends/gtk/res/toolbar.gtk3.ui b/frontends/gtk/res/toolbar.gtk3.ui
deleted file mode 100644
index 1f1148703..000000000
--- a/frontends/gtk/res/toolbar.gtk3.ui
+++ /dev/null
@@ -1,137 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.18.3 -->
-<!--*- mode: xml -*-->
-<interface>
- <requires lib="gtk+" version="3.0"/>
- <object class="GtkImage" id="image2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="stock">gtk-refresh</property>
- </object>
- <object class="GtkDialog" id="dialogToolbar">
- <property name="width_request">700</property>
- <property name="height_request">450</property>
- <property name="can_focus">False</property>
- <property name="title" translatable="yes">gtkToolBarTitle</property>
- <property name="type_hint">dialog</property>
- <child internal-child="vbox">
- <object class="GtkBox" id="dialog-vbox1">
- <property name="can_focus">False</property>
- <property name="orientation">vertical</property>
- <property name="spacing">2</property>
- <child internal-child="action_area">
- <object class="GtkButtonBox" id="dialog-action_area1">
- <property name="can_focus">False</property>
- <property name="layout_style">end</property>
- <child>
- <object class="GtkButton" id="reset">
- <property name="label" translatable="yes">Reset To Defaults</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="image">image2</property>
- <property name="yalign">0.52999997138977051</property>
- <property name="always_show_image">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="close">
- <property name="label">gtk-close</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_stock">True</property>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <object class="GtkGrid" id="grid1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="column_homogeneous">True</property>
- <child>
- <object class="GtkLabel" id="label1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Move items from store to toolbar</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label2">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Rearrange items in toolbar</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkLabel" id="label3">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="label" translatable="yes">Move items from toolbar to store</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkScrolledWindow" id="scrolledwindow1">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <child>
- <object class="GtkViewport" id="viewport1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <object class="GtkVBox" id="widgetvbox">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <child>
- <placeholder/>
- </child>
- </object>
- </child>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- </child>
- </object>
-</interface>
diff --git a/frontends/gtk/res/ui.gresource.xml b/frontends/gtk/res/ui.gresource.xml
new file mode 100644
index 000000000..dd43ddf59
--- /dev/null
+++ b/frontends/gtk/res/ui.gresource.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/netsurf">
+ <file>cookies.ui</file>
+ <file>downloads.ui</file>
+ <file>globalhistory.ui</file>
+ <file>hotlist.ui</file>
+ <file>localhistory.ui</file>
+ <file>netsurf.ui</file>
+ <file>options.ui</file>
+ <file>pageinfo.ui</file>
+ <file>password.ui</file>
+ <file>tabcontents.ui</file>
+ <file>toolbar.ui</file>
+ <file>viewdata.ui</file>
+ <file>warning.ui</file>
+ </gresource>
+</gresources>
diff --git a/frontends/gtk/res/zh_CN/credits.html b/frontends/gtk/res/zh_CN/credits.html
new file mode 120000
index 000000000..6fd96ea63
--- /dev/null
+++ b/frontends/gtk/res/zh_CN/credits.html
@@ -0,0 +1 @@
+../../../../resources/zh_CN/credits.html \ No newline at end of file
diff --git a/frontends/gtk/res/zh_CN/licence.html b/frontends/gtk/res/zh_CN/licence.html
new file mode 120000
index 000000000..d757031d5
--- /dev/null
+++ b/frontends/gtk/res/zh_CN/licence.html
@@ -0,0 +1 @@
+../../../../resources/zh_CN/licence.html \ No newline at end of file
diff --git a/frontends/gtk/res/zh_CN/welcome.html b/frontends/gtk/res/zh_CN/welcome.html
new file mode 120000
index 000000000..fa10c2a20
--- /dev/null
+++ b/frontends/gtk/res/zh_CN/welcome.html
@@ -0,0 +1 @@
+../../../../resources/zh_CN/welcome.html \ No newline at end of file
diff --git a/frontends/gtk/resources.c b/frontends/gtk/resources.c
index fc3ac6ff3..fc17f7418 100644
--- a/frontends/gtk/resources.c
+++ b/frontends/gtk/resources.c
@@ -77,8 +77,6 @@ static struct nsgtk_resource_s ui_resource[] = {
RES_ENTRY("netsurf"),
RES_ENTRY("tabcontents"),
RES_ENTRY("password"),
- RES_ENTRY("login"),
- RES_ENTRY("ssl"),
RES_ENTRY("toolbar"),
RES_ENTRY("downloads"),
RES_ENTRY("globalhistory"),
@@ -88,6 +86,7 @@ static struct nsgtk_resource_s ui_resource[] = {
RES_ENTRY("cookies"),
RES_ENTRY("viewdata"),
RES_ENTRY("warning"),
+ RES_ENTRY("pageinfo"),
{ NULL, 0, NSGTK_RESOURCE_FILE, NULL },
};
@@ -96,7 +95,18 @@ static struct nsgtk_resource_s pixbuf_resource[] = {
RES_ENTRY("favicon.png"),
RES_ENTRY("netsurf.xpm"),
RES_ENTRY("menu_cursor.png"),
- RES_ENTRY("arrow_down_8x32.png"),
+ RES_ENTRY("icons/local-history.png"),
+ RES_ENTRY("icons/show-cookie.png"),
+ RES_ENTRY("icons/24x24/actions/page-info-insecure.png"),
+ RES_ENTRY("icons/24x24/actions/page-info-internal.png"),
+ RES_ENTRY("icons/24x24/actions/page-info-local.png"),
+ RES_ENTRY("icons/24x24/actions/page-info-secure.png"),
+ RES_ENTRY("icons/24x24/actions/page-info-warning.png"),
+ RES_ENTRY("icons/48x48/actions/page-info-insecure.png"),
+ RES_ENTRY("icons/48x48/actions/page-info-internal.png"),
+ RES_ENTRY("icons/48x48/actions/page-info-local.png"),
+ RES_ENTRY("icons/48x48/actions/page-info-secure.png"),
+ RES_ENTRY("icons/48x48/actions/page-info-warning.png"),
RES_ENTRY("throbber/throbber0.png"),
RES_ENTRY("throbber/throbber1.png"),
RES_ENTRY("throbber/throbber2.png"),
@@ -114,7 +124,6 @@ static struct nsgtk_resource_s direct_resource[] = {
RES_ENTRY("welcome.html"),
RES_ENTRY("credits.html"),
RES_ENTRY("licence.html"),
- RES_ENTRY("maps.html"),
RES_ENTRY("default.css"),
RES_ENTRY("adblock.css"),
RES_ENTRY("internal.css"),
@@ -336,11 +345,6 @@ init_pixbuf_resource(char **respath, struct nsgtk_resource_s *resource)
*/
static nserror init_ui_resource(char **respath, struct nsgtk_resource_s *ui_res)
{
-#if GTK_CHECK_VERSION(3,0,0)
- int gtkv = 3;
-#else
- int gtkv = 2;
-#endif
int resnamelen;
char *resname;
struct nsgtk_resource_s resource;
@@ -352,7 +356,7 @@ static nserror init_ui_resource(char **respath, struct nsgtk_resource_s *ui_res)
if (resname == NULL) {
return NSERROR_NOMEM;
}
- snprintf(resname, resnamelen, "%s.gtk%d.ui", ui_res->name, gtkv);
+ snprintf(resname, resnamelen, "%s.ui", ui_res->name);
resource.name = resname;
resource.len = ui_res->len;
resource.path = NULL;
diff --git a/frontends/gtk/scaffolding.c b/frontends/gtk/scaffolding.c
index 6f81e91db..f9d4f6d67 100644
--- a/frontends/gtk/scaffolding.c
+++ b/frontends/gtk/scaffolding.c
@@ -1,6 +1,5 @@
/*
- * Copyright 2006 Rob Kendrick <rjek@rjek.com>
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -17,92 +16,51 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <assert.h>
+#include <gtk/gtk.h>
#include <stdbool.h>
-#include <stdio.h>
-#include <errno.h>
#include <stdlib.h>
-#include <unistd.h>
#include <string.h>
-#include <gtk/gtk.h>
-#include <gdk-pixbuf/gdk-pixbuf.h>
#include "utils/utils.h"
-#include "utils/dirent.h"
-#include "utils/messages.h"
-#include "utils/corestrings.h"
#include "utils/log.h"
-#include "utils/nsoption.h"
-#include "utils/file.h"
+#include "utils/messages.h"
#include "utils/nsurl.h"
-#include "netsurf/content.h"
-#include "netsurf/keypress.h"
+#include "utils/nsoption.h"
#include "netsurf/browser_window.h"
-#include "netsurf/plotters.h"
#include "desktop/browser_history.h"
#include "desktop/hotlist.h"
-#include "desktop/print.h"
-#include "desktop/save_complete.h"
-#ifdef WITH_PDF_EXPORT
-#include "desktop/font_haru.h"
-#include "desktop/save_pdf.h"
-#endif
-#include "desktop/save_text.h"
-#include "desktop/searchweb.h"
-#include "desktop/search.h"
#include "gtk/compat.h"
-#include "gtk/warn.h"
-#include "gtk/cookies.h"
-#include "gtk/completion.h"
-#include "gtk/preferences.h"
-#include "gtk/about.h"
-#include "gtk/viewsource.h"
-#include "gtk/bitmap.h"
-#include "gtk/gui.h"
-#include "gtk/global_history.h"
+#include "gtk/toolbar_items.h"
+#include "gtk/menu.h"
#include "gtk/local_history.h"
-#include "gtk/hotlist.h"
+#include "gtk/gui.h"
#include "gtk/download.h"
-#include "gtk/menu.h"
-#include "gtk/plotters.h"
-#include "gtk/print.h"
-#include "gtk/search.h"
-#include "gtk/throbber.h"
-#include "gtk/toolbar.h"
#include "gtk/window.h"
-#include "gtk/gdk.h"
-#include "gtk/scaffolding.h"
+#include "gtk/warn.h"
#include "gtk/tabs.h"
-#include "gtk/schedule.h"
-#include "gtk/viewdata.h"
#include "gtk/resources.h"
-#include "gtk/layout_pango.h"
-
-/** Macro to define a handler for menu, button and activate events. */
-#define MULTIHANDLER(q)\
-static gboolean nsgtk_on_##q##_activate(struct nsgtk_scaffolding *g);\
-static gboolean nsgtk_on_##q##_activate_menu(GtkMenuItem *widget, gpointer data)\
-{\
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;\
- return nsgtk_on_##q##_activate(g);\
-}\
-static gboolean nsgtk_on_##q##_activate_button(GtkButton *widget, gpointer data)\
-{\
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;\
- return nsgtk_on_##q##_activate(g);\
-}\
-static gboolean nsgtk_on_##q##_activate(struct nsgtk_scaffolding *g)
-
-/** Macro to define a handler for menu events. */
-#define MENUHANDLER(q)\
-static gboolean nsgtk_on_##q##_activate_menu(GtkMenuItem *widget, gpointer data)
-
-/** Macro to define a handler for button events. */
-#define BUTTONHANDLER(q)\
-static gboolean nsgtk_on_##q##_activate(GtkButton *widget, gpointer data)
-
-/** Core scaffolding structure. */
+#include "gtk/scaffolding.h"
+
+
+/**
+ * menu entry context
+ */
+struct nsgtk_menu {
+ GtkWidget *main; /* main menu entry */
+ GtkWidget *burger; /* right click menu */
+ GtkWidget *popup; /* popup menu entry */
+ /**
+ * menu item handler
+ */
+ gboolean (*mhandler)(GtkMenuItem *widget, gpointer data);
+ const char *iconname; /* name of the icon to use */
+ bool sensitivity; /* menu item is sensitive */
+};
+
+/**
+ * Core scaffolding structure.
+ */
struct nsgtk_scaffolding {
/** global linked list of scaffolding for gui interface adjustments */
struct nsgtk_scaffolding *next, *prev;
@@ -115,45 +73,37 @@ struct nsgtk_scaffolding {
/** scaffold container window */
GtkWindow *window;
- bool fullscreen; /**< flag for the scaffold window fullscreen status */
/** tab widget holding displayed pages */
GtkNotebook *notebook;
- /** entry widget holding the url of the current displayed page */
- GtkWidget *url_bar;
- GtkEntryCompletion *url_bar_completion; /**< Completions for url_bar */
-
- /** Activity throbber */
- GtkImage *throbber;
- int throb_frame; /**< Current frame of throbber animation */
-
- struct gtk_search *search;
- /** Web search widget */
- GtkWidget *webSearchEntry;
-
- /** controls toolbar */
- GtkToolbar *tool_bar;
- struct nsgtk_button_connect *buttons[PLACEHOLDER_BUTTON];
- int offset;
- int toolbarmem;
- int toolbarbase;
- int historybase;
+ /** handler id for tabs remove callback */
+ gulong tabs_remove_handler_id;
/** menu bar hierarchy */
struct nsgtk_bar_submenu *menu_bar;
+ /** burger menu hierarchy */
+ struct nsgtk_burger_menu *burger_menu;
+
/** right click popup menu hierarchy */
- struct nsgtk_popup_menu *menu_popup;
+ struct nsgtk_popup_menu *popup_menu;
/** link popup menu */
struct nsgtk_link_menu *link_menu;
+
+ /** menu entries widgets for sensitivity adjustment */
+ struct nsgtk_menu menus[PLACEHOLDER_BUTTON];
};
-/** current scaffold for model dialogue use */
+/**
+ * current scaffold for model dialogue use
+ */
static struct nsgtk_scaffolding *scaf_current;
-/** global list for interface changes */
+/**
+ * global list for interface changes
+ */
static struct nsgtk_scaffolding *scaf_list = NULL;
/**
@@ -167,45 +117,31 @@ static struct browser_window_features current_menu_features;
* Helper to hide popup menu entries by grouping.
*
* \param menu The popup menu to modify.
- * \param submenu flag to indicate if submenus should be hidden.
* \param nav flag to indicate if navigation entries should be hidden.
* \param cnp flag to indicate if cut and paste entries should be hidden.
* \param custom flag to indicate if menu customisation is hidden.
*/
static void
-popup_menu_hide(struct nsgtk_popup_menu *menu,
- bool submenu,
- bool nav,
- bool cnp,
- bool custom)
+popup_menu_hide(struct nsgtk_popup_menu *menu, bool nav, bool cnp)
{
- if (submenu) {
- gtk_widget_hide(GTK_WIDGET(menu->file_menuitem));
- gtk_widget_hide(GTK_WIDGET(menu->edit_menuitem));
- gtk_widget_hide(GTK_WIDGET(menu->view_menuitem));
- gtk_widget_hide(GTK_WIDGET(menu->nav_menuitem));
- gtk_widget_hide(GTK_WIDGET(menu->help_menuitem));
-
- gtk_widget_hide(menu->first_separator);
- }
-
if (nav) {
gtk_widget_hide(GTK_WIDGET(menu->back_menuitem));
gtk_widget_hide(GTK_WIDGET(menu->forward_menuitem));
gtk_widget_hide(GTK_WIDGET(menu->stop_menuitem));
gtk_widget_hide(GTK_WIDGET(menu->reload_menuitem));
+
+ gtk_widget_hide(menu->first_separator);
}
if (cnp) {
gtk_widget_hide(GTK_WIDGET(menu->cut_menuitem));
gtk_widget_hide(GTK_WIDGET(menu->copy_menuitem));
gtk_widget_hide(GTK_WIDGET(menu->paste_menuitem));
- }
- if (custom) {
- gtk_widget_hide(GTK_WIDGET(menu->customize_menuitem));
+ gtk_widget_hide(menu->second_separator);
}
+
}
@@ -213,48 +149,32 @@ popup_menu_hide(struct nsgtk_popup_menu *menu,
* Helper to show popup menu entries by grouping.
*
* \param menu The popup menu to modify.
- * \param submenu flag to indicate if submenus should be visible.
* \param nav flag to indicate if navigation entries should be visible.
* \param cnp flag to indicate if cut and paste entries should be visible.
* \param custom flag to indicate if menu customisation is visible.
*/
static void
-popup_menu_show(struct nsgtk_popup_menu *menu,
- bool submenu,
- bool nav,
- bool cnp,
- bool custom)
+popup_menu_show(struct nsgtk_popup_menu *menu, bool nav, bool cnp)
{
- if (submenu) {
- gtk_widget_show(GTK_WIDGET(menu->file_menuitem));
- gtk_widget_show(GTK_WIDGET(menu->edit_menuitem));
- gtk_widget_show(GTK_WIDGET(menu->view_menuitem));
- gtk_widget_show(GTK_WIDGET(menu->nav_menuitem));
- gtk_widget_show(GTK_WIDGET(menu->help_menuitem));
-
- gtk_widget_show(menu->first_separator);
- }
-
if (nav) {
gtk_widget_show(GTK_WIDGET(menu->back_menuitem));
gtk_widget_show(GTK_WIDGET(menu->forward_menuitem));
gtk_widget_show(GTK_WIDGET(menu->stop_menuitem));
gtk_widget_show(GTK_WIDGET(menu->reload_menuitem));
+
+ gtk_widget_show(menu->first_separator);
}
if (cnp) {
gtk_widget_show(GTK_WIDGET(menu->cut_menuitem));
gtk_widget_show(GTK_WIDGET(menu->copy_menuitem));
gtk_widget_show(GTK_WIDGET(menu->paste_menuitem));
- }
- if (custom) {
- gtk_widget_show(GTK_WIDGET(menu->customize_menuitem));
+ gtk_widget_show(menu->second_separator);
}
-}
+}
-/* event handlers and support functions for them */
/**
* resource cleanup function for window destruction.
@@ -273,6 +193,18 @@ static void scaffolding_window_destroy(GtkWidget *widget, gpointer data)
nsgtk_local_history_hide();
+ /* ensure scaffolding being destroyed is not current */
+ if (scaf_current == gs) {
+ scaf_current = NULL;
+ /* attempt to select nearest scaffold instead of just selecting the first */
+ if (gs->prev != NULL) {
+ scaf_current = gs->prev;
+ } else if (gs->next != NULL) {
+ scaf_current = gs->next;
+ }
+ }
+
+ /* remove scaffolding from list */
if (gs->prev != NULL) {
gs->prev->next = gs->next;
} else {
@@ -284,6 +216,16 @@ static void scaffolding_window_destroy(GtkWidget *widget, gpointer data)
NSLOG(netsurf, INFO, "scaffold list head: %p", scaf_list);
+ /* ensure menu resources are freed */
+ nsgtk_menu_bar_destroy(gs->menu_bar);
+ nsgtk_burger_menu_destroy(gs->burger_menu);
+ nsgtk_popup_menu_destroy(gs->popup_menu);
+ nsgtk_link_menu_destroy(gs->link_menu);
+
+ g_signal_handler_disconnect(gs->notebook, gs->tabs_remove_handler_id);
+
+ free(gs);
+
if (scaf_list == NULL) {
/* no more open windows - stop the browser */
nsgtk_complete = true;
@@ -326,100 +268,74 @@ static void scaffolding_update_context(struct nsgtk_scaffolding *g)
{
struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- g->buttons[BACK_BUTTON]->sensitivity =
- browser_window_history_back_available(bw);
- g->buttons[FORWARD_BUTTON]->sensitivity =
- browser_window_history_forward_available(bw);
+ g->menus[BACK_BUTTON].sensitivity =
+ browser_window_history_back_available(bw);
+ g->menus[FORWARD_BUTTON].sensitivity =
+ browser_window_history_forward_available(bw);
nsgtk_scaffolding_set_sensitivity(g);
- /* update the url bar, particularly necessary when tabbing */
- browser_window_refresh_url_bar(bw);
-
nsgtk_local_history_hide();
}
/**
- * Make the throbber run.
- *
- * scheduled callback to update the throbber
- *
- * \param p The context passed when scheduled.
- */
-static void nsgtk_throb(void *p)
-{
- struct nsgtk_scaffolding *g = p;
-
- if (g->throb_frame >= (nsgtk_throbber->nframes - 1)) {
- g->throb_frame = 1;
- } else {
- g->throb_frame++;
- }
-
- gtk_image_set_from_pixbuf(g->throbber,
- nsgtk_throbber->framedata[g->throb_frame]);
-
- nsgtk_schedule(100, nsgtk_throb, p);
-}
-
-
-/**
* edit the sensitivity of focused widget
*
+ * \todo this needs to update toolbar sensitivity
+ *
* \param g The scaffolding context.
*/
static guint
-nsgtk_scaffolding_update_edit_actions_sensitivity(
- struct nsgtk_scaffolding *g)
+nsgtk_scaffolding_update_edit_actions_sensitivity(struct nsgtk_scaffolding *g)
{
GtkWidget *widget = gtk_window_get_focus(g->window);
- gboolean has_selection;
if (GTK_IS_EDITABLE(widget)) {
+ gboolean has_selection;
has_selection = gtk_editable_get_selection_bounds(
- GTK_EDITABLE (widget), NULL, NULL);
-
- g->buttons[COPY_BUTTON]->sensitivity = has_selection;
- g->buttons[CUT_BUTTON]->sensitivity = has_selection;
- g->buttons[PASTE_BUTTON]->sensitivity = true;
+ GTK_EDITABLE(widget), NULL, NULL);
+ g->menus[COPY_BUTTON].sensitivity = has_selection;
+ g->menus[CUT_BUTTON].sensitivity = has_selection;
+ g->menus[PASTE_BUTTON].sensitivity = true;
} else {
struct browser_window *bw =
- nsgtk_get_browser_window(g->top_level);
+ nsgtk_get_browser_window(g->top_level);
browser_editor_flags edit_f =
- browser_window_get_editor_flags(bw);
-
- g->buttons[COPY_BUTTON]->sensitivity =
- edit_f & BW_EDITOR_CAN_COPY;
- g->buttons[CUT_BUTTON]->sensitivity =
- edit_f & BW_EDITOR_CAN_CUT;
- g->buttons[PASTE_BUTTON]->sensitivity =
- edit_f & BW_EDITOR_CAN_PASTE;
+ browser_window_get_editor_flags(bw);
+
+ g->menus[COPY_BUTTON].sensitivity =
+ edit_f & BW_EDITOR_CAN_COPY;
+ g->menus[CUT_BUTTON].sensitivity =
+ edit_f & BW_EDITOR_CAN_CUT;
+ g->menus[PASTE_BUTTON].sensitivity =
+ edit_f & BW_EDITOR_CAN_PASTE;
}
nsgtk_scaffolding_set_sensitivity(g);
- return ((g->buttons[COPY_BUTTON]->sensitivity) |
- (g->buttons[CUT_BUTTON]->sensitivity) |
- (g->buttons[PASTE_BUTTON]->sensitivity));
+
+ return ((g->menus[COPY_BUTTON].sensitivity) |
+ (g->menus[CUT_BUTTON].sensitivity) |
+ (g->menus[PASTE_BUTTON].sensitivity));
}
/**
* make edit actions sensitive
*
+ * \todo toolbar sensitivity
+ *
* \param g The scaffolding context.
*/
static void
-nsgtk_scaffolding_enable_edit_actions_sensitivity(
- struct nsgtk_scaffolding *g)
+nsgtk_scaffolding_enable_edit_actions_sensitivity(struct nsgtk_scaffolding *g)
{
-
- g->buttons[PASTE_BUTTON]->sensitivity = true;
- g->buttons[COPY_BUTTON]->sensitivity = true;
- g->buttons[CUT_BUTTON]->sensitivity = true;
+ g->menus[PASTE_BUTTON].sensitivity = true;
+ g->menus[COPY_BUTTON].sensitivity = true;
+ g->menus[CUT_BUTTON].sensitivity = true;
nsgtk_scaffolding_set_sensitivity(g);
- popup_menu_show(g->menu_popup, false, false, true, false);
+ popup_menu_show(g->popup_menu, false, true);
}
/* signal handling functions for the toolbar, URL bar, and menu bar */
@@ -456,6 +372,7 @@ nsgtk_window_edit_menu_hidden(GtkWidget *widget,
return TRUE;
}
+
/**
* gtk event handler for popup menu being hidden.
*
@@ -463,80 +380,10 @@ nsgtk_window_edit_menu_hidden(GtkWidget *widget,
* \param g scaffolding handle
* \return TRUE to indicate event handled
*/
-static gboolean nsgtk_window_popup_menu_hidden(GtkWidget *widget,
- struct nsgtk_scaffolding *g)
-{
- nsgtk_scaffolding_enable_edit_actions_sensitivity(g);
- return TRUE;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-gboolean nsgtk_window_url_activate_event(GtkWidget *widget, gpointer data)
-{
- struct nsgtk_scaffolding *g = data;
- nserror ret;
- nsurl *url;
-
- ret = search_web_omni(gtk_entry_get_text(GTK_ENTRY(g->url_bar)),
- SEARCH_WEB_OMNI_NONE,
- &url);
- if (ret == NSERROR_OK) {
- ret = browser_window_navigate(nsgtk_get_browser_window(g->top_level),
- url, NULL, BW_NAVIGATE_HISTORY,
- NULL, NULL, NULL);
- nsurl_unref(url);
- }
- if (ret != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(ret), 0);
- }
-
- return TRUE;
-}
-
-
-/**
- * update handler for URL entry widget
- *
- * \param widget The widget receiving the delete event
- * \param event The event
- * \param data The context pointer passed when the connection was made.
- * \return TRUE to indicate signal handled.
- */
-gboolean
-nsgtk_window_url_changed(GtkWidget *widget,
- GdkEventKey *event,
- gpointer data)
-{
- return nsgtk_completion_update(GTK_ENTRY(widget));
-}
-
-
-/**
- * Event handler for popup menu on toolbar.
- *
- * \param toolbar The toolbar being clicked
- * \param x The x coordinate where the click happened
- * \param y The x coordinate where the click happened
- * \param button the buttons being pressed
- * \param data The context pointer passed when the connection was made.
- * \return TRUE to indicate event handled.
- */
static gboolean
-nsgtk_window_tool_bar_clicked(GtkToolbar *toolbar,
- gint x,
- gint y,
- gint button,
- gpointer data)
+nsgtk_window_popup_menu_hidden(GtkWidget *widget, struct nsgtk_scaffolding *g)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
-
- /* set visibility for right-click popup menu */
- popup_menu_hide(g->menu_popup, true, false, true, false);
- popup_menu_show(g->menu_popup, false, false, false, true);
-
- gtk_menu_popup(g->menu_popup->popup_menu, NULL, NULL, NULL, NULL, 0,
- gtk_get_current_event_time());
-
+ nsgtk_scaffolding_enable_edit_actions_sensitivity(g);
return TRUE;
}
@@ -544,6 +391,9 @@ nsgtk_window_tool_bar_clicked(GtkToolbar *toolbar,
/**
* Update the menus when the number of tabs changes.
*
+ * \todo toolbar sensitivity
+ * \todo next/previous tab ought to only be visible if there is such a tab
+ *
* \param notebook The notebook all the tabs are in
* \param page The newly added page container widget
* \param page_num The index of the newly added page
@@ -557,12 +407,18 @@ nsgtk_window_tabs_add(GtkNotebook *notebook,
{
gboolean visible = gtk_notebook_get_show_tabs(g->notebook);
g_object_set(g->menu_bar->view_submenu->tabs_menuitem,
- "visible", visible, NULL);
- g_object_set(g->menu_popup->view_submenu->tabs_menuitem,
- "visible", visible, NULL);
- g->buttons[NEXTTAB_BUTTON]->sensitivity = visible;
- g->buttons[PREVTAB_BUTTON]->sensitivity = visible;
- g->buttons[CLOSETAB_BUTTON]->sensitivity = visible;
+ "visible",
+ visible,
+ NULL);
+ g_object_set(g->burger_menu->view_submenu->tabs_menuitem,
+ "visible",
+ visible,
+ NULL);
+
+ g->menus[NEXTTAB_BUTTON].sensitivity = visible;
+ g->menus[PREVTAB_BUTTON].sensitivity = visible;
+ g->menus[CLOSETAB_BUTTON].sensitivity = visible;
+
nsgtk_scaffolding_set_sensitivity(g);
}
@@ -570,6 +426,8 @@ nsgtk_window_tabs_add(GtkNotebook *notebook,
/**
* Update the menus when the number of tabs changes.
*
+ * \todo toolbar sensitivity
+ *
* \param notebook The notebook all the tabs are in
* \param page The page container widget being removed
* \param page_num The index of the removed page
@@ -581,6 +439,8 @@ nsgtk_window_tabs_remove(GtkNotebook *notebook,
guint page_num,
struct nsgtk_scaffolding *gs)
{
+ gboolean visible;
+
/* if the scaffold is being destroyed it is not useful to
* update the state, further many of the widgets may have
* already been destroyed.
@@ -595,472 +455,46 @@ nsgtk_window_tabs_remove(GtkNotebook *notebook,
return;
}
- gboolean visible = gtk_notebook_get_show_tabs(gs->notebook);
- g_object_set(gs->menu_bar->view_submenu->tabs_menuitem, "visible", visible, NULL);
- g_object_set(gs->menu_popup->view_submenu->tabs_menuitem, "visible", visible, NULL);
- gs->buttons[NEXTTAB_BUTTON]->sensitivity = visible;
- gs->buttons[PREVTAB_BUTTON]->sensitivity = visible;
- gs->buttons[CLOSETAB_BUTTON]->sensitivity = visible;
- nsgtk_scaffolding_set_sensitivity(gs);
-}
-
-/**
- * Handle opening a file path.
- *
- * \param filename The filename to open.
- */
-static void nsgtk_openfile_open(const char *filename)
-{
- struct browser_window *bw;
- char *urltxt;
- nsurl *url;
- nserror error;
-
- bw = nsgtk_get_browser_window(scaf_current->top_level);
-
- urltxt = malloc(strlen(filename) + FILE_SCHEME_PREFIX_LEN + 1);
-
- if (urltxt != NULL) {
- sprintf(urltxt, FILE_SCHEME_PREFIX"%s", filename);
-
- error = nsurl_create(urltxt, &url);
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- } else {
- browser_window_navigate(bw,
- url,
- NULL,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
- }
- free(urltxt);
- }
-}
-
-/* signal handlers for menu entries */
-
-MULTIHANDLER(newwindow)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- const char *addr;
- nsurl *url;
- nserror error;
-
- if (nsoption_charp(homepage_url) != NULL) {
- addr = nsoption_charp(homepage_url);
- } else {
- addr = NETSURF_HOMEPAGE;
- }
-
- error = nsurl_create(addr, &url);
- if (error == NSERROR_OK) {
- error = browser_window_create(BW_CREATE_HISTORY,
- url,
- NULL,
- bw,
- NULL);
- nsurl_unref(url);
- }
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- }
-
- return TRUE;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-nserror nsgtk_scaffolding_new_tab(struct gui_window *gw)
-{
- struct browser_window *bw = nsgtk_get_browser_window(gw);
- nsurl *url = NULL;
- nserror error;
-
- if (!nsoption_bool(new_blank)) {
- const char *addr;
- if (nsoption_charp(homepage_url) != NULL) {
- addr = nsoption_charp(homepage_url);
- } else {
- addr = NETSURF_HOMEPAGE;
- }
- error = nsurl_create(addr, &url);
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- }
- }
-
- error = browser_window_create(BW_CREATE_HISTORY |
- BW_CREATE_TAB,
- url,
- NULL,
- bw,
- NULL);
- if (url != NULL) {
- nsurl_unref(url);
- }
- return error;
-}
+ visible = gtk_notebook_get_show_tabs(gs->notebook);
+ g_object_set(gs->menu_bar->view_submenu->tabs_menuitem,
+ "visible", visible, NULL);
+ g_object_set(gs->burger_menu->view_submenu->tabs_menuitem,
+ "visible", visible, NULL);
-MULTIHANDLER(newtab)
-{
- nserror error;
+ gs->menus[NEXTTAB_BUTTON].sensitivity = visible;
+ gs->menus[PREVTAB_BUTTON].sensitivity = visible;
+ gs->menus[CLOSETAB_BUTTON].sensitivity = visible;
- error = nsgtk_scaffolding_new_tab(g->top_level);
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- }
- return TRUE;
+ nsgtk_scaffolding_set_sensitivity(gs);
}
-MULTIHANDLER(openfile)
-{
- GtkWidget *dlgOpen;
- gint response;
-
- scaf_current = g;
- dlgOpen = gtk_file_chooser_dialog_new("Open File",
- scaf_current->window,
- GTK_FILE_CHOOSER_ACTION_OPEN,
- NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NSGTK_STOCK_OPEN, GTK_RESPONSE_OK,
- NULL, NULL);
-
- response = gtk_dialog_run(GTK_DIALOG(dlgOpen));
- if (response == GTK_RESPONSE_OK) {
- gchar *filename;
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlgOpen));
-
- nsgtk_openfile_open((const char *)filename);
-
- g_free(filename);
- }
- gtk_widget_destroy(dlgOpen);
- return TRUE;
-}
+/* signal handlers for menu entries */
/**
- * callback to determine if a path is a directory.
- *
- * \param info The path information
- * \param data context pointer set to NULL
- * \return TRUE if path is a directory else false
+ * handle menu activate signals by calling toolbar item activation
*/
-static gboolean
-nsgtk_filter_directory(const GtkFileFilterInfo *info,
- gpointer data)
-{
- DIR *d = opendir(info->filename);
- if (d == NULL)
- return FALSE;
- closedir(d);
- return TRUE;
-}
-
-MULTIHANDLER(savepage)
-{
- if (!browser_window_has_content(nsgtk_get_browser_window(g->top_level)))
- return FALSE;
-
- GtkWidget *fc = gtk_file_chooser_dialog_new(
- messages_get("gtkcompleteSave"), g->window,
- GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER,
- NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NSGTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
- DIR *d;
- char *path;
- nserror res;
- GtkFileFilter *filter = gtk_file_filter_new();
- gtk_file_filter_set_name(filter, "Directories");
- gtk_file_filter_add_custom(filter, GTK_FILE_FILTER_FILENAME,
- nsgtk_filter_directory, NULL, NULL);
- gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(fc), filter);
- gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(fc), filter);
-
- res = nsurl_nice(browser_window_get_url(
- nsgtk_get_browser_window(g->top_level)), &path, false);
- if (res != NSERROR_OK) {
- path = strdup(messages_get("SaveText"));
- if (path == NULL) {
- nsgtk_warning("NoMemory", 0);
- return FALSE;
- }
- }
-
- if (access(path, F_OK) != 0)
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), path);
- free(path);
-
- gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fc),
- TRUE);
-
- if (gtk_dialog_run(GTK_DIALOG(fc)) != GTK_RESPONSE_ACCEPT) {
- gtk_widget_destroy(fc);
- return TRUE;
- }
-
- path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc));
- d = opendir(path);
- if (d == NULL) {
- NSLOG(netsurf, INFO,
- "Unable to open directory %s for complete save: %s",
- path,
- strerror(errno));
- if (errno == ENOTDIR)
- nsgtk_warning("NoDirError", path);
- else
- nsgtk_warning("gtkFileError", path);
- gtk_widget_destroy(fc);
- g_free(path);
- return TRUE;
- }
- closedir(d);
- save_complete(browser_window_get_content(nsgtk_get_browser_window(
- g->top_level)), path, NULL);
- g_free(path);
-
- gtk_widget_destroy(fc);
-
- return TRUE;
-}
-
-
-MULTIHANDLER(pdf)
-{
-#ifdef WITH_PDF_EXPORT
-
- GtkWidget *save_dialog;
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- struct print_settings *settings;
- char filename[PATH_MAX];
- char dirname[PATH_MAX];
- char *url_name;
- nserror res;
-
- NSLOG(netsurf, INFO, "Print preview (generating PDF) started.");
-
- res = nsurl_nice(browser_window_get_url(bw), &url_name, true);
- if (res != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(res), 0);
- return TRUE;
- }
-
- strncpy(filename, url_name, PATH_MAX);
- strncat(filename, ".pdf", PATH_MAX - strlen(filename));
- filename[PATH_MAX - 1] = '\0';
-
- free(url_name);
-
- strncpy(dirname, option_downloads_directory, PATH_MAX);
- strncat(dirname, "/", PATH_MAX - strlen(dirname));
- dirname[PATH_MAX - 1] = '\0';
-
- /* this way the scale used by PDF functions is synchronised with that
- * used by the all-purpose print interface
- */
- haru_nsfont_set_scale((float)option_export_scale / 100);
-
- save_dialog = gtk_file_chooser_dialog_new("Export to PDF", g->window,
- GTK_FILE_CHOOSER_ACTION_SAVE,
- NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NSGTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
-
- gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(save_dialog),
- dirname);
-
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(save_dialog),
- filename);
-
- if (gtk_dialog_run(GTK_DIALOG(save_dialog)) == GTK_RESPONSE_ACCEPT) {
- gchar *filename = gtk_file_chooser_get_filename(
- GTK_FILE_CHOOSER(save_dialog));
-
- settings = print_make_settings(PRINT_OPTIONS,
- (const char *) filename, &haru_nsfont);
- g_free(filename);
-
- if (settings == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- gtk_widget_destroy(save_dialog);
- return TRUE;
- }
-
- /* This will clean up the print_settings object for us */
- print_basic_run(browser_window_get_content(bw),
- &pdf_printer, settings);
- }
-
- gtk_widget_destroy(save_dialog);
-
-#endif /* WITH_PDF_EXPORT */
-
- return TRUE;
-}
-
-MULTIHANDLER(plaintext)
-{
- if (!browser_window_has_content(nsgtk_get_browser_window(g->top_level)))
- return FALSE;
-
- GtkWidget *fc = gtk_file_chooser_dialog_new(
- messages_get("gtkplainSave"), g->window,
- GTK_FILE_CHOOSER_ACTION_SAVE,
- NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
- NSGTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
- NULL);
- char *filename;
- nserror res;
-
- res = nsurl_nice(browser_window_get_url(
- nsgtk_get_browser_window(g->top_level)),
- &filename, false);
- if (res != NSERROR_OK) {
- filename = strdup(messages_get("SaveText"));
- if (filename == NULL) {
- nsgtk_warning("NoMemory", 0);
- return FALSE;
- }
- }
-
- gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), filename);
- gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fc),
- TRUE);
+#define TOOLBAR_ITEM_p(identifier, name) \
+ static gboolean \
+nsgtk_on_##name##_activate_menu(GtkMenuItem *widget, gpointer data) \
+{ \
+ struct nsgtk_scaffolding *gs = (struct nsgtk_scaffolding *)data;\
+ nsgtk_window_item_activate(gs->top_level, identifier); \
+ return TRUE; \
+}
+#define TOOLBAR_ITEM_y(identifier, name)
+#define TOOLBAR_ITEM_n(identifier, name)
+#define TOOLBAR_ITEM(identifier, name, sensitivity, clicked, activate, label, iconame) \
+ TOOLBAR_ITEM_ ## activate(identifier, name)
+#include "gtk/toolbar_items.h"
+#undef TOOLBAR_ITEM_y
+#undef TOOLBAR_ITEM_n
+#undef TOOLBAR_ITEM_p
+#undef TOOLBAR_ITEM
- free(filename);
- if (gtk_dialog_run(GTK_DIALOG(fc)) == GTK_RESPONSE_ACCEPT) {
- filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc));
- save_as_text(browser_window_get_content(
- nsgtk_get_browser_window(
- g->top_level)), filename);
- g_free(filename);
- }
-
- gtk_widget_destroy(fc);
- return TRUE;
-}
-
-MULTIHANDLER(drawfile)
-{
- return TRUE;
-}
-
-MULTIHANDLER(postscript)
-{
- return TRUE;
-}
-
-MULTIHANDLER(printpreview)
-{
- return TRUE;
-}
-
-
-MULTIHANDLER(print)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
-
- GtkPrintOperation *print_op;
- GtkPageSetup *page_setup;
- GtkPrintSettings *print_settings;
- GtkPrintOperationResult res = GTK_PRINT_OPERATION_RESULT_ERROR;
- struct print_settings *nssettings;
- char *settings_fname = NULL;
-
- print_op = gtk_print_operation_new();
- if (print_op == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- return TRUE;
- }
-
- /* use previously saved settings if any */
- netsurf_mkpath(&settings_fname, NULL, 2, nsgtk_config_home, "Print");
- if (settings_fname != NULL) {
- print_settings = gtk_print_settings_new_from_file(settings_fname, NULL);
- if (print_settings != NULL) {
- gtk_print_operation_set_print_settings(print_op,
- print_settings);
-
- /* We're not interested in the settings any more */
- g_object_unref(print_settings);
- }
- }
-
- content_to_print = browser_window_get_content(bw);
-
- page_setup = gtk_print_run_page_setup_dialog(g->window, NULL, NULL);
- if (page_setup == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- free(settings_fname);
- g_object_unref(print_op);
- return TRUE;
- }
- gtk_print_operation_set_default_page_setup(print_op, page_setup);
-
- nssettings = print_make_settings(PRINT_DEFAULT, NULL, nsgtk_layout_table);
-
- g_signal_connect(print_op, "begin_print",
- G_CALLBACK(gtk_print_signal_begin_print), nssettings);
- g_signal_connect(print_op, "draw_page",
- G_CALLBACK(gtk_print_signal_draw_page), NULL);
- g_signal_connect(print_op, "end_print",
- G_CALLBACK(gtk_print_signal_end_print), nssettings);
-
- if (content_get_type(browser_window_get_content(bw)) !=
- CONTENT_TEXTPLAIN) {
- res = gtk_print_operation_run(print_op,
- GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
- g->window,
- NULL);
- }
-
- /* if the settings were used save them for future use */
- if (settings_fname != NULL) {
- if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
- /* Do not increment the settings reference */
- print_settings =
- gtk_print_operation_get_print_settings(print_op);
-
- gtk_print_settings_to_file(print_settings,
- settings_fname,
- NULL);
- }
- free(settings_fname);
- }
-
- /* Our print_settings object is destroyed by the end print handler */
- g_object_unref(page_setup);
- g_object_unref(print_op);
-
- return TRUE;
-}
-
-MULTIHANDLER(closewindow)
-{
- gtk_widget_destroy(GTK_WIDGET(g->window));
- return TRUE;
-}
-
-MULTIHANDLER(quit)
-{
- struct nsgtk_scaffolding *gs;
-
- if (nsgtk_check_for_downloads(g->window) == false) {
- gs = scaf_list;
- while (gs != NULL) {
- gtk_widget_destroy(GTK_WIDGET(gs->window));
- gs = gs->next;
- }
- }
-
- return TRUE;
-}
-
-MENUHANDLER(savelink)
+static gboolean
+nsgtk_on_savelink_activate_menu(GtkMenuItem *widget, gpointer data)
{
struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *) data;
struct gui_window *gui = g->top_level;
@@ -1084,10 +518,12 @@ MENUHANDLER(savelink)
return TRUE;
}
+
/**
* Handler for opening new window from a link. attached to the popup menu.
*/
-MENUHANDLER(link_openwin)
+static gboolean
+nsgtk_on_link_openwin_activate_menu(GtkMenuItem *widget, gpointer data)
{
struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *) data;
struct gui_window *gui = g->top_level;
@@ -1106,10 +542,12 @@ MENUHANDLER(link_openwin)
return TRUE;
}
+
/**
* Handler for opening new tab from a link. attached to the popup menu.
*/
-MENUHANDLER(link_opentab)
+static gboolean
+nsgtk_on_link_opentab_activate_menu(GtkMenuItem *widget, gpointer data)
{
struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *) data;
struct gui_window *gui = g->top_level;
@@ -1119,8 +557,6 @@ MENUHANDLER(link_opentab)
if (current_menu_features.link == NULL)
return FALSE;
- temp_open_background = 1;
-
err = browser_window_create(BW_CREATE_CLONE |
BW_CREATE_HISTORY |
BW_CREATE_TAB,
@@ -1129,15 +565,15 @@ MENUHANDLER(link_opentab)
nsgtk_warning(messages_get_errorcode(err), 0);
}
- temp_open_background = -1;
-
return TRUE;
}
+
/**
* Handler for bookmarking a link. attached to the popup menu.
*/
-MENUHANDLER(link_bookmark)
+static gboolean
+nsgtk_on_link_bookmark_activate_menu(GtkMenuItem *widget, gpointer data)
{
if (current_menu_features.link == NULL)
return FALSE;
@@ -1147,10 +583,12 @@ MENUHANDLER(link_bookmark)
return TRUE;
}
+
/**
* Handler for copying a link. attached to the popup menu.
*/
-MENUHANDLER(link_copy)
+static gboolean
+nsgtk_on_link_copy_activate_menu(GtkMenuItem *widget, gpointer data)
{
GtkClipboard *clipboard;
@@ -1165,624 +603,346 @@ MENUHANDLER(link_copy)
}
-MULTIHANDLER(cut)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- GtkWidget *focused = gtk_window_get_focus(g->window);
-
- /* If the url bar has focus, let gtk handle it */
- if (GTK_IS_EDITABLE (focused))
- gtk_editable_cut_clipboard (GTK_EDITABLE(g->url_bar));
- else
- browser_window_key_press(bw, NS_KEY_CUT_SELECTION);
-
- return TRUE;
-}
-
-MULTIHANDLER(copy)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- GtkWidget *focused = gtk_window_get_focus(g->window);
-
- /* If the url bar has focus, let gtk handle it */
- if (GTK_IS_EDITABLE (focused))
- gtk_editable_copy_clipboard(GTK_EDITABLE(g->url_bar));
- else
- browser_window_key_press(bw, NS_KEY_COPY_SELECTION);
-
- return TRUE;
-}
-
-MULTIHANDLER(paste)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- GtkWidget *focused = gtk_window_get_focus(g->window);
-
- /* If the url bar has focus, let gtk handle it */
- if (GTK_IS_EDITABLE (focused))
- gtk_editable_paste_clipboard (GTK_EDITABLE (focused));
- else
- browser_window_key_press(bw, NS_KEY_PASTE);
-
- return TRUE;
-}
-
-MULTIHANDLER(delete)
-{
- return TRUE;
-}
-
-MENUHANDLER(customize)
+static gboolean nsgtk_on_find_activate_menu(GtkMenuItem *widget, gpointer data)
{
struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- nsgtk_toolbar_customization_init(g);
- return TRUE;
-}
-
-MULTIHANDLER(selectall)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- if (nsgtk_widget_has_focus(GTK_WIDGET(g->url_bar))) {
- NSLOG(netsurf, INFO, "Selecting all URL bar text");
- gtk_editable_select_region(GTK_EDITABLE(g->url_bar), 0, -1);
- } else {
- NSLOG(netsurf, INFO, "Selecting all document text");
- browser_window_key_press(bw, NS_KEY_SELECT_ALL);
- }
+ nsgtk_window_search_toggle(g->top_level);
return TRUE;
}
-MULTIHANDLER(find)
+static nserror get_bar_show(bool *menu, bool *tool)
{
- nsgtk_scaffolding_toggle_search_bar_visibility(g);
- return TRUE;
-}
+ const char *cur_bar_show;
-MULTIHANDLER(preferences)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- GtkWidget* wndpreferences;
+ *menu = false;
+ *tool = false;
- wndpreferences = nsgtk_preferences(bw, g->window);
- if (wndpreferences != NULL) {
- gtk_widget_show(GTK_WIDGET(wndpreferences));
+ cur_bar_show = nsoption_charp(bar_show);
+ if (cur_bar_show != NULL) {
+ if (strcmp(cur_bar_show, "menu/tool") == 0) {
+ *menu = true;
+ *tool = true;
+ } else if (strcmp(cur_bar_show, "menu") == 0) {
+ *menu = true;
+ } else if (strcmp(cur_bar_show, "tool") == 0) {
+ *tool = true;
+ }
}
- return TRUE;
-}
-
-MULTIHANDLER(zoomplus)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- float old_scale = nsgtk_get_scale_for_gui(g->top_level);
-
- browser_window_set_scale(bw, old_scale + 0.05, true);
-
- return TRUE;
-}
-
-MULTIHANDLER(zoomnormal)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
-
- browser_window_set_scale(bw, 1.0, true);
-
- return TRUE;
+ return NSERROR_OK;
}
-MULTIHANDLER(zoomminus)
+static nserror set_bar_show(const char *bar, bool show)
{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- float old_scale = nsgtk_get_scale_for_gui(g->top_level);
+ bool menu;
+ bool tool;
+ const char *new_bar_show;
- browser_window_set_scale(bw, old_scale - 0.05, true);
+ get_bar_show(&menu, &tool);
- return TRUE;
-}
+ if (strcmp(bar, "menu") == 0) {
+ menu = show;
+ } else if (strcmp(bar, "tool") == 0) {
+ tool = show;
+ }
-MULTIHANDLER(fullscreen)
-{
- if (g->fullscreen) {
- gtk_window_unfullscreen(g->window);
+ if ((menu == true) && (tool == true)) {
+ new_bar_show = "menu/tool";
+ } else if (menu == true) {
+ new_bar_show = "menu";
+ } else if (tool == true) {
+ new_bar_show = "tool";
} else {
- gtk_window_fullscreen(g->window);
+ new_bar_show = "none";
}
+ nsoption_set_charp(bar_show, strdup(new_bar_show));
- g->fullscreen = !g->fullscreen;
-
- return TRUE;
+ return NSERROR_OK;
}
-MULTIHANDLER(viewsource)
+static gboolean
+nsgtk_on_menubar_activate_menu(GtkMenuItem *widget, gpointer data)
{
- nserror ret;
+ struct nsgtk_scaffolding *gs = (struct nsgtk_scaffolding *)data;
+ GtkCheckMenuItem *bmcmi; /* burger menu check */
+ GtkCheckMenuItem *mbcmi; /* menu bar check */
+ GtkCheckMenuItem *tbcmi; /* popup menu check */
- ret = nsgtk_viewsource(g->window, nsgtk_get_browser_window(g->top_level));
- if (ret != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(ret), 0);
- }
-
- return TRUE;
-}
-
-MENUHANDLER(menubar)
-{
- GtkWidget *w;
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
+ bmcmi = GTK_CHECK_MENU_ITEM(gs->burger_menu->view_submenu->toolbars_submenu->menubar_menuitem);
+ mbcmi = GTK_CHECK_MENU_ITEM(gs->menu_bar->view_submenu->toolbars_submenu->menubar_menuitem);
+ tbcmi = GTK_CHECK_MENU_ITEM(gs->popup_menu->toolbars_submenu->menubar_menuitem);
- /* if the menubar is not being shown the popup menu shows the
- * menubar entries instead.
- */
+ /* ensure menubar and burger menu checkboxes are both updated */
if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
- /* need to synchronise menus as gtk grumbles when one menu
- * is attached to both headers */
- w = GTK_WIDGET(g->menu_popup->view_submenu->toolbars_submenu->menubar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))
- == FALSE)
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- TRUE);
-
- w = GTK_WIDGET(g->menu_bar->view_submenu->toolbars_submenu->menubar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))
- == FALSE)
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- TRUE);
-
- gtk_widget_show(GTK_WIDGET(g->menu_bar->bar_menu));
-
- popup_menu_show(g->menu_popup, false, true, true, true);
- popup_menu_hide(g->menu_popup, true, false, false, false);
- } else {
- w = GTK_WIDGET(g->menu_popup->view_submenu->toolbars_submenu->menubar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- FALSE);
-
- w = GTK_WIDGET(g->menu_bar->view_submenu->toolbars_submenu->menubar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- FALSE);
-
- gtk_widget_hide(GTK_WIDGET(g->menu_bar->bar_menu));
-
- popup_menu_show(g->menu_popup, true, true, true, true);
+ if (gtk_check_menu_item_get_active(bmcmi) == FALSE) {
+ gtk_check_menu_item_set_active(bmcmi, TRUE);
+ }
- }
- return TRUE;
-}
+ if (gtk_check_menu_item_get_active(mbcmi) == FALSE) {
+ gtk_check_menu_item_set_active(mbcmi, TRUE);
+ }
-MENUHANDLER(toolbar)
-{
- GtkWidget *w;
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
+ if (gtk_check_menu_item_get_active(tbcmi) == FALSE) {
+ gtk_check_menu_item_set_active(tbcmi, TRUE);
+ }
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
- w = GTK_WIDGET(g->menu_popup->view_submenu->toolbars_submenu->toolbar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))
- == FALSE)
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- TRUE);
-
- w = GTK_WIDGET(g->menu_bar->view_submenu->toolbars_submenu->toolbar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w))
- == FALSE)
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- TRUE);
- gtk_widget_show(GTK_WIDGET(g->tool_bar));
+ gtk_widget_show(GTK_WIDGET(gs->menu_bar->bar_menu));
+ set_bar_show("menu", true);
} else {
- w = GTK_WIDGET(g->menu_popup->view_submenu->toolbars_submenu->toolbar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- FALSE);
- w = GTK_WIDGET(g->menu_bar->view_submenu->toolbars_submenu->toolbar_menuitem);
- if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(w)))
- gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(w),
- FALSE);
- gtk_widget_hide(GTK_WIDGET(g->tool_bar));
- }
-
- return TRUE;
-}
-
-MULTIHANDLER(downloads)
-{
- nsgtk_download_show(g->window);
-
- return TRUE;
-}
-
-MULTIHANDLER(savewindowsize)
-{
- int x,y,w,h;
- char *choices = NULL;
+ if (gtk_check_menu_item_get_active(bmcmi) == TRUE) {
+ gtk_check_menu_item_set_active(bmcmi, FALSE);
+ }
- gtk_window_get_position(g->window, &x, &y);
- gtk_window_get_size(g->window, &w, &h);
+ if (gtk_check_menu_item_get_active(mbcmi) == TRUE) {
+ gtk_check_menu_item_set_active(mbcmi, FALSE);
+ }
- nsoption_set_int(window_width, w);
- nsoption_set_int(window_height, h);
- nsoption_set_int(window_x, x);
- nsoption_set_int(window_y, y);
+ if (gtk_check_menu_item_get_active(tbcmi) == TRUE) {
+ gtk_check_menu_item_set_active(tbcmi, FALSE);
+ }
- netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
- if (choices != NULL) {
- nsoption_write(choices, NULL, NULL);
- free(choices);
+ gtk_widget_hide(GTK_WIDGET(gs->menu_bar->bar_menu));
+ set_bar_show("menu", false);
}
-
return TRUE;
}
-MULTIHANDLER(toggledebugging)
-{
- struct browser_window *bw;
-
- bw = nsgtk_get_browser_window(g->top_level);
-
- browser_window_debug(bw, CONTENT_DEBUG_REDRAW);
-
- nsgtk_reflow_all_windows();
-
- return TRUE;
-}
-MULTIHANDLER(debugboxtree)
+static gboolean
+nsgtk_on_toolbar_activate_menu(GtkMenuItem *widget, gpointer data)
{
- gchar *fname;
- gint handle;
- FILE *f;
- struct browser_window *bw;
+ struct nsgtk_scaffolding *gs = (struct nsgtk_scaffolding *)data;
+ GtkCheckMenuItem *bmcmi; /* burger menu check */
+ GtkCheckMenuItem *mbcmi; /* menu bar check */
+ GtkCheckMenuItem *tbcmi; /* popup menu check */
- handle = g_file_open_tmp("nsgtkboxtreeXXXXXX", &fname, NULL);
- if ((handle == -1) || (fname == NULL)) {
- return TRUE;
- }
- close(handle); /* in case it was binary mode */
-
- /* save data to temporary file */
- f = fopen(fname, "w");
- if (f == NULL) {
- nsgtk_warning("Error saving box tree dump.",
- "Unable to open file for writing.");
- unlink(fname);
- return TRUE;
- }
-
- bw = nsgtk_get_browser_window(g->top_level);
+ bmcmi = GTK_CHECK_MENU_ITEM(gs->burger_menu->view_submenu->toolbars_submenu->toolbar_menuitem);
+ mbcmi = GTK_CHECK_MENU_ITEM(gs->menu_bar->view_submenu->toolbars_submenu->toolbar_menuitem);
+ tbcmi = GTK_CHECK_MENU_ITEM(gs->popup_menu->toolbars_submenu->toolbar_menuitem);
- browser_window_debug_dump(bw, f, CONTENT_DEBUG_RENDER);
+ /* ensure menubar and burger menu checkboxes are both updated */
+ if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) {
+ if (gtk_check_menu_item_get_active(bmcmi) == FALSE) {
+ gtk_check_menu_item_set_active(bmcmi, TRUE);
+ }
- fclose(f);
+ if (gtk_check_menu_item_get_active(mbcmi) == FALSE) {
+ gtk_check_menu_item_set_active(mbcmi, TRUE);
+ }
- nsgtk_viewfile("Box Tree Debug", "boxtree", fname);
+ if (gtk_check_menu_item_get_active(tbcmi) == FALSE) {
+ gtk_check_menu_item_set_active(tbcmi, TRUE);
+ }
- g_free(fname);
+ nsgtk_window_toolbar_show(gs, true);
+ set_bar_show("tool", true);
+ } else {
+ if (gtk_check_menu_item_get_active(bmcmi) == TRUE) {
+ gtk_check_menu_item_set_active(bmcmi, FALSE);
+ }
- return TRUE;
-}
+ if (gtk_check_menu_item_get_active(mbcmi) == TRUE) {
+ gtk_check_menu_item_set_active(mbcmi, FALSE);
+ }
-MULTIHANDLER(debugdomtree)
-{
- gchar *fname;
- gint handle;
- FILE *f;
- struct browser_window *bw;
+ if (gtk_check_menu_item_get_active(tbcmi) == TRUE) {
+ gtk_check_menu_item_set_active(tbcmi, FALSE);
+ }
- handle = g_file_open_tmp("nsgtkdomtreeXXXXXX", &fname, NULL);
- if ((handle == -1) || (fname == NULL)) {
- return TRUE;
+ nsgtk_window_toolbar_show(gs, false);
+ set_bar_show("tool", false);
}
- close(handle); /* in case it was binary mode */
-
- /* save data to temporary file */
- f = fopen(fname, "w");
- if (f == NULL) {
- nsgtk_warning("Error saving box tree dump.",
- "Unable to open file for writing.");
- unlink(fname);
- return TRUE;
- }
-
- bw = nsgtk_get_browser_window(g->top_level);
-
- browser_window_debug_dump(bw, f, CONTENT_DEBUG_DOM);
-
- fclose(f);
-
- nsgtk_viewfile("DOM Tree Debug", "domtree", fname);
-
- g_free(fname);
-
return TRUE;
}
-MULTIHANDLER(stop)
+static gboolean
+nsgtk_on_nexttab_activate_menu(GtkMenuItem *widget, gpointer data)
{
- struct browser_window *bw =
- nsgtk_get_browser_window(g->top_level);
+ struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- browser_window_stop(bw);
+ nsgtk_tab_next(g->notebook);
return TRUE;
}
-MULTIHANDLER(reload)
-{
- struct browser_window *bw =
- nsgtk_get_browser_window(g->top_level);
- if (bw == NULL)
- return TRUE;
-
- /* clear potential search effects */
- browser_window_search_clear(bw);
- browser_window_reload(bw, true);
-
- return TRUE;
-}
-
-MULTIHANDLER(back)
+static gboolean
+nsgtk_on_prevtab_activate_menu(GtkMenuItem *widget, gpointer data)
{
- struct browser_window *bw =
- nsgtk_get_browser_window(g->top_level);
-
- if ((bw == NULL) || (!browser_window_history_back_available(bw)))
- return TRUE;
-
- /* clear potential search effects */
- browser_window_search_clear(bw);
+ struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- browser_window_history_back(bw, false);
- scaffolding_update_context(g);
+ nsgtk_tab_prev(g->notebook);
return TRUE;
}
-MULTIHANDLER(forward)
-{
- struct browser_window *bw =
- nsgtk_get_browser_window(g->top_level);
-
- if ((bw == NULL) || (!browser_window_history_forward_available(bw)))
- return TRUE;
-
- /* clear potential search effects */
- browser_window_search_clear(bw);
-
- browser_window_history_forward(bw, false);
- scaffolding_update_context(g);
-
- return TRUE;
-}
-MULTIHANDLER(home)
+/**
+ * menu signal handler for activation on close tab item
+ */
+static gboolean
+nsgtk_on_closetab_activate_menu(GtkMenuItem *widget, gpointer data)
{
- static const char *addr = NETSURF_HOMEPAGE;
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- nsurl *url;
- nserror error;
-
- if (nsoption_charp(homepage_url) != NULL) {
- addr = nsoption_charp(homepage_url);
- }
+ struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- error = nsurl_create(addr, &url);
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- } else {
- browser_window_navigate(bw,
- url,
- NULL,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
- }
+ nsgtk_tab_close_current(g->notebook);
return TRUE;
}
-MULTIHANDLER(localhistory)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- nserror res;
+/* end of menu callback handlers */
- res = nsgtk_local_history_present(g->window, bw);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to initialise local history window.");
+/**
+ * attach gtk signal handlers for menus
+ */
+static void nsgtk_menu_connect_signals(struct nsgtk_scaffolding *g)
+{
+ int idx; /* item index */
+ for (idx = BACK_BUTTON; idx < PLACEHOLDER_BUTTON; idx++) {
+ if (g->menus[idx].main != NULL) {
+ g_signal_connect(g->menus[idx].main,
+ "activate",
+ G_CALLBACK(g->menus[idx].mhandler),
+ g);
+ }
+ if (g->menus[idx].burger != NULL) {
+ g_signal_connect(g->menus[idx].burger,
+ "activate",
+ G_CALLBACK(g->menus[idx].mhandler),
+ g);
+ }
+ if (g->menus[idx].popup != NULL) {
+ g_signal_connect(g->menus[idx].popup,
+ "activate",
+ G_CALLBACK(g->menus[idx].mhandler),
+ g);
+ }
}
- return TRUE;
}
-MULTIHANDLER(globalhistory)
-{
- nserror res;
- res = nsgtk_global_history_present();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to initialise global history window.");
- }
- return TRUE;
-}
-MULTIHANDLER(addbookmarks)
+/**
+ * Create and connect handlers to bar menu.
+ *
+ * \param gs scaffolding to attach popup menu to.
+ * \param group The accelerator group to use for the popup.
+ * \param showmenu if the bar menu should be shown
+ * \param showtool if the toolabar should be shown
+ * \return menu structure on success or NULL on error.
+ */
+static struct nsgtk_bar_submenu *
+create_scaffolding_bar_menu(struct nsgtk_scaffolding *gs,
+ GtkAccelGroup *group,
+ bool showmenu,
+ bool showtool)
{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
+ GtkMenuShell *menushell;
+ struct nsgtk_bar_submenu *nmenu;
- if (bw == NULL || !browser_window_has_content(bw))
- return TRUE;
- hotlist_add_url(browser_window_get_url(bw));
- return TRUE;
-}
+ menushell = GTK_MENU_SHELL(gtk_builder_get_object(gs->builder,
+ "menubar"));
-MULTIHANDLER(showbookmarks)
-{
- nserror res;
- res = nsgtk_hotlist_present();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise bookmark window.");
+ nmenu = nsgtk_menu_bar_create(menushell, group);
+ if (nmenu == NULL) {
+ return NULL;
}
- return TRUE;
-}
-MULTIHANDLER(showcookies)
-{
- nserror res;
- res = nsgtk_cookies_present();
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to initialise cookies window.");
+ /* set menu bar visibility */
+ if (showmenu) {
+ gtk_widget_show(GTK_WIDGET(nmenu->bar_menu));
+ } else {
+ gtk_widget_hide(GTK_WIDGET(nmenu->bar_menu));
}
- return TRUE;
-}
-MULTIHANDLER(openlocation)
-{
- gtk_widget_grab_focus(GTK_WIDGET(g->url_bar));
- return TRUE;
-}
+ /* set checks correct way on toolbar submenu */
+ gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->menubar_menuitem, showmenu);
+ gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem, showtool);
-MULTIHANDLER(nexttab)
-{
- nsgtk_tab_next(g->notebook);
+ /* bar menu signal handlers for edit controls */
+ g_signal_connect(nmenu->edit_submenu->edit,
+ "show",
+ G_CALLBACK(nsgtk_window_edit_menu_shown),
+ gs);
- return TRUE;
-}
+ g_signal_connect(nmenu->edit_submenu->edit,
+ "hide",
+ G_CALLBACK(nsgtk_window_edit_menu_hidden),
+ gs);
-MULTIHANDLER(prevtab)
-{
+ /*
+ * attach signal handlers for menubar and toolbar visibility toggling
+ */
+ g_signal_connect(nmenu->view_submenu->toolbars_submenu->menubar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_menubar_activate_menu),
+ gs);
- nsgtk_tab_prev(g->notebook);
+ g_signal_connect(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_toolbar_activate_menu),
+ gs);
- return TRUE;
-}
-MULTIHANDLER(closetab)
-{
- nsgtk_tab_close_current(g->notebook);
-
- return TRUE;
+ return nmenu;
}
-MULTIHANDLER(contents)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- nsurl *url;
- nserror error;
-
- error = nsurl_create("http://www.netsurf-browser.org/documentation/", &url);
- if (error != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(error), 0);
- } else {
- browser_window_navigate(bw,
- url,
- NULL,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
- }
- return TRUE;
-}
-
-MULTIHANDLER(guide)
+/**
+ * Create and connect handlers to burger menu.
+ *
+ * \param g scaffolding to attach popup menu to.
+ * \param group The accelerator group to use for the popup.
+ * \param showbar if the bar menu should be shown
+ * \param showtool if the toolabar should be shown
+ * \return menu structure on success or NULL on error.
+ */
+static struct nsgtk_burger_menu *
+create_scaffolding_burger_menu(struct nsgtk_scaffolding *gs,
+ GtkAccelGroup *group,
+ bool showbar,
+ bool showtool)
{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- nsurl *url;
+ struct nsgtk_burger_menu *nmenu;
- if (nsurl_create("http://www.netsurf-browser.org/documentation/guide", &url) != NSERROR_OK) {
- nsgtk_warning("NoMemory", 0);
- } else {
- browser_window_navigate(bw,
- url,
- NULL,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
- }
+ nmenu = nsgtk_burger_menu_create(group);
- return TRUE;
-}
-
-MULTIHANDLER(info)
-{
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
- nsurl *url;
-
- if (nsurl_create("http://www.netsurf-browser.org/documentation/info", &url) != NSERROR_OK) {
- nsgtk_warning("NoMemory", 0);
- } else {
- browser_window_navigate(bw,
- url,
- NULL,
- BW_NAVIGATE_HISTORY,
- NULL,
- NULL,
- NULL);
- nsurl_unref(url);
+ if (nmenu == NULL) {
+ return NULL;
}
- return TRUE;
-}
-
-MULTIHANDLER(about)
-{
- nsgtk_about_dialog_init(g->window);
- return TRUE;
-}
+ /* set checks correct way on toolbar submenu */
+ gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->menubar_menuitem, showbar);
+ gtk_check_menu_item_set_active(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem, showtool);
-BUTTONHANDLER(history)
-{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- return nsgtk_on_localhistory_activate(g);
+ g_signal_connect(nmenu->view_submenu->toolbars_submenu->menubar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_menubar_activate_menu),
+ gs);
+ g_signal_connect(nmenu->view_submenu->toolbars_submenu->toolbar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_toolbar_activate_menu),
+ gs);
+ return nmenu;
}
-#undef MULTIHANDLER
-#undef CHECKHANDLER
-#undef BUTTONHANDLER
-
-static void nsgtk_attach_menu_handlers(struct nsgtk_scaffolding *g)
-{
- for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- if (g->buttons[i]->main != NULL) {
- g_signal_connect(g->buttons[i]->main, "activate",
- G_CALLBACK(g->buttons[i]->mhandler), g);
- }
- if (g->buttons[i]->rclick != NULL) {
- g_signal_connect(g->buttons[i]->rclick, "activate",
- G_CALLBACK(g->buttons[i]->mhandler), g);
- }
- if (g->buttons[i]->popup != NULL) {
- g_signal_connect(g->buttons[i]->popup, "activate",
- G_CALLBACK(g->buttons[i]->mhandler), g);
- }
- }
-#define CONNECT_CHECK(q)\
- g_signal_connect(g->menu_bar->view_submenu->toolbars_submenu->q##_menuitem, "toggled", G_CALLBACK(nsgtk_on_##q##_activate_menu), g);\
- g_signal_connect(g->menu_popup->view_submenu->toolbars_submenu->q##_menuitem, "toggled", G_CALLBACK(nsgtk_on_##q##_activate_menu), g)
- CONNECT_CHECK(menubar);
- CONNECT_CHECK(toolbar);
-#undef CONNECT_CHECK
-
-}
/**
* Create and connect handlers to popup menu.
*
- * \param g scaffolding to attach popup menu to.
+ * \param gs scaffolding to attach popup menu to.
* \param group The accelerator group to use for the popup.
+ * \param showbar if the bar menu should be shown
+ * \param showtool if the toolabar should be shown
* \return menu structure on success or NULL on error.
*/
static struct nsgtk_popup_menu *
-nsgtk_new_scaffolding_popup(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
+create_scaffolding_popup_menu(struct nsgtk_scaffolding *gs,
+ GtkAccelGroup *group,
+ bool showbar,
+ bool showtool)
{
struct nsgtk_popup_menu *nmenu;
@@ -1791,28 +951,31 @@ nsgtk_new_scaffolding_popup(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
if (nmenu == NULL) {
return NULL;
}
+ /* set checks correct way on toolbar submenu */
+ gtk_check_menu_item_set_active(nmenu->toolbars_submenu->menubar_menuitem, showbar);
+ gtk_check_menu_item_set_active(nmenu->toolbars_submenu->toolbar_menuitem, showtool);
- g_signal_connect(nmenu->popup_menu, "hide",
- G_CALLBACK(nsgtk_window_popup_menu_hidden), g);
-
- g_signal_connect(nmenu->cut_menuitem, "activate",
- G_CALLBACK(nsgtk_on_cut_activate_menu), g);
-
- g_signal_connect(nmenu->copy_menuitem, "activate",
- G_CALLBACK(nsgtk_on_copy_activate_menu), g);
+ g_signal_connect(nmenu->popup_menu,
+ "hide",
+ G_CALLBACK(nsgtk_window_popup_menu_hidden),
+ gs);
- g_signal_connect(nmenu->paste_menuitem, "activate",
- G_CALLBACK(nsgtk_on_paste_activate_menu), g);
-
- g_signal_connect(nmenu->customize_menuitem, "activate",
- G_CALLBACK(nsgtk_on_customize_activate_menu), g);
+ g_signal_connect(nmenu->toolbars_submenu->menubar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_menubar_activate_menu),
+ gs);
+ g_signal_connect(nmenu->toolbars_submenu->toolbar_menuitem,
+ "toggled",
+ G_CALLBACK(nsgtk_on_toolbar_activate_menu),
+ gs);
/* set initial popup menu visibility */
- popup_menu_hide(nmenu, true, false, false, true);
+ popup_menu_hide(nmenu, false, false);
return nmenu;
}
+
/**
* Create and connect handlers to link popup menu.
*
@@ -1821,7 +984,7 @@ nsgtk_new_scaffolding_popup(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
* \return true on success or false on error.
*/
static struct nsgtk_link_menu *
-nsgtk_new_scaffolding_link_popup(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
+create_scaffolding_link_menu(struct nsgtk_scaffolding *g, GtkAccelGroup *group)
{
struct nsgtk_link_menu *nmenu;
@@ -1831,482 +994,261 @@ nsgtk_new_scaffolding_link_popup(struct nsgtk_scaffolding *g, GtkAccelGroup *gro
return NULL;
}
- g_signal_connect(nmenu->save_menuitem, "activate",
- G_CALLBACK(nsgtk_on_savelink_activate_menu), g);
+ g_signal_connect(nmenu->save_menuitem,
+ "activate",
+ G_CALLBACK(nsgtk_on_savelink_activate_menu),
+ g);
- g_signal_connect(nmenu->opentab_menuitem, "activate",
- G_CALLBACK(nsgtk_on_link_opentab_activate_menu), g);
+ g_signal_connect(nmenu->opentab_menuitem,
+ "activate",
+ G_CALLBACK(nsgtk_on_link_opentab_activate_menu),
+ g);
- g_signal_connect(nmenu->openwin_menuitem, "activate",
- G_CALLBACK(nsgtk_on_link_openwin_activate_menu), g);
+ g_signal_connect(nmenu->openwin_menuitem,
+ "activate",
+ G_CALLBACK(nsgtk_on_link_openwin_activate_menu),
+ g);
- g_signal_connect(nmenu->bookmark_menuitem, "activate",
- G_CALLBACK(nsgtk_on_link_bookmark_activate_menu), g);
+ g_signal_connect(nmenu->bookmark_menuitem,
+ "activate",
+ G_CALLBACK(nsgtk_on_link_bookmark_activate_menu),
+ g);
- g_signal_connect(nmenu->copy_menuitem, "activate",
- G_CALLBACK(nsgtk_on_link_copy_activate_menu), g);
+ g_signal_connect(nmenu->copy_menuitem,
+ "activate",
+ G_CALLBACK(nsgtk_on_link_copy_activate_menu),
+ g);
return nmenu;
}
-/* exported interface documented in gtk/scaffolding.h */
-struct nsgtk_scaffolding *nsgtk_current_scaffolding(void)
-{
- if (scaf_current == NULL) {
- scaf_current = scaf_list;
- }
- return scaf_current;
-}
/**
- * init the array g->buttons[]
+ * initialiase the menu signal handlers ready for connection
*/
-static void nsgtk_scaffolding_toolbar_init(struct nsgtk_scaffolding *g)
-{
-#define ITEM_MAIN(p, q, r)\
- g->buttons[p##_BUTTON]->main = g->menu_bar->q->r##_menuitem;\
- g->buttons[p##_BUTTON]->rclick = g->menu_popup->q->r##_menuitem;\
- g->buttons[p##_BUTTON]->mhandler = nsgtk_on_##r##_activate_menu;\
- g->buttons[p##_BUTTON]->bhandler = nsgtk_on_##r##_activate_button;\
- g->buttons[p##_BUTTON]->dataplus = nsgtk_toolbar_##r##_button_data;\
- g->buttons[p##_BUTTON]->dataminus = nsgtk_toolbar_##r##_toolbar_button_data
-
-#define ITEM_SUB(p, q, r, s)\
- g->buttons[p##_BUTTON]->main =\
- g->menu_bar->q->r##_submenu->s##_menuitem;\
- g->buttons[p##_BUTTON]->rclick =\
- g->menu_popup->q->r##_submenu->s##_menuitem;\
- g->buttons[p##_BUTTON]->mhandler =\
- nsgtk_on_##s##_activate_menu;\
- g->buttons[p##_BUTTON]->bhandler =\
- nsgtk_on_##s##_activate_button;\
- g->buttons[p##_BUTTON]->dataplus =\
- nsgtk_toolbar_##s##_button_data;\
- g->buttons[p##_BUTTON]->dataminus =\
- nsgtk_toolbar_##s##_toolbar_button_data
-
-#define ITEM_BUTTON(p, q)\
- g->buttons[p##_BUTTON]->bhandler =\
- nsgtk_on_##q##_activate;\
- g->buttons[p##_BUTTON]->dataplus =\
- nsgtk_toolbar_##q##_button_data;\
- g->buttons[p##_BUTTON]->dataminus =\
- nsgtk_toolbar_##q##_toolbar_button_data
-
-#define ITEM_POP(p, q) \
- g->buttons[p##_BUTTON]->popup = g->menu_popup->q##_menuitem
-
-#define SENSITIVITY(q) \
- g->buttons[q##_BUTTON]->sensitivity = false
-
-#define ITEM_ITEM(p, q)\
- g->buttons[p##_ITEM]->dataplus =\
- nsgtk_toolbar_##q##_button_data;\
- g->buttons[p##_ITEM]->dataminus =\
- nsgtk_toolbar_##q##_toolbar_button_data
-
- ITEM_ITEM(WEBSEARCH, websearch);
- ITEM_ITEM(THROBBER, throbber);
- ITEM_MAIN(NEWWINDOW, file_submenu, newwindow);
- ITEM_MAIN(NEWTAB, file_submenu, newtab);
- ITEM_MAIN(OPENFILE, file_submenu, openfile);
- ITEM_MAIN(PRINT, file_submenu, print);
- ITEM_MAIN(CLOSEWINDOW, file_submenu, closewindow);
- ITEM_MAIN(SAVEPAGE, file_submenu, savepage);
- ITEM_MAIN(PRINTPREVIEW, file_submenu, printpreview);
- ITEM_MAIN(PRINT, file_submenu, print);
- ITEM_MAIN(QUIT, file_submenu, quit);
- ITEM_MAIN(CUT, edit_submenu, cut);
- ITEM_MAIN(COPY, edit_submenu, copy);
- ITEM_MAIN(PASTE, edit_submenu, paste);
- ITEM_MAIN(DELETE, edit_submenu, delete);
- ITEM_MAIN(SELECTALL, edit_submenu, selectall);
- ITEM_MAIN(FIND, edit_submenu, find);
- ITEM_MAIN(PREFERENCES, edit_submenu, preferences);
- ITEM_MAIN(STOP, view_submenu, stop);
- ITEM_POP(STOP, stop);
- ITEM_MAIN(RELOAD, view_submenu, reload);
- ITEM_POP(RELOAD, reload);
- ITEM_MAIN(FULLSCREEN, view_submenu, fullscreen);
- ITEM_MAIN(DOWNLOADS, tools_submenu, downloads);
- ITEM_MAIN(SAVEWINDOWSIZE, view_submenu, savewindowsize);
- ITEM_MAIN(BACK, nav_submenu, back);
- ITEM_POP(BACK, back);
- ITEM_MAIN(FORWARD, nav_submenu, forward);
- ITEM_POP(FORWARD, forward);
- ITEM_MAIN(HOME, nav_submenu, home);
- ITEM_MAIN(LOCALHISTORY, nav_submenu, localhistory);
- ITEM_MAIN(GLOBALHISTORY, nav_submenu, globalhistory);
- ITEM_MAIN(ADDBOOKMARKS, nav_submenu, addbookmarks);
- ITEM_MAIN(SHOWBOOKMARKS, nav_submenu, showbookmarks);
- ITEM_MAIN(SHOWCOOKIES, tools_submenu, showcookies);
- ITEM_MAIN(OPENLOCATION, nav_submenu, openlocation);
- ITEM_MAIN(CONTENTS, help_submenu, contents);
- ITEM_MAIN(INFO, help_submenu, info);
- ITEM_MAIN(GUIDE, help_submenu, guide);
- ITEM_MAIN(ABOUT, help_submenu, about);
- ITEM_SUB(PLAINTEXT, file_submenu, export, plaintext);
- ITEM_SUB(PDF, file_submenu, export, pdf);
- ITEM_SUB(DRAWFILE, file_submenu, export, drawfile);
- ITEM_SUB(POSTSCRIPT, file_submenu, export, postscript);
- ITEM_SUB(ZOOMPLUS, view_submenu, scaleview, zoomplus);
- ITEM_SUB(ZOOMMINUS, view_submenu, scaleview, zoomminus);
- ITEM_SUB(ZOOMNORMAL, view_submenu, scaleview, zoomnormal);
- ITEM_SUB(NEXTTAB, view_submenu, tabs, nexttab);
- ITEM_SUB(PREVTAB, view_submenu, tabs, prevtab);
- ITEM_SUB(CLOSETAB, view_submenu, tabs, closetab);
-
- /* development submenu */
- ITEM_SUB(VIEWSOURCE, tools_submenu, developer, viewsource);
- ITEM_SUB(TOGGLEDEBUGGING, tools_submenu, developer, toggledebugging);
- ITEM_SUB(SAVEBOXTREE, tools_submenu, developer, debugboxtree);
- ITEM_SUB(SAVEDOMTREE, tools_submenu, developer, debugdomtree);
- ITEM_BUTTON(HISTORY, history);
-
- /* disable items that make no sense initially, as well as
- * as-yet-unimplemented items */
- SENSITIVITY(BACK);
- SENSITIVITY(FORWARD);
- SENSITIVITY(STOP);
- SENSITIVITY(PRINTPREVIEW);
- SENSITIVITY(DELETE);
- SENSITIVITY(DRAWFILE);
- SENSITIVITY(POSTSCRIPT);
- SENSITIVITY(NEXTTAB);
- SENSITIVITY(PREVTAB);
- SENSITIVITY(CLOSETAB);
-#ifndef WITH_PDF_EXPORT
- SENSITIVITY(PDF);
-#endif
-
-#undef ITEM_MAIN
-#undef ITEM_SUB
-#undef ITEM_BUTTON
-#undef ITEM_POP
-#undef SENSITIVITY
+static nserror nsgtk_menu_initialise(struct nsgtk_scaffolding *g)
+{
+#define TOOLBAR_ITEM_p(identifier, name, iconame) \
+ g->menus[identifier].mhandler = nsgtk_on_##name##_activate_menu; \
+ g->menus[identifier].iconname = iconame;
+#define TOOLBAR_ITEM_y(identifier, name, iconame) \
+ g->menus[identifier].mhandler = nsgtk_on_##name##_activate_menu; \
+ g->menus[identifier].iconname = iconame;
+#define TOOLBAR_ITEM_n(identifier, name, iconame) \
+ g->menus[identifier].mhandler = NULL; \
+ g->menus[identifier].iconname = iconame;
+#define TOOLBAR_ITEM(identifier, name, snstvty, clicked, activate, label, iconame) \
+ g->menus[identifier].sensitivity = snstvty; \
+ TOOLBAR_ITEM_ ## activate(identifier, name, iconame)
+#include "gtk/toolbar_items.h"
+#undef TOOLBAR_ITEM_y
+#undef TOOLBAR_ITEM_n
+#undef TOOLBAR_ITEM
+
+ /* items on menubar, burger */
+#define ITEM_MB(p, q, r) \
+ g->menus[p##_BUTTON].main = g->menu_bar->r##_submenu->q##_menuitem; \
+ g->menus[p##_BUTTON].burger = g->burger_menu->r##_submenu->q##_menuitem
+
+ /* items on menubar, burger and context popup submenu */
+#define ITEM_MBP(p, q, r) \
+ g->menus[p##_BUTTON].main = g->menu_bar->r##_submenu->q##_menuitem; \
+ g->menus[p##_BUTTON].burger = g->burger_menu->r##_submenu->q##_menuitem; \
+ g->menus[p##_BUTTON].popup = g->popup_menu->r##_submenu->q##_menuitem
+
+ /* items on menubar, burger and context popup */
+#define ITEM_MBp(p, q, r) \
+ g->menus[p##_BUTTON].main = g->menu_bar->r##_submenu->q##_menuitem; \
+ g->menus[p##_BUTTON].burger = g->burger_menu->r##_submenu->q##_menuitem; \
+ g->menus[p##_BUTTON].popup = g->popup_menu->q##_menuitem
+
+
+ /* file menu */
+ ITEM_MB(NEWWINDOW, newwindow, file);
+ ITEM_MB(NEWTAB, newtab, file);
+ ITEM_MB(OPENFILE, openfile, file);
+ ITEM_MB(CLOSEWINDOW, closewindow, file);
+ ITEM_MB(PRINTPREVIEW, printpreview, file);
+ ITEM_MB(PRINT, print, file);
+ ITEM_MB(QUIT, quit, file);
+ /* file - export submenu */
+ ITEM_MB(SAVEPAGE, savepage, file_submenu->export);
+ ITEM_MB(PLAINTEXT, plaintext, file_submenu->export);
+ ITEM_MB(PDF, pdf, file_submenu->export);
+
+ /* edit menu */
+ ITEM_MBp(CUT, cut, edit);
+ ITEM_MBp(COPY, copy, edit);
+ ITEM_MBp(PASTE, paste, edit);
+ ITEM_MB(DELETE, delete, edit);
+ ITEM_MB(SELECTALL, selectall, edit);
+ ITEM_MB(FIND, find, edit);
+ ITEM_MB(PREFERENCES, preferences, edit);
+
+ /* view menu */
+ ITEM_MB(FULLSCREEN, fullscreen, view);
+ ITEM_MB(SAVEWINDOWSIZE, savewindowsize, view);
+ /* view - scale submenu */
+ ITEM_MB(ZOOMPLUS, zoomplus, view_submenu->scaleview);
+ ITEM_MB(ZOOMMINUS, zoomminus, view_submenu->scaleview);
+ ITEM_MB(ZOOMNORMAL, zoomnormal, view_submenu->scaleview);
+ /* view - tabs submenu */
+ ITEM_MB(NEXTTAB, nexttab, view_submenu->tabs);
+ ITEM_MB(PREVTAB, prevtab, view_submenu->tabs);
+ ITEM_MB(CLOSETAB, closetab, view_submenu->tabs);
+ /* view - toolbars submenu */
+ ITEM_MB(CUSTOMIZE, customize, view_submenu->toolbars);
+ g->menus[CUSTOMIZE_BUTTON].popup = g->popup_menu->toolbars_submenu->customize_menuitem;
+
+ /* navigation menu */
+ ITEM_MBp(BACK, back, nav);
+ ITEM_MBp(FORWARD, forward, nav);
+ ITEM_MBp(STOP, stop, nav);
+ ITEM_MBp(RELOAD, reload, nav);
+ ITEM_MB(HOME, home, nav);
+ ITEM_MB(LOCALHISTORY, localhistory, nav);
+ ITEM_MB(GLOBALHISTORY, globalhistory, nav);
+ ITEM_MB(ADDBOOKMARKS, addbookmarks, nav);
+ ITEM_MB(SHOWBOOKMARKS, showbookmarks, nav);
+ ITEM_MB(OPENLOCATION, openlocation, nav);
+
+ /* tools menu */
+ ITEM_MBP(DOWNLOADS, downloads, tools);
+ ITEM_MBP(SHOWCOOKIES, showcookies, tools);
+ /* tools > developer submenu */
+ ITEM_MBP(VIEWSOURCE, viewsource, tools_submenu->developer);
+ ITEM_MBP(TOGGLEDEBUGGING, toggledebugging, tools_submenu->developer);
+ ITEM_MBP(SAVEBOXTREE, debugboxtree, tools_submenu->developer);
+ ITEM_MBP(SAVEDOMTREE, debugdomtree, tools_submenu->developer);
+
+ /* help menu */
+ ITEM_MB(CONTENTS, contents, help);
+ ITEM_MB(GUIDE, guide, help);
+ ITEM_MB(INFO, info, help);
+ ITEM_MB(ABOUT, about, help);
+
+
+#undef ITEM_MB
+#undef ITEM_MBp
+#undef ITEM_MBP
+ return NSERROR_OK;
}
-static void nsgtk_scaffolding_initial_sensitivity(struct nsgtk_scaffolding *g)
+
+static void nsgtk_menu_set_sensitivity(struct nsgtk_scaffolding *g)
{
+
for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- if (g->buttons[i]->main != NULL)
- gtk_widget_set_sensitive(GTK_WIDGET(
- g->buttons[i]->main),
- g->buttons[i]->sensitivity);
- if (g->buttons[i]->rclick != NULL)
+ if (g->menus[i].main != NULL) {
gtk_widget_set_sensitive(GTK_WIDGET(
- g->buttons[i]->rclick),
- g->buttons[i]->sensitivity);
- if ((g->buttons[i]->location != -1) &&
- (g->buttons[i]->button != NULL))
+ g->menus[i].main),
+ g->menus[i].sensitivity);
+ }
+ if (g->menus[i].burger != NULL) {
gtk_widget_set_sensitive(GTK_WIDGET(
- g->buttons[i]->button),
- g->buttons[i]->sensitivity);
- if (g->buttons[i]->popup != NULL)
+ g->menus[i].burger),
+ g->menus[i].sensitivity);
+ }
+ if (g->menus[i].popup != NULL) {
gtk_widget_set_sensitive(GTK_WIDGET(
- g->buttons[i]->popup),
- g->buttons[i]->sensitivity);
+ g->menus[i].popup),
+ g->menus[i].sensitivity);
+ }
}
- gtk_widget_set_sensitive(GTK_WIDGET(g->menu_bar->view_submenu->images_menuitem), FALSE);
}
-void nsgtk_scaffolding_toolbars(struct nsgtk_scaffolding *g, int tbi)
-{
- switch (tbi) {
- /* case 0 is 'unset' [from fresh install / clearing options]
- * see above */
-
- case 1: /* Small icons */
- /* main toolbar */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->tool_bar),
- GTK_TOOLBAR_ICONS);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->tool_bar),
- GTK_ICON_SIZE_SMALL_TOOLBAR);
- /* search toolbar */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->search->bar),
- GTK_TOOLBAR_ICONS);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->search->bar),
- GTK_ICON_SIZE_SMALL_TOOLBAR);
- break;
-
- case 2: /* Large icons */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->tool_bar),
- GTK_TOOLBAR_ICONS);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->tool_bar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
- /* search toolbar */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->search->bar),
- GTK_TOOLBAR_ICONS);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->search->bar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
- break;
-
- case 3: /* Large icons with text */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->tool_bar),
- GTK_TOOLBAR_BOTH);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->tool_bar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
- /* search toolbar */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->search->bar),
- GTK_TOOLBAR_BOTH);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(g->search->bar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
- break;
-
- case 4: /* Text icons only */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->tool_bar),
- GTK_TOOLBAR_TEXT);
- /* search toolbar */
- gtk_toolbar_set_style(GTK_TOOLBAR(g->search->bar),
- GTK_TOOLBAR_TEXT);
- default:
- break;
- }
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-struct nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel)
+/* set menu items to have icons */
+static void nsgtk_menu_set_icons(struct nsgtk_scaffolding *g)
{
- struct nsgtk_scaffolding *gs;
- int i;
- GtkAccelGroup *group;
-
- gs = calloc(1, sizeof(*gs));
- if (gs == NULL) {
- return NULL;
- }
-
- NSLOG(netsurf, INFO,
- "Constructing a scaffold of %p for gui_window %p", gs, toplevel);
-
- gs->top_level = toplevel;
-
- /* Construct UI widgets */
- if (nsgtk_builder_new_from_resname("netsurf", &gs->builder) != NSERROR_OK) {
- free(gs);
- return NULL;
- }
-
- gtk_builder_connect_signals(gs->builder, NULL);
-
-/** Obtain a GTK widget handle from UI builder object */
-#define GET_WIDGET(x) GTK_WIDGET (gtk_builder_get_object(gs->builder, (x)))
-
- gs->window = GTK_WINDOW(GET_WIDGET("wndBrowser"));
- gs->notebook = GTK_NOTEBOOK(GET_WIDGET("notebook"));
- gs->tool_bar = GTK_TOOLBAR(GET_WIDGET("toolbar"));
-
- gs->search = malloc(sizeof(struct gtk_search));
- if (gs->search == NULL) {
- free(gs);
- return NULL;
- }
-
- gs->search->bar = GTK_TOOLBAR(GET_WIDGET("searchbar"));
- gs->search->entry = GTK_ENTRY(GET_WIDGET("searchEntry"));
-
- gs->search->buttons[0] = GTK_TOOL_BUTTON(GET_WIDGET("searchBackButton"));
- gs->search->buttons[1] = GTK_TOOL_BUTTON(GET_WIDGET("searchForwardButton"));
- gs->search->buttons[2] = GTK_TOOL_BUTTON(GET_WIDGET("closeSearchButton"));
- gs->search->checkAll = GTK_CHECK_BUTTON(GET_WIDGET("checkAllSearch"));
- gs->search->caseSens = GTK_CHECK_BUTTON(GET_WIDGET("caseSensButton"));
-
-#undef GET_WIDGET
-
- /* allocate buttons */
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- gs->buttons[i] = calloc(1, sizeof(struct nsgtk_button_connect));
- if (gs->buttons[i] == NULL) {
- for (i-- ; i >= BACK_BUTTON; i--) {
- free(gs->buttons[i]);
- }
- free(gs);
- return NULL;
+ GtkWidget *img;
+ for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
+ /* ensure there is an icon name */
+ if (g->menus[i].iconname == NULL) {
+ continue;
}
- gs->buttons[i]->location = -1;
- gs->buttons[i]->sensitivity = true;
- }
-
- /* here custom toolbutton adding code */
- gs->offset = 0;
- gs->toolbarmem = 0;
- gs->toolbarbase = 0;
- gs->historybase = 0;
- nsgtk_toolbar_customization_load(gs);
- nsgtk_toolbar_set_physical(gs);
-
- group = gtk_accel_group_new();
- gtk_window_add_accel_group(gs->window, group);
-
- gs->menu_bar = nsgtk_menu_bar_create(GTK_MENU_SHELL(gtk_builder_get_object(gs->builder, "menubar")), group);
-
-
- /* set this window's size and position to what's in the options, or
- * or some sensible default if they're not set yet.
- */
- if (nsoption_int(window_width) > 0) {
- gtk_window_move(gs->window,
- nsoption_int(window_x),
- nsoption_int(window_y));
- gtk_window_resize(gs->window,
- nsoption_int(window_width),
- nsoption_int(window_height));
- } else {
- /* Set to 1000x700, so we're very likely to fit even on
- * 1024x768 displays, not being able to take into account
- * window furniture or panels.
- */
- gtk_window_set_default_size(gs->window, 1000, 700);
- }
-
- /* Default toolbar button type uses system defaults */
- if (nsoption_int(button_type) == 0) {
- GtkSettings *settings = gtk_settings_get_default();
- GtkIconSize tooliconsize;
- GtkToolbarStyle toolbarstyle;
-
- g_object_get(settings,
- "gtk-toolbar-icon-size", &tooliconsize,
- "gtk-toolbar-style", &toolbarstyle, NULL);
-
- switch (toolbarstyle) {
- case GTK_TOOLBAR_ICONS:
- if (tooliconsize == GTK_ICON_SIZE_SMALL_TOOLBAR) {
- nsoption_set_int(button_type, 1);
- } else {
- nsoption_set_int(button_type, 2);
- }
- break;
- case GTK_TOOLBAR_TEXT:
- nsoption_set_int(button_type, 4);
- break;
-
- case GTK_TOOLBAR_BOTH:
- case GTK_TOOLBAR_BOTH_HORIZ:
- /* no labels in default configuration */
- default:
- /* No system default, so use large icons */
- nsoption_set_int(button_type, 2);
- break;
+ if (g->menus[i].main != NULL) {
+ img = gtk_image_new_from_icon_name(g->menus[i].iconname,
+ GTK_ICON_SIZE_MENU);
+ nsgtk_image_menu_item_set_image(GTK_WIDGET(g->menus[i].main), img);
+ }
+ if (g->menus[i].burger != NULL) {
+ img = gtk_image_new_from_icon_name(g->menus[i].iconname,
+ GTK_ICON_SIZE_MENU);
+ nsgtk_image_menu_item_set_image(GTK_WIDGET(g->menus[i].burger), img);
+ }
+ if (g->menus[i].popup != NULL) {
+ img = gtk_image_new_from_icon_name(g->menus[i].iconname,
+ GTK_ICON_SIZE_MENU);
+ nsgtk_image_menu_item_set_image(GTK_WIDGET(g->menus[i].popup), img);
}
}
+}
- nsgtk_scaffolding_toolbars(gs, nsoption_int(button_type));
-
- gtk_toolbar_set_show_arrow(gs->tool_bar, TRUE);
- gtk_widget_show_all(GTK_WIDGET(gs->tool_bar));
- nsgtk_tab_init(gs);
-
- gtk_widget_set_size_request(GTK_WIDGET(
- gs->buttons[HISTORY_BUTTON]->button), 20, -1);
-
-
- /* set up URL bar completion */
- gs->url_bar_completion = nsgtk_url_entry_completion_new(gs);
-
- /* set up the throbber. */
- gs->throb_frame = 0;
-
-
-#define CONNECT(obj, sig, callback, ptr) \
- g_signal_connect(G_OBJECT(obj), (sig), G_CALLBACK(callback), (ptr))
-
- g_signal_connect_after(gs->notebook, "page-added",
- G_CALLBACK(nsgtk_window_tabs_add), gs);
- g_signal_connect_after(gs->notebook, "page-removed",
- G_CALLBACK(nsgtk_window_tabs_remove), gs);
-
- /* connect main window signals to their handlers. */
- CONNECT(gs->window, "delete-event",
- scaffolding_window_delete_event, gs);
-
- CONNECT(gs->window, "destroy", scaffolding_window_destroy, gs);
-
- /* toolbar URL bar menu bar search bar signal handlers */
- CONNECT(gs->menu_bar->edit_submenu->edit, "show",
- nsgtk_window_edit_menu_shown, gs);
- CONNECT(gs->menu_bar->edit_submenu->edit, "hide",
- nsgtk_window_edit_menu_hidden, gs);
-
- CONNECT(gs->search->buttons[1], "clicked",
- nsgtk_search_forward_button_clicked, gs);
-
- CONNECT(gs->search->buttons[0], "clicked",
- nsgtk_search_back_button_clicked, gs);
-
- CONNECT(gs->search->entry, "changed", nsgtk_search_entry_changed, gs);
-
- CONNECT(gs->search->entry, "activate", nsgtk_search_entry_activate, gs);
-
- CONNECT(gs->search->entry, "key-press-event",
- nsgtk_search_entry_key, gs);
- CONNECT(gs->search->buttons[2], "clicked",
- nsgtk_search_close_button_clicked, gs);
+/**
+ * create and initialise menus
+ *
+ * There are four menus held by the scaffolding:
+ *
+ * 1. Main menubar menu.
+ * This can be hidden which causes the right click popup context menu
+ * to use the burger menu.
+ * 2. Burger menu.
+ * This can be opened from a burger icon on the toolbar.
+ * 3. popup context menu.
+ * This is opened by right mouse clicking on the toolbar or browser area
+ * 4. link context menu
+ * Opened like the other popup menu when the mouse is over a link in the
+ * browser area
+ *
+ * The cut, copy, paste, delete and back, forwards, stop, reload groups of
+ * menu entries are context sensitive and must be updated as appropriate
+ * when a menu is opened which contains those groups.
+ */
+static nserror nsgtk_menus_create(struct nsgtk_scaffolding *gs)
+{
+ GtkAccelGroup *group;
+ bool showmenu; /* show menubar */
+ bool showtool; /* show toolbar */
- CONNECT(gs->search->caseSens, "toggled",
- nsgtk_search_entry_changed, gs);
+ get_bar_show(&showmenu, &showtool);
- CONNECT(gs->tool_bar, "popup-context-menu",
- nsgtk_window_tool_bar_clicked, gs);
+ group = gtk_accel_group_new();
- /* create popup menu */
- gs->menu_popup = nsgtk_new_scaffolding_popup(gs, group);
+ gtk_window_add_accel_group(gs->window, group);
- gs->link_menu = nsgtk_new_scaffolding_link_popup(gs, group);
+ gs->menu_bar = create_scaffolding_bar_menu(gs, group, showmenu, showtool);
+ gs->burger_menu = create_scaffolding_burger_menu(gs, group, showmenu, showtool);
+ gs->popup_menu = create_scaffolding_popup_menu(gs, group, showmenu, showtool);
+ gs->link_menu = create_scaffolding_link_menu(gs, group);
/* set up the menu signal handlers */
- nsgtk_scaffolding_toolbar_init(gs);
- nsgtk_toolbar_connect_all(gs);
- nsgtk_attach_menu_handlers(gs);
-
- nsgtk_scaffolding_initial_sensitivity(gs);
+ nsgtk_menu_initialise(gs);
+ nsgtk_menu_set_icons(gs);
+ nsgtk_menu_connect_signals(gs);
+ nsgtk_menu_set_sensitivity(gs);
- gs->fullscreen = false;
-
- /* attach to the list */
- if (scaf_list) {
- scaf_list->prev = gs;
- }
- gs->next = scaf_list;
- gs->prev = NULL;
- scaf_list = gs;
-
- /* set icon images */
- nsgtk_theme_implement(gs);
-
- /* set web search provider */
- search_web_select_provider(nsoption_int(search_provider));
-
- /* finally, show the window. */
- gtk_widget_show(GTK_WIDGET(gs->window));
-
- NSLOG(netsurf, INFO, "creation complete");
-
- return gs;
+ return NSERROR_OK;
}
+
/* 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;
}
@@ -2321,213 +1263,48 @@ void nsgtk_window_set_title(struct gui_window *gw, const char *title)
gtk_window_set_title(gs->window, newtitle);
free(newtitle);
-}
-
-nserror gui_window_set_url(struct gui_window *gw, nsurl *url)
-{
- struct nsgtk_scaffolding *g;
- size_t idn_url_l;
- char *idn_url_s = NULL;
-
- g = nsgtk_get_scaffold(gw);
- if (g->top_level == gw) {
- if (nsoption_bool(display_decoded_idn) == true) {
- if (nsurl_get_utf8(url, &idn_url_s, &idn_url_l) != NSERROR_OK)
- idn_url_s = NULL;
- }
-
- gtk_entry_set_text(GTK_ENTRY(g->url_bar), idn_url_s ? idn_url_s : nsurl_access(url));
-
- if(idn_url_s)
- free(idn_url_s);
-
- gtk_editable_set_position(GTK_EDITABLE(g->url_bar), -1);
- }
- return NSERROR_OK;
-}
-
-void gui_window_start_throbber(struct gui_window* _g)
-{
- struct nsgtk_scaffolding *g = nsgtk_get_scaffold(_g);
- g->buttons[STOP_BUTTON]->sensitivity = true;
- g->buttons[RELOAD_BUTTON]->sensitivity = false;
- nsgtk_scaffolding_set_sensitivity(g);
-
- scaffolding_update_context(g);
-
- nsgtk_schedule(100, nsgtk_throb, g);
-}
-
-void gui_window_stop_throbber(struct gui_window* _g)
-{
- struct nsgtk_scaffolding *g = nsgtk_get_scaffold(_g);
- if (g == NULL)
- return;
- scaffolding_update_context(g);
- nsgtk_schedule(-1, nsgtk_throb, g);
- if (g->buttons[STOP_BUTTON] != NULL)
- g->buttons[STOP_BUTTON]->sensitivity = false;
- if (g->buttons[RELOAD_BUTTON] != NULL)
- g->buttons[RELOAD_BUTTON]->sensitivity = true;
-
- nsgtk_scaffolding_set_sensitivity(g);
-
- if ((g->throbber == NULL) || (nsgtk_throbber == NULL) ||
- (nsgtk_throbber->framedata == NULL) ||
- (nsgtk_throbber->framedata[0] == NULL))
- return;
- gtk_image_set_from_pixbuf(g->throbber, nsgtk_throbber->framedata[0]);
}
-/**
- * set favicon
- */
-void
-nsgtk_scaffolding_set_icon(struct gui_window *gw)
+/* exported interface documented in scaffolding.h */
+nserror nsgtk_scaffolding_throbber(struct gui_window* gw, bool active)
{
- struct nsgtk_scaffolding *sc = nsgtk_get_scaffold(gw);
- GdkPixbuf *icon_pixbuf = nsgtk_get_icon(gw);
-
- /* check icon needs to be shown */
- if ((icon_pixbuf == NULL) ||
- (sc->top_level != gw)) {
- return;
+ struct nsgtk_scaffolding *gs = nsgtk_get_scaffold(gw);
+ if (active) {
+ gs->menus[STOP_BUTTON].sensitivity = true;
+ gs->menus[RELOAD_BUTTON].sensitivity = false;
+ } else {
+ gs->menus[STOP_BUTTON].sensitivity = false;
+ gs->menus[RELOAD_BUTTON].sensitivity = true;
}
+ scaffolding_update_context(gs);
- nsgtk_entry_set_icon_from_pixbuf(sc->url_bar,
- GTK_ENTRY_ICON_PRIMARY,
- icon_pixbuf);
-
- gtk_widget_show_all(GTK_WIDGET(sc->buttons[URL_BAR_ITEM]->button));
+ return NSERROR_OK;
}
-static void
-nsgtk_scaffolding_set_websearch(struct nsgtk_scaffolding *g, const char *content)
-{
- /** \todo this code appears technically correct, though
- * currently has no effect at all.
- */
- PangoLayout *lo = gtk_entry_get_layout(GTK_ENTRY(g->webSearchEntry));
- if (lo != NULL) {
- pango_layout_set_font_description(lo, NULL);
- PangoFontDescription *desc = pango_font_description_new();
- if (desc != NULL) {
- pango_font_description_set_style(desc,
- PANGO_STYLE_ITALIC);
- pango_font_description_set_family(desc, "Arial");
- pango_font_description_set_weight(desc,
- PANGO_WEIGHT_ULTRALIGHT);
- pango_font_description_set_size(desc,
- 10 * PANGO_SCALE);
- pango_layout_set_font_description(lo, desc);
- }
-
- PangoAttrList *list = pango_attr_list_new();
- if (list != NULL) {
- PangoAttribute *italic = pango_attr_style_new(
- PANGO_STYLE_ITALIC);
- if (italic != NULL) {
- italic->start_index = 0;
- italic->end_index = strlen(content);
- }
- PangoAttribute *grey = pango_attr_foreground_new(
- 0x7777, 0x7777, 0x7777);
- if (grey != NULL) {
- grey->start_index = 0;
- grey->end_index = strlen(content);
- }
- pango_attr_list_insert(list, italic);
- pango_attr_list_insert(list, grey);
- pango_layout_set_attributes(lo, list);
- pango_attr_list_unref(list);
- }
- pango_layout_set_text(lo, content, -1);
- }
-/* an alternative method */
-/* char *parse = malloc(strlen(content) + 1);
- PangoAttrList *list = pango_layout_get_attributes(lo);
- char *markup = g_strconcat("<span foreground='#777777'><i>", content,
- "</i></span>", NULL);
- pango_parse_markup(markup, -1, 0, &list, &parse, NULL, NULL);
- gtk_widget_show_all(g->webSearchEntry);
-*/
- gtk_entry_set_visibility(GTK_ENTRY(g->webSearchEntry), TRUE);
- gtk_entry_set_text(GTK_ENTRY(g->webSearchEntry), content);
-}
-/**
- * GTK UI callback when search provider details are updated.
- *
- * \param provider_name The providers name.
- * \param provider_bitmap The bitmap representing the provider.
- * \return NSERROR_OK on success else error code.
- */
-static nserror
-gui_search_web_provider_update(const char *provider_name,
- struct bitmap *provider_bitmap)
+/* exported interface documented in gtk/scaffolding.h */
+nserror nsgtk_scaffolding_destroy_all(void)
{
- struct nsgtk_scaffolding *current;
- GdkPixbuf *srch_pixbuf = NULL;
- char *searchcontent;
-
- NSLOG(netsurf, INFO, "name:%s bitmap %p", provider_name,
- provider_bitmap);
-
- if (provider_bitmap != NULL) {
- srch_pixbuf = nsgdk_pixbuf_get_from_surface(provider_bitmap->surface, 16, 16);
-
- if (srch_pixbuf == NULL) {
- return NSERROR_NOMEM;
- }
- }
-
- /* setup the search content name */
- searchcontent = malloc(strlen(provider_name) + SLEN("Search ") + 1);
- if (searchcontent != NULL) {
- sprintf(searchcontent, "Search %s", provider_name);
- }
-
- /* set the search provider parameters up in each scaffold */
- for (current = scaf_list; current != NULL; current = current->next) {
- if (current->webSearchEntry == NULL) {
- continue;
- }
+ struct nsgtk_scaffolding *gs;
- /* add ico to each window's toolbar */
- if (srch_pixbuf != NULL) {
- nsgtk_entry_set_icon_from_pixbuf(current->webSearchEntry,
- GTK_ENTRY_ICON_PRIMARY,
- srch_pixbuf);
- } else {
- nsgtk_entry_set_icon_from_stock(current->webSearchEntry,
- GTK_ENTRY_ICON_PRIMARY,
- NSGTK_STOCK_FIND);
- }
+ gs = scaf_list;
+ assert(gs != NULL);
- /* set search entry text */
- if (searchcontent != NULL) {
- nsgtk_scaffolding_set_websearch(current, searchcontent);
- } else {
- nsgtk_scaffolding_set_websearch(current, provider_name);
- }
+ if (nsgtk_check_for_downloads(gs->window) == true) {
+ return NSERROR_INVALID;
}
- free(searchcontent);
-
- if (srch_pixbuf != NULL) {
- g_object_unref(srch_pixbuf);
+ /* iterate all scaffolding windows and destroy them */
+ while (gs != NULL) {
+ struct nsgtk_scaffolding *next = gs->next;
+ gtk_widget_destroy(GTK_WIDGET(gs->window));
+ gs = next;
}
-
return NSERROR_OK;
}
-static struct gui_search_web_table search_web_table = {
- .provider_update = gui_search_web_provider_update,
-};
-
-struct gui_search_web_table *nsgtk_search_web_table = &search_web_table;
/* exported interface documented in gtk/scaffolding.h */
GtkWindow* nsgtk_scaffolding_window(struct nsgtk_scaffolding *g)
@@ -2541,41 +1318,14 @@ GtkNotebook* nsgtk_scaffolding_notebook(struct nsgtk_scaffolding *g)
return g->notebook;
}
-/* exported interface documented in gtk/scaffolding.h */
-GtkWidget *nsgtk_scaffolding_urlbar(struct nsgtk_scaffolding *g)
-{
- return g->url_bar;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-GtkWidget *nsgtk_scaffolding_websearch(struct nsgtk_scaffolding *g)
-{
- return g->webSearchEntry;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-GtkToolbar *nsgtk_scaffolding_toolbar(struct nsgtk_scaffolding *g)
-{
- return g->tool_bar;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-struct nsgtk_button_connect *
-nsgtk_scaffolding_button(struct nsgtk_scaffolding *g, int i)
-{
- return g->buttons[i];
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-struct gtk_search *nsgtk_scaffolding_search(struct nsgtk_scaffolding *g)
-{
- return g->search;
-}
/* exported interface documented in gtk/scaffolding.h */
-GtkMenuBar *nsgtk_scaffolding_menu_bar(struct nsgtk_scaffolding *g)
+GtkMenuBar *nsgtk_scaffolding_menu_bar(struct nsgtk_scaffolding *gs)
{
- return g->menu_bar->bar_menu;
+ if (gs == NULL) {
+ return NULL;
+ }
+ return gs->menu_bar->bar_menu;
}
/* exported interface documented in gtk/scaffolding.h */
@@ -2587,54 +1337,6 @@ struct nsgtk_scaffolding *nsgtk_scaffolding_iterate(struct nsgtk_scaffolding *g)
return g->next;
}
-/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_reset_offset(struct nsgtk_scaffolding *g)
-{
- g->offset = 0;
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_update_url_bar_ref(struct nsgtk_scaffolding *g)
-{
- g->url_bar = GTK_WIDGET(gtk_bin_get_child(GTK_BIN(
- nsgtk_scaffolding_button(g, URL_BAR_ITEM)->button)));
-
- gtk_entry_set_completion(GTK_ENTRY(g->url_bar),
- g->url_bar_completion);
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_update_throbber_ref(struct nsgtk_scaffolding *g)
-{
- g->throbber = GTK_IMAGE(gtk_bin_get_child(
- GTK_BIN(g->buttons[THROBBER_ITEM]->button)));
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_update_websearch_ref(struct nsgtk_scaffolding *g)
-{
- g->webSearchEntry = gtk_bin_get_child(GTK_BIN(
- g->buttons[WEBSEARCH_ITEM]->button));
-}
-
-/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_toggle_search_bar_visibility(struct nsgtk_scaffolding *g)
-{
- gboolean vis;
- struct browser_window *bw = nsgtk_get_browser_window(g->top_level);
-
- g_object_get(G_OBJECT(g->search->bar), "visible", &vis, NULL);
- if (vis) {
- if (bw != NULL) {
- browser_window_search_clear(bw);
- }
-
- gtk_widget_hide(GTK_WIDGET(g->search->bar));
- } else {
- gtk_widget_show(GTK_WIDGET(g->search->bar));
- gtk_widget_grab_focus(GTK_WIDGET(g->search->entry));
- }
-}
/* exported interface documented in gtk/scaffolding.h */
struct gui_window *nsgtk_scaffolding_top_level(struct nsgtk_scaffolding *g)
@@ -2642,6 +1344,7 @@ struct gui_window *nsgtk_scaffolding_top_level(struct nsgtk_scaffolding *g)
return g->top_level;
}
+
/* exported interface documented in gtk/scaffolding.h */
void nsgtk_scaffolding_set_top_level(struct gui_window *gw)
{
@@ -2657,44 +1360,33 @@ void nsgtk_scaffolding_set_top_level(struct gui_window *gw)
sc = nsgtk_get_scaffold(gw);
assert(sc != NULL);
+ scaf_current = sc;
+
sc->top_level = gw;
- /* Synchronise the history (will also update the URL bar) */
+ /* Synchronise the history */
scaffolding_update_context(sc);
- /* clear effects of potential searches */
- browser_window_search_clear(bw);
-
- nsgtk_scaffolding_set_icon(gw);
-
/* 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));
}
+
/* exported interface documented in scaffolding.h */
void nsgtk_scaffolding_set_sensitivity(struct nsgtk_scaffolding *g)
{
int i;
-#define SENSITIVITY(q)\
- i = q##_BUTTON;\
- if (g->buttons[i]->main != NULL)\
- gtk_widget_set_sensitive(GTK_WIDGET(\
- g->buttons[i]->main),\
- g->buttons[i]->sensitivity);\
- if (g->buttons[i]->rclick != NULL)\
- gtk_widget_set_sensitive(GTK_WIDGET(\
- g->buttons[i]->rclick),\
- g->buttons[i]->sensitivity);\
- if ((g->buttons[i]->location != -1) && \
- (g->buttons[i]->button != NULL))\
- gtk_widget_set_sensitive(GTK_WIDGET(\
- g->buttons[i]->button),\
- g->buttons[i]->sensitivity);\
- if (g->buttons[i]->popup != NULL)\
- gtk_widget_set_sensitive(GTK_WIDGET(\
- g->buttons[i]->popup),\
- g->buttons[i]->sensitivity);
+#define SENSITIVITY(q) \
+ i = q##_BUTTON; \
+ if (g->menus[i].main != NULL) \
+ gtk_widget_set_sensitive(GTK_WIDGET(g->menus[i].main), \
+ g->menus[i].sensitivity); \
+ if (g->menus[i].burger != NULL) \
+ gtk_widget_set_sensitive(GTK_WIDGET(g->menus[i].burger), \
+ g->menus[i].sensitivity); \
+ if (g->menus[i].popup != NULL) \
+ gtk_widget_set_sensitive(GTK_WIDGET(g->menus[i].popup), \
+ g->menus[i].sensitivity);
SENSITIVITY(STOP)
SENSITIVITY(RELOAD)
@@ -2707,86 +1399,205 @@ void nsgtk_scaffolding_set_sensitivity(struct nsgtk_scaffolding *g)
SENSITIVITY(PREVTAB)
SENSITIVITY(CLOSETAB)
#undef SENSITIVITY
+
}
/* exported interface documented in gtk/scaffolding.h */
-void nsgtk_scaffolding_context_menu(struct nsgtk_scaffolding *g,
- gdouble x,
- gdouble y)
+nserror nsgtk_scaffolding_toolbar_context_menu(struct nsgtk_scaffolding *gs)
+{
+ /* set visibility for right-click popup menu */
+ popup_menu_hide(gs->popup_menu, false, true);
+
+ nsgtk_menu_popup_at_pointer(gs->popup_menu->popup_menu, NULL);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in gtk/scaffolding.h */
+nserror nsgtk_scaffolding_burger_menu(struct nsgtk_scaffolding *gs)
+{
+ nsgtk_menu_popup_at_pointer(gs->burger_menu->burger_menu, NULL);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in gtk/scaffolding.h */
+void
+nsgtk_scaffolding_context_menu(struct nsgtk_scaffolding *g,
+ gdouble x,
+ gdouble y)
{
GtkMenu *gtkmenu;
+ struct browser_window *bw;
+
+ bw = nsgtk_get_browser_window(g->top_level);
/* update the global context menu features */
- browser_window_get_features(nsgtk_get_browser_window(g->top_level),
- x, y, &current_menu_features);
+ browser_window_get_features(bw, x, y, &current_menu_features);
if (current_menu_features.link != NULL) {
/* menu is opening over a link */
gtkmenu = g->link_menu->link_menu;
} else {
- gtkmenu = g->menu_popup->popup_menu;
+ gtkmenu = g->popup_menu->popup_menu;
nsgtk_scaffolding_update_edit_actions_sensitivity(g);
- if (!(g->buttons[COPY_BUTTON]->sensitivity)) {
- gtk_widget_hide(GTK_WIDGET(g->menu_popup->copy_menuitem));
+ if (!(g->menus[COPY_BUTTON].sensitivity)) {
+ gtk_widget_hide(GTK_WIDGET(g->popup_menu->copy_menuitem));
} else {
- gtk_widget_show(GTK_WIDGET(g->menu_popup->copy_menuitem));
+ gtk_widget_show(GTK_WIDGET(g->popup_menu->copy_menuitem));
}
- if (!(g->buttons[CUT_BUTTON]->sensitivity)) {
- gtk_widget_hide(GTK_WIDGET(g->menu_popup->cut_menuitem));
+ if (!(g->menus[CUT_BUTTON].sensitivity)) {
+ gtk_widget_hide(GTK_WIDGET(g->popup_menu->cut_menuitem));
} else {
- gtk_widget_show(GTK_WIDGET(g->menu_popup->cut_menuitem));
+ gtk_widget_show(GTK_WIDGET(g->popup_menu->cut_menuitem));
}
- if (!(g->buttons[PASTE_BUTTON]->sensitivity)) {
- gtk_widget_hide(GTK_WIDGET(g->menu_popup->paste_menuitem));
+ if (!(g->menus[PASTE_BUTTON].sensitivity)) {
+ gtk_widget_hide(GTK_WIDGET(g->popup_menu->paste_menuitem));
} else {
- gtk_widget_show(GTK_WIDGET(g->menu_popup->paste_menuitem));
+ gtk_widget_show(GTK_WIDGET(g->popup_menu->paste_menuitem));
}
- /* hide customise */
- popup_menu_hide(g->menu_popup, false, false, false, true);
}
- gtk_menu_popup(gtkmenu, NULL, NULL, NULL, NULL, 0,
- gtk_get_current_event_time());
+ nsgtk_menu_popup_at_pointer(gtkmenu, NULL);
}
-/**
- * reallocate width for history button, reallocate buttons right of history;
- * memorise base of history button / toolbar
- */
-void nsgtk_scaffolding_toolbar_size_allocate(GtkWidget *widget,
- GtkAllocation *alloc, gpointer data)
+/* exported interface documented in gtk/scaffolding.h */
+struct nsgtk_scaffolding *nsgtk_current_scaffolding(void)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- int i = nsgtk_toolbar_get_id_from_widget(widget, g);
- if (i == -1)
- return;
- if ((g->toolbarmem == alloc->x) ||
- (g->buttons[i]->location <
- g->buttons[HISTORY_BUTTON]->location))
- /* no reallocation after first adjustment, no reallocation for buttons
- * left of history button */
- return;
- if (widget == GTK_WIDGET(g->buttons[HISTORY_BUTTON]->button)) {
- if (alloc->width == 20)
- return;
-
- g->toolbarbase = alloc->y + alloc->height;
- g->historybase = alloc->x + 20;
- if (g->offset == 0)
- g->offset = alloc->width - 20;
- alloc->width = 20;
- } else if (g->buttons[i]->location <=
- g->buttons[URL_BAR_ITEM]->location) {
- alloc->x -= g->offset;
- if (i == URL_BAR_ITEM)
- alloc->width += g->offset;
+ if (scaf_current == NULL) {
+ scaf_current = scaf_list;
}
- g->toolbarmem = alloc->x;
- gtk_widget_size_allocate(widget, alloc);
+ return scaf_current;
+}
+
+/* exported interface documented in gtk/scaffolding.h */
+struct nsgtk_scaffolding *nsgtk_scaffolding_from_notebook(GtkNotebook *notebook)
+{
+ struct nsgtk_scaffolding *gs;
+ gs = scaf_list;
+ while (gs != NULL) {
+ if (gs->notebook == notebook) {
+ break;
+ }
+ gs = gs->next;
+ }
+ return gs;
+}
+
+/* exported interface documented in gtk/scaffolding.h */
+struct nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel)
+{
+ nserror res;
+ struct nsgtk_scaffolding *gs;
+
+ gs = calloc(1, sizeof(*gs));
+ if (gs == NULL) {
+ return NULL;
+ }
+
+ NSLOG(netsurf, INFO,
+ "Constructing a scaffold of %p for gui_window %p", gs, toplevel);
+
+ gs->top_level = toplevel;
+
+ /* Construct UI widgets */
+ if (nsgtk_builder_new_from_resname("netsurf", &gs->builder) != NSERROR_OK) {
+ free(gs);
+ return NULL;
+ }
+
+ gtk_builder_connect_signals(gs->builder, NULL);
+
+ /* containing window setup */
+ gs->window = GTK_WINDOW(gtk_builder_get_object(gs->builder,
+ "wndBrowser"));
+
+ /**
+ * set this window's size and position to what's in the options, or
+ * some sensible default if they are not set yet.
+ */
+ if (nsoption_int(window_width) > 0) {
+ gtk_window_move(gs->window,
+ nsoption_int(window_x),
+ nsoption_int(window_y));
+ gtk_window_resize(gs->window,
+ nsoption_int(window_width),
+ nsoption_int(window_height));
+ } else {
+ /* Set to 1000x700, so we're very likely to fit even on
+ * 1024x768 displays, not being able to take into account
+ * window furniture or panels.
+ */
+ gtk_window_set_default_size(gs->window, 1000, 700);
+ }
+
+ g_signal_connect(gs->window,
+ "delete-event",
+ G_CALLBACK(scaffolding_window_delete_event),
+ gs);
+
+ g_signal_connect(gs->window,
+ "destroy",
+ G_CALLBACK(scaffolding_window_destroy),
+ gs);
+
+
+ /* notebook */
+ res = nsgtk_notebook_create(gs->builder, &gs->notebook);
+ if (res != NSERROR_OK) {
+ free(gs);
+ return NULL;
+ }
+
+ g_signal_connect_after(gs->notebook,
+ "page-added",
+ G_CALLBACK(nsgtk_window_tabs_add),
+ gs);
+ gs->tabs_remove_handler_id = g_signal_connect_after(gs->notebook,
+ "page-removed",
+ G_CALLBACK(nsgtk_window_tabs_remove),
+ gs);
+
+
+ res = nsgtk_menus_create(gs);
+ if (res != NSERROR_OK) {
+ free(gs);
+ return NULL;
+ }
+
+ /* attach to the list */
+ if (scaf_list) {
+ scaf_list->prev = gs;
+ }
+ gs->next = scaf_list;
+ gs->prev = NULL;
+ scaf_list = gs;
+
+ /* finally, show the window. */
+ gtk_widget_show(GTK_WIDGET(gs->window));
+
+ NSLOG(netsurf, INFO, "creation complete");
+
+ return gs;
+}
+
+/* exported interface documented in gtk/scaffolding.h */
+nserror nsgtk_scaffolding_position_page_info(struct nsgtk_scaffolding *gs,
+ struct nsgtk_pi_window *win)
+{
+ return nsgtk_window_position_page_info(gs->top_level, win);
+}
+
+/* exported interface documented in gtk/scaffolding.h */
+nserror nsgtk_scaffolding_position_local_history(struct nsgtk_scaffolding *gs)
+{
+ return nsgtk_window_position_local_history(gs->top_level);
}
diff --git a/frontends/gtk/scaffolding.h b/frontends/gtk/scaffolding.h
index e1fd9bf2a..87d4f3bd6 100644
--- a/frontends/gtk/scaffolding.h
+++ b/frontends/gtk/scaffolding.h
@@ -27,91 +27,8 @@ struct hlcache_handle;
struct gui_window;
struct gui_search_web_table;
struct nsurl;
+struct nsgtk_pi_window;
-extern struct gui_search_web_table *nsgtk_search_web_table;
-
-typedef enum {
- BACK_BUTTON = 0,
- HISTORY_BUTTON,
- FORWARD_BUTTON,
- STOP_BUTTON,
- RELOAD_BUTTON,
- HOME_BUTTON,
- URL_BAR_ITEM,
- WEBSEARCH_ITEM,
- THROBBER_ITEM,
- NEWWINDOW_BUTTON,
- NEWTAB_BUTTON,
- OPENFILE_BUTTON,
- CLOSETAB_BUTTON,
- CLOSEWINDOW_BUTTON,
- SAVEPAGE_BUTTON,
- PDF_BUTTON,
- PLAINTEXT_BUTTON,
- DRAWFILE_BUTTON,
- POSTSCRIPT_BUTTON,
- PRINTPREVIEW_BUTTON,
- PRINT_BUTTON,
- QUIT_BUTTON,
- CUT_BUTTON,
- COPY_BUTTON,
- PASTE_BUTTON,
- DELETE_BUTTON,
- SELECTALL_BUTTON,
- FIND_BUTTON,
- PREFERENCES_BUTTON,
- ZOOMPLUS_BUTTON,
- ZOOMMINUS_BUTTON,
- ZOOMNORMAL_BUTTON,
- FULLSCREEN_BUTTON,
- VIEWSOURCE_BUTTON,
- DOWNLOADS_BUTTON,
- SAVEWINDOWSIZE_BUTTON,
- TOGGLEDEBUGGING_BUTTON,
- SAVEBOXTREE_BUTTON,
- SAVEDOMTREE_BUTTON,
- LOCALHISTORY_BUTTON,
- GLOBALHISTORY_BUTTON,
- ADDBOOKMARKS_BUTTON,
- SHOWBOOKMARKS_BUTTON,
- SHOWCOOKIES_BUTTON,
- OPENLOCATION_BUTTON,
- NEXTTAB_BUTTON,
- PREVTAB_BUTTON,
- CONTENTS_BUTTON,
- GUIDE_BUTTON,
- INFO_BUTTON,
- ABOUT_BUTTON,
- PLACEHOLDER_BUTTON /* size indicator; array maximum indices */
-} nsgtk_toolbar_button; /* PLACEHOLDER_BUTTON - 1 */
-
-struct gtk_history_window {
- struct nsgtk_scaffolding *g;
- GtkWindow *window;
- GtkScrolledWindow *scrolled;
- GtkDrawingArea *drawing_area;
-};
-
-struct gtk_search {
- GtkToolbar *bar;
- GtkEntry *entry;
- GtkToolButton *buttons[3]; /* back, forward, */
- GtkCheckButton *checkAll; /* close */
- GtkCheckButton *caseSens;
-};
-
-struct nsgtk_button_connect {
- GtkToolItem *button;
- int location; /* in toolbar */
- bool sensitivity;
- GtkWidget *main; /* left click menu entry */
- GtkWidget *rclick; /* right click menu */
- GtkWidget *popup; /* popup menu entry */
- void *mhandler; /* menu item clicked */
- void *bhandler; /* button clicked */
- void *dataplus; /* customization -> toolbar */
- void *dataminus; /* customization -> store */
-};
/**
* create a new scaffolding for a window.
@@ -122,69 +39,75 @@ struct nsgtk_button_connect {
struct nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *gw);
/**
- * Obtain the most recently used scaffolding element.
+ * causes all scaffolding windows to be destroyed.
*
- * This allows tabs to be opened in the most recently used window
+ * \return NSERROR_OK and all scaffolding windows destroyed else
+ * NSERROR_INVALID if download in progress and user continued.
*/
-struct nsgtk_scaffolding *nsgtk_current_scaffolding(void);
+nserror nsgtk_scaffolding_destroy_all(void);
-/* acessors for gtk elements within a scaffold */
+/**
+ * Update scaffolding window when throbber state changes
+ */
+nserror nsgtk_scaffolding_throbber(struct gui_window* gw, bool active);
/**
- * Get the gtk window for a scaffolding.
+ * open the toolbar context menu
*/
-GtkWindow *nsgtk_scaffolding_window(struct nsgtk_scaffolding *g);
+nserror nsgtk_scaffolding_toolbar_context_menu(struct nsgtk_scaffolding *gs);
/**
- * Get the gtk notebook from a scaffold.
+ * Position the page-info popup in the right place
+ *
+ * \param gs The scaffolding to position relative to
+ * \param win The page-info window to position
*/
-GtkNotebook *nsgtk_scaffolding_notebook(struct nsgtk_scaffolding *g);
+nserror nsgtk_scaffolding_position_page_info(struct nsgtk_scaffolding *gs,
+ struct nsgtk_pi_window *win);
/**
- * Get the gtk url bar from a scaffold.
+ * Position the local-history popup in the right place
+ *
+ * \param gs The scaffolding to position relative to
*/
-GtkWidget *nsgtk_scaffolding_urlbar(struct nsgtk_scaffolding *g);
+nserror nsgtk_scaffolding_position_local_history(struct nsgtk_scaffolding *gs);
/**
- * Get the gtk web search entry from a scaffold.
+ * open the burger menu
*/
-GtkWidget *nsgtk_scaffolding_websearch(struct nsgtk_scaffolding *g);
+nserror nsgtk_scaffolding_burger_menu(struct nsgtk_scaffolding *gs);
/**
- * Get the gtk toolbar from a scaffold.
+ * Obtain the most recently used scaffolding element.
+ *
+ * This allows tabs to be opened in the most recently used window
*/
-GtkToolbar *nsgtk_scaffolding_toolbar(struct nsgtk_scaffolding *g);
+struct nsgtk_scaffolding *nsgtk_current_scaffolding(void);
+/* acessors for gtk elements within a scaffold */
-struct nsgtk_button_connect *nsgtk_scaffolding_button(struct nsgtk_scaffolding *g, int i);
+/**
+ * Get the gtk window for a scaffolding.
+ */
+GtkWindow *nsgtk_scaffolding_window(struct nsgtk_scaffolding *g);
+
+/**
+ * Get the gtk notebook from a scaffold.
+ */
+GtkNotebook *nsgtk_scaffolding_notebook(struct nsgtk_scaffolding *g);
struct gtk_search *nsgtk_scaffolding_search(struct nsgtk_scaffolding *g);
GtkMenuBar *nsgtk_scaffolding_menu_bar(struct nsgtk_scaffolding *g);
-struct gtk_history_window *nsgtk_scaffolding_history_window(struct nsgtk_scaffolding *g);
-
struct gui_window *nsgtk_scaffolding_top_level(struct nsgtk_scaffolding *g);
-/**
- * reset the scaffold offset value to 0.
- *
- * \todo The value is only ever altered in
- * nsgtk_scaffolding_toolbar_size_allocate and is something to do with
- * the history button either clarify or remove!
- */
-void nsgtk_scaffolding_reset_offset(struct nsgtk_scaffolding *g);
/**
* Iterate through available scaffolding.
*/
struct nsgtk_scaffolding *nsgtk_scaffolding_iterate(struct nsgtk_scaffolding *g);
-void nsgtk_scaffolding_update_url_bar_ref(struct nsgtk_scaffolding *g);
-
-void nsgtk_scaffolding_update_throbber_ref(struct nsgtk_scaffolding *g);
-
-void nsgtk_scaffolding_update_websearch_ref(struct nsgtk_scaffolding *g);
void nsgtk_scaffolding_toggle_search_bar_visibility(struct nsgtk_scaffolding *g);
@@ -224,29 +147,20 @@ void nsgtk_scaffolding_set_sensitivity(struct nsgtk_scaffolding *g);
*/
void nsgtk_scaffolding_context_menu(struct nsgtk_scaffolding *g, gdouble x, gdouble y);
-void nsgtk_scaffolding_toolbar_size_allocate(GtkWidget *widget, GtkAllocation *alloc, gpointer data);
-
-void nsgtk_scaffolding_set_icon(struct gui_window *gw);
-
-gboolean nsgtk_window_url_activate_event(GtkWidget *, gpointer);
-
-gboolean nsgtk_window_url_changed(GtkWidget *, GdkEventKey *, gpointer);
-
-nserror nsgtk_scaffolding_new_tab(struct gui_window *gw);
-
-/* 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);
-
-nserror gui_window_set_url(struct gui_window *g, struct nsurl *url);
-void gui_window_start_throbber(struct gui_window *g);
-void gui_window_stop_throbber(struct gui_window *g);
+void nsgtk_scaffolding_set_title(struct gui_window *gw, const char *title);
-void nsgtk_scaffolding_toolbars(struct nsgtk_scaffolding *g, int tbi);
+/**
+ * find which scaffolding contains a gtk notebook
+ *
+ * \param notebook The notebook to search for.
+ * \return The scaffolding containing the notebook or NULL if not found
+ */
+struct nsgtk_scaffolding *nsgtk_scaffolding_from_notebook(GtkNotebook *notebook);
#endif /* NETSURF_GTK_SCAFFOLDING_H */
diff --git a/frontends/gtk/schedule.c b/frontends/gtk/schedule.c
index d5b45674b..69678924d 100644
--- a/frontends/gtk/schedule.c
+++ b/frontends/gtk/schedule.c
@@ -28,9 +28,9 @@
/** Killable callback closure embodiment. */
typedef struct {
- void (*callback)(void *); /**< The callback function. */
- void *context; /**< The context for the callback. */
- bool callback_killed; /**< Whether or not this was killed. */
+ void (*callback)(void *); /**< The callback function. */
+ void *context; /**< The context for the callback. */
+ bool callback_killed; /**< Whether or not this was killed. */
} _nsgtk_callback_t;
/** List of callbacks which have occurred and are pending running. */
@@ -61,20 +61,29 @@ nsgtk_schedule_kill_callback(void *_target, void *_match)
if ((target->callback == match->callback) &&
(target->context == match->context)) {
NSLOG(schedule, DEBUG,
- "Found match for %p(%p), killing.",
+ "Found match for %p(%p), killing.",
target->callback, target->context);
target->callback = NULL;
target->context = NULL;
target->callback_killed = true;
+ match->callback_killed = true;
}
}
-static void
-schedule_remove(void (*callback)(void *p), void *p)
+/**
+ * remove a matching callback and context tuple from all lists
+ *
+ * \param callback The callback to match
+ * \param cbctx The callback context to match
+ * \return NSERROR_OK if the tuple was removed from at least one list else NSERROR_NOT_FOUND
+ */
+static nserror
+schedule_remove(void (*callback)(void *p), void *cbctx)
{
_nsgtk_callback_t cb_match = {
.callback = callback,
- .context = p,
+ .context = cbctx,
+ .callback_killed = false,
};
g_list_foreach(queued_callbacks,
@@ -83,29 +92,36 @@ schedule_remove(void (*callback)(void *p), void *p)
nsgtk_schedule_kill_callback, &cb_match);
g_list_foreach(this_run,
nsgtk_schedule_kill_callback, &cb_match);
+
+ if (cb_match.callback_killed == false) {
+ return NSERROR_NOT_FOUND;
+ }
+ return NSERROR_OK;
}
/* exported interface documented in gtk/schedule.h */
-nserror nsgtk_schedule(int t, void (*callback)(void *p), void *p)
+nserror nsgtk_schedule(int t, void (*callback)(void *p), void *cbctx)
{
- _nsgtk_callback_t *cb;
+ _nsgtk_callback_t *cb;
+ nserror res;
/* Kill any pending schedule of this kind. */
- schedule_remove(callback, p);
+ res = schedule_remove(callback, cbctx);
- if (t < 0) {
- return NSERROR_OK;
- }
+ /* only removal */
+ if (t < 0) {
+ return res;
+ }
- cb = malloc(sizeof(_nsgtk_callback_t));
+ cb = malloc(sizeof(_nsgtk_callback_t));
cb->callback = callback;
- cb->context = p;
+ cb->context = cbctx;
cb->callback_killed = false;
/* Prepend is faster right now. */
queued_callbacks = g_list_prepend(queued_callbacks, cb);
g_timeout_add(t, nsgtk_schedule_generic_callback, cb);
- return NSERROR_OK;
+ return NSERROR_OK;
}
bool
@@ -121,7 +137,7 @@ schedule_run(void)
pending_callbacks = NULL;
NSLOG(schedule, DEBUG,
- "Captured a run of %d callbacks to fire.",
+ "Captured a run of %d callbacks to fire.",
g_list_length(this_run));
/* Run all the callbacks which made it this far. */
@@ -132,5 +148,5 @@ schedule_run(void)
cb->callback(cb->context);
free(cb);
}
- return true;
+ return true;
}
diff --git a/frontends/gtk/search.c b/frontends/gtk/search.c
index 298309679..f9a509f6e 100644
--- a/frontends/gtk/search.c
+++ b/frontends/gtk/search.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -17,228 +17,340 @@
*/
- /** \file
- * Free text search (front component)
+/**
+ * \file
+ * find in page gtk frontend implementation
+ *
+ * \todo this whole thing should be named find rather than search as
+ * that generally means web search and is confusing.
*/
-#include <stdint.h>
-#include <ctype.h>
-#include <string.h>
-#include <gdk/gdkkeysyms.h>
-
-#include "utils/config.h"
-#include "utils/log.h"
-#include "utils/messages.h"
-#include "utils/nsurl.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <gtk/gtk.h>
+
+#include "utils/nsoption.h"
#include "netsurf/search.h"
-#include "netsurf/browser_window.h"
#include "desktop/search.h"
-#include "desktop/searchweb.h"
-#include "gtk/warn.h"
#include "gtk/compat.h"
-#include "gtk/search.h"
-#include "gtk/scaffolding.h"
+#include "gtk/toolbar_items.h"
#include "gtk/window.h"
+#include "gtk/search.h"
+
+
+struct gtk_search {
+ GtkToolbar *bar;
+ GtkEntry *entry;
+ GtkToolButton *back;
+ GtkToolButton *forward;
+ GtkToolButton *close;
+ GtkCheckButton *checkAll;
+ GtkCheckButton *caseSens;
+
+ struct browser_window *bw;
+};
/**
* activate search forwards button in gui.
*
* \param active activate/inactivate
- * \param gw The gui window in which to activite the search button in.
+ * \param search the gtk search context
*/
-static void nsgtk_search_set_forward_state(bool active, struct gui_window *gw)
+static void nsgtk_search_set_forward_state(bool active, struct gtk_search *search)
{
- if (gw != NULL && nsgtk_get_browser_window(gw) != NULL) {
- struct nsgtk_scaffolding *g = nsgtk_get_scaffold(gw);
- gtk_widget_set_sensitive(
- GTK_WIDGET(nsgtk_scaffolding_search(g)->buttons[1]),
- active);
- }
+ gtk_widget_set_sensitive(GTK_WIDGET(search->forward), active);
}
+
/**
* activate search back button in gui.
*
* \param active activate/inactivate
- * \param gw The gui window in which to activite the search button in.
+ * \param search the gtk search context
*/
-static void nsgtk_search_set_back_state(bool active, struct gui_window *gw)
+static void nsgtk_search_set_back_state(bool active, struct gtk_search *search)
{
- if (gw != NULL && nsgtk_get_browser_window(gw) != NULL) {
- struct nsgtk_scaffolding *g = nsgtk_get_scaffold(gw);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_search(
- g)->buttons[0]), active);
- }
+ gtk_widget_set_sensitive(GTK_WIDGET(search->back), active);
}
-/** connected to the search forward button */
-gboolean nsgtk_search_forward_button_clicked(GtkWidget *widget, gpointer data)
+/**
+ * connected to the search forward button
+ */
+static gboolean
+nsgtk_search_forward_button_clicked(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- struct gui_window *gw = nsgtk_scaffolding_top_level(g);
- struct browser_window *bw = nsgtk_get_browser_window(gw);
-
- assert(bw);
-
- search_flags_t flags = SEARCH_FLAG_FORWARDS |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->caseSens)) ?
- SEARCH_FLAG_CASE_SENSITIVE : 0) |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->checkAll)) ?
- SEARCH_FLAG_SHOWALL : 0);
-
- browser_window_search(bw, gw, flags,
- gtk_entry_get_text(nsgtk_scaffolding_search(g)->entry));
+ struct gtk_search *search;
+ search_flags_t flags;
+
+ search = (struct gtk_search *)data;
+
+ flags = SEARCH_FLAG_FORWARDS;
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->caseSens))) {
+ flags |= SEARCH_FLAG_CASE_SENSITIVE;
+ }
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->checkAll))) {
+ flags |= SEARCH_FLAG_SHOWALL;
+ }
+
+ browser_window_search(search->bw, search, flags,
+ gtk_entry_get_text(search->entry));
+
return TRUE;
}
-/** connected to the search back button */
-
-gboolean nsgtk_search_back_button_clicked(GtkWidget *widget, gpointer data)
+/**
+ * connected to the search back button
+ */
+static gboolean
+nsgtk_search_back_button_clicked(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- struct gui_window *gw = nsgtk_scaffolding_top_level(g);
- struct browser_window *bw = nsgtk_get_browser_window(gw);
-
- assert(bw);
-
- search_flags_t flags = 0 |(gtk_toggle_button_get_active(
- GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->caseSens)) ?
- SEARCH_FLAG_CASE_SENSITIVE : 0) |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->checkAll)) ?
- SEARCH_FLAG_SHOWALL : 0);
-
- browser_window_search(bw, gw, flags,
- gtk_entry_get_text(nsgtk_scaffolding_search(g)->entry));
+ struct gtk_search *search;
+ search_flags_t flags;
+
+ search = (struct gtk_search *)data;
+
+ flags = 0;
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->caseSens))) {
+ flags |= SEARCH_FLAG_CASE_SENSITIVE;
+ }
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->checkAll))) {
+ flags |= SEARCH_FLAG_SHOWALL;
+ }
+
+ browser_window_search(search->bw, search, flags,
+ gtk_entry_get_text(search->entry));
+
return TRUE;
}
-/** connected to the search close button */
-
-gboolean nsgtk_search_close_button_clicked(GtkWidget *widget, gpointer data)
+/**
+ * connected to the search close button
+ */
+static gboolean
+nsgtk_search_close_button_clicked(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- nsgtk_scaffolding_toggle_search_bar_visibility(g);
- return TRUE;
+ struct gtk_search *search;
+
+ search = (struct gtk_search *)data;
+
+ nsgtk_search_toggle_visibility(search);
+
+ return TRUE;
}
-/** connected to the search entry [typing] */
-gboolean nsgtk_search_entry_changed(GtkWidget *widget, gpointer data)
+/**
+ * connected to the search entry [typing]
+ */
+static gboolean nsgtk_search_entry_changed(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- struct gui_window *gw = nsgtk_scaffolding_top_level(g);
- struct browser_window *bw = nsgtk_get_browser_window(gw);
+ struct gtk_search *search;
search_flags_t flags;
- assert(bw != NULL);
+ search = (struct gtk_search *)data;
+
+ flags = 0;
- nsgtk_search_set_forward_state(true, gw);
- nsgtk_search_set_back_state(true, gw);
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->caseSens))) {
+ flags |= SEARCH_FLAG_CASE_SENSITIVE;
+ }
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->checkAll))) {
+ flags |= SEARCH_FLAG_SHOWALL;
+ }
- flags = SEARCH_FLAG_FORWARDS |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->caseSens)) ?
- SEARCH_FLAG_CASE_SENSITIVE : 0) |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->checkAll)) ?
- SEARCH_FLAG_SHOWALL : 0);
+ browser_window_search(search->bw, search, flags,
+ gtk_entry_get_text(search->entry));
- browser_window_search(bw, gw, flags,
- gtk_entry_get_text(nsgtk_scaffolding_search(g)->entry));
return TRUE;
}
-/** connected to the search entry [return key] */
-
-gboolean nsgtk_search_entry_activate(GtkWidget *widget, gpointer data)
+/**
+ * connected to the search entry [return key]
+ */
+static gboolean nsgtk_search_entry_activate(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- struct gui_window *gw = nsgtk_scaffolding_top_level(g);
- struct browser_window *bw = nsgtk_get_browser_window(gw);
+ struct gtk_search *search;
search_flags_t flags;
- assert(bw);
+ search = (struct gtk_search *)data;
- flags = SEARCH_FLAG_FORWARDS |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->caseSens)) ?
- SEARCH_FLAG_CASE_SENSITIVE : 0) |
- (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(
- nsgtk_scaffolding_search(g)->checkAll)) ?
- SEARCH_FLAG_SHOWALL : 0);
+ flags = SEARCH_FLAG_FORWARDS;
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->caseSens))) {
+ flags |= SEARCH_FLAG_CASE_SENSITIVE;
+ }
+
+ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(search->checkAll))) {
+ flags |= SEARCH_FLAG_SHOWALL;
+ }
+
+ browser_window_search(search->bw, search, flags,
+ gtk_entry_get_text(search->entry));
- browser_window_search(bw, gw, flags,
- gtk_entry_get_text(nsgtk_scaffolding_search(g)->entry));
return FALSE;
}
-/** allows escape key to close search bar too */
-
-gboolean
+/**
+ * allows escape key to close search bar too
+ */
+static gboolean
nsgtk_search_entry_key(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
if (event->keyval == GDK_KEY(Escape)) {
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- nsgtk_scaffolding_toggle_search_bar_visibility(g);
+ struct gtk_search *search;
+ search = (struct gtk_search *)data;
+
+ nsgtk_search_toggle_visibility(search);
}
return FALSE;
}
-/** connected to the websearch entry [return key] */
-gboolean nsgtk_websearch_activate(GtkWidget *widget, gpointer data)
+static struct gui_search_table search_table = {
+ .forward_state = (void *)nsgtk_search_set_forward_state,
+ .back_state = (void *)nsgtk_search_set_back_state,
+};
+
+struct gui_search_table *nsgtk_search_table = &search_table;
+
+
+/* exported interface documented in gtk/scaffolding.h */
+nserror nsgtk_search_toggle_visibility(struct gtk_search *search)
{
- struct nsgtk_scaffolding *g = data;
- nserror ret;
- nsurl *url;
-
- ret = search_web_omni(
- gtk_entry_get_text(GTK_ENTRY(nsgtk_scaffolding_websearch(g))),
- SEARCH_WEB_OMNI_SEARCHONLY,
- &url);
- if (ret == NSERROR_OK) {
- temp_open_background = 0;
- ret = browser_window_create(
- BW_CREATE_HISTORY | BW_CREATE_TAB,
- url,
- NULL,
- nsgtk_get_browser_window(nsgtk_scaffolding_top_level(g)),
- NULL);
- temp_open_background = -1;
- nsurl_unref(url);
- }
- if (ret != NSERROR_OK) {
- nsgtk_warning(messages_get_errorcode(ret), 0);
+ gboolean vis;
+
+ browser_window_search_clear(search->bw);
+
+ g_object_get(G_OBJECT(search->bar), "visible", &vis, NULL);
+ if (vis) {
+ gtk_widget_hide(GTK_WIDGET(search->bar));
+ } else {
+ gtk_widget_show(GTK_WIDGET(search->bar));
+ gtk_widget_grab_focus(GTK_WIDGET(search->entry));
+ nsgtk_search_entry_changed(GTK_WIDGET(search->entry), search);
}
- return TRUE;
+ return NSERROR_OK;
}
-/**
- * allows a click in the websearch entry field to clear the name of the
- * provider
- */
-gboolean nsgtk_websearch_clear(GtkWidget *widget, GdkEventFocus *f,
- gpointer data)
+/* exported interface documented in gtk/search.h */
+nserror nsgtk_search_restyle(struct gtk_search *search)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- gtk_editable_select_region(GTK_EDITABLE(
- nsgtk_scaffolding_websearch(g)), 0, -1);
- gtk_widget_grab_focus(GTK_WIDGET(nsgtk_scaffolding_websearch(g)));
- return TRUE;
+ switch (nsoption_int(button_type)) {
+
+ case 1: /* Small icons */
+ gtk_toolbar_set_style(GTK_TOOLBAR(search->bar),
+ GTK_TOOLBAR_ICONS);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(search->bar),
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
+ break;
+
+ case 2: /* Large icons */
+ gtk_toolbar_set_style(GTK_TOOLBAR(search->bar),
+ GTK_TOOLBAR_ICONS);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(search->bar),
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ break;
+
+ case 3: /* Large icons with text */
+ gtk_toolbar_set_style(GTK_TOOLBAR(search->bar),
+ GTK_TOOLBAR_BOTH);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(search->bar),
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ break;
+
+ case 4: /* Text icons only */
+ gtk_toolbar_set_style(GTK_TOOLBAR(search->bar),
+ GTK_TOOLBAR_TEXT);
+ break;
+
+ default:
+ break;
+ }
+ return NSERROR_OK;
}
+/* exported interface documented in gtk/search.h */
+nserror
+nsgtk_search_create(GtkBuilder *builder,
+ struct browser_window *bw,
+ struct gtk_search **search_out)
+{
+ struct gtk_search *search;
-static struct gui_search_table search_table = {
- .forward_state = (void *)nsgtk_search_set_forward_state,
- .back_state = (void *)nsgtk_search_set_back_state,
-};
+ search = malloc(sizeof(struct gtk_search));
+ if (search == NULL) {
+ return NSERROR_NOMEM;
+ }
-struct gui_search_table *nsgtk_search_table = &search_table;
+ search->bw = bw;
+
+ search->bar = GTK_TOOLBAR(gtk_builder_get_object(builder, "findbar"));
+ search->entry = GTK_ENTRY(gtk_builder_get_object(builder, "Find"));
+ search->back = GTK_TOOL_BUTTON(gtk_builder_get_object(builder,
+ "FindBack"));
+ search->forward = GTK_TOOL_BUTTON(gtk_builder_get_object(builder,
+ "FindForward"));
+ search->close = GTK_TOOL_BUTTON(gtk_builder_get_object(builder,
+ "FindClose"));
+ search->checkAll = GTK_CHECK_BUTTON(gtk_builder_get_object(builder,
+ "FindHighlightAll"));
+ search->caseSens = GTK_CHECK_BUTTON(gtk_builder_get_object(builder,
+ "FindMatchCase"));
+
+ g_signal_connect(search->forward,
+ "clicked",
+ G_CALLBACK(nsgtk_search_forward_button_clicked),
+ search);
+
+ g_signal_connect(search->back,
+ "clicked",
+ G_CALLBACK(nsgtk_search_back_button_clicked),
+ search);
+
+ g_signal_connect(search->entry,
+ "changed",
+ G_CALLBACK(nsgtk_search_entry_changed),
+ search);
+
+ g_signal_connect(search->entry,
+ "activate",
+ G_CALLBACK(nsgtk_search_entry_activate),
+ search);
+
+ g_signal_connect(search->entry,
+ "key-press-event",
+ G_CALLBACK(nsgtk_search_entry_key),
+ search);
+
+ g_signal_connect(search->close,
+ "clicked",
+ G_CALLBACK(nsgtk_search_close_button_clicked),
+ search);
+
+ g_signal_connect(search->caseSens,
+ "toggled",
+ G_CALLBACK(nsgtk_search_entry_changed),
+ search);
+
+ g_signal_connect(search->checkAll,
+ "toggled",
+ G_CALLBACK(nsgtk_search_entry_changed),
+ search);
+
+ nsgtk_search_restyle(search);
+
+
+ *search_out = search;
+
+ return NSERROR_OK;
+}
diff --git a/frontends/gtk/search.h b/frontends/gtk/search.h
index dd8c60d0f..5eb0b35cc 100644
--- a/frontends/gtk/search.h
+++ b/frontends/gtk/search.h
@@ -16,21 +16,36 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_GTK_SEARCH_H_
-#define _NETSURF_GTK_SEARCH_H_
-
-struct gui_search_table *nsgtk_search_table;
-
-struct nsgtk_scaffolding;
-
-void nsgtk_search_bar_toggle_visibility(struct nsgtk_scaffolding * g);
-gboolean nsgtk_search_entry_changed(GtkWidget *widget, gpointer data);
-gboolean nsgtk_search_entry_activate(GtkWidget *widget, gpointer data);
-gboolean nsgtk_search_entry_key(GtkWidget *widget, GdkEventKey *event, gpointer data);
-gboolean nsgtk_search_forward_button_clicked(GtkWidget *widget, gpointer data);
-gboolean nsgtk_search_back_button_clicked(GtkWidget *widget, gpointer data);
-gboolean nsgtk_search_close_button_clicked(GtkWidget *widget, gpointer data);
-gboolean nsgtk_websearch_activate(GtkWidget *widget, gpointer data);
-gboolean nsgtk_websearch_clear(GtkWidget *widget, GdkEventFocus *f, gpointer data);
-
+/**
+ * \file
+ * free text page search for gtk interface
+ */
+
+#ifndef NETSURF_GTK_SEARCH_H_
+#define NETSURF_GTK_SEARCH_H_
+
+extern struct gui_search_table *nsgtk_search_table;
+
+struct gtk_search;
+
+/**
+ * create text search context
+ *
+ * \param builder the gtk builder containing the search toolbar
+ * \param bw The browsing context to run the find operations against
+ * \param search search context result
+ * \return NSERROR_OK and search_out updated
+ */
+nserror nsgtk_search_create(GtkBuilder *builder, struct browser_window *bw, struct gtk_search **search);
+
+/**
+ * update search toolbar size and style
+ */
+nserror nsgtk_search_restyle(struct gtk_search *search);
+
+/**
+ * toggle search bar visibility
+ */
+nserror nsgtk_search_toggle_visibility(struct gtk_search *search);
+
#endif
diff --git a/frontends/gtk/selection.c b/frontends/gtk/selection.c
index 228d65dbe..871526047 100644
--- a/frontends/gtk/selection.c
+++ b/frontends/gtk/selection.c
@@ -24,6 +24,7 @@
#include "netsurf/browser_window.h"
#include "netsurf/clipboard.h"
+#include "gtk/toolbar_items.h"
#include "gtk/window.h"
static GString *current_selection = NULL;
diff --git a/frontends/gtk/selection.h b/frontends/gtk/selection.h
index 6463692cf..07716a0d9 100644
--- a/frontends/gtk/selection.h
+++ b/frontends/gtk/selection.h
@@ -19,6 +19,6 @@
#ifndef GTK_SELECTION_H
#define GTK_SELECTION_H
-struct gui_clipboard_table *nsgtk_clipboard_table;
+extern struct gui_clipboard_table *nsgtk_clipboard_table;
#endif
diff --git a/frontends/gtk/ssl_cert.c b/frontends/gtk/ssl_cert.c
deleted file mode 100644
index 9d98db1f6..000000000
--- a/frontends/gtk/ssl_cert.c
+++ /dev/null
@@ -1,259 +0,0 @@
-/*
- * Copyright 2015 Vincent Sanders <vince@netsurf-browser.org>
- *
- * This file is part of NetSurf, http://www.netsurf-browser.org/
- *
- * NetSurf is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * NetSurf is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * \file
- * Implementation of gtk certificate viewing using gtk core windows.
- */
-
-#include <stdint.h>
-#include <stdlib.h>
-#include <gtk/gtk.h>
-
-#include "utils/log.h"
-#include "netsurf/keypress.h"
-#include "netsurf/plotters.h"
-#include "desktop/sslcert_viewer.h"
-
-#include "gtk/plotters.h"
-#include "gtk/scaffolding.h"
-#include "gtk/resources.h"
-#include "gtk/ssl_cert.h"
-#include "gtk/corewindow.h"
-
-
-/**
- * GTK certificate viewing window context
- */
-struct nsgtk_crtvrfy_window {
- /** GTK core window context */
- struct nsgtk_corewindow core;
- /** GTK builder for window */
- GtkBuilder *builder;
- /** GTK dialog window being shown */
- GtkDialog *dlg;
- /** SSL certificate viewer context data */
- struct sslcert_session_data *ssl_data;
-};
-
-/**
- * destroy a previously created certificate view
- */
-static nserror nsgtk_crtvrfy_destroy(struct nsgtk_crtvrfy_window *crtvrfy_win)
-{
- nserror res;
-
- res = sslcert_viewer_fini(crtvrfy_win->ssl_data);
- if (res == NSERROR_OK) {
- res = nsgtk_corewindow_fini(&crtvrfy_win->core);
- gtk_widget_destroy(GTK_WIDGET(crtvrfy_win->dlg));
- g_object_unref(G_OBJECT(crtvrfy_win->builder));
- free(crtvrfy_win);
- }
- return res;
-}
-
-static void
-nsgtk_crtvrfy_accept(GtkButton *w, gpointer data)
-{
- struct nsgtk_crtvrfy_window *crtvrfy_win;
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)data;
-
- sslcert_viewer_accept(crtvrfy_win->ssl_data);
-
- nsgtk_crtvrfy_destroy(crtvrfy_win);
-}
-
-static void
-nsgtk_crtvrfy_reject(GtkWidget *w, gpointer data)
-{
- struct nsgtk_crtvrfy_window *crtvrfy_win;
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)data;
-
- sslcert_viewer_reject(crtvrfy_win->ssl_data);
-
- nsgtk_crtvrfy_destroy(crtvrfy_win);
-}
-
-static gboolean
-nsgtk_crtvrfy_delete_event(GtkWidget *w, GdkEvent *event, gpointer data)
-{
- nsgtk_crtvrfy_reject(w, data);
- return FALSE;
-}
-
-/**
- * callback for mouse action for certificate verify on core window
- *
- * \param nsgtk_cw The nsgtk core window structure.
- * \param mouse_state netsurf mouse state on event
- * \param x location of event
- * \param y location of event
- * \return NSERROR_OK on success otherwise appropriate error code
- */
-static nserror
-nsgtk_crtvrfy_mouse(struct nsgtk_corewindow *nsgtk_cw,
- browser_mouse_state mouse_state,
- int x, int y)
-{
- struct nsgtk_crtvrfy_window *crtvrfy_win;
- /* technically degenerate container of */
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)nsgtk_cw;
-
- sslcert_viewer_mouse_action(crtvrfy_win->ssl_data, mouse_state, x, y);
-
- return NSERROR_OK;
-}
-
-/**
- * callback for keypress for certificate verify on core window
- *
- * \param nsgtk_cw The nsgtk core window structure.
- * \param nskey The netsurf key code
- * \return NSERROR_OK on success otherwise appropriate error code
- */
-static nserror
-nsgtk_crtvrfy_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
-{
- struct nsgtk_crtvrfy_window *crtvrfy_win;
-
- /* technically degenerate container of */
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)nsgtk_cw;
-
- if (sslcert_viewer_keypress(crtvrfy_win->ssl_data, nskey)) {
- return NSERROR_OK;
- }
- return NSERROR_NOT_IMPLEMENTED;
-}
-
-/**
- * callback on draw event for certificate verify on core window
- *
- * \param nsgtk_cw The nsgtk core window structure.
- * \param r The rectangle of the window that needs updating.
- * \return NSERROR_OK on success otherwise appropriate error code
- */
-static nserror
-nsgtk_crtvrfy_draw(struct nsgtk_corewindow *nsgtk_cw, struct rect *r)
-{
- struct redraw_context ctx = {
- .interactive = true,
- .background_images = true,
- .plot = &nsgtk_plotters
- };
- struct nsgtk_crtvrfy_window *crtvrfy_win;
-
- /* technically degenerate container of */
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)nsgtk_cw;
-
- sslcert_viewer_redraw(crtvrfy_win->ssl_data, 0, 0, r, &ctx);
-
- return NSERROR_OK;
-}
-
-/* exported interface documented in gtk/ssl_cert.h */
-nserror gtk_cert_verify(struct nsurl *url,
- const struct ssl_cert_info *certs,
- unsigned long num,
- nserror (*cb)(bool proceed, void *pw),
- void *cbpw)
-{
- struct nsgtk_crtvrfy_window *ncwin;
- nserror res;
-
- ncwin = malloc(sizeof(struct nsgtk_crtvrfy_window));
- if (ncwin == NULL) {
- return NSERROR_NOMEM;
- }
-
- res = nsgtk_builder_new_from_resname("ssl", &ncwin->builder);
- if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "SSL UI builder init failed");
- free(ncwin);
- return res;
- }
-
- gtk_builder_connect_signals(ncwin->builder, NULL);
-
- ncwin->dlg = GTK_DIALOG(gtk_builder_get_object(ncwin->builder,
- "wndSSLProblem"));
-
- /* set parent for transient dialog */
- gtk_window_set_transient_for(GTK_WINDOW(ncwin->dlg),
- nsgtk_scaffolding_window(nsgtk_current_scaffolding()));
-
- ncwin->core.scrolled = GTK_SCROLLED_WINDOW(
- gtk_builder_get_object(ncwin->builder, "SSLScrolled"));
-
- ncwin->core.drawing_area = GTK_DRAWING_AREA(
- gtk_builder_get_object(ncwin->builder, "SSLDrawingArea"));
-
- /* make the delete event call our destructor */
- g_signal_connect(G_OBJECT(ncwin->dlg),
- "delete_event",
- G_CALLBACK(nsgtk_crtvrfy_delete_event),
- ncwin);
-
- /* accept button */
- g_signal_connect(G_OBJECT(gtk_builder_get_object(ncwin->builder,
- "sslaccept")),
- "clicked",
- G_CALLBACK(nsgtk_crtvrfy_accept),
- ncwin);
-
- /* reject button */
- g_signal_connect(G_OBJECT(gtk_builder_get_object(ncwin->builder,
- "sslreject")),
- "clicked",
- G_CALLBACK(nsgtk_crtvrfy_reject),
- ncwin);
-
- /* initialise GTK core window */
- ncwin->core.draw = nsgtk_crtvrfy_draw;
- ncwin->core.key = nsgtk_crtvrfy_key;
- ncwin->core.mouse = nsgtk_crtvrfy_mouse;
-
- res = nsgtk_corewindow_init(&ncwin->core);
- if (res != NSERROR_OK) {
- g_object_unref(G_OBJECT(ncwin->dlg));
- free(ncwin);
- return res;
- }
-
- /* initialise certificate viewing interface */
- res = sslcert_viewer_create_session_data(num, url, cb, cbpw, certs,
- &ncwin->ssl_data);
- if (res != NSERROR_OK) {
- g_object_unref(G_OBJECT(ncwin->dlg));
- free(ncwin);
- return res;
- }
-
- res = sslcert_viewer_init(ncwin->core.cb_table,
- (struct core_window *)ncwin,
- ncwin->ssl_data);
- if (res != NSERROR_OK) {
- g_object_unref(G_OBJECT(ncwin->dlg));
- free(ncwin);
- return res;
- }
-
- gtk_widget_show(GTK_WIDGET(ncwin->dlg));
-
- return NSERROR_OK;
-}
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 */
diff --git a/frontends/gtk/tabs.h b/frontends/gtk/tabs.h
index 440d61336..63edae3cc 100644
--- a/frontends/gtk/tabs.h
+++ b/frontends/gtk/tabs.h
@@ -16,24 +16,58 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_GTK_TABS_H_
-#define _NETSURF_GTK_TABS_H_
+#ifndef NETSURF_GTK_TABS_H_
+#define NETSURF_GTK_TABS_H_
struct gui_window;
-void nsgtk_tab_init(struct nsgtk_scaffolding *gs);
-void nsgtk_tab_add(struct gui_window *window, GtkWidget *tab_contents, bool background);
+/**
+ * create notebook
+ *
+ * creates a notebook for use inside a window, creates the special add
+ * page(tab) and attaches all signals.
+ *
+ * \param builder the gtk builder object to create notbook from
+ * \param notebook_out reciveds the created notebook
+ * \return NSERROR_OK and notebook_out updated else error code
+ */
+nserror nsgtk_notebook_create(GtkBuilder *builder, GtkNotebook **notebook_out);
+
+/**
+ * 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
+
+/**
+ * set the tab title
*
* The tab title will be set to the parameter
*
* \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.
+ */
+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 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.
*/
-void nsgtk_tab_set_title(struct gui_window *g, const char *title);
+nserror nsgtk_tab_set_icon(GtkWidget *page, GdkPixbuf *pixbuf);
+
void nsgtk_tab_options_changed(GtkNotebook *notebook);
nserror nsgtk_tab_close_current(GtkNotebook *notebook);
nserror nsgtk_tab_prev(GtkNotebook *notebook);
diff --git a/frontends/gtk/throbber.c b/frontends/gtk/throbber.c
index b8efceca1..f94893bef 100644
--- a/frontends/gtk/throbber.c
+++ b/frontends/gtk/throbber.c
@@ -28,7 +28,16 @@
#include "gtk/resources.h"
#include "gtk/throbber.h"
-struct nsgtk_throbber *nsgtk_throbber = NULL;
+/**
+ * Throbber images context
+ */
+struct nsgtk_throbber
+{
+ int nframes; /**< Number of frames in the throbber */
+ GdkPixbuf **framedata; /* pixbuf data for the frames */
+};
+
+static struct nsgtk_throbber *nsgtk_throbber = NULL;
#define THROBBER_FRAMES 9
#define THROBBER_FMT "throbber/throbber%d.png"
@@ -36,10 +45,10 @@ struct nsgtk_throbber *nsgtk_throbber = NULL;
/* exported interface documented in gtk/throbber.h */
nserror nsgtk_throbber_init(void)
{
- struct nsgtk_throbber *throb; /**< structure we generate */
+ nserror res = NSERROR_OK;
+ struct nsgtk_throbber *throb;
int frame;
char resname[] = THROBBER_FMT;
- nserror res = NSERROR_OK;
throb = malloc(sizeof(*throb));
if (throb == NULL) {
@@ -49,7 +58,7 @@ nserror nsgtk_throbber_init(void)
throb->framedata = malloc(sizeof(GdkPixbuf *) * THROBBER_FRAMES);
if (throb->framedata == NULL) {
free(throb);
- return false;
+ return NSERROR_NOMEM;
}
for (frame = 0; frame < THROBBER_FRAMES; frame++) {
@@ -73,11 +82,9 @@ nserror nsgtk_throbber_init(void)
throb->nframes = frame;
nsgtk_throbber = throb;
return res;
-
-
}
-
+/* exported interface documented in gtk/throbber.h */
void nsgtk_throbber_finalise(void)
{
int i;
@@ -91,3 +98,30 @@ void nsgtk_throbber_finalise(void)
nsgtk_throbber = NULL;
}
+
+/* exported interface documented in gtk/throbber.h */
+nserror nsgtk_throbber_get_frame(int frame, GdkPixbuf **pixbuf)
+{
+ nserror res = NSERROR_OK;
+
+ /* ensure initialisation */
+ if (nsgtk_throbber == NULL) {
+ res = nsgtk_throbber_init();
+ }
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* ensure frame in range */
+ if ((frame < 0) || (frame >= nsgtk_throbber->nframes)) {
+ return NSERROR_BAD_SIZE;
+ }
+
+ /* ensure there is frame data */
+ if (nsgtk_throbber->framedata[frame] == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ *pixbuf = nsgtk_throbber->framedata[frame];
+ return NSERROR_OK;
+}
diff --git a/frontends/gtk/throbber.h b/frontends/gtk/throbber.h
index e0b47e15c..c8529d2e2 100644
--- a/frontends/gtk/throbber.h
+++ b/frontends/gtk/throbber.h
@@ -16,20 +16,27 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef __GTK_THROBBER_H__
-#define __GTK_THROBBER_H__
-
-#include <gtk/gtk.h>
-
-struct nsgtk_throbber
-{
- int nframes; /**< Number of frames in the throbber */
- GdkPixbuf **framedata;
-};
-
-extern struct nsgtk_throbber *nsgtk_throbber;
+#ifndef NETSURF_GTK_THROBBER_H
+#define NETSURF_GTK_THROBBER_H
+/**
+ * Initialise global throbber context
+ */
nserror nsgtk_throbber_init(void);
+
+/**
+ * release global throbber context
+ */
void nsgtk_throbber_finalise(void);
-#endif /* __GTK_THROBBER_H__ */
+/**
+ * get the pixbuf of a given frame of the throbber
+ *
+ * \param frame The frame number starting at 0 for stopped frame
+ * \param pixbuf updated on success
+ * \return NSERROR_OK and pixbuf updated on success, NSERROR_BAD_SIZE if frame
+ * is out of range else error code.
+ */
+nserror nsgtk_throbber_get_frame(int frame, GdkPixbuf **pixbuf);
+
+#endif /* NETSURF_GTK_THROBBER_H */
diff --git a/frontends/gtk/toolbar.c b/frontends/gtk/toolbar.c
index e93bd49f9..6ec41cc1d 100644
--- a/frontends/gtk/toolbar.c
+++ b/frontends/gtk/toolbar.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2009 Mark Benjamin <netsurf-browser.org.MarkBenjamin@dfgh.net>
+ * Copyright 2019 Vincent Sanders <vince@netsurf-browser.org>
*
* This file is part of NetSurf, http://www.netsurf-browser.org/
*
@@ -16,18 +16,36 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/**
+ * \file
+ * implementation of toolbar to control browsing context
+ */
+
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <errno.h>
#include <gtk/gtk.h>
-#include "netsurf/browser_window.h"
-#include "desktop/searchweb.h"
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/nsoption.h"
#include "utils/file.h"
+#include "utils/nsurl.h"
+#include "utils/corestrings.h"
+#include "desktop/browser_history.h"
+#include "desktop/searchweb.h"
+#include "desktop/search.h"
+#include "desktop/save_complete.h"
+#include "desktop/save_text.h"
+#include "desktop/print.h"
+#include "desktop/hotlist.h"
+#include "netsurf/content.h"
+#include "netsurf/browser_window.h"
+#include "netsurf/keypress.h"
+#include "gtk/toolbar_items.h"
+#include "gtk/completion.h"
#include "gtk/gui.h"
#include "gtk/warn.h"
#include "gtk/search.h"
@@ -36,63 +54,203 @@
#include "gtk/window.h"
#include "gtk/compat.h"
#include "gtk/resources.h"
+#include "gtk/schedule.h"
+#include "gtk/local_history.h"
+#include "gtk/global_history.h"
+#include "gtk/viewsource.h"
+#include "gtk/download.h"
+#include "gtk/viewdata.h"
+#include "gtk/tabs.h"
+#include "gtk/print.h"
+#include "gtk/layout_pango.h"
+#include "gtk/preferences.h"
+#include "gtk/hotlist.h"
+#include "gtk/cookies.h"
+#include "gtk/about.h"
+#include "gtk/gdk.h"
+#include "gtk/bitmap.h"
+#include "gtk/page_info.h"
#include "gtk/toolbar.h"
-static GtkTargetEntry entry = {(char *)"nsgtk_button_data",
- GTK_TARGET_SAME_APP, 0};
-
-static bool edit_mode = false;
-
-struct nsgtk_toolbar_custom_store {
- GtkWidget *window;
- GtkWidget *store_buttons[PLACEHOLDER_BUTTON];
- GtkWidget *widgetvbox;
- GtkWidget *currentbar;
- char numberh; /* current horizontal location while adding */
- GtkBuilder *builder; /* button widgets to store */
- int buttonlocations[PLACEHOLDER_BUTTON];
- int currentbutton;
- bool fromstore;
-};
-/* the number of buttons that fit in the width of the store window */
-#define NSGTK_STORE_WIDTH 6
+/**
+ * button location indicating button is not to be shown
+ */
+#define INACTIVE_LOCATION (-1)
-/* the 'standard' width of a button that makes sufficient of its label
-visible */
-#define NSGTK_BUTTON_WIDTH 111
+/**
+ * time (in ms) between throbber animation frame updates
+ */
+#define THROBBER_FRAME_TIME (100)
-/* the 'standard' height of a button that fits as many toolbars as
-possible into the store */
+/**
+ * the minimum number of columns in the tool store
+ */
+#define NSGTK_MIN_STORE_COLUMNS 4
+
+/**
+ * the 'standard' width of a button that makes sufficient of its label visible
+ */
+#define NSGTK_BUTTON_WIDTH 120
+
+/**
+ * the 'standard' height of a button that fits as many toolbars as
+ * possible into the store
+ */
#define NSGTK_BUTTON_HEIGHT 70
-/* the 'normal' width of the websearch bar */
+/**
+ * the 'normal' width of the websearch bar
+ */
#define NSGTK_WEBSEARCH_WIDTH 150
-static struct nsgtk_toolbar_custom_store store;
-static struct nsgtk_toolbar_custom_store *window = &store;
+/**
+ * toolbar item context
+ */
+struct nsgtk_toolbar_item {
+
+ /**
+ * GTK widget in the toolbar
+ */
+ GtkToolItem *button;
+
+ /**
+ * location index in toolbar
+ */
+ int location;
+
+ /**
+ * if the item is currently sensitive in the toolbar
+ */
+ bool sensitivity;
+
+ /**
+ * textural name used in serialising items
+ */
+ const char *name;
+
+ /**
+ * button clicked on toolbar handler
+ */
+ gboolean (*clicked)(GtkWidget *widget, gpointer data);
+
+ /**
+ * handler when dragging from customisation toolbox to toolbar
+ */
+ void *dataplus;
+
+ /**
+ * handler when dragging from toolbar to customisation toolbox
+ */
+ void *dataminus;
+};
+/**
+ * Location focus state machine
+ *
+ * 1. If we don't care, we're in LFS_IDLE
+ * 2. When we create a new toolbar, we can put it into
+ * LFS_WANT which means that we want the url bar to focus
+ * 3. When we start throbbing if we're in LFS_WANT we move to LFS_THROB
+ * 4. When we stop throbbing, if we're in LFS_THROB we move to LFS_LAST
+ *
+ * While not in LFS_IDLE, if the url bar is updated and we previously had it
+ * fully selected then we reselect it all. If we're in LFS_LAST we move to
+ * LFS_IDLE at that point.
+ */
+typedef enum {
+ LFS_IDLE, /**< Nothing to do */
+ LFS_WANT, /**< Want focus, will apply */
+ LFS_THROB, /**< Want focus, we have started throbbing */
+ LFS_LAST, /**< Last chance for a focus update */
+} nsgtk_toolbar_location_focus_state;
-enum image_sets {
- IMAGE_SET_MAIN_MENU = 0,
- IMAGE_SET_RCLICK_MENU,
- IMAGE_SET_POPUP_MENU,
- IMAGE_SET_BUTTONS,
- IMAGE_SET_COUNT
+/**
+ * control toolbar context
+ */
+struct nsgtk_toolbar {
+ /** gtk toolbar widget */
+ GtkToolbar *widget;
+
+ /* toolbar size allocation context */
+ int offset;
+ int toolbarmem;
+ int toolbarbase;
+ int historybase;
+
+ /**
+ * Toolbar item contexts
+ */
+ struct nsgtk_toolbar_item items[PLACEHOLDER_BUTTON];
+
+ /**
+ * Current frame of throbber animation
+ */
+ int throb_frame;
+
+ /**
+ * Web search widget
+ */
+ GtkWidget *webSearchEntry;
+
+ /**
+ * callback to obtain a browser window for navigation
+ */
+ struct browser_window *(*get_bw)(void *ctx);
+
+ /**
+ * context passed to get_bw function
+ */
+ void *get_ctx;
+
+ /**
+ * Location focus state machine, current state
+ */
+ nsgtk_toolbar_location_focus_state loc_focus;
};
-typedef enum search_buttons {
- SEARCH_BACK_BUTTON = 0,
- SEARCH_FORWARD_BUTTON,
- SEARCH_CLOSE_BUTTON,
- SEARCH_BUTTONS_COUNT
-} nsgtk_search_buttons;
-
-struct nsgtk_theme {
- GtkImage *image[PLACEHOLDER_BUTTON];
- GtkImage *searchimage[SEARCH_BUTTONS_COUNT];
- /* apng throbber element */
+
+/**
+ * toolbar cusomisation context
+ */
+struct nsgtk_toolbar_customisation {
+ /**
+ * first entry is a toolbar widget so a customisation widget
+ * can be cast to toolbar and back.
+ */
+ struct nsgtk_toolbar toolbar;
+
+ /**
+ * The top level container (tabBox)
+ */
+ GtkWidget *container;
+
+ /**
+ * The vertical box into which the available tools are shown
+ */
+ GtkBox *toolbox;
+
+ /**
+ * widget handles for items in the customisation toolbox area
+ */
+ GtkToolItem *items[PLACEHOLDER_BUTTON];
+
+ /**
+ * which item is being dragged
+ */
+ int dragitem; /* currentbutton */
+ /**
+ * true if item being dragged onto toolbar, false if from toolbar
+ */
+ bool dragfrom; /*fromstore */
+
};
+
+/* forward declaration */
+static nserror toolbar_item_create(nsgtk_toolbar_button id,
+ struct nsgtk_toolbar_item *item_out);
+
+
/**
* returns a string without its underscores
*
@@ -122,1372 +280,3608 @@ static char *remove_underscores(const char *s, bool replacespace)
/**
- * get default image for buttons / menu items from gtk stock items.
- *
- * \param tbbutton button reference
- * \param iconsize The size of icons to select.
- * \param usedef Use the default image if not found.
- * \return default images.
- */
-static GtkImage *
-nsgtk_theme_image_default(nsgtk_toolbar_button tbbutton,
- GtkIconSize iconsize,
- bool usedef)
-{
- GtkImage *image; /* The GTK image to return */
-
- switch(tbbutton) {
-
-#define BUTTON_IMAGE(p, q) \
- case p##_BUTTON: \
- image = GTK_IMAGE(nsgtk_image_new_from_stock(q, iconsize)); \
- break
-
- BUTTON_IMAGE(BACK, NSGTK_STOCK_GO_BACK);
- BUTTON_IMAGE(FORWARD, NSGTK_STOCK_GO_FORWARD);
- BUTTON_IMAGE(STOP, NSGTK_STOCK_STOP);
- BUTTON_IMAGE(RELOAD, NSGTK_STOCK_REFRESH);
- BUTTON_IMAGE(HOME, NSGTK_STOCK_HOME);
- BUTTON_IMAGE(NEWWINDOW, "gtk-new");
- BUTTON_IMAGE(NEWTAB, "gtk-new");
- BUTTON_IMAGE(OPENFILE, NSGTK_STOCK_OPEN);
- BUTTON_IMAGE(CLOSETAB, NSGTK_STOCK_CLOSE);
- BUTTON_IMAGE(CLOSEWINDOW, NSGTK_STOCK_CLOSE);
- BUTTON_IMAGE(SAVEPAGE, NSGTK_STOCK_SAVE_AS);
- BUTTON_IMAGE(PRINTPREVIEW, "gtk-print-preview");
- BUTTON_IMAGE(PRINT, "gtk-print");
- BUTTON_IMAGE(QUIT, "gtk-quit");
- BUTTON_IMAGE(CUT, "gtk-cut");
- BUTTON_IMAGE(COPY, "gtk-copy");
- BUTTON_IMAGE(PASTE, "gtk-paste");
- BUTTON_IMAGE(DELETE, "gtk-delete");
- BUTTON_IMAGE(SELECTALL, "gtk-select-all");
- BUTTON_IMAGE(FIND, NSGTK_STOCK_FIND);
- BUTTON_IMAGE(PREFERENCES, "gtk-preferences");
- BUTTON_IMAGE(ZOOMPLUS, "gtk-zoom-in");
- BUTTON_IMAGE(ZOOMMINUS, "gtk-zoom-out");
- BUTTON_IMAGE(ZOOMNORMAL, "gtk-zoom-100");
- BUTTON_IMAGE(FULLSCREEN, "gtk-fullscreen");
- BUTTON_IMAGE(VIEWSOURCE, "gtk-index");
- BUTTON_IMAGE(CONTENTS, "gtk-help");
- BUTTON_IMAGE(ABOUT, "gtk-about");
-#undef BUTTON_IMAGE
+ * create throbber toolbar item widget
+ *
+ * create a gtk entry widget with a completion attached
+ */
+static GtkToolItem *
+make_toolbar_item_throbber(bool sensitivity, bool edit)
+{
+ nserror res;
+ GtkToolItem *item;
+ GdkPixbuf *pixbuf;
+ GtkWidget *image;
- case HISTORY_BUTTON:
- image = GTK_IMAGE(gtk_image_new_from_pixbuf(arrow_down_pixbuf));
- break;
+ res = nsgtk_throbber_get_frame(0, &pixbuf);
+ if (res != NSERROR_OK) {
+ return NULL;
+ }
- default:
- image = NULL;
- break;
+ if (edit) {
+ const char *msg;
+ msg = messages_get("ToolThrob");
+ item = gtk_tool_button_new(
+ GTK_WIDGET(gtk_image_new_from_pixbuf(pixbuf)),
+ msg);
+ } else {
+ item = gtk_tool_item_new();
+
+ image = gtk_image_new_from_pixbuf(pixbuf);
+ if (image != NULL) {
+ nsgtk_widget_set_alignment(image,
+ GTK_ALIGN_CENTER,
+ GTK_ALIGN_CENTER);
+ nsgtk_widget_set_margins(image, 3, 0);
+
+ gtk_container_add(GTK_CONTAINER(item), image);
+ }
+ }
+ gtk_widget_set_sensitive(GTK_WIDGET(item), sensitivity);
+
+ return item;
+}
+
+
+/**
+ * create url bar toolbar item widget
+ *
+ * create a gtk entry widget with a completion attached
+ *
+ * \param sensitivity if the entry should be created sensitive to input
+ * \param edit if the entry should be editable
+ */
+static GtkToolItem *
+make_toolbar_item_url_bar(bool sensitivity, bool edit)
+{
+ GtkToolItem *item;
+ GtkWidget *entry;
+ GtkEntryCompletion *completion;
+
+ entry = nsgtk_entry_new();
+ if (entry == NULL) {
+ return NULL;
}
+ nsgtk_entry_set_icon_from_icon_name(entry,
+ GTK_ENTRY_ICON_PRIMARY,
+ "page-info-internal");
+
+ if (edit) {
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 9);
+
+ item = gtk_tool_button_new(NULL, "URL");
+ gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(item), entry);
+ } else {
+ completion = gtk_entry_completion_new();
+ if (completion != NULL) {
+ gtk_entry_set_completion(GTK_ENTRY(entry), completion);
+ }
+
+ item = gtk_tool_item_new();
+ if (item == NULL) {
+ return NULL;
+ }
+
+ gtk_container_add(GTK_CONTAINER(item), entry);
+ gtk_tool_item_set_expand(item, TRUE);
- if (usedef && (image == NULL)) {
- image = GTK_IMAGE(nsgtk_image_new_from_stock("gtk-missing-image", iconsize));
}
+ gtk_widget_set_sensitive(GTK_WIDGET(item), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(entry), sensitivity);
- return image;
+ return item;
}
+
/**
- * Get default image for search buttons / menu items from gtk stock items
+ * create web search toolbar item widget
+ */
+static GtkToolItem *
+make_toolbar_item_websearch(bool sensitivity, bool edit)
+{
+ GtkToolItem *item;
+ nserror res;
+ GtkWidget *entry;
+ struct bitmap *bitmap;
+ GdkPixbuf *pixbuf = NULL;
+
+ res = search_web_get_provider_bitmap(&bitmap);
+ if ((res == NSERROR_OK) && (bitmap != NULL)) {
+ pixbuf = nsgdk_pixbuf_get_from_surface(bitmap->surface, 32, 32);
+ }
+
+ entry = nsgtk_entry_new();
+
+ if (entry == NULL) {
+ return NULL;
+ }
+
+ if (pixbuf != NULL) {
+ nsgtk_entry_set_icon_from_pixbuf(entry,
+ GTK_ENTRY_ICON_PRIMARY,
+ pixbuf);
+ g_object_unref(pixbuf);
+ } else {
+ nsgtk_entry_set_icon_from_icon_name(entry,
+ GTK_ENTRY_ICON_PRIMARY,
+ NSGTK_STOCK_INFO);
+ }
+
+ if (edit) {
+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 9);
+
+ item = gtk_tool_button_new(NULL, "Web Search");
+ gtk_tool_button_set_icon_widget(GTK_TOOL_BUTTON(item),
+ entry);
+ } else {
+ gtk_widget_set_size_request(entry, NSGTK_WEBSEARCH_WIDTH, -1);
+
+ item = gtk_tool_item_new();
+ if (item == NULL) {
+ return NULL;
+ }
+
+ gtk_container_add(GTK_CONTAINER(item), entry);
+ }
+ gtk_widget_set_sensitive(GTK_WIDGET(item), TRUE);
+ gtk_widget_set_sensitive(GTK_WIDGET(entry), sensitivity);
+
+ return item;
+}
+
+
+/**
+ * create local history toolbar item widget
+ */
+static GtkToolItem *
+make_toolbar_item_history(bool sensitivity, bool edit)
+{
+ GtkToolItem *item;
+ const char *msg = "H";
+ char *label = NULL;
+
+ if (edit) {
+ msg = messages_get("gtkLocalHistory");
+ }
+ label = remove_underscores(msg, false);
+ item = gtk_tool_button_new(NULL, label);
+ if (label != NULL) {
+ free(label);
+ }
+ gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), "local-history");
+
+ /* set history widget minimum width */
+ gtk_widget_set_size_request(GTK_WIDGET(item), 20, -1);
+ gtk_widget_set_sensitive(GTK_WIDGET(item), sensitivity);
+
+ return item;
+}
+
+
+/**
+ * create generic button toolbar item widget
+ */
+static GtkToolItem *
+make_toolbar_item_button(const char *labelmsg,
+ const char *iconname,
+ bool sensitivity,
+ bool edit)
+{
+ GtkToolItem *item;
+ char *label = NULL;
+
+ label = remove_underscores(messages_get(labelmsg), false);
+
+ item = gtk_tool_button_new(NULL, label);
+ if (label != NULL) {
+ free(label);
+ }
+
+ if (item != NULL) {
+ gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(item), iconname);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(item), sensitivity);
+ if (edit) {
+ nsgtk_widget_set_margins(GTK_WIDGET(item), 0, 0);
+ }
+ }
+
+ return item;
+}
+
+
+/**
+ * widget factory for creation of toolbar item widgets
*
- * \param tbbutton search button reference
- * \param iconsize The size of icons to select.
- * \param usedef Use the default image if not found.
- * \return default search image.
+ * \param i the id of the widget
+ * \param theme the theme to make the widgets from
+ * \return gtk widget
*/
+static GtkToolItem *
+make_toolbar_item(nsgtk_toolbar_button itemid, bool sensitivity)
+{
+ GtkToolItem *toolitem = NULL;
+
+ switch(itemid) {
+#define TOOLBAR_ITEM_y(identifier, label, iconame)
+#define TOOLBAR_ITEM_n(identifier, label, iconame)
+#define TOOLBAR_ITEM_t(identifier, label, iconame) \
+ case identifier: \
+ toolitem = make_toolbar_item_button(#label, iconame, sensitivity, false); \
+ break;
+#define TOOLBAR_ITEM_b(identifier, label, iconame) \
+ case identifier: \
+ toolitem = make_toolbar_item_button(#label, iconame, sensitivity, false); \
+ break;
+#define TOOLBAR_ITEM(identifier, name, snstvty, clicked, activate, label, iconame) \
+ TOOLBAR_ITEM_ ## clicked(identifier, label, iconame)
+
+#include "gtk/toolbar_items.h"
+
+#undef TOOLBAR_ITEM_t
+#undef TOOLBAR_ITEM_b
+#undef TOOLBAR_ITEM_n
+#undef TOOLBAR_ITEM_y
+#undef TOOLBAR_ITEM
+
+ case HISTORY_BUTTON:
+ toolitem = make_toolbar_item_history(sensitivity, false);
+ break;
+
+ case URL_BAR_ITEM:
+ toolitem = make_toolbar_item_url_bar(sensitivity, false);
+ break;
-static GtkImage *
-nsgtk_theme_searchimage_default(nsgtk_search_buttons tbbutton,
- GtkIconSize iconsize,
- bool usedef)
+ case THROBBER_ITEM:
+ toolitem = make_toolbar_item_throbber(sensitivity, false);
+ break;
+
+ case WEBSEARCH_ITEM:
+ toolitem = make_toolbar_item_websearch(sensitivity, false);
+ break;
+
+ default:
+ break;
+
+ }
+ return toolitem;
+}
+
+
+/**
+ * widget factory for creation of toolbar item widgets for the toolbox
+ *
+ * \param itemid the id of the widget
+ * \return gtk tool item widget
+ */
+static GtkToolItem *
+make_toolbox_item(nsgtk_toolbar_button itemid, bool bar)
{
- GtkImage *image;
+ GtkToolItem *toolitem = NULL;
+
+ switch(itemid) {
+#define TOOLBAR_ITEM_y(identifier, label, iconame)
+#define TOOLBAR_ITEM_n(identifier, label, iconame)
+#define TOOLBAR_ITEM_t(identifier, label, iconame) \
+ case identifier: \
+ if (bar) { \
+ toolitem = make_toolbar_item_button(#label, iconame, true, true); \
+ } \
+ break;
+#define TOOLBAR_ITEM_b(identifier, label, iconame) \
+ case identifier: \
+ toolitem = make_toolbar_item_button(#label, iconame, true, true); \
+ break;
+#define TOOLBAR_ITEM(identifier, name, snstvty, clicked, activate, label, iconame) \
+ TOOLBAR_ITEM_ ## clicked(identifier, label, iconame)
+
+#include "gtk/toolbar_items.h"
- switch (tbbutton) {
+#undef TOOLBAR_ITEM_t
+#undef TOOLBAR_ITEM_b
+#undef TOOLBAR_ITEM_n
+#undef TOOLBAR_ITEM_y
+#undef TOOLBAR_ITEM
+
+ case HISTORY_BUTTON:
+ toolitem = make_toolbar_item_history(true, true);
+ break;
- case (SEARCH_BACK_BUTTON):
- image = GTK_IMAGE(nsgtk_image_new_from_stock(
- NSGTK_STOCK_GO_BACK, iconsize));
+ case URL_BAR_ITEM:
+ toolitem = make_toolbar_item_url_bar(false, true);
break;
- case (SEARCH_FORWARD_BUTTON):
- image = GTK_IMAGE(nsgtk_image_new_from_stock(
- NSGTK_STOCK_GO_FORWARD, iconsize));
+ case THROBBER_ITEM:
+ toolitem = make_toolbar_item_throbber(true, true);
break;
- case (SEARCH_CLOSE_BUTTON):
- image = GTK_IMAGE(nsgtk_image_new_from_stock(
- NSGTK_STOCK_CLOSE, iconsize));
+ case WEBSEARCH_ITEM:
+ toolitem = make_toolbar_item_websearch(false, true);
break;
default:
- image = NULL;
+ break;
+
}
+ return toolitem;
+}
+
+
+/**
+ * target entry for drag source
+ */
+static GtkTargetEntry target_entry = {
+ (char *)"nsgtk_button_data",
+ GTK_TARGET_SAME_APP,
+ 0
+};
+
- if (usedef && (image == NULL)) {
- image = GTK_IMAGE(nsgtk_image_new_from_stock(
- "gtk-missing-image", iconsize));
+/**
+ * find the toolbar item with a given location.
+ *
+ * \param tb the toolbar instance
+ * \param locaction the location to search for
+ * \return the item id for a location
+ */
+static nsgtk_toolbar_button
+itemid_from_location(struct nsgtk_toolbar *tb, int location)
+{
+ int iidx;
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ if (tb->items[iidx].location == location) {
+ break;
+ }
}
+ return iidx;
+}
+
- return image;
+/**
+ * save toolbar settings to file
+ */
+static nserror
+nsgtk_toolbar_customisation_save(struct nsgtk_toolbar *tb)
+{
+ int iidx; /* item index */
+ char *order; /* item ordering */
+ char *start; /* start of next item name to be output */
+ int orderlen = 0; /* length of item ordering */
+ nsgtk_toolbar_button itemid;
+ int location;
+ char *choices = NULL;
+
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ if (tb->items[iidx].location != INACTIVE_LOCATION) {
+ orderlen += strlen(tb->items[iidx].name);
+ orderlen++; /* allow for separator */
+ }
+ }
+
+ /* ensure there are some items to store */
+ if (orderlen == 0) {
+ return NSERROR_INVALID;
+ }
+
+ order = malloc(orderlen);
+ if (order == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ start = order;
+
+ for (location = BACK_BUTTON;
+ location < PLACEHOLDER_BUTTON;
+ location++) {
+ int written;
+ itemid = itemid_from_location(tb, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ /* no more filled locations */
+ break;
+ }
+ written = snprintf(start,
+ orderlen - (start - order),
+ "%s/",
+ tb->items[itemid].name);
+ if ((written < 0) ||
+ (written >= orderlen - (start - order))) {
+ free(order);
+ return NSERROR_UNKNOWN;
+ }
+ start += written;
+
+ if ((start - order) >= orderlen) {
+ break;
+ }
+ }
+
+ order[orderlen - 1] = 0;
+
+ nsoption_set_charp(toolbar_items, order);
+
+ /* ensure choices are saved */
+ netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
+ if (choices != NULL) {
+ nsoption_write(choices, NULL, NULL);
+ free(choices);
+ }
+
+ return NSERROR_OK;
}
+
/**
- * initialise a theme structure with gtk images
+ * connect signals to a toolbar item in a customisation toolbar
*
- * \param iconsize The size of icon to load
- * \param usedef use the default gtk icon if unset
+ * \param tb The toolbar
+ * \param itemid The item id within to toolbar to connect
+ * \param NSERROR_OK on success
*/
-static struct nsgtk_theme *nsgtk_theme_load(GtkIconSize iconsize, bool usedef)
+static nserror
+toolbar_item_connect_signals(struct nsgtk_toolbar *tb, int itemid)
{
- struct nsgtk_theme *theme;
- int btnloop;
+ /* set toolbar items to be a drag source */
+ gtk_tool_item_set_use_drag_window(tb->items[itemid].button, TRUE);
+ gtk_drag_source_set(GTK_WIDGET(tb->items[itemid].button),
+ GDK_BUTTON1_MASK,
+ &target_entry,
+ 1,
+ GDK_ACTION_COPY);
+ g_signal_connect(tb->items[itemid].button,
+ "drag-data-get",
+ G_CALLBACK(tb->items[itemid].dataminus),
+ tb);
+ return NSERROR_OK;
+}
- theme = malloc(sizeof(struct nsgtk_theme));
- if (theme == NULL) {
- return NULL;
+
+/**
+ * customisation container handler for drag drop signal
+ *
+ * called when a widget is dropped onto the store window
+ */
+static gboolean
+customisation_container_drag_drop_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ gint x, gint y,
+ guint time,
+ gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ tbc = (struct nsgtk_toolbar_customisation *)data;
+ int location;
+ int itemid;
+
+ if ((tbc->dragfrom) || (tbc->dragitem == -1)) {
+ tbc->dragitem = -1;
+ return FALSE;
}
- for (btnloop = BACK_BUTTON;
- btnloop < PLACEHOLDER_BUTTON ;
- btnloop++) {
- theme->image[btnloop] = nsgtk_theme_image_default(btnloop,
- iconsize,
- usedef);
+ if (tbc->toolbar.items[tbc->dragitem].location == INACTIVE_LOCATION) {
+ tbc->dragitem = -1;
+ gtk_drag_finish(gdc, TRUE, TRUE, time);
+ return FALSE;
+
}
- for (btnloop = SEARCH_BACK_BUTTON;
- btnloop < SEARCH_BUTTONS_COUNT;
- btnloop++) {
- theme->searchimage[btnloop] =
- nsgtk_theme_searchimage_default(btnloop,
- iconsize,
- usedef);
+ /* update the locations for all the subsequent toolbar items */
+ for (location = tbc->toolbar.items[tbc->dragitem].location;
+ location < PLACEHOLDER_BUTTON;
+ location++) {
+ itemid = itemid_from_location(&tbc->toolbar, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ break;
+ }
+ tbc->toolbar.items[itemid].location--;
}
- return theme;
-}
+ /* remove existing item */
+ tbc->toolbar.items[tbc->dragitem].location = -1;
+ gtk_container_remove(GTK_CONTAINER(tbc->toolbar.widget),
+ GTK_WIDGET(tbc->toolbar.items[tbc->dragitem].button));
+
+ tbc->dragitem = -1;
+ gtk_drag_finish(gdc, TRUE, TRUE, time);
+ return FALSE;
+}
-/* exported function documented in gtk/toolbar.h */
-void nsgtk_theme_implement(struct nsgtk_scaffolding *g)
+/**
+ * customisation container handler for drag motion signal
+ *
+ * called when hovering above the store
+ */
+static gboolean
+customisation_container_drag_motion_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ gint x, gint y,
+ guint time,
+ gpointer data)
{
- struct nsgtk_theme *theme[IMAGE_SET_COUNT];
- int i;
- struct nsgtk_button_connect *button;
- struct gtk_search *search;
+ return FALSE;
+}
- theme[IMAGE_SET_MAIN_MENU] = nsgtk_theme_load(GTK_ICON_SIZE_MENU, false);
- theme[IMAGE_SET_RCLICK_MENU] = nsgtk_theme_load(GTK_ICON_SIZE_MENU, false);
- theme[IMAGE_SET_POPUP_MENU] = nsgtk_theme_load(GTK_ICON_SIZE_MENU, false);
- theme[IMAGE_SET_BUTTONS] = nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR, false);
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- if ((i == URL_BAR_ITEM) || (i == THROBBER_ITEM) ||
- (i == WEBSEARCH_ITEM))
- continue;
+/**
+ * customisation toolbar handler for drag drop signal
+ *
+ * called when a widget is dropped onto the toolbar
+ */
+static gboolean
+customisation_toolbar_drag_drop_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ gint x,
+ gint y,
+ guint time,
+ gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ tbc = (struct nsgtk_toolbar_customisation *)data;
+ gint position; /* drop position in toolbar */
+ int location;
+ int itemid;
+ struct nsgtk_toolbar_item *dragitem; /* toolbar item being dragged */
+
+ position = gtk_toolbar_get_drop_index(tbc->toolbar.widget, x, y);
+ if (tbc->dragitem == -1) {
+ return TRUE;
+ }
- button = nsgtk_scaffolding_button(g, i);
- if (button == NULL)
- continue;
+ /* pure conveiance variable */
+ dragitem = &tbc->toolbar.items[tbc->dragitem];
- /* gtk_image_menu_item_set_image accepts NULL image */
- if ((button->main != NULL) &&
- (theme[IMAGE_SET_MAIN_MENU] != NULL)) {
- nsgtk_image_menu_item_set_image(
- GTK_WIDGET(button->main),
- GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->image[i]));
- gtk_widget_show_all(GTK_WIDGET(button->main));
+ /* deal with replacing existing item in toolbar */
+ if (dragitem->location != INACTIVE_LOCATION) {
+ if (dragitem->location < position) {
+ position--;
}
- if ((button->rclick != NULL) &&
- (theme[IMAGE_SET_RCLICK_MENU] != NULL)) {
- nsgtk_image_menu_item_set_image(GTK_WIDGET(button->rclick),
- GTK_WIDGET(
- theme[IMAGE_SET_RCLICK_MENU]->
- image[i]));
- gtk_widget_show_all(GTK_WIDGET(button->rclick));
+
+ /* update the locations for all the subsequent toolbar items */
+ for (location = dragitem->location;
+ location < PLACEHOLDER_BUTTON;
+ location++) {
+ itemid = itemid_from_location(&tbc->toolbar, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ break;
+ }
+ tbc->toolbar.items[itemid].location--;
}
- if ((button->popup != NULL) &&
- (theme[IMAGE_SET_POPUP_MENU] != NULL)) {
- nsgtk_image_menu_item_set_image(GTK_WIDGET(button->popup),
- GTK_WIDGET(
- theme[IMAGE_SET_POPUP_MENU]->
- image[i]));
- gtk_widget_show_all(GTK_WIDGET(button->popup));
+
+ /* remove existing item */
+ dragitem->location = INACTIVE_LOCATION;
+ gtk_container_remove(GTK_CONTAINER(tbc->toolbar.widget),
+ GTK_WIDGET(dragitem->button));
+ }
+
+
+ dragitem->button = make_toolbox_item(tbc->dragitem, true);
+
+ if (dragitem->button == NULL) {
+ nsgtk_warning("NoMemory", 0);
+ return TRUE;
+ }
+
+ /* update locations */
+ for (location = PLACEHOLDER_BUTTON; location >= position; location--) {
+ itemid = itemid_from_location(&tbc->toolbar, location);
+ if (itemid != PLACEHOLDER_BUTTON) {
+ tbc->toolbar.items[itemid].location++;
}
- if ((button->location != -1) && (button->button != NULL) &&
- (theme[IMAGE_SET_BUTTONS] != NULL)) {
- gtk_tool_button_set_icon_widget(
- GTK_TOOL_BUTTON(button->button),
- GTK_WIDGET(
- theme[IMAGE_SET_BUTTONS]->
- image[i]));
- gtk_widget_show_all(GTK_WIDGET(button->button));
+ }
+ dragitem->location = position;
+
+ gtk_toolbar_insert(tbc->toolbar.widget,
+ dragitem->button,
+ dragitem->location);
+
+ toolbar_item_connect_signals(&tbc->toolbar, tbc->dragitem);
+ gtk_widget_show_all(GTK_WIDGET(dragitem->button));
+ tbc->dragitem = -1;
+ return TRUE;
+}
+
+
+/**
+ * customisation toolbar handler for drag data received signal
+ *
+ * connected to toolbutton drop; perhaps one day it'll work properly
+ * so it may replace the global current_button
+ */
+static gboolean
+customisation_toolbar_drag_data_received_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ gint x,
+ gint y,
+ GtkSelectionData *selection,
+ guint info,
+ guint time,
+ gpointer data)
+{
+ return FALSE;
+}
+
+
+/**
+ * customisation toolbar handler for drag motion signal
+ *
+ * called when hovering an item above the toolbar
+ */
+static gboolean
+customisation_toolbar_drag_motion_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ gint x,
+ gint y,
+ guint time,
+ gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ GtkToolItem *item;
+ gint position; /* position in toolbar */
+
+ item = gtk_tool_button_new(NULL, NULL);
+ position = gtk_toolbar_get_drop_index(tb->widget, x, y);
+
+ gtk_toolbar_set_drop_highlight_item(tb->widget, item, position);
+
+ return FALSE; /* drag not in drop zone */
+}
+
+
+/**
+ * customisation toolbar handler for drag leave signal
+ *
+ * called when hovering stops
+ */
+static void
+customisation_toolbar_drag_leave_cb(GtkWidget *widget,
+ GdkDragContext *gdc,
+ guint time,
+ gpointer data)
+{
+ gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(widget), NULL, 0);
+}
+
+
+/**
+ * create a new browser window
+ *
+ * creates a browser window with default url depending on user choices.
+ *
+ * \param bw The browser window to pass for existing window/
+ * \param intab true if the new window should be in a tab else false
+ * for new window.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+nsgtk_browser_window_create(struct browser_window *bw, bool intab)
+{
+ nserror res = NSERROR_OK;
+ nsurl *url = NULL;
+ int flags = BW_CREATE_HISTORY | BW_CREATE_FOREGROUND | BW_CREATE_FOCUS_LOCATION;
+
+ if (intab) {
+ flags |= BW_CREATE_TAB;
+ }
+
+ if (!nsoption_bool(new_blank)) {
+ const char *addr;
+ if (nsoption_charp(homepage_url) != NULL) {
+ addr = nsoption_charp(homepage_url);
+ } else {
+ addr = NETSURF_HOMEPAGE;
}
+ res = nsurl_create(addr, &url);
+ }
+
+ if (res == NSERROR_OK) {
+ res = browser_window_create(flags, url, NULL, bw, NULL);
+ }
+
+ if (url != NULL) {
+ nsurl_unref(url);
+ }
+
+ return res;
+}
+
+
+/**
+ * Apply the user toolbar button settings from configuration
+ *
+ * GTK specific user option string is a set of fields arranged as
+ * [itemreference];[itemlocation]|[itemreference];[itemlocation]| etc
+ *
+ * \param tb The toolbar to apply customisation to
+ * \param NSERROR_OK on success else error code.
+ */
+static nserror
+apply_user_button_customisation(struct nsgtk_toolbar *tb)
+{
+ const char *tbitems; /* item order user config */
+ const char *start;
+ const char *end;
+ int iidx; /* item index */
+ int location = 0; /* location index */
+
+ /* set all button locations to inactive */
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ tb->items[iidx].location = INACTIVE_LOCATION;
}
- /* set search bar images */
- search = nsgtk_scaffolding_search(g);
- if ((search != NULL) && (theme[IMAGE_SET_MAIN_MENU] != NULL)) {
- /* gtk_tool_button_set_icon_widget accepts NULL image */
- if (search->buttons[SEARCH_BACK_BUTTON] != NULL) {
- gtk_tool_button_set_icon_widget(
- search->buttons[SEARCH_BACK_BUTTON],
- GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->
- searchimage[SEARCH_BACK_BUTTON]));
- gtk_widget_show_all(GTK_WIDGET(
- search->buttons[SEARCH_BACK_BUTTON]));
+ tbitems = nsoption_charp(toolbar_items);
+ if (tbitems == NULL) {
+ tbitems = "";
+ }
+
+ end = tbitems;
+ while (*end != 0) {
+ start = end;
+ while ((*end != 0) && (*end !='/')) {
+ end++;
}
- if (search->buttons[SEARCH_FORWARD_BUTTON] != NULL) {
- gtk_tool_button_set_icon_widget(
- search->buttons[SEARCH_FORWARD_BUTTON],
- GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->
- searchimage[SEARCH_FORWARD_BUTTON]));
- gtk_widget_show_all(GTK_WIDGET(
- search->buttons[
- SEARCH_FORWARD_BUTTON]));
+
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ if (((ssize_t)strlen(tb->items[iidx].name) == (end - start)) &&
+ (strncmp(tb->items[iidx].name, start, end - start) == 0)) {
+ tb->items[iidx].location = location++;
+ break;
+ }
}
- if (search->buttons[SEARCH_CLOSE_BUTTON] != NULL) {
- gtk_tool_button_set_icon_widget(
- search->buttons[SEARCH_CLOSE_BUTTON],
- GTK_WIDGET(theme[IMAGE_SET_MAIN_MENU]->
- searchimage[SEARCH_CLOSE_BUTTON]));
- gtk_widget_show_all(GTK_WIDGET(
- search->buttons[SEARCH_CLOSE_BUTTON]));
+
+ if (*end == '/') {
+ end++;
}
}
- for (i = 0; i < IMAGE_SET_COUNT; i++) {
- if (theme[i] != NULL) {
- free(theme[i]);
- }
+ if (location == 0) {
+ /* completely failed to create any buttons so use defaults */
+ tb->items[BACK_BUTTON].location = location++;
+ tb->items[HISTORY_BUTTON].location = location++;
+ tb->items[FORWARD_BUTTON].location = location++;
+ tb->items[RELOADSTOP_BUTTON].location = location++;
+ tb->items[URL_BAR_ITEM].location = location++;
+ tb->items[WEBSEARCH_ITEM].location = location++;
+ tb->items[OPENMENU_BUTTON].location = location++;
+ tb->items[THROBBER_ITEM].location = location++;
}
+
+
+ return NSERROR_OK;
}
/**
- * callback function to iterate toolbar's widgets
+ * callback function to remove a widget from a container
*/
-static void nsgtk_toolbar_clear_toolbar(GtkWidget *widget, gpointer data)
+static void container_remove_widget(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- gtk_container_remove(GTK_CONTAINER(nsgtk_scaffolding_toolbar(g)),
- widget);
+ GtkContainer *container = GTK_CONTAINER(data);
+ gtk_container_remove(container, widget);
}
+
/**
- * connect temporary handler for toolbar edit events
+ * populates a toolbar with widgets in correct order
*
- * \param g The scaffolding
- * \param bi The button index
+ * \param tb toolbar
+ * \return NSERROR_OK on success else error code.
*/
-static void nsgtk_toolbar_temp_connect(struct nsgtk_scaffolding *g,
- nsgtk_toolbar_button bi)
+static nserror populate_gtk_toolbar_widget(struct nsgtk_toolbar *tb)
{
- struct nsgtk_button_connect *bc;
+ int location; /* location index */
+ int itemid;
+
+ /* clear the toolbar container of all widgets */
+ gtk_container_foreach(GTK_CONTAINER(tb->widget),
+ container_remove_widget,
+ tb->widget);
+
+ /* add widgets to toolbar */
+ for (location = 0; location < PLACEHOLDER_BUTTON; location++) {
+ itemid = itemid_from_location(tb, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ break;
+ }
+ tb->items[itemid].button =
+ make_toolbar_item(itemid,
+ tb->items[itemid].sensitivity);
+
+ gtk_toolbar_insert(tb->widget,
+ tb->items[itemid].button,
+ location);
+ }
- if (bi != URL_BAR_ITEM) {
- bc = nsgtk_scaffolding_button(g, bi);
- if ((bc->button != NULL) && (bc->dataminus != NULL)) {
- g_signal_connect(bc->button,
- "drag-data-get",
- G_CALLBACK(bc->dataminus),
- g);
+ gtk_widget_show_all(GTK_WIDGET(tb->widget));
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * populates the customization toolbar with widgets in correct order
+ *
+ * \param tb toolbar
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror customisation_toolbar_populate(struct nsgtk_toolbar *tb)
+{
+ int location; /* location index */
+ int itemid;
+
+ /* clear the toolbar container of all widgets */
+ gtk_container_foreach(GTK_CONTAINER(tb->widget),
+ container_remove_widget,
+ tb->widget);
+
+ /* add widgets to toolbar */
+ for (location = 0; location < PLACEHOLDER_BUTTON; location++) {
+ itemid = itemid_from_location(tb, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ break;
}
+ tb->items[itemid].button = make_toolbox_item(itemid, true);
+
+ gtk_toolbar_insert(tb->widget,
+ tb->items[itemid].button,
+ location);
}
+
+ gtk_widget_show_all(GTK_WIDGET(tb->widget));
+
+ return NSERROR_OK;
}
+
/**
- * get scaffolding button index of button at location
+ * find the toolbar item with a given gtk widget.
*
- * \return toolbar item id from location when there is an item at that logical
- * location; else -1
+ * \param tb the toolbar instance
+ * \param toolitem the tool item widget to search for
+ * \return the item id matching the widget
*/
static nsgtk_toolbar_button
-nsgtk_toolbar_get_id_at_location(struct nsgtk_scaffolding *g, int i)
+itemid_from_gtktoolitem(struct nsgtk_toolbar *tb, GtkToolItem *toolitem)
{
- int q;
- for (q = BACK_BUTTON; q < PLACEHOLDER_BUTTON; q++) {
- if (nsgtk_scaffolding_button(g, q)->location == i) {
- return q;
+ int iidx;
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ if ((tb->items[iidx].location != INACTIVE_LOCATION) &&
+ (tb->items[iidx].button == toolitem)) {
+ break;
}
}
- return -1;
+ return iidx;
}
+
/**
- * widget factory for creation of toolbar item widgets
- * \param g the reference scaffolding
- * \param i the id of the widget
- * \param theme the theme to make the widgets from
+ * set a toolbar items sensitivity
+ *
+ * note this does not set menu items sensitivity
*/
-static GtkWidget *
-nsgtk_toolbar_make_widget(struct nsgtk_scaffolding *g,
- nsgtk_toolbar_button i,
- struct nsgtk_theme *theme)
-{
- GtkWidget *w = NULL;
-
- switch(i) {
-
-/* gtk_tool_button_new() accepts NULL args */
-#define MAKE_STOCKBUTTON(p, q) \
- case p##_BUTTON: { \
- GtkStockItem item; \
- char *label = NULL; \
- if (nsgtk_stock_lookup(q, &item) && \
- (item.label != NULL) && \
- ((label = remove_underscores(item.label, false)) != NULL)) { \
- w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET( \
- theme->image[p##_BUTTON]), label)); \
- free(label); \
- } else { \
- w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET( \
- theme->image[p##_BUTTON]), q)); \
- } \
- break; \
+static nserror
+set_item_sensitivity(struct nsgtk_toolbar_item *item, bool sensitivity)
+{
+ if (item->sensitivity != sensitivity) {
+ /* item requires sensitivity changing */
+ item->sensitivity = sensitivity;
+
+ if ((item->location != -1) && (item->button != NULL)) {
+ gtk_widget_set_sensitive(GTK_WIDGET(item->button),
+ item->sensitivity);
+ }
}
- MAKE_STOCKBUTTON(HOME, NSGTK_STOCK_HOME)
- MAKE_STOCKBUTTON(BACK, NSGTK_STOCK_GO_BACK)
- MAKE_STOCKBUTTON(FORWARD, NSGTK_STOCK_GO_FORWARD)
- MAKE_STOCKBUTTON(STOP, NSGTK_STOCK_STOP)
- MAKE_STOCKBUTTON(RELOAD, NSGTK_STOCK_REFRESH)
-#undef MAKE_STOCKBUTTON
+ return NSERROR_OK;
+}
- case HISTORY_BUTTON:
- w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET(
- theme->image[HISTORY_BUTTON]), "H"));
- break;
- case URL_BAR_ITEM: {
- GtkWidget *entry = nsgtk_entry_new();
- w = GTK_WIDGET(gtk_tool_item_new());
+/**
+ * set an item to its alternative action
+ *
+ * this is currently only used for the stop/reload button where we
+ * also reuse the item sensitivity for the state indicator.
+ *
+ * \param tb the toolbar instance
+ */
+static nserror set_item_action(struct nsgtk_toolbar *tb, int itemid, bool alt)
+{
+ const char *iconname;
+ char *label = NULL;
+
+ if (itemid != RELOADSTOP_BUTTON) {
+ return NSERROR_INVALID;
+ }
+ if (tb->items[itemid].location == -1) {
+ return NSERROR_OK;
+ }
+ tb->items[itemid].sensitivity = alt;
- if ((entry == NULL) || (w == NULL)) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- return NULL;
- }
+ if (tb->items[itemid].button == NULL) {
+ return NSERROR_INVALID;
+ }
- nsgtk_entry_set_icon_from_pixbuf(entry,
- GTK_ENTRY_ICON_PRIMARY,
- favicon_pixbuf);
+ if (tb->items[itemid].sensitivity) {
+ iconname = NSGTK_STOCK_REFRESH;
+ label = remove_underscores(messages_get("Reload"), false);
+
+ } else {
+ iconname = NSGTK_STOCK_STOP;
+ label = remove_underscores(messages_get("gtkStop"), false);
- gtk_container_add(GTK_CONTAINER(w), entry);
- gtk_tool_item_set_expand(GTK_TOOL_ITEM(w), TRUE);
- break;
}
+ gtk_tool_button_set_label(GTK_TOOL_BUTTON(tb->items[itemid].button),
+ label);
- case THROBBER_ITEM: {
- if ((nsgtk_throbber == NULL) ||
- (nsgtk_throbber->framedata == NULL) ||
- (nsgtk_throbber->framedata[0] == NULL)) {
- return NULL;
+ gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(tb->items[itemid].button),
+ iconname);
+
+ gtk_widget_set_sensitive(GTK_WIDGET(tb->items[itemid].button), TRUE);
+
+ if (label != NULL) {
+ free(label);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * cause the toolbar browsing context to navigate to a new url.
+ *
+ * \param tb the toolbar context.
+ * \param urltxt The url string.
+ * \return NSERROR_OK on success else appropriate error code.
+ */
+static nserror
+toolbar_navigate_to_url(struct nsgtk_toolbar *tb, const char *urltxt)
+{
+ struct browser_window *bw;
+ nsurl *url;
+ nserror res;
+
+ res = nsurl_create(urltxt, &url);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ res = browser_window_navigate(bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+
+ return res;
+}
+
+
+/**
+ * run a gtk file chooser as a save dialog to obtain a path
+ */
+static nserror
+nsgtk_saveas_dialog(struct browser_window *bw,
+ const char *title,
+ GtkWindow *parent,
+ bool folder,
+ gchar **path_out)
+{
+ nserror res;
+ GtkWidget *fc; /* file chooser widget */
+ GtkFileChooserAction action;
+ char *path; /* proposed path */
+
+ if (!browser_window_has_content(bw)) {
+ /* cannot save a page with no content */
+ return NSERROR_INVALID;
+ }
+
+ if (folder) {
+ action = GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
+ } else {
+ action = GTK_FILE_CHOOSER_ACTION_SAVE;
+ }
+
+ fc = gtk_file_chooser_dialog_new(title,
+ parent,
+ action,
+ NSGTK_STOCK_CANCEL,
+ GTK_RESPONSE_CANCEL,
+ NSGTK_STOCK_SAVE,
+ GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ /* set a default file name */
+ res = nsurl_nice(browser_window_access_url(bw), &path, false);
+ if (res != NSERROR_OK) {
+ path = strdup(messages_get("SaveText"));
+ if (path == NULL) {
+ gtk_widget_destroy(fc);
+ return NSERROR_NOMEM;
}
+ }
- if (edit_mode) {
- w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET(
- gtk_image_new_from_pixbuf(
- nsgtk_throbber->framedata[0])),
- "[throbber]"));
- } else {
- GtkWidget *image;
+ if ((!folder) || (access(path, F_OK) != 0)) {
+ gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(fc), path);
+ }
+ free(path);
- w = GTK_WIDGET(gtk_tool_item_new());
+ /* confirm overwriting */
+ gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(fc), TRUE);
- image = gtk_image_new_from_pixbuf(nsgtk_throbber->framedata[0]);
- if (image != NULL) {
- nsgtk_widget_set_alignment(image,
- GTK_ALIGN_CENTER,
- GTK_ALIGN_CENTER);
- nsgtk_widget_set_margins(image, 3, 0);
+ /* run the dialog to let user select path */
+ if (gtk_dialog_run(GTK_DIALOG(fc)) != GTK_RESPONSE_ACCEPT) {
+ gtk_widget_destroy(fc);
+ return NSERROR_NOT_FOUND;
+ }
- gtk_container_add(GTK_CONTAINER(w), image);
- }
+ *path_out = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fc));
+
+ gtk_widget_destroy(fc);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * connect all signals to widgets in a customisation
+ */
+static nserror
+toolbar_customisation_connect_signals(struct nsgtk_toolbar *tb)
+{
+ int iidx;
+
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ /* skip inactive items in toolbar */
+ if (tb->items[iidx].location != INACTIVE_LOCATION) {
+ toolbar_item_connect_signals(tb, iidx);
}
- break;
}
- case WEBSEARCH_ITEM: {
- if (edit_mode)
- return GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET(
- nsgtk_image_new_from_stock(NSGTK_STOCK_FIND,
- GTK_ICON_SIZE_LARGE_TOOLBAR)),
- "[websearch]"));
+ /* add move button listeners */
+ g_signal_connect(tb->widget,
+ "drag-drop",
+ G_CALLBACK(customisation_toolbar_drag_drop_cb),
+ tb);
+ g_signal_connect(tb->widget,
+ "drag-data-received",
+ G_CALLBACK(customisation_toolbar_drag_data_received_cb),
+ tb);
+ g_signal_connect(tb->widget,
+ "drag-motion",
+ G_CALLBACK(customisation_toolbar_drag_motion_cb),
+ tb);
+ g_signal_connect(tb->widget,
+ "drag-leave",
+ G_CALLBACK(customisation_toolbar_drag_leave_cb),
+ tb);
+
+ /* set data types */
+ gtk_drag_dest_set(GTK_WIDGET(tb->widget),
+ GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+ &target_entry,
+ 1,
+ GDK_ACTION_COPY);
+
+ return NSERROR_OK;
+}
+
+
+static void
+item_size_allocate_cb(GtkWidget *widget,
+ GdkRectangle *alloc,
+ gpointer user_data)
+{
+ if (alloc->width > NSGTK_BUTTON_WIDTH) {
+ alloc->width = NSGTK_BUTTON_WIDTH;
+ }
+ if (alloc->height > NSGTK_BUTTON_HEIGHT) {
+ alloc->height = NSGTK_BUTTON_HEIGHT;
+ }
+ gtk_widget_set_allocation(widget, alloc);
+}
+
- GtkWidget *entry = nsgtk_entry_new();
+/**
+ * add a row to a toolbar customisation toolbox
+ *
+ * \param tbc The toolbar customisation context
+ * \param startitem The item index of the beginning of the row
+ * \param enditem The item index of the beginning of the next row
+ * \return NSERROR_OK on successs else error
+ */
+static nserror
+add_toolbox_row(struct nsgtk_toolbar_customisation *tbc,
+ int startitem,
+ int enditem)
+{
+ GtkToolbar *rowbar;
+ int iidx;
- w = GTK_WIDGET(gtk_tool_item_new());
+ rowbar = GTK_TOOLBAR(gtk_toolbar_new());
+ if (rowbar == NULL) {
+ return NSERROR_NOMEM;
+ }
- if ((entry == NULL) || (w == NULL)) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- return NULL;
+ gtk_toolbar_set_style(rowbar, GTK_TOOLBAR_BOTH);
+ gtk_toolbar_set_icon_size(rowbar, GTK_ICON_SIZE_LARGE_TOOLBAR);
+ gtk_box_pack_start(tbc->toolbox, GTK_WIDGET(rowbar), FALSE, FALSE, 0);
+
+ for (iidx = startitem; iidx < enditem; iidx++) {
+ if (tbc->items[iidx] == NULL) {
+ /* skip any widgets that failed to initialise */
+ continue;
}
+ gtk_widget_set_size_request(GTK_WIDGET(tbc->items[iidx]),
+ NSGTK_BUTTON_WIDTH,
+ NSGTK_BUTTON_HEIGHT);
+ gtk_tool_item_set_use_drag_window(tbc->items[iidx], TRUE);
+ gtk_drag_source_set(GTK_WIDGET(tbc->items[iidx]),
+ GDK_BUTTON1_MASK,
+ &target_entry,
+ 1,
+ GDK_ACTION_COPY);
+ g_signal_connect(tbc->items[iidx],
+ "drag-data-get",
+ G_CALLBACK(tbc->toolbar.items[iidx].dataplus),
+ &tbc->toolbar);
+ g_signal_connect(tbc->items[iidx],
+ "size-allocate",
+ G_CALLBACK(item_size_allocate_cb),
+ NULL);
+ gtk_toolbar_insert(rowbar, tbc->items[iidx], -1);
+ }
+ return NSERROR_OK;
+}
- gtk_widget_set_size_request(entry, NSGTK_WEBSEARCH_WIDTH, -1);
- nsgtk_entry_set_icon_from_stock(entry, GTK_ENTRY_ICON_PRIMARY,
- NSGTK_STOCK_INFO);
+/**
+ * creates widgets in customisation toolbox
+ *
+ * \param tbc The toolbar customisation context
+ * \param width The width to layout the toolbox to
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+toolbar_customisation_create_toolbox(struct nsgtk_toolbar_customisation *tbc,
+ int width)
+{
+ int columns; /* number of items in a single row */
+ int curcol; /* current column in creation */
+ int iidx; /* item index */
+ int startidx; /* index of item at start of row */
+
+ /* ensure there are a minimum number of items per row */
+ columns = width / NSGTK_BUTTON_WIDTH;
+ if (columns < NSGTK_MIN_STORE_COLUMNS) {
+ columns = NSGTK_MIN_STORE_COLUMNS;
+ }
- gtk_container_add(GTK_CONTAINER(w), entry);
- break;
+ curcol = 0;
+ for (iidx = startidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ if (curcol >= columns) {
+ add_toolbox_row(tbc, startidx, iidx);
+ curcol = 0;
+ startidx = iidx;
+ }
+ tbc->items[iidx] = make_toolbox_item(iidx, false);
+ if (tbc->items[iidx] != NULL) {
+ curcol++;
+ }
+ }
+ if (curcol > 0) {
+ add_toolbox_row(tbc, startidx, iidx);
}
-/* gtk_tool_button_new accepts NULL args */
-#define MAKE_MENUBUTTON(p, q) \
- case p##_BUTTON: { \
- char *label = NULL; \
- label = remove_underscores(messages_get(#q), false); \
- w = GTK_WIDGET(gtk_tool_button_new(GTK_WIDGET( \
- theme->image[p##_BUTTON]), label)); \
- if (label != NULL) \
- free(label); \
- break; \
- }
-
- MAKE_MENUBUTTON(NEWWINDOW, gtkNewWindow)
- MAKE_MENUBUTTON(NEWTAB, gtkNewTab)
- MAKE_MENUBUTTON(OPENFILE, gtkOpenFile)
- MAKE_MENUBUTTON(CLOSETAB, gtkCloseTab)
- MAKE_MENUBUTTON(CLOSEWINDOW, gtkCloseWindow)
- MAKE_MENUBUTTON(SAVEPAGE, gtkSavePage)
- MAKE_MENUBUTTON(PRINTPREVIEW, gtkPrintPreview)
- MAKE_MENUBUTTON(PRINT, gtkPrint)
- MAKE_MENUBUTTON(QUIT, gtkQuitMenu)
- MAKE_MENUBUTTON(CUT, gtkCut)
- MAKE_MENUBUTTON(COPY, gtkCopy)
- MAKE_MENUBUTTON(PASTE, gtkPaste)
- MAKE_MENUBUTTON(DELETE, gtkDelete)
- MAKE_MENUBUTTON(SELECTALL, gtkSelectAll)
- MAKE_MENUBUTTON(PREFERENCES, gtkPreferences)
- MAKE_MENUBUTTON(ZOOMPLUS, gtkZoomPlus)
- MAKE_MENUBUTTON(ZOOMMINUS, gtkZoomMinus)
- MAKE_MENUBUTTON(ZOOMNORMAL, gtkZoomNormal)
- MAKE_MENUBUTTON(FULLSCREEN, gtkFullScreen)
- MAKE_MENUBUTTON(VIEWSOURCE, gtkViewSource)
- MAKE_MENUBUTTON(CONTENTS, gtkContents)
- MAKE_MENUBUTTON(ABOUT, gtkAbout)
- MAKE_MENUBUTTON(PDF, gtkPDF)
- MAKE_MENUBUTTON(PLAINTEXT, gtkPlainText)
- MAKE_MENUBUTTON(DRAWFILE, gtkDrawFile)
- MAKE_MENUBUTTON(POSTSCRIPT, gtkPostScript)
- MAKE_MENUBUTTON(FIND, gtkFind)
- MAKE_MENUBUTTON(DOWNLOADS, gtkDownloads)
- MAKE_MENUBUTTON(SAVEWINDOWSIZE, gtkSaveWindowSize)
- MAKE_MENUBUTTON(TOGGLEDEBUGGING, gtkToggleDebugging)
- MAKE_MENUBUTTON(SAVEBOXTREE, gtkDebugBoxTree)
- MAKE_MENUBUTTON(SAVEDOMTREE, gtkDebugDomTree)
- MAKE_MENUBUTTON(LOCALHISTORY, gtkLocalHistory)
- MAKE_MENUBUTTON(GLOBALHISTORY, gtkGlobalHistory)
- MAKE_MENUBUTTON(ADDBOOKMARKS, gtkAddBookMarks)
- MAKE_MENUBUTTON(SHOWBOOKMARKS, gtkShowBookMarks)
- MAKE_MENUBUTTON(SHOWCOOKIES, gtkShowCookies)
- MAKE_MENUBUTTON(OPENLOCATION, gtkOpenLocation)
- MAKE_MENUBUTTON(NEXTTAB, gtkNextTab)
- MAKE_MENUBUTTON(PREVTAB, gtkPrevTab)
- MAKE_MENUBUTTON(GUIDE, gtkGuide)
- MAKE_MENUBUTTON(INFO, gtkUserInformation)
-#undef MAKE_MENUBUTTON
+ return NSERROR_OK;
+}
- default:
- break;
+/**
+ * update toolbar in customisation to user settings
+ */
+static nserror
+customisation_toolbar_update(struct nsgtk_toolbar_customisation *tbc)
+{
+ nserror res;
+
+ res = apply_user_button_customisation(&tbc->toolbar);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* populate toolbar widget */
+ res = customisation_toolbar_populate(&tbc->toolbar);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* ensure icon sizes and text labels on toolbar are set */
+ res = nsgtk_toolbar_restyle(&tbc->toolbar);
+ if (res != NSERROR_OK) {
+ return res;
}
- return w;
+
+ /* attach handlers to toolbar widgets */
+ res = toolbar_customisation_connect_signals(&tbc->toolbar);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ return NSERROR_OK;
}
+
/**
- * called when a widget is dropped onto the toolbar
+ * customisation apply handler for clicked signal
+ *
+ * when 'save settings' button is clicked
+ */
+static gboolean
+customisation_apply_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ tbc = (struct nsgtk_toolbar_customisation *)data;
+
+ /* save state to file, update toolbars for all windows */
+ nsgtk_toolbar_customisation_save(&tbc->toolbar);
+ nsgtk_window_toolbar_update();
+ gtk_widget_destroy(tbc->container);
+
+ return TRUE;
+}
+
+
+/**
+ * customisation reset handler for clicked signal
+ *
+ * when 'reload defaults' button is clicked
*/
static gboolean
-nsgtk_toolbar_data(GtkWidget *widget,
- GdkDragContext *gdc,
- gint x,
- gint y,
- guint time,
- gpointer data)
-{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- int ind = gtk_toolbar_get_drop_index(nsgtk_scaffolding_toolbar(g),
- x, y);
- int q, i;
- if (window->currentbutton == -1)
+customisation_reset_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ tbc = (struct nsgtk_toolbar_customisation *)data;
+
+ customisation_toolbar_update(tbc);
+
+ return TRUE;
+}
+
+
+/**
+ * customisation container destroy handler
+ */
+static void customisation_container_destroy_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ tbc = (struct nsgtk_toolbar_customisation *)data;
+
+ free(tbc);
+}
+
+/*
+ * Toolbar button clicked handlers
+ */
+
+/**
+ * create a toolbar customisation tab
+ *
+ * this is completely different approach to previous implementation. it
+ * is not modal and the toolbar configuration is performed completely
+ * within the tab. once the user is happy they can apply the change or
+ * cancel as they see fit while continuing to use the browser as usual.
+ */
+static gboolean cutomize_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar_customisation *tbc;
+ nserror res;
+ GtkBuilder *builder;
+ GtkNotebook *notebook; /* notebook containing widget */
+ GtkAllocation notebook_alloc; /* notebook size allocation */
+ int iidx; /* item index */
+
+ /* obtain the notebook being added to */
+ notebook = GTK_NOTEBOOK(gtk_widget_get_ancestor(widget,
+ GTK_TYPE_NOTEBOOK));
+ if (notebook == NULL) {
return TRUE;
- struct nsgtk_theme *theme =
- nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR, false);
- if (theme == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
+ }
+
+ /* create builder */
+ res = nsgtk_builder_new_from_resname("toolbar", &builder);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Toolbar UI builder init failed");
return TRUE;
}
- if (nsgtk_scaffolding_button(g, window->currentbutton)->location
- != -1) {
- /* widget was already in the toolbar; so replace */
- if (nsgtk_scaffolding_button(g, window->currentbutton)->
- location < ind)
- ind--;
- gtk_container_remove(GTK_CONTAINER(
- nsgtk_scaffolding_toolbar(g)), GTK_WIDGET(
- nsgtk_scaffolding_button(g,
- window->currentbutton)->button));
- /* 'move' all widgets further right than the original location,
- * one place to the left in logical schema */
- for (i = nsgtk_scaffolding_button(g, window->currentbutton)->
- location + 1; i < PLACEHOLDER_BUTTON; i++) {
- q = nsgtk_toolbar_get_id_at_location(g, i);
- if (q == -1)
- continue;
- nsgtk_scaffolding_button(g, q)->location--;
- }
- nsgtk_scaffolding_button(g, window->currentbutton)->
- location = -1;
- }
- nsgtk_scaffolding_button(g, window->currentbutton)->button =
- GTK_TOOL_ITEM(nsgtk_toolbar_make_widget(g,
- window->currentbutton, theme));
- free(theme);
- if (nsgtk_scaffolding_button(g, window->currentbutton)->button
- == NULL) {
- nsgtk_warning("NoMemory", 0);
+ gtk_builder_connect_signals(builder, NULL);
+
+ /* create nsgtk_toolbar_customisation which has nsgtk_toolbar
+ * at the front so we can reuse functions that take
+ * nsgtk_toolbar
+ */
+ tbc = calloc(1, sizeof(struct nsgtk_toolbar_customisation));
+ if (tbc == NULL) {
+ g_object_unref(builder);
return TRUE;
}
- /* update logical schema */
- nsgtk_scaffolding_reset_offset(g);
- /* 'move' all widgets further right than the new location, one place to
- * the right in logical schema */
- for (i = PLACEHOLDER_BUTTON - 1; i >= ind; i--) {
- q = nsgtk_toolbar_get_id_at_location(g, i);
- if (q == -1)
- continue;
- nsgtk_scaffolding_button(g, q)->location++;
+
+ /* get container box widget which forms a page of the tabs */
+ tbc->container = GTK_WIDGET(gtk_builder_get_object(builder, "customisation"));
+ if (tbc->container == NULL) {
+ goto cutomize_button_clicked_cb_error;
}
- nsgtk_scaffolding_button(g, window->currentbutton)->location = ind;
- /* complete action */
- GtkToolItem *current_button;
+ /* vertical box for the toolbox to drag items into and out of */
+ tbc->toolbox = GTK_BOX(gtk_builder_get_object(builder, "toolbox"));
+ if (tbc->toolbox == NULL) {
+ goto cutomize_button_clicked_cb_error;
+ }
- current_button = GTK_TOOL_ITEM(nsgtk_scaffolding_button(g, window->currentbutton)->button);
+ /* customisation toolbar container */
+ tbc->toolbar.widget = GTK_TOOLBAR(gtk_builder_get_object(builder, "toolbar"));
+ if (tbc->toolbar.widget == NULL) {
+ goto cutomize_button_clicked_cb_error;
+ }
- gtk_toolbar_insert(nsgtk_scaffolding_toolbar(g), current_button, ind);
+ /* build customisation toolbar */
+ gtk_toolbar_set_show_arrow(tbc->toolbar.widget, TRUE);
- gtk_tool_item_set_use_drag_window(current_button, TRUE);
- gtk_drag_source_set(GTK_WIDGET(current_button),
- GDK_BUTTON1_MASK, &entry, 1,
- GDK_ACTION_COPY);
- nsgtk_toolbar_temp_connect(g, window->currentbutton);
- gtk_widget_show_all(GTK_WIDGET(current_button));
+ for (iidx = BACK_BUTTON; iidx < PLACEHOLDER_BUTTON; iidx++) {
+ res = toolbar_item_create(iidx, &tbc->toolbar.items[iidx]);
+ if (res != NSERROR_OK) {
+ goto cutomize_button_clicked_cb_error;
+ }
+ }
+
+ res = customisation_toolbar_update(tbc);
+ if (res != NSERROR_OK) {
+ goto cutomize_button_clicked_cb_error;
+ }
+
+ /* use toolbox for widgets to drag to/from */
+ gtk_widget_get_allocation(GTK_WIDGET(notebook), &notebook_alloc);
+
+ res = toolbar_customisation_create_toolbox(tbc, notebook_alloc.width);
+ if (res != NSERROR_OK) {
+ goto cutomize_button_clicked_cb_error;
+ }
+
+ /* configure the container */
+ gtk_drag_dest_set(GTK_WIDGET(tbc->container),
+ GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+ &target_entry,
+ 1,
+ GDK_ACTION_COPY);
+
+ /* discard button calls destroy */
+ g_signal_connect_swapped(GTK_WIDGET(gtk_builder_get_object(builder,
+ "discard")),
+ "clicked",
+ G_CALLBACK(gtk_widget_destroy),
+ tbc->container);
+
+ /* save and update on apply button */
+ g_signal_connect(GTK_WIDGET(gtk_builder_get_object(builder, "apply")),
+ "clicked",
+ G_CALLBACK(customisation_apply_clicked_cb),
+ tbc);
+
+ g_signal_connect(GTK_WIDGET(gtk_builder_get_object(builder, "reset")),
+ "clicked",
+ G_CALLBACK(customisation_reset_clicked_cb),
+ tbc);
+
+ /* close and cleanup on delete signal */
+ g_signal_connect(tbc->container,
+ "destroy",
+ G_CALLBACK(customisation_container_destroy_cb),
+ tbc);
+
+
+ g_signal_connect(tbc->container,
+ "drag-drop",
+ G_CALLBACK(customisation_container_drag_drop_cb),
+ tbc);
+
+ g_signal_connect(tbc->container,
+ "drag-motion",
+ G_CALLBACK(customisation_container_drag_motion_cb),
+ tbc);
- window->currentbutton = -1;
+ 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;
+
+ cutomize_button_clicked_cb_error:
+ free(tbc);
+ g_object_unref(builder);
return TRUE;
+
+}
+
+
+/**
+ * callback for all toolbar items widget size allocation
+ *
+ * handler connected to all toolbar items for the size-allocate signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param alloc The size allocation being set.
+ * \param data The toolbar context passed when the signal was connected
+ */
+static void
+toolbar_item_size_allocate_cb(GtkWidget *widget,
+ GtkAllocation *alloc,
+ gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ nsgtk_toolbar_button itemid;
+
+ itemid = itemid_from_gtktoolitem(tb, GTK_TOOL_ITEM(widget));
+
+ if ((tb->toolbarmem == alloc->x) ||
+ (tb->items[itemid].location < tb->items[HISTORY_BUTTON].location)) {
+ /*
+ * no reallocation after first adjustment,
+ * no reallocation for buttons left of history button
+ */
+ return;
+ }
+
+ if (itemid == HISTORY_BUTTON) {
+ if (alloc->width == 20) {
+ return;
+ }
+
+ tb->toolbarbase = alloc->y + alloc->height;
+ tb->historybase = alloc->x + 20;
+ if (tb->offset == 0) {
+ tb->offset = alloc->width - 20;
+ }
+ alloc->width = 20;
+ } else if (tb->items[itemid].location <= tb->items[URL_BAR_ITEM].location) {
+ alloc->x -= tb->offset;
+ if (itemid == URL_BAR_ITEM) {
+ alloc->width += tb->offset;
+ }
+ }
+ tb->toolbarmem = alloc->x;
+
+ gtk_widget_size_allocate(widget, alloc);
}
+
/**
- * connected to toolbutton drop; perhaps one day it'll work properly so it may
- * replace the global current_button
+ * handler for back tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
static gboolean
-nsgtk_toolbar_move_complete(GtkWidget *widget,
- GdkDragContext *gdc,
- gint x,
- gint y,
- GtkSelectionData *selection,
- guint info,
- guint time,
- gpointer data)
+back_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- return FALSE;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ if ((bw != NULL) && browser_window_history_back_available(bw)) {
+ /* clear potential search effects */
+ browser_window_search_clear(bw);
+
+ browser_window_history_back(bw, false);
+
+ set_item_sensitivity(&tb->items[BACK_BUTTON],
+ browser_window_history_back_available(bw));
+ set_item_sensitivity(&tb->items[FORWARD_BUTTON],
+ browser_window_history_forward_available(bw));
+
+ nsgtk_local_history_hide();
+ }
+ return TRUE;
}
+
/**
- * called when hovering an item above the toolbar
+ * handler for forward tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
static gboolean
-nsgtk_toolbar_action(GtkWidget *widget, GdkDragContext *gdc, gint x,
- gint y, guint time, gpointer data)
-{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- GtkToolItem *item = gtk_tool_button_new(NULL, NULL);
- if (item != NULL)
- gtk_toolbar_set_drop_highlight_item(
- nsgtk_scaffolding_toolbar(g),
- GTK_TOOL_ITEM(item),
- gtk_toolbar_get_drop_index(
- nsgtk_scaffolding_toolbar(g), x, y));
- return FALSE;
+forward_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ if ((bw != NULL) && browser_window_history_forward_available(bw)) {
+ /* clear potential search effects */
+ browser_window_search_clear(bw);
+
+ browser_window_history_forward(bw, false);
+
+ set_item_sensitivity(&tb->items[BACK_BUTTON],
+ browser_window_history_back_available(bw));
+ set_item_sensitivity(&tb->items[FORWARD_BUTTON],
+ browser_window_history_forward_available(bw));
+ nsgtk_local_history_hide();
+ }
+ return TRUE;
}
+
/**
- * called when hovering stops
+ * handler for stop tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static void
-nsgtk_toolbar_clear(GtkWidget *widget, GdkDragContext *gdc, guint time,
- gpointer data)
+static gboolean
+stop_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(widget), NULL, 0);
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+
+ browser_window_stop(tb->get_bw(tb->get_ctx));
+
+ return TRUE;
+}
+
+
+/**
+ * handler for reload tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+reload_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ /* clear potential search effects */
+ browser_window_search_clear(bw);
+
+ browser_window_reload(bw, true);
+
+ return TRUE;
+}
+
+
+/**
+ * handler for reload/stop tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+reloadstop_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ /* clear potential search effects */
+ browser_window_search_clear(bw);
+
+ if (tb->items[RELOADSTOP_BUTTON].sensitivity) {
+ browser_window_reload(bw, true);
+ } else {
+ browser_window_stop(tb->get_bw(tb->get_ctx));
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for home tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+home_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ nserror res;
+ const char *addr;
+
+ if (nsoption_charp(homepage_url) != NULL) {
+ addr = nsoption_charp(homepage_url);
+ } else {
+ addr = NETSURF_HOMEPAGE;
+ }
+
+ res = toolbar_navigate_to_url(tb, addr);
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * callback for url entry widget activation
+ *
+ * handler connected to url entry widget for the activate signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE to allow activation.
+ */
+static gboolean url_entry_activate_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ nsurl *url;
+
+ res = search_web_omni(gtk_entry_get_text(GTK_ENTRY(widget)),
+ SEARCH_WEB_OMNI_NONE,
+ &url);
+ if (res == NSERROR_OK) {
+ bw = tb->get_bw(tb->get_ctx);
+ res = browser_window_navigate(
+ bw, url, NULL, BW_NAVIGATE_HISTORY, NULL, NULL, NULL);
+ nsurl_unref(url);
+ }
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * callback for url entry widget changing
+ *
+ * handler connected to url entry widget for the change signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param event The key change event that changed the entry.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE to allow activation.
+ */
+static gboolean
+url_entry_changed_cb(GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+ return nsgtk_completion_update(GTK_ENTRY(widget));
}
+
/**
- * add item to toolbar.
+ * callback for url entry widget icon button release
*
- * the function should be called, when multiple items are being added,
- * in ascending order.
+ * handler connected to url entry widget for the icon release signal
*
- * \param g the scaffolding whose toolbar an item is added to.
- * \param i the location in the toolbar.
- * \param theme The theme in use.
+ * \param widget The widget the signal is being delivered to.
+ * \param event The key change event that changed the entry.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE to allow activation.
*/
static void
-nsgtk_toolbar_add_item_to_toolbar(struct nsgtk_scaffolding *g, int i,
- struct nsgtk_theme *theme)
-{
- int q;
- for (q = BACK_BUTTON; q < PLACEHOLDER_BUTTON; q++)
- if (nsgtk_scaffolding_button(g, q)->location == i) {
- nsgtk_scaffolding_button(g, q)->button = GTK_TOOL_ITEM(
- nsgtk_toolbar_make_widget(g, q,
- theme));
- gtk_toolbar_insert(nsgtk_scaffolding_toolbar(g),
- nsgtk_scaffolding_button(g, q)->button,
- i);
- break;
- }
+url_entry_icon_release_cb(GtkEntry *entry,
+ GtkEntryIconPosition icon_pos,
+ GdkEvent *event,
+ gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ nsgtk_page_info(bw);
+}
+
+
+/**
+ * handler for web search tool bar entry item activate signal
+ *
+ * handler connected to web search entry widget for the activate signal
+ *
+ * \todo make this user selectable to switch between opening in new
+ * and navigating current window. Possibly improve core search_web interfaces
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean websearch_entry_activate_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ nsurl *url;
+
+ res = search_web_omni(gtk_entry_get_text(GTK_ENTRY(widget)),
+ SEARCH_WEB_OMNI_SEARCHONLY,
+ &url);
+ if (res == NSERROR_OK) {
+ bw = tb->get_bw(tb->get_ctx);
+
+ res = browser_window_create(
+ BW_CREATE_HISTORY | BW_CREATE_TAB | BW_CREATE_FOREGROUND,
+ url,
+ NULL,
+ bw,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
}
/**
- * cleanup code physical update of all toolbars; resensitize
- * \param g the 'front' scaffolding that called customize
+ * handler for web search tool bar item button press signal
+ *
+ * allows a click in the websearch entry field to clear the name of the
+ * provider.
+ *
+ * \todo this does not work well, different behaviour wanted perhaps?
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static void nsgtk_toolbar_close(struct nsgtk_scaffolding *g)
+static gboolean
+websearch_entry_button_press_cb(GtkWidget *widget,
+ GdkEventFocus *f,
+ gpointer data)
{
- int i;
+ gtk_editable_select_region(GTK_EDITABLE(widget), 0, -1);
+ gtk_widget_grab_focus(GTK_WIDGET(widget));
- struct nsgtk_scaffolding *list;
- struct nsgtk_theme *theme;
+ return TRUE;
+}
- list = nsgtk_scaffolding_iterate(NULL);
- while (list) {
- theme = nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR, false);
- if (theme == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- continue;
- }
- /* clear toolbar */
- gtk_container_foreach(GTK_CONTAINER(nsgtk_scaffolding_toolbar(
- list)), nsgtk_toolbar_clear_toolbar, list);
- /* then add items */
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- nsgtk_toolbar_add_item_to_toolbar(list, i, theme);
+
+/**
+ * handler for new window tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+newwindow_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+
+ res = nsgtk_browser_window_create(tb->get_bw(tb->get_ctx), false);
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for new tab tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+newtab_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+
+ res = nsgtk_browser_window_create(tb->get_bw(tb->get_ctx), true);
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+ return TRUE;
+}
+
+
+/**
+ * handler for open file tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+openfile_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *dlgOpen;
+ gint response;
+ GtkWidget *toplevel;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ dlgOpen = gtk_file_chooser_dialog_new("Open File",
+ GTK_WINDOW(toplevel),
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ NSGTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ NSGTK_STOCK_OPEN, GTK_RESPONSE_OK,
+ NULL, NULL);
+
+ response = gtk_dialog_run(GTK_DIALOG(dlgOpen));
+ if (response == GTK_RESPONSE_OK) {
+ char *urltxt;
+ gchar *filename;
+ nserror res;
+ nsurl *url;
+
+ filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dlgOpen));
+
+ urltxt = malloc(strlen(filename) + FILE_SCHEME_PREFIX_LEN + 1);
+ if (urltxt != NULL) {
+ sprintf(urltxt, FILE_SCHEME_PREFIX"%s", filename);
+
+ res = nsurl_create(urltxt, &url);
+ if (res == NSERROR_OK) {
+ bw = tb->get_bw(tb->get_ctx);
+ res = browser_window_navigate(bw,
+ url,
+ NULL,
+ BW_NAVIGATE_HISTORY,
+ NULL,
+ NULL,
+ NULL);
+ nsurl_unref(url);
+ }
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+ free(urltxt);
}
- nsgtk_toolbar_connect_all(list);
- gtk_widget_show_all(GTK_WIDGET(nsgtk_scaffolding_toolbar(
- list)));
- nsgtk_scaffolding_set_sensitivity(list);
- nsgtk_widget_override_background_color(GTK_WIDGET(nsgtk_window_get_layout(nsgtk_scaffolding_top_level(list))), GTK_STATE_NORMAL, 0, 0xFFFF, 0xFFFF, 0xFFFF);
- g_signal_handler_unblock(GTK_WIDGET(
- nsgtk_window_get_layout(
- nsgtk_scaffolding_top_level(list))),
- nsgtk_window_get_signalhandler(
- nsgtk_scaffolding_top_level(list),
- NSGTK_WINDOW_SIGNAL_CLICK));
- g_signal_handler_unblock(GTK_WIDGET(
- nsgtk_window_get_layout(
- nsgtk_scaffolding_top_level(list))),
- nsgtk_window_get_signalhandler(
- nsgtk_scaffolding_top_level(list),
- NSGTK_WINDOW_SIGNAL_REDRAW));
- browser_window_refresh_url_bar(
- nsgtk_get_browser_window(
- nsgtk_scaffolding_top_level(list)));
-
- if (list != g)
- gtk_widget_set_sensitive(GTK_WIDGET(
- nsgtk_scaffolding_window(list)), TRUE);
- free(theme);
- list = nsgtk_scaffolding_iterate(list);
- }
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_notebook(g)),
- TRUE);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_menu_bar(g)),
- TRUE);
- /* update favicon etc */
- nsgtk_scaffolding_set_top_level(nsgtk_scaffolding_top_level(g));
-
- search_web_select_provider(-1);
-}
-
-/**
- * when cancel button is clicked
- */
-static gboolean nsgtk_toolbar_cancel_clicked(GtkWidget *widget, gpointer data)
-{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
-
- edit_mode = false;
- /* reset g->buttons->location */
- for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- nsgtk_scaffolding_button(g, i)->location =
- window->buttonlocations[i];
- }
- nsgtk_toolbar_set_physical(g);
- nsgtk_toolbar_connect_all(g);
- nsgtk_toolbar_close(g);
- nsgtk_scaffolding_set_sensitivity(g);
- gtk_widget_destroy(window->window);
+
+
+ g_free(filename);
+ }
+
+ gtk_widget_destroy(dlgOpen);
+
+ return TRUE;
+}
+
+
+/**
+ * handler for close window tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+closewindow_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWidget *toplevel;
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+ gtk_widget_destroy(toplevel);
return TRUE;
}
+
/**
- * physically add widgets to store window
+ * handler for full save export tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static bool nsgtk_toolbar_add_store_widget(GtkWidget *widget)
+static gboolean
+savepage_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- if (window->numberh >= NSGTK_STORE_WIDTH) {
- window->currentbar = gtk_toolbar_new();
- if (window->currentbar == NULL) {
- nsgtk_warning("NoMemory", 0);
- return false;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ DIR *d;
+ gchar *path;
+ nserror res;
+ GtkWidget *toplevel;
+
+ bw = tb->get_bw(tb->get_ctx);
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ res = nsgtk_saveas_dialog(bw,
+ messages_get("gtkcompleteSave"),
+ GTK_WINDOW(toplevel),
+ true,
+ &path);
+ if (res != NSERROR_OK) {
+ return FALSE;
+ }
+
+ d = opendir(path);
+ if (d == NULL) {
+ NSLOG(netsurf, INFO,
+ "Unable to open directory %s for complete save: %s",
+ path,
+ strerror(errno));
+ if (errno == ENOTDIR) {
+ nsgtk_warning("NoDirError", path);
+ } else {
+ nsgtk_warning("gtkFileError", path);
}
- gtk_toolbar_set_style(GTK_TOOLBAR(window->currentbar),
- GTK_TOOLBAR_BOTH);
- gtk_toolbar_set_icon_size(GTK_TOOLBAR(window->currentbar),
- GTK_ICON_SIZE_LARGE_TOOLBAR);
- gtk_box_pack_start(GTK_BOX(window->widgetvbox),
- window->currentbar, FALSE, FALSE, 0);
- window->numberh = 0;
+ g_free(path);
+ return TRUE;
}
- gtk_widget_set_size_request(widget, NSGTK_BUTTON_WIDTH,
- NSGTK_BUTTON_HEIGHT);
- gtk_toolbar_insert(GTK_TOOLBAR(window->currentbar), GTK_TOOL_ITEM(
- widget), window->numberh++);
- gtk_tool_item_set_use_drag_window(GTK_TOOL_ITEM(widget), TRUE);
- gtk_drag_source_set(widget, GDK_BUTTON1_MASK, &entry, 1,
- GDK_ACTION_COPY);
- gtk_widget_show_all(window->window);
- return true;
+ closedir(d);
+
+ save_complete(browser_window_get_content(bw), path, NULL);
+ g_free(path);
+
+ return TRUE;
}
/**
- * cast toolbar settings to all scaffoldings referenced from the global linked
- * list of gui_windows
+ * handler for pdf export tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static void nsgtk_toolbar_cast(struct nsgtk_scaffolding *g)
+static gboolean
+pdf_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- int i;
- struct nsgtk_scaffolding *list;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *toplevel;
+ gchar *filename;
+ nserror res;
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- window->buttonlocations[i] =
- ((nsgtk_scaffolding_button(g, i)->location
- >= -1) &&
- (nsgtk_scaffolding_button(g, i)->location
- < PLACEHOLDER_BUTTON)) ?
- nsgtk_scaffolding_button(g, i)->location : -1;
+ bw = tb->get_bw(tb->get_ctx);
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ res = nsgtk_saveas_dialog(bw,
+ "Export to PDF",
+ GTK_WINDOW(toplevel),
+ false,
+ &filename);
+ if (res != NSERROR_OK) {
+ return FALSE;
}
- list = nsgtk_scaffolding_iterate(NULL);
- while (list) {
- if (list != g)
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++)
- nsgtk_scaffolding_button(list, i)->location =
- window->buttonlocations[i];
- list = nsgtk_scaffolding_iterate(list);
+#ifdef WITH_PDF_EXPORT
+ struct print_settings *settings;
+
+ /* this way the scale used by PDF functions is synchronised with that
+ * used by the all-purpose print interface
+ */
+ haru_nsfont_set_scale((float)option_export_scale / 100);
+
+ settings = print_make_settings(PRINT_OPTIONS,
+ (const char *) filename,
+ &haru_nsfont);
+ g_free(filename);
+ if (settings == NULL) {
+ return TRUE;
}
+ /* This will clean up the print_settings object for us */
+ print_basic_run(browser_window_get_content(bw), &pdf_printer, settings);
+#endif
+ return TRUE;
+
}
/**
- * load toolbar settings from file; file is a set of fields arranged as
- * [itemreference];[itemlocation]|[itemreference];[itemlocation]| etc
+ * handler for plain text export tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-void nsgtk_toolbar_customization_load(struct nsgtk_scaffolding *g)
+static gboolean
+plaintext_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- int i, ii;
- char *buffer;
- char *buffer1, *subbuffer, *ptr = NULL, *pter = NULL;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *toplevel;
+ gchar *filename;
+ nserror res;
+
+ bw = tb->get_bw(tb->get_ctx);
- /* default toolbar button order */
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- nsgtk_scaffolding_button(g, i)->location =
- (i <= THROBBER_ITEM) ? i : -1;
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ res = nsgtk_saveas_dialog(bw,
+ messages_get("gtkplainSave"),
+ GTK_WINDOW(toplevel),
+ false,
+ &filename);
+ if (res != NSERROR_OK) {
+ return FALSE;
}
- /* ensure the option is actually set */
- if (nsoption_charp(toolbar_order) == NULL) {
- return;
+
+ save_as_text(browser_window_get_content(bw), filename);
+ g_free(filename);
+
+ return TRUE;
+}
+
+
+/**
+ * handler for print tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+print_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkPrintOperation *print_op;
+ GtkPageSetup *page_setup;
+ GtkPrintSettings *print_settings;
+ GtkPrintOperationResult res = GTK_PRINT_OPERATION_RESULT_ERROR;
+ struct print_settings *nssettings;
+ char *settings_fname = NULL;
+ GtkWidget *toplevel;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ print_op = gtk_print_operation_new();
+ if (print_op == NULL) {
+ nsgtk_warning(messages_get("NoMemory"), 0);
+ return TRUE;
}
- buffer = strdup(nsoption_charp(toolbar_order));
-
- i = BACK_BUTTON;
- ii = BACK_BUTTON;
- buffer1 = strtok_r(buffer, "|", &ptr);
- while (buffer1 != NULL) {
- subbuffer = strtok_r(buffer1, ";", &pter);
- if (subbuffer != NULL) {
- i = atoi(subbuffer);
- subbuffer = strtok_r(NULL, ";", &pter);
- if (subbuffer != NULL) {
- ii = atoi(subbuffer);
- if ((i >= BACK_BUTTON) &&
- (i < PLACEHOLDER_BUTTON) &&
- (ii >= -1) &&
- (ii < PLACEHOLDER_BUTTON)) {
- nsgtk_scaffolding_button(g, i)->location = ii;
- }
- }
+
+ /* use previously saved settings if any */
+ netsurf_mkpath(&settings_fname, NULL, 2, nsgtk_config_home, "Print");
+ if (settings_fname != NULL) {
+ print_settings = gtk_print_settings_new_from_file(settings_fname, NULL);
+ if (print_settings != NULL) {
+ gtk_print_operation_set_print_settings(print_op,
+ print_settings);
+
+ /* We're not interested in the settings any more */
+ g_object_unref(print_settings);
+ }
+ }
+
+ content_to_print = browser_window_get_content(bw);
+
+ page_setup = gtk_print_run_page_setup_dialog(GTK_WINDOW(toplevel),
+ NULL,
+ NULL);
+ if (page_setup == NULL) {
+ nsgtk_warning(messages_get("NoMemory"), 0);
+ free(settings_fname);
+ g_object_unref(print_op);
+ return TRUE;
+ }
+ gtk_print_operation_set_default_page_setup(print_op, page_setup);
+
+ nssettings = print_make_settings(PRINT_DEFAULT,
+ NULL,
+ nsgtk_layout_table);
+
+ g_signal_connect(print_op,
+ "begin_print",
+ G_CALLBACK(gtk_print_signal_begin_print),
+ nssettings);
+ g_signal_connect(print_op,
+ "draw_page",
+ G_CALLBACK(gtk_print_signal_draw_page),
+ NULL);
+ g_signal_connect(print_op,
+ "end_print",
+ G_CALLBACK(gtk_print_signal_end_print),
+ nssettings);
+
+ if (content_get_type(browser_window_get_content(bw)) != CONTENT_TEXTPLAIN) {
+ res = gtk_print_operation_run(print_op,
+ GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG,
+ GTK_WINDOW(toplevel),
+ NULL);
+ }
+
+ /* if the settings were used save them for future use */
+ if (settings_fname != NULL) {
+ if (res == GTK_PRINT_OPERATION_RESULT_APPLY) {
+ /* Do not increment the settings reference */
+ print_settings = gtk_print_operation_get_print_settings(print_op);
+
+ gtk_print_settings_to_file(print_settings,
+ settings_fname,
+ NULL);
}
- buffer1 = strtok_r(NULL, "|", &ptr);
+ free(settings_fname);
+ }
+
+ /* Our print_settings object is destroyed by the end print handler */
+ g_object_unref(page_setup);
+ g_object_unref(print_op);
+
+ return TRUE;
+}
+
+/**
+ * handler for quit tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+quit_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nsgtk_scaffolding_destroy_all();
+ return TRUE;
+}
+
+
+/**
+ * handler for cut tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+cut_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *focused;
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
+
+ /* let gtk handle it if focused widget is an editable */
+ if (GTK_IS_EDITABLE(focused)) {
+ gtk_editable_cut_clipboard(GTK_EDITABLE(focused));
+ } else {
+ bw = tb->get_bw(tb->get_ctx);
+ browser_window_key_press(bw, NS_KEY_CUT_SELECTION);
}
- free(buffer);
+ return TRUE;
}
/**
- * save toolbar settings to file
+ * handler for copy tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static nserror nsgtk_toolbar_customization_save(struct nsgtk_scaffolding *g)
+static gboolean
+copy_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- char *choices = NULL;
- char *order;
- int order_len = PLACEHOLDER_BUTTON * 12; /* length of order buffer */
- int tbidx;
- char *cur;
- int plen;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *focused;
+ GtkWidget *toplevel;
- order = malloc(order_len);
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
- if (order == NULL) {
- return NSERROR_NOMEM;
+ focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
+
+ /* let gtk handle it if focused widget is an editable */
+ if (GTK_IS_EDITABLE(focused)) {
+ gtk_editable_copy_clipboard(GTK_EDITABLE(focused));
+ } else {
+ bw = tb->get_bw(tb->get_ctx);
+ browser_window_key_press(bw, NS_KEY_COPY_SELECTION);
}
- cur = order;
- for (tbidx = BACK_BUTTON; tbidx < PLACEHOLDER_BUTTON; tbidx++) {
- plen = snprintf(cur,
- order_len,
- "%d;%d|",
- tbidx,
- nsgtk_scaffolding_button(g, tbidx)->location);
- if (plen == order_len) {
- /* ran out of space, bail early */
- NSLOG(netsurf, INFO,
- "toolbar ordering exceeded available space");
- break;
- }
- cur += plen;
- order_len -= plen;
+ return TRUE;
+}
+
+
+/**
+ * handler for paste tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+paste_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *focused;
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
+
+ /* let gtk handle it if focused widget is an editable */
+ if (GTK_IS_EDITABLE(focused)) {
+ gtk_editable_paste_clipboard(GTK_EDITABLE(focused));
+ } else {
+ bw = tb->get_bw(tb->get_ctx);
+ browser_window_key_press(bw, NS_KEY_PASTE);
}
- nsoption_set_charp(toolbar_order, order);
+ return TRUE;
+}
+
+
+/**
+ * handler for delete tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+delete_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *focused;
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
+
+ /* let gtk handle it if focused widget is an editable */
+ if (GTK_IS_EDITABLE(focused)) {
+ gtk_editable_delete_selection(GTK_EDITABLE(focused));
+ } else {
+ bw = tb->get_bw(tb->get_ctx);
+ browser_window_key_press(bw, NS_KEY_CLEAR_SELECTION);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for select all tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+selectall_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *focused;
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ focused = gtk_window_get_focus(GTK_WINDOW(toplevel));
+
+ /* let gtk handle it if focused widget is an editable */
+ if (GTK_IS_EDITABLE(focused)) {
+ gtk_editable_select_region(GTK_EDITABLE(focused), 0, -1);
+ } else {
+ bw = tb->get_bw(tb->get_ctx);
+ browser_window_key_press(bw, NS_KEY_SELECT_ALL);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for preferences tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+preferences_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *toplevel;
+ GtkWidget *wndpreferences;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+
+ wndpreferences = nsgtk_preferences(bw, GTK_WINDOW(toplevel));
+ if (wndpreferences != NULL) {
+ gtk_widget_show(wndpreferences);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for zoom plus tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+zoomplus_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_set_scale(bw, 0.05, false);
+
+ return TRUE;
+}
+
+
+/**
+ * handler for zoom minus tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+zoomminus_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_set_scale(bw, -0.05, false);
+
+ return TRUE;
+
+}
+
+
+/**
+ * handler for zoom normal tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+zoomnormal_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_set_scale(bw, 1.0, true);
+
+ return TRUE;
+}
+
+
+/**
+ * handler for full screen tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+fullscreen_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWindow *gtkwindow; /* gtk window widget is in */
+ GdkWindow *gdkwindow;
+ GdkWindowState state;
+
+ gtkwindow = GTK_WINDOW(gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW));
+ gdkwindow = gtk_widget_get_window(GTK_WIDGET(gtkwindow));
+ state = gdk_window_get_state(gdkwindow);
+
+ if (state & GDK_WINDOW_STATE_FULLSCREEN) {
+ gtk_window_unfullscreen(gtkwindow);
+ } else {
+ gtk_window_fullscreen(gtkwindow);
+ }
+ return TRUE;
+}
+
+
+/**
+ * handler for view source tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+viewsource_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWindow *gtkwindow; /* gtk window widget is in */
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ gtkwindow = GTK_WINDOW(gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW));
+
+ res = nsgtk_viewsource(gtkwindow, bw);
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
+}
+
+
+/**
+ * handler for show downloads tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+downloads_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWindow *gtkwindow; /* gtk window widget is in */
+ gtkwindow = GTK_WINDOW(gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW));
+ nsgtk_download_show(gtkwindow);
+ return TRUE;
+}
+
+
+/**
+ * handler for show downloads tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+savewindowsize_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWindow *gtkwindow; /* gtk window widget is in */
+ int x,y,w,h;
+ char *choices = NULL;
+
+ gtkwindow = GTK_WINDOW(gtk_widget_get_ancestor(widget,GTK_TYPE_WINDOW));
+
+ gtk_window_get_position(gtkwindow, &x, &y);
+ gtk_window_get_size(gtkwindow, &w, &h);
+
+ nsoption_set_int(window_width, w);
+ nsoption_set_int(window_height, h);
+ nsoption_set_int(window_x, x);
+ nsoption_set_int(window_y, y);
- /* ensure choices are saved */
netsurf_mkpath(&choices, NULL, 2, nsgtk_config_home, "Choices");
if (choices != NULL) {
nsoption_write(choices, NULL, NULL);
free(choices);
}
- return NSERROR_OK;
+ return TRUE;
}
/**
- * when 'save settings' button is clicked
+ * handler for show downloads tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static gboolean nsgtk_toolbar_persist(GtkWidget *widget, gpointer data)
+static gboolean
+toggledebugging_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_debug(bw, CONTENT_DEBUG_REDRAW);
+
+ nsgtk_window_update_all();
- edit_mode = false;
- /* save state to file, update toolbars for all windows */
- nsgtk_toolbar_customization_save(g);
- nsgtk_toolbar_cast(g);
- nsgtk_toolbar_set_physical(g);
- nsgtk_toolbar_close(g);
- gtk_widget_destroy(window->window);
return TRUE;
}
+
/**
- * when 'reload defaults' button is clicked
+ * handler for debug box tree tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static gboolean nsgtk_toolbar_reset(GtkWidget *widget, gpointer data)
+static gboolean
+debugboxtree_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- int i;
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++)
- nsgtk_scaffolding_button(g, i)->location =
- (i <= THROBBER_ITEM) ? i : -1;
- nsgtk_toolbar_set_physical(g);
- for (i = BACK_BUTTON; i <= THROBBER_ITEM; i++) {
- if (i == URL_BAR_ITEM)
- continue;
- gtk_tool_item_set_use_drag_window(GTK_TOOL_ITEM(
- nsgtk_scaffolding_button(g, i)->button), TRUE);
- gtk_drag_source_set(GTK_WIDGET(
- nsgtk_scaffolding_button(g, i)->button),
- GDK_BUTTON1_MASK, &entry, 1, GDK_ACTION_COPY);
- nsgtk_toolbar_temp_connect(g, i);
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ gchar *fname;
+ gint handle;
+ FILE *f;
+
+ handle = g_file_open_tmp("nsgtkboxtreeXXXXXX", &fname, NULL);
+ if ((handle == -1) || (fname == NULL)) {
+ return TRUE;
}
+ close(handle); /* in case it was binary mode */
+
+ /* save data to temporary file */
+ f = fopen(fname, "w");
+ if (f == NULL) {
+ nsgtk_warning("Error saving box tree dump.",
+ "Unable to open file for writing.");
+ unlink(fname);
+ return TRUE;
+ }
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_debug_dump(bw, f, CONTENT_DEBUG_RENDER);
+
+ fclose(f);
+
+ nsgtk_viewfile("Box Tree Debug", "boxtree", fname);
+
+ g_free(fname);
+
return TRUE;
}
+
/**
- * when titlebar / alt-F4 window close event happens
+ * handler for debug dom tree tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static gboolean nsgtk_toolbar_delete(GtkWidget *widget, GdkEvent *event,
- gpointer data)
+static gboolean
+debugdomtree_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- edit_mode = false;
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- /* reset g->buttons->location */
- for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- nsgtk_scaffolding_button(g, i)->location =
- window->buttonlocations[i];
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ gchar *fname;
+ gint handle;
+ FILE *f;
+
+ handle = g_file_open_tmp("nsgtkdomtreeXXXXXX", &fname, NULL);
+ if ((handle == -1) || (fname == NULL)) {
+ return TRUE;
}
- nsgtk_toolbar_set_physical(g);
- nsgtk_toolbar_connect_all(g);
- nsgtk_toolbar_close(g);
- nsgtk_scaffolding_set_sensitivity(g);
- gtk_widget_destroy(window->window);
+ close(handle); /* in case it was binary mode */
+
+ /* save data to temporary file */
+ f = fopen(fname, "w");
+ if (f == NULL) {
+ nsgtk_warning("Error saving box tree dump.",
+ "Unable to open file for writing.");
+ unlink(fname);
+ return TRUE;
+ }
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ browser_window_debug_dump(bw, f, CONTENT_DEBUG_DOM);
+
+ fclose(f);
+
+ nsgtk_viewfile("DOM Tree Debug", "domtree", fname);
+
+ g_free(fname);
+
return TRUE;
+
}
+
/**
- * called when a widget is dropped onto the store window
+ * handler for local history tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
static gboolean
-nsgtk_toolbar_store_return(GtkWidget *widget, GdkDragContext *gdc,
- gint x, gint y, guint time, gpointer data)
+localhistory_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- struct nsgtk_scaffolding *g = (struct nsgtk_scaffolding *)data;
- int q, i;
+ nserror res;
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+ GtkWidget *toplevel;
- if ((window->fromstore) || (window->currentbutton == -1)) {
- window->currentbutton = -1;
- return FALSE;
- }
- if (nsgtk_scaffolding_button(g, window->currentbutton)->location
- != -1) {
- /* 'move' all widgets further right, one place to the left
- * in logical schema */
- for (i = nsgtk_scaffolding_button(g, window->currentbutton)->
- location + 1; i < PLACEHOLDER_BUTTON; i++) {
- q = nsgtk_toolbar_get_id_at_location(g, i);
- if (q == -1)
- continue;
- nsgtk_scaffolding_button(g, q)->location--;
+ toplevel = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
+ if (toplevel != NULL) {
+ bw = tb->get_bw(tb->get_ctx);
+
+ res = nsgtk_local_history_present(GTK_WINDOW(toplevel), bw);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to present local history window.");
}
- gtk_container_remove(GTK_CONTAINER(
- nsgtk_scaffolding_toolbar(g)), GTK_WIDGET(
- nsgtk_scaffolding_button(g,
- window->currentbutton)->button));
- nsgtk_scaffolding_button(g, window->currentbutton)->location
- = -1;
- }
- window->currentbutton = -1;
- gtk_drag_finish(gdc, TRUE, TRUE, time);
- return FALSE;
+ }
+ return TRUE;
}
/**
- * called when hovering above the store
+ * handler for history tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
static gboolean
-nsgtk_toolbar_store_action(GtkWidget *widget, GdkDragContext *gdc,
- gint x, gint y, guint time, gpointer data)
+history_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- return FALSE;
+ return localhistory_button_clicked_cb(widget, data);
}
+
/**
- * create store window
+ * handler for global history tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
*/
-static void nsgtk_toolbar_window_open(struct nsgtk_scaffolding *g)
+static gboolean
+globalhistory_button_clicked_cb(GtkWidget *widget, gpointer data)
{
- struct nsgtk_theme *theme;
nserror res;
+ res = nsgtk_global_history_present();
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to initialise global history window.");
+ }
+ return TRUE;
+}
- theme = nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR, true);
- if (theme == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- nsgtk_toolbar_cancel_clicked(NULL, g);
- return;
+
+/**
+ * handler for add bookmark tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+addbookmarks_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct browser_window *bw;
+
+ bw = tb->get_bw(tb->get_ctx);
+ if (browser_window_has_content(bw)) {
+ hotlist_add_url(browser_window_access_url(bw));
}
+ return TRUE;
+}
+
- res = nsgtk_builder_new_from_resname("toolbar", &window->builder);
+/**
+ * handler for show bookmark tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+showbookmarks_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ res = nsgtk_hotlist_present();
if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Toolbar UI builder init failed");
- nsgtk_warning("Toolbar UI builder init failed", 0);
- nsgtk_toolbar_cancel_clicked(NULL, g);
- free(theme);
- return;
+ NSLOG(netsurf, INFO, "Unable to initialise bookmark window.");
}
+ return TRUE;
+}
- gtk_builder_connect_signals(window->builder, NULL);
- window->window = GTK_WIDGET(gtk_builder_get_object(
- window->builder, "dialogToolbar"));
- if (window->window == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- nsgtk_toolbar_cancel_clicked(NULL, g);
- free(theme);
- return;
+/**
+ * handler for show cookies tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+showcookies_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ nserror res;
+ res = nsgtk_cookies_present(NULL);
+ if (res != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to initialise cookies window.");
}
+ return TRUE;
+}
- gtk_window_set_transient_for(GTK_WINDOW(window->window),
- nsgtk_scaffolding_window(g));
- window->widgetvbox = GTK_WIDGET(gtk_builder_get_object(
- window->builder, "widgetvbox"));
- if (window->widgetvbox == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- nsgtk_toolbar_cancel_clicked(NULL, g);
- free(theme);
- return;
+/**
+ * handler for open location tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+openlocation_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ GtkToolItem *urltitem;
+
+ urltitem = tb->items[URL_BAR_ITEM].button;
+ if (urltitem != NULL) {
+ GtkEntry *entry;
+ entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(urltitem)));
+ gtk_widget_grab_focus(GTK_WIDGET(entry));
}
+ return TRUE;
+}
- /* preset to width [in buttons] of */
- window->numberh = NSGTK_STORE_WIDTH;
- /* store to cause creation of a new toolbar */
- window->currentbutton = -1;
+/**
+ * handler for contents tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+contents_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ nserror res;
- /* load toolbuttons */
- /* add toolbuttons to window */
- /* set event handlers */
- for (int i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- if (i == URL_BAR_ITEM)
- continue;
- window->store_buttons[i] =
- nsgtk_toolbar_make_widget(g, i, theme);
- if (window->store_buttons[i] == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- continue;
- }
- nsgtk_toolbar_add_store_widget(window->store_buttons[i]);
- g_signal_connect(window->store_buttons[i], "drag-data-get",
- G_CALLBACK(
- nsgtk_scaffolding_button(g, i)->dataplus), g);
+ res = toolbar_navigate_to_url(tb, "https://www.netsurf-browser.org/documentation/");
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
+
+ return TRUE;
+}
+
+/**
+ * handler for contents tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+guide_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ nserror res;
+
+ res = toolbar_navigate_to_url(tb, "https://www.netsurf-browser.org/documentation/guide");
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
}
- free(theme);
+ return TRUE;
+}
+
+
+/**
+ * handler for contents tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean
+info_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ nserror res;
- gtk_window_set_accept_focus(GTK_WINDOW(window->window), FALSE);
+ res = toolbar_navigate_to_url(tb, "https://www.netsurf-browser.org/documentation/info");
+ if (res != NSERROR_OK) {
+ nsgtk_warning(messages_get_errorcode(res), 0);
+ }
- gtk_drag_dest_set(GTK_WIDGET(window->window), GTK_DEST_DEFAULT_MOTION |
- GTK_DEST_DEFAULT_DROP, &entry, 1, GDK_ACTION_COPY);
+ return TRUE;
+}
- g_signal_connect(GTK_WIDGET(gtk_builder_get_object(
- window->builder, "close")),
- "clicked",
- G_CALLBACK(nsgtk_toolbar_persist),
- g);
- g_signal_connect(GTK_WIDGET(gtk_builder_get_object(
- window->builder, "reset")),
- "clicked",
- G_CALLBACK(nsgtk_toolbar_reset),
- g);
+/**
+ * handler for contents tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE
+ */
+static gboolean about_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ GtkWindow *parent; /* gtk window widget is in */
+
+ parent = GTK_WINDOW(gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW));
+
+ nsgtk_about_dialog_init(parent);
+ return TRUE;
+}
+
+/**
+ * handler for openmenu tool bar item clicked signal
+ *
+ * \param widget The widget the signal is being delivered to.
+ * \param data The toolbar context passed when the signal was connected
+ * \return TRUE to indicate signal handled.
+ */
+static gboolean openmenu_button_clicked_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct gui_window *gw;
+ struct nsgtk_scaffolding *gs;
+
+ gw = tb->get_ctx; /** \todo stop assuming the context is a gui window */
- g_signal_connect(window->window, "delete-event",
- G_CALLBACK(nsgtk_toolbar_delete), g);
+ gs = nsgtk_get_scaffold(gw);
- g_signal_connect(window->window, "drag-drop",
- G_CALLBACK(nsgtk_toolbar_store_return), g);
+ nsgtk_scaffolding_burger_menu(gs);
+
+ return TRUE;
+}
- g_signal_connect(window->window, "drag-motion",
- G_CALLBACK(nsgtk_toolbar_store_action), g);
- gtk_widget_show_all(window->window);
+/* define data plus and data minus handlers */
+#define TOOLBAR_ITEM(identifier, name, snstvty, clicked, activate, label, iconame) \
+static gboolean \
+nsgtk_toolbar_##name##_data_plus(GtkWidget *widget, \
+ GdkDragContext *cont, \
+ GtkSelectionData *selection, \
+ guint info, \
+ guint time, \
+ gpointer data) \
+{ \
+ struct nsgtk_toolbar_customisation *tbc; \
+ tbc = (struct nsgtk_toolbar_customisation *)data; \
+ tbc->dragitem = identifier; \
+ tbc->dragfrom = true; \
+ return TRUE; \
+} \
+static gboolean \
+nsgtk_toolbar_##name##_data_minus(GtkWidget *widget, \
+ GdkDragContext *cont, \
+ GtkSelectionData *selection, \
+ guint info, \
+ guint time, \
+ gpointer data) \
+{ \
+ struct nsgtk_toolbar_customisation *tbc; \
+ tbc = (struct nsgtk_toolbar_customisation *)data; \
+ tbc->dragitem = identifier; \
+ tbc->dragfrom = false; \
+ return TRUE; \
}
+#include "gtk/toolbar_items.h"
+
+#undef TOOLBAR_ITEM
+
+
/**
- * change behaviour of scaffoldings while editing toolbar
+ * create a toolbar item
*
- * All buttons as well as window clicks are desensitized; then buttons
- * in the front window are changed to movable buttons
+ * create a toolbar item and set up its default handlers
*/
-void nsgtk_toolbar_customization_init(struct nsgtk_scaffolding *g)
+static nserror
+toolbar_item_create(nsgtk_toolbar_button id, struct nsgtk_toolbar_item *item)
{
- int i;
- struct nsgtk_scaffolding *list;
- edit_mode = true;
+ item->location = INACTIVE_LOCATION;
+
+ /* set item defaults from macro */
+ switch (id) {
+#define TOOLBAR_ITEM_t(name) \
+ item->clicked = name##_button_clicked_cb;
+#define TOOLBAR_ITEM_b(name) \
+ item->clicked = name##_button_clicked_cb;
+#define TOOLBAR_ITEM_y(name) \
+ item->clicked = name##_button_clicked_cb;
+#define TOOLBAR_ITEM_n(name) \
+ item->clicked = NULL;
+#define TOOLBAR_ITEM(identifier, iname, snstvty, clicked, activate, label, iconame) \
+ case identifier: \
+ item->name = #iname; \
+ item->sensitivity = snstvty; \
+ item->dataplus = nsgtk_toolbar_##iname##_data_plus; \
+ item->dataminus = nsgtk_toolbar_##iname##_data_minus; \
+ TOOLBAR_ITEM_ ## clicked(iname) \
+ break;
- list = nsgtk_scaffolding_iterate(NULL);
- while (list) {
- g_signal_handler_block(GTK_WIDGET(
- nsgtk_window_get_layout(
- nsgtk_scaffolding_top_level(list))),
- nsgtk_window_get_signalhandler(
- nsgtk_scaffolding_top_level(list),
- NSGTK_WINDOW_SIGNAL_CLICK));
- g_signal_handler_block(GTK_WIDGET(
- nsgtk_window_get_layout(
- nsgtk_scaffolding_top_level(list))),
- nsgtk_window_get_signalhandler(
- nsgtk_scaffolding_top_level(list),
- NSGTK_WINDOW_SIGNAL_REDRAW));
- nsgtk_widget_override_background_color(
- GTK_WIDGET(nsgtk_window_get_layout(
- nsgtk_scaffolding_top_level(list))),
- GTK_STATE_NORMAL, 0, 0xEEEE, 0xEEEE, 0xEEEE);
+#include "gtk/toolbar_items.h"
- if (list == g) {
- list = nsgtk_scaffolding_iterate(list);
- continue;
- }
- /* set sensitive for all gui_windows save g */
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_window(
- list)), FALSE);
- list = nsgtk_scaffolding_iterate(list);
- }
- /* set sensitive for all of g save toolbar */
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_menu_bar(g)),
- FALSE);
- gtk_widget_set_sensitive(GTK_WIDGET(nsgtk_scaffolding_notebook(g)),
- FALSE);
-
- /* set editable aspect for toolbar */
- gtk_container_foreach(GTK_CONTAINER(nsgtk_scaffolding_toolbar(g)),
- nsgtk_toolbar_clear_toolbar, g);
- nsgtk_toolbar_set_physical(g);
- /* memorize button locations, set editable */
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- window->buttonlocations[i] = nsgtk_scaffolding_button(g, i)
- ->location;
- if ((window->buttonlocations[i] == -1) || (i == URL_BAR_ITEM))
- continue;
- gtk_tool_item_set_use_drag_window(GTK_TOOL_ITEM(
- nsgtk_scaffolding_button(g, i)->button), TRUE);
- gtk_drag_source_set(GTK_WIDGET(nsgtk_scaffolding_button(
- g, i)->button), GDK_BUTTON1_MASK, &entry, 1,
- GDK_ACTION_COPY);
- nsgtk_toolbar_temp_connect(g, i);
+#undef TOOLBAR_ITEM_t
+#undef TOOLBAR_ITEM_y
+#undef TOOLBAR_ITEM_n
+#undef TOOLBAR_ITEM
+
+ case PLACEHOLDER_BUTTON:
+ return NSERROR_INVALID;
}
- /* add move button listeners */
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)),
- "drag-drop", G_CALLBACK(nsgtk_toolbar_data), g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)),
- "drag-data-received", G_CALLBACK(
- nsgtk_toolbar_move_complete), g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)),
- "drag-motion", G_CALLBACK(nsgtk_toolbar_action), g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)),
- "drag-leave", G_CALLBACK(
- nsgtk_toolbar_clear), g);
+ return NSERROR_OK;
+}
- /* set data types */
- gtk_drag_dest_set(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)),
- GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
- &entry, 1, GDK_ACTION_COPY);
- /* open toolbar window */
- nsgtk_toolbar_window_open(g);
+/**
+ * set a toolbar item to a throbber frame number
+ *
+ * \param toolbar_item The toolbar item to update
+ * \param frame The animation frame number to update to
+ * \return NSERROR_OK on success,
+ * NSERROR_INVALID if the toolbar item does not contain an image,
+ * NSERROR_BAD_SIZE if the frame is out of range.
+ */
+static nserror set_throbber_frame(GtkToolItem *toolbar_item, int frame)
+{
+ nserror res;
+ GdkPixbuf *pixbuf;
+ GtkImage *throbber;
+
+ if (toolbar_item == NULL) {
+ /* no toolbar item */
+ return NSERROR_INVALID;
+ }
+
+ res = nsgtk_throbber_get_frame(frame, &pixbuf);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ throbber = GTK_IMAGE(gtk_bin_get_child(GTK_BIN(toolbar_item)));
+
+ gtk_image_set_from_pixbuf(throbber, pixbuf);
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * Make the throbber run.
+ *
+ * scheduled callback to update the throbber
+ *
+ * \param p The context passed when scheduled.
+ */
+static void next_throbber_frame(void *p)
+{
+ struct nsgtk_toolbar *tb = p;
+ nserror res;
+
+ tb->throb_frame++; /* advance to next frame */
+
+ res = set_throbber_frame(tb->items[THROBBER_ITEM].button,
+ tb->throb_frame);
+ if (res == NSERROR_BAD_SIZE) {
+ tb->throb_frame = 1;
+ res = set_throbber_frame(tb->items[THROBBER_ITEM].button,
+ tb->throb_frame);
+ }
+
+ /* only schedule next frame if there are no errors */
+ if (res == NSERROR_OK) {
+ nsgtk_schedule(THROBBER_FRAME_TIME, next_throbber_frame, p);
+ }
}
+
/**
- * set toolbar logical -> physical; physically visible toolbar buttons are made
- * to correspond to the logically stored schema in terms of location
- * visibility etc
+ * connect signal handlers to a gtk toolbar item
*/
-void nsgtk_toolbar_set_physical(struct nsgtk_scaffolding *g)
+static nserror
+toolbar_connect_signal(struct nsgtk_toolbar *tb, nsgtk_toolbar_button itemid)
{
- int i;
- struct nsgtk_theme *theme;
+ struct nsgtk_toolbar_item *item;
+ GtkEntry *entry;
- theme = nsgtk_theme_load(GTK_ICON_SIZE_LARGE_TOOLBAR, false);
- if (theme == NULL) {
- nsgtk_warning(messages_get("NoMemory"), 0);
- return;
+ item = &tb->items[itemid];
+
+ if (item->button != NULL) {
+ g_signal_connect(item->button,
+ "size-allocate",
+ G_CALLBACK(toolbar_item_size_allocate_cb),
+ tb);
}
- /* simplest is to clear the toolbar then reload it from memory */
- gtk_container_foreach(GTK_CONTAINER(nsgtk_scaffolding_toolbar(g)),
- nsgtk_toolbar_clear_toolbar, g);
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- nsgtk_toolbar_add_item_to_toolbar(g, i, theme);
+
+ switch (itemid) {
+ case URL_BAR_ITEM:
+ entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(item->button)));
+
+ g_signal_connect(GTK_WIDGET(entry),
+ "activate",
+ G_CALLBACK(url_entry_activate_cb),
+ tb);
+ g_signal_connect(GTK_WIDGET(entry),
+ "changed",
+ G_CALLBACK(url_entry_changed_cb),
+ tb);
+ g_signal_connect(GTK_WIDGET(entry),
+ "icon-release",
+ G_CALLBACK(url_entry_icon_release_cb),
+ tb);
+
+ nsgtk_completion_connect_signals(entry,
+ tb->get_bw,
+ tb->get_ctx);
+ break;
+
+
+ case WEBSEARCH_ITEM:
+ entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(item->button)));
+
+ g_signal_connect(GTK_WIDGET(entry),
+ "activate",
+ G_CALLBACK(websearch_entry_activate_cb),
+ tb);
+ g_signal_connect(GTK_WIDGET(entry),
+ "button-press-event",
+ G_CALLBACK(websearch_entry_button_press_cb),
+ tb);
+ break;
+
+ default:
+ if ((item->clicked != NULL) && (item->button != NULL)) {
+ g_signal_connect(item->button,
+ "clicked",
+ G_CALLBACK(item->clicked),
+ tb);
+ }
+ break;
+
}
- gtk_widget_show_all(GTK_WIDGET(nsgtk_scaffolding_toolbar(g)));
- free(theme);
+
+ return NSERROR_OK;
}
/**
- * \return toolbar item id when a widget is an element of the scaffolding
- * else -1
+ * connect all signals to widgets in a toolbar
*/
-int nsgtk_toolbar_get_id_from_widget(GtkWidget *widget,
- struct nsgtk_scaffolding *g)
+static nserror toolbar_connect_signals(struct nsgtk_toolbar *tb)
{
- int i;
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- if ((nsgtk_scaffolding_button(g, i)->location != -1)
- && (widget == GTK_WIDGET(
- nsgtk_scaffolding_button(g, i)->button))) {
- return i;
+ int location; /* location index */
+ nsgtk_toolbar_button itemid; /* item id */
+
+ for (location = BACK_BUTTON; location < PLACEHOLDER_BUTTON; location++) {
+ itemid = itemid_from_location(tb, location);
+ if (itemid == PLACEHOLDER_BUTTON) {
+ /* no more filled locations */
+ break;
}
+ toolbar_connect_signal(tb, itemid);
}
- return -1;
+
+ return NSERROR_OK;
}
/**
- * add handlers to factory widgets
- * \param g the scaffolding to attach handlers to
- * \param i the toolbar item id
+ * signal handler for toolbar context menu
+ *
+ * \param toolbar The toolbar event is being delivered to
+ * \param x The x coordinate where the click happened
+ * \param y The x coordinate where the click happened
+ * \param button the buttons being pressed
+ * \param data The context pointer passed when the connection was made.
+ * \return TRUE to indicate signal handled.
*/
-static void
-nsgtk_toolbar_set_handler(struct nsgtk_scaffolding *g, nsgtk_toolbar_button i)
+static gboolean
+toolbar_popup_context_menu_cb(GtkToolbar *toolbar,
+ gint x,
+ gint y,
+ gint button,
+ gpointer data)
{
- switch(i){
- case URL_BAR_ITEM:
- nsgtk_scaffolding_update_url_bar_ref(g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_urlbar(g)),
- "activate", G_CALLBACK(
- nsgtk_window_url_activate_event), g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_urlbar(g)),
- "changed", G_CALLBACK(
- nsgtk_window_url_changed), g);
+ struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
+ struct gui_window *gw;
+ struct nsgtk_scaffolding *gs;
+
+ gw = tb->get_ctx; /** \todo stop assuming the context is a gui window */
+
+ gs = nsgtk_get_scaffold(gw);
+
+ nsgtk_scaffolding_toolbar_context_menu(gs);
+
+ return TRUE;
+}
+
+
+/**
+ * toolbar delete signal handler
+ */
+static void toolbar_destroy_cb(GtkWidget *widget, gpointer data)
+{
+ struct nsgtk_toolbar *tb;
+ tb = (struct nsgtk_toolbar *)data;
+
+ /* ensure any throbber scheduled is stopped */
+ nsgtk_schedule(-1, next_throbber_frame, tb);
+
+ free(tb);
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror
+nsgtk_toolbar_create(GtkBuilder *builder,
+ struct browser_window *(*get_bw)(void *ctx),
+ void *get_ctx,
+ bool want_location_focus,
+ struct nsgtk_toolbar **tb_out)
+{
+ nserror res;
+ struct nsgtk_toolbar *tb;
+ int bidx; /* button index */
+
+ tb = calloc(1, sizeof(struct nsgtk_toolbar));
+ if (tb == NULL) {
+ return NSERROR_NOMEM;
+ }
+
+ tb->get_bw = get_bw;
+ tb->get_ctx = get_ctx;
+ /* set the throbber start frame. */
+ tb->throb_frame = 0;
+ if (want_location_focus) {
+ tb->loc_focus = LFS_WANT;
+ } else {
+ tb->loc_focus = LFS_IDLE;
+ }
+
+ tb->widget = GTK_TOOLBAR(gtk_builder_get_object(builder, "toolbar"));
+ gtk_toolbar_set_show_arrow(tb->widget, TRUE);
+
+ g_signal_connect(tb->widget,
+ "popup-context-menu",
+ G_CALLBACK(toolbar_popup_context_menu_cb),
+ tb);
+
+ /* close and cleanup on delete signal */
+ g_signal_connect(tb->widget,
+ "destroy",
+ G_CALLBACK(toolbar_destroy_cb),
+ tb);
+
+ /* allocate button contexts */
+ for (bidx = BACK_BUTTON; bidx < PLACEHOLDER_BUTTON; bidx++) {
+ res = toolbar_item_create(bidx, &tb->items[bidx]);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+ }
+
+ res = nsgtk_toolbar_update(tb);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ *tb_out = tb;
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_restyle(struct nsgtk_toolbar *tb)
+{
+ /*
+ * reset toolbar size allocation so icon size change affects
+ * allocated widths.
+ */
+ tb->offset = 0;
+
+ switch (nsoption_int(button_type)) {
+
+ case 1: /* Small icons */
+ gtk_toolbar_set_style(GTK_TOOLBAR(tb->widget),
+ GTK_TOOLBAR_ICONS);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(tb->widget),
+ GTK_ICON_SIZE_SMALL_TOOLBAR);
break;
- case THROBBER_ITEM:
- nsgtk_scaffolding_update_throbber_ref(g);
+ case 2: /* Large icons */
+ gtk_toolbar_set_style(GTK_TOOLBAR(tb->widget),
+ GTK_TOOLBAR_ICONS);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(tb->widget),
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
break;
- case WEBSEARCH_ITEM:
- nsgtk_scaffolding_update_websearch_ref(g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_websearch(g)),
- "activate", G_CALLBACK(
- nsgtk_websearch_activate), g);
- g_signal_connect(GTK_WIDGET(nsgtk_scaffolding_websearch(g)),
- "button-press-event", G_CALLBACK(
- nsgtk_websearch_clear), g);
+ case 3: /* Large icons with text */
+ gtk_toolbar_set_style(GTK_TOOLBAR(tb->widget),
+ GTK_TOOLBAR_BOTH);
+ gtk_toolbar_set_icon_size(GTK_TOOLBAR(tb->widget),
+ GTK_ICON_SIZE_LARGE_TOOLBAR);
+ break;
+
+ case 4: /* Text icons only */
+ gtk_toolbar_set_style(GTK_TOOLBAR(tb->widget),
+ GTK_TOOLBAR_TEXT);
break;
default:
- if ((nsgtk_scaffolding_button(g, i)->bhandler != NULL) &&
- (nsgtk_scaffolding_button(g, i)->button != NULL)) {
- g_signal_connect(
- nsgtk_scaffolding_button(g, i)->button,
- "clicked",
- G_CALLBACK(nsgtk_scaffolding_button(
- g, i)->bhandler), g);
+ break;
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_throbber(struct nsgtk_toolbar *tb, bool active)
+{
+ nserror res;
+ struct browser_window *bw;
+
+ /* Manage the location focus state */
+ switch (tb->loc_focus) {
+ case LFS_IDLE:
+ break;
+ case LFS_WANT:
+ if (active) {
+ tb->loc_focus = LFS_THROB;
+ }
+ break;
+ case LFS_THROB:
+ if (!active) {
+ tb->loc_focus = LFS_LAST;
}
break;
+ case LFS_LAST:
+ break;
+ }
+
+ /* when activating the throbber simply schedule the next frame update */
+ if (active) {
+ nsgtk_schedule(THROBBER_FRAME_TIME, next_throbber_frame, tb);
+
+ set_item_sensitivity(&tb->items[STOP_BUTTON], true);
+ set_item_sensitivity(&tb->items[RELOAD_BUTTON], false);
+ set_item_action(tb, RELOADSTOP_BUTTON, false);
+
+ return NSERROR_OK;
+ }
+
+ /* stopping the throbber */
+ nsgtk_schedule(-1, next_throbber_frame, tb);
+ tb->throb_frame = 0;
+ res = set_throbber_frame(tb->items[THROBBER_ITEM].button,
+ tb->throb_frame);
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ /* adjust sensitivity of other items */
+ set_item_sensitivity(&tb->items[STOP_BUTTON], false);
+ set_item_sensitivity(&tb->items[RELOAD_BUTTON], true);
+ set_item_action(tb, RELOADSTOP_BUTTON, true);
+ set_item_sensitivity(&tb->items[BACK_BUTTON],
+ browser_window_history_back_available(bw));
+ set_item_sensitivity(&tb->items[FORWARD_BUTTON],
+ browser_window_history_forward_available(bw));
+ nsgtk_local_history_hide();
+
+ return res;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_page_info_change(struct nsgtk_toolbar *tb)
+{
+ GtkEntry *url_entry;
+ browser_window_page_info_state pistate;
+ struct browser_window *bw;
+ const char *icon_name;
+
+ if (tb->items[URL_BAR_ITEM].button == NULL) {
+ /* no toolbar item */
+ return NSERROR_INVALID;
+ }
+ url_entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(tb->items[URL_BAR_ITEM].button)));
+
+ bw = tb->get_bw(tb->get_ctx);
+
+ pistate = browser_window_get_page_info_state(bw);
+
+ switch (pistate) {
+ case PAGE_STATE_INTERNAL:
+ icon_name = "page-info-internal";
+ break;
+
+ case PAGE_STATE_LOCAL:
+ icon_name = "page-info-local";
+ break;
+
+ case PAGE_STATE_INSECURE:
+ icon_name = "page-info-insecure";
+ break;
+
+ case PAGE_STATE_SECURE_OVERRIDE:
+ icon_name = "page-info-warning";
+ break;
+
+ case PAGE_STATE_SECURE_ISSUES:
+ icon_name = "page-info-warning";
+ break;
+
+ case PAGE_STATE_SECURE:
+ icon_name = "page-info-secure";
+ break;
+
+ default:
+ icon_name = "page-info-internal";
+ break;
+ }
+
+ nsgtk_entry_set_icon_from_icon_name(GTK_WIDGET(url_entry),
+ GTK_ENTRY_ICON_PRIMARY,
+ icon_name);
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_set_url(struct nsgtk_toolbar *tb, nsurl *url)
+{
+ size_t idn_url_l;
+ char *idn_url_s = NULL;
+ const char *url_text = NULL;
+ GtkEntry *url_entry;
+
+ if (tb->items[URL_BAR_ITEM].button == NULL) {
+ /* no toolbar item */
+ return NSERROR_INVALID;
+ }
+ url_entry = GTK_ENTRY(gtk_bin_get_child(GTK_BIN(tb->items[URL_BAR_ITEM].button)));
+
+ if (nsoption_bool(display_decoded_idn) == true) {
+ if (nsurl_get_utf8(url, &idn_url_s, &idn_url_l) != NSERROR_OK) {
+ idn_url_s = NULL;
+ }
+ url_text = idn_url_s;
+ }
+ if (url_text == NULL) {
+ url_text = nsurl_access(url);
+ }
+
+ if (strcmp(url_text, gtk_entry_get_text(url_entry)) != 0) {
+ /* The URL bar content has changed, we need to update it */
+ gint startpos, endpos;
+ bool was_selected;
+ gtk_editable_get_selection_bounds(GTK_EDITABLE(url_entry),
+ &startpos, &endpos);
+ was_selected = gtk_widget_is_focus(GTK_WIDGET(url_entry)) &&
+ startpos == 0 &&
+ endpos == gtk_entry_get_text_length(url_entry);
+ gtk_entry_set_text(url_entry, url_text);
+ if (was_selected && tb->loc_focus != LFS_IDLE) {
+ gtk_widget_grab_focus(GTK_WIDGET(url_entry));
+ if (tb->loc_focus == LFS_LAST) {
+ tb->loc_focus = LFS_IDLE;
+ }
+ }
}
+
+ if (idn_url_s != NULL) {
+ free(idn_url_s);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror
+nsgtk_toolbar_set_websearch_image(struct nsgtk_toolbar *tb, GdkPixbuf *pixbuf)
+{
+ GtkWidget *entry;
+
+ if (tb->items[WEBSEARCH_ITEM].button == NULL) {
+ /* no toolbar item */
+ return NSERROR_INVALID;
+ }
+
+ entry = gtk_bin_get_child(GTK_BIN(tb->items[WEBSEARCH_ITEM].button));
+
+ if (pixbuf != NULL) {
+ nsgtk_entry_set_icon_from_pixbuf(entry,
+ GTK_ENTRY_ICON_PRIMARY,
+ pixbuf);
+ } else {
+ nsgtk_entry_set_icon_from_icon_name(entry,
+ GTK_ENTRY_ICON_PRIMARY,
+ NSGTK_STOCK_INFO);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror
+nsgtk_toolbar_item_activate(struct nsgtk_toolbar *tb,
+ nsgtk_toolbar_button itemid)
+{
+ GtkWidget *widget;
+
+ /* ensure item id in range */
+ if ((itemid < BACK_BUTTON) || (itemid >= PLACEHOLDER_BUTTON)) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
+ if (tb->items[itemid].clicked == NULL) {
+ return NSERROR_INVALID;
+ }
+
+ /*
+ * if item has a widget in the current toolbar use that as the
+ * signal source otherwise use the toolbar widget itself.
+ */
+ if (tb->items[itemid].button != NULL) {
+ widget = GTK_WIDGET(tb->items[itemid].button);
+ } else {
+ widget = GTK_WIDGET(tb->widget);
+ }
+
+ tb->items[itemid].clicked(widget, tb);
+
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_show(struct nsgtk_toolbar *tb, bool show)
+{
+ if (show) {
+ gtk_widget_show(GTK_WIDGET(tb->widget));
+ } else {
+ gtk_widget_hide(GTK_WIDGET(tb->widget));
+ }
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_update(struct nsgtk_toolbar *tb)
+{
+ nserror res;
+
+ /* setup item locations based on user config */
+ res = apply_user_button_customisation(tb);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* populate toolbar widget */
+ res = populate_gtk_toolbar_widget(tb);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ /* ensure icon sizes and text labels on toolbar are set */
+ res = nsgtk_toolbar_restyle(tb);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ res = toolbar_connect_signals(tb);
+
+ return res;
}
/**
- * connect 'normal' handlers to toolbar buttons
+ * Find the correct location for popping up a window for the chosen item.
+ *
+ * \param tb The toolbar to select from
+ * \param item_idx The toolbar item to select from
+ * \param out_x Filled with an appropriate X coordinate
+ * \param out_y Filled with an appropriate Y coordinate
*/
-void nsgtk_toolbar_connect_all(struct nsgtk_scaffolding *g)
+static nserror
+nsgtk_toolbar_get_icon_window_position(struct nsgtk_toolbar *tb,
+ int item_idx,
+ int *out_x,
+ int *out_y)
{
- int q, i;
- for (i = BACK_BUTTON; i < PLACEHOLDER_BUTTON; i++) {
- q = nsgtk_toolbar_get_id_at_location(g, i);
- if (q == -1)
- continue;
- if (nsgtk_scaffolding_button(g, q)->button != NULL)
- g_signal_connect(
- nsgtk_scaffolding_button(g, q)->button,
- "size-allocate", G_CALLBACK(
- nsgtk_scaffolding_toolbar_size_allocate
- ), g);
- nsgtk_toolbar_set_handler(g, q);
- }
-}
-
-
-#define DATAHANDLER(p, q, r)\
-gboolean nsgtk_toolbar_##p##_button_data(GtkWidget *widget, GdkDragContext\
- *cont, GtkSelectionData *selection, guint info, guint time,\
- gpointer data)\
-{\
- r->currentbutton = q##_BUTTON;\
- r->fromstore = true;\
- return TRUE;\
-}\
-gboolean nsgtk_toolbar_##p##_toolbar_button_data(GtkWidget *widget,\
- GdkDragContext *cont, GtkSelectionData *selection, guint info,\
- guint time, gpointer data)\
-{\
- r->currentbutton = q##_BUTTON;\
- r->fromstore = false;\
- return TRUE;\
-}
-
-DATAHANDLER(home, HOME, window)
-DATAHANDLER(forward, FORWARD, window)
-DATAHANDLER(back, BACK, window)
-DATAHANDLER(stop, STOP, window)
-DATAHANDLER(reload, RELOAD, window)
-DATAHANDLER(history, HISTORY, window)
-DATAHANDLER(newwindow, NEWWINDOW, window)
-DATAHANDLER(newtab, NEWTAB, window)
-DATAHANDLER(openfile, OPENFILE, window)
-DATAHANDLER(closetab, CLOSETAB, window)
-DATAHANDLER(closewindow, CLOSEWINDOW, window)
-DATAHANDLER(savepage, SAVEPAGE, window)
-DATAHANDLER(printpreview, PRINTPREVIEW, window)
-DATAHANDLER(print, PRINT, window)
-DATAHANDLER(quit, QUIT, window)
-DATAHANDLER(cut, CUT, window)
-DATAHANDLER(copy, COPY, window)
-DATAHANDLER(paste, PASTE, window)
-DATAHANDLER(delete, DELETE, window)
-DATAHANDLER(selectall, SELECTALL, window)
-DATAHANDLER(preferences, PREFERENCES, window)
-DATAHANDLER(zoomplus, ZOOMPLUS, window)
-DATAHANDLER(zoomminus, ZOOMMINUS, window)
-DATAHANDLER(zoomnormal, ZOOMNORMAL, window)
-DATAHANDLER(fullscreen, FULLSCREEN, window)
-DATAHANDLER(viewsource, VIEWSOURCE, window)
-DATAHANDLER(contents, CONTENTS, window)
-DATAHANDLER(about, ABOUT, window)
-DATAHANDLER(pdf, PDF, window)
-DATAHANDLER(plaintext, PLAINTEXT, window)
-DATAHANDLER(drawfile, DRAWFILE, window)
-DATAHANDLER(postscript, POSTSCRIPT, window)
-DATAHANDLER(find, FIND, window)
-DATAHANDLER(downloads, DOWNLOADS, window)
-DATAHANDLER(savewindowsize, SAVEWINDOWSIZE, window)
-DATAHANDLER(toggledebugging, TOGGLEDEBUGGING, window)
-DATAHANDLER(debugboxtree, SAVEBOXTREE, window)
-DATAHANDLER(debugdomtree, SAVEDOMTREE, window)
-DATAHANDLER(localhistory, LOCALHISTORY, window)
-DATAHANDLER(globalhistory, GLOBALHISTORY, window)
-DATAHANDLER(addbookmarks, ADDBOOKMARKS, window)
-DATAHANDLER(showbookmarks, SHOWBOOKMARKS, window)
-DATAHANDLER(showcookies, SHOWCOOKIES, window)
-DATAHANDLER(openlocation, OPENLOCATION, window)
-DATAHANDLER(nexttab, NEXTTAB, window)
-DATAHANDLER(prevtab, PREVTAB, window)
-DATAHANDLER(guide, GUIDE, window)
-DATAHANDLER(info, INFO, window)
-#undef DATAHANDLER
-
-#define DATAHANDLER(p, q, r) \
-gboolean nsgtk_toolbar_##p##_button_data(GtkWidget *widget, GdkDragContext\
- *cont, GtkSelectionData *selection, guint info, guint time,\
- gpointer data)\
-{\
- r->currentbutton = q##_ITEM;\
- r->fromstore = true;\
- return TRUE;\
-}\
-gboolean nsgtk_toolbar_##p##_toolbar_button_data(GtkWidget *widget,\
- GdkDragContext *cont, GtkSelectionData *selection, guint info,\
- guint time, gpointer data)\
-{\
- r->currentbutton = q##_ITEM;\
- r->fromstore = false;\
- return TRUE;\
-}
-
-DATAHANDLER(throbber, THROBBER, window)
-DATAHANDLER(websearch, WEBSEARCH, window)
-#undef DATAHANDLER
+ struct nsgtk_toolbar_item *item = &tb->items[item_idx];
+ GtkWidget *widget = GTK_WIDGET(item->button);
+ GtkAllocation alloc;
+ gint rootx, rooty, x, y;
+
+ switch (item_idx) {
+ case URL_BAR_ITEM:
+ widget = GTK_WIDGET(gtk_bin_get_child(GTK_BIN(item->button)));
+ break;
+ default:
+ /* Nothing to do here */
+ break;
+ }
+
+ nsgtk_widget_get_allocation(widget, &alloc);
+
+ if (gtk_widget_translate_coordinates(widget,
+ gtk_widget_get_toplevel(widget),
+ 0,
+ alloc.height - 1,
+ &x, &y) != TRUE) {
+ return NSERROR_UNKNOWN;
+ }
+
+ gtk_window_get_position(GTK_WINDOW(gtk_widget_get_toplevel(widget)),
+ &rootx, &rooty);
+
+ *out_x = rootx + x + 4;
+ *out_y = rooty + y + 4;
+
+ return NSERROR_OK;
+}
+
+nserror nsgtk_toolbar_position_page_info(struct nsgtk_toolbar *tb,
+ struct nsgtk_pi_window *win)
+{
+ nserror res;
+ int x, y;
+
+ res = nsgtk_toolbar_get_icon_window_position(tb, URL_BAR_ITEM, &x, &y);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ nsgtk_page_info_set_position(win, x, y);
+
+ return NSERROR_OK;
+}
+
+/* exported interface documented in toolbar.h */
+nserror nsgtk_toolbar_position_local_history(struct nsgtk_toolbar *tb)
+{
+ nserror res;
+ int x, y;
+
+ res = nsgtk_toolbar_get_icon_window_position(tb, HISTORY_BUTTON, &x, &y);
+ if (res != NSERROR_OK) {
+ return res;
+ }
+
+ nsgtk_local_history_set_position(x, y);
+
+ return NSERROR_OK;
+}
diff --git a/frontends/gtk/toolbar.h b/frontends/gtk/toolbar.h
index 4286fe3f0..4ecca9f02 100644
--- a/frontends/gtk/toolbar.h
+++ b/frontends/gtk/toolbar.h
@@ -16,77 +16,127 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _NETSURF_GTK_TOOLBAR_H_
-#define _NETSURF_GTK_TOOLBAR_H_
+#ifndef NETSURF_GTK_TOOLBAR_H_
+#define NETSURF_GTK_TOOLBAR_H_
/**
- * sets up the images for scaffolding.
+ * control toolbar context
*/
-void nsgtk_theme_implement(struct nsgtk_scaffolding *g);
+struct nsgtk_toolbar;
+struct nsgtk_scaffolding;
+/**
+ * create a control toolbar
+ *
+ * \param[in] builder The gtk builder object the toolbar is being created from
+ * \param[out] toolbar a pointer to receive the result.
+ * \return NSERROR_OK and toolbar updated on success else error code
+ */
+nserror nsgtk_toolbar_create(GtkBuilder *builder,
+ struct browser_window *(*get_bw)(void *ctx),
+ void *get_bw_ctx,
+ bool want_location_focus,
+ struct nsgtk_toolbar **toolbar);
+
+
+/**
+ * Update the toolbar items being shown based on current settings
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_update(struct nsgtk_toolbar *tb);
+
+
+/**
+ * Update toolbar style and size based on current settings
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_restyle(struct nsgtk_toolbar *tb);
+
+
+/**
+ * Start or stop a throbber in a toolbar
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \param active True if the throbber animation should play.
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_throbber(struct nsgtk_toolbar *tb, bool active);
+
+
+/**
+ * Page info has changed state
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_page_info_change(struct nsgtk_toolbar *tb);
+
+
+/**
+ * Update the toolbar url entry
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \param url The URL to set
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_set_url(struct nsgtk_toolbar *tb, nsurl *url);
+
+
+/**
+ * set the websearch image
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \param pixbuf The pixel buffer data to use to set the web search icon
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_set_websearch_image(struct nsgtk_toolbar *tb, GdkPixbuf *pixbuf);
+
+
+/**
+ * activate the handler for a toolbar item
+ *
+ * This allows the same action to be performed for menu enties as if
+ * the user had clicked the toolbar widget.
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \param itemid the id of the item to activate
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_item_activate(struct nsgtk_toolbar *tb, nsgtk_toolbar_button itemid);
+
+/**
+ * set the toolbar to be shown or hidden
+ *
+ * \param toolbar A toolbar returned from a creation
+ * \param show true to show the toolbar and false to hide it.
+ * \return NSERROR_OK on success
+ */
+nserror nsgtk_toolbar_show(struct nsgtk_toolbar *tb, bool show);
+
+/**
+ * position the page info window appropriately
+ *
+ * \param tb The toolbar to position relative to
+ * \param win The page-info window to position
+ */
+nserror nsgtk_toolbar_position_page_info(struct nsgtk_toolbar *tb,
+ struct nsgtk_pi_window *win);
+
+/**
+ * position the local history window appropriately
+ *
+ * \param tb The toolbar to position relative to
+ */
+nserror nsgtk_toolbar_position_local_history(struct nsgtk_toolbar *tb);
+
+/**
+ * Initialise customization of toolbar entries
+ */
void nsgtk_toolbar_customization_init(struct nsgtk_scaffolding *g);
-void nsgtk_toolbar_init(struct nsgtk_scaffolding *g);
-void nsgtk_toolbar_customization_load(struct nsgtk_scaffolding *g);
-void nsgtk_toolbar_set_physical(struct nsgtk_scaffolding *g);
-void nsgtk_toolbar_connect_all(struct nsgtk_scaffolding *g);
-int nsgtk_toolbar_get_id_from_widget(GtkWidget *widget, struct nsgtk_scaffolding *g);
-
-#define TOOLPROTO(q) gboolean nsgtk_toolbar_##q##_button_data(\
- GtkWidget *widget, GdkDragContext *cont, GtkSelectionData\
- *selection, guint info, guint time, gpointer data);\
-gboolean nsgtk_toolbar_##q##_toolbar_button_data(GtkWidget *widget,\
- GdkDragContext *cont, GtkSelectionData *selection, guint info,\
- guint time, gpointer data)
-TOOLPROTO(home);
-TOOLPROTO(back);
-TOOLPROTO(forward);
-TOOLPROTO(reload);
-TOOLPROTO(stop);
-TOOLPROTO(throbber);
-TOOLPROTO(websearch);
-TOOLPROTO(history);
-TOOLPROTO(newwindow);
-TOOLPROTO(newtab);
-TOOLPROTO(openfile);
-TOOLPROTO(closetab);
-TOOLPROTO(closewindow);
-TOOLPROTO(savepage);
-TOOLPROTO(pdf);
-TOOLPROTO(plaintext);
-TOOLPROTO(drawfile);
-TOOLPROTO(postscript);
-TOOLPROTO(printpreview);
-TOOLPROTO(print);
-TOOLPROTO(quit);
-TOOLPROTO(cut);
-TOOLPROTO(copy);
-TOOLPROTO(paste);
-TOOLPROTO(delete);
-TOOLPROTO(selectall);
-TOOLPROTO(find);
-TOOLPROTO(preferences);
-TOOLPROTO(zoomplus);
-TOOLPROTO(zoomminus);
-TOOLPROTO(zoomnormal);
-TOOLPROTO(fullscreen);
-TOOLPROTO(viewsource);
-TOOLPROTO(downloads);
-TOOLPROTO(localhistory);
-TOOLPROTO(globalhistory);
-TOOLPROTO(addbookmarks);
-TOOLPROTO(showbookmarks);
-TOOLPROTO(showcookies);
-TOOLPROTO(openlocation);
-TOOLPROTO(nexttab);
-TOOLPROTO(prevtab);
-TOOLPROTO(savewindowsize);
-TOOLPROTO(toggledebugging);
-TOOLPROTO(debugboxtree);
-TOOLPROTO(debugdomtree);
-TOOLPROTO(contents);
-TOOLPROTO(guide);
-TOOLPROTO(info);
-TOOLPROTO(about);
-#undef TOOLPROTO
+
#endif
diff --git a/frontends/gtk/toolbar_items.h b/frontends/gtk/toolbar_items.h
new file mode 100644
index 000000000..b4bed371f
--- /dev/null
+++ b/frontends/gtk/toolbar_items.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETSURF_GTK_TOOLBAR_ITEMS_H
+#define NETSURF_GTK_TOOLBAR_ITEMS_H
+
+typedef enum {
+ BACK_BUTTON = 0,
+ HISTORY_BUTTON,
+ FORWARD_BUTTON,
+ RELOADSTOP_BUTTON,
+ URL_BAR_ITEM,
+ WEBSEARCH_ITEM,
+ OPENMENU_BUTTON,
+ STOP_BUTTON,
+ RELOAD_BUTTON,
+ HOME_BUTTON,
+ THROBBER_ITEM,
+ NEWWINDOW_BUTTON,
+ NEWTAB_BUTTON,
+ OPENFILE_BUTTON,
+ CLOSETAB_BUTTON,
+ CLOSEWINDOW_BUTTON,
+ SAVEPAGE_BUTTON,
+ PDF_BUTTON,
+ PLAINTEXT_BUTTON,
+ DRAWFILE_BUTTON,
+ POSTSCRIPT_BUTTON,
+ PRINTPREVIEW_BUTTON,
+ PRINT_BUTTON,
+ QUIT_BUTTON,
+ CUT_BUTTON,
+ COPY_BUTTON,
+ PASTE_BUTTON,
+ DELETE_BUTTON,
+ SELECTALL_BUTTON,
+ FIND_BUTTON,
+ PREFERENCES_BUTTON,
+ ZOOMPLUS_BUTTON,
+ ZOOMMINUS_BUTTON,
+ ZOOMNORMAL_BUTTON,
+ FULLSCREEN_BUTTON,
+ VIEWSOURCE_BUTTON,
+ DOWNLOADS_BUTTON,
+ SAVEWINDOWSIZE_BUTTON,
+ TOGGLEDEBUGGING_BUTTON,
+ SAVEBOXTREE_BUTTON,
+ SAVEDOMTREE_BUTTON,
+ LOCALHISTORY_BUTTON,
+ GLOBALHISTORY_BUTTON,
+ ADDBOOKMARKS_BUTTON,
+ SHOWBOOKMARKS_BUTTON,
+ SHOWCOOKIES_BUTTON,
+ OPENLOCATION_BUTTON,
+ NEXTTAB_BUTTON,
+ PREVTAB_BUTTON,
+ CONTENTS_BUTTON,
+ GUIDE_BUTTON,
+ INFO_BUTTON,
+ ABOUT_BUTTON,
+ CUSTOMIZE_BUTTON,
+ PLACEHOLDER_BUTTON /* size indicator; array maximum indices */
+} nsgtk_toolbar_button; /* PLACEHOLDER_BUTTON - 1 */
+
+#endif
+
+/*
+ * Item fields are:
+ * - item identifier (enum value)
+ * - name (identifier)
+ * - initial sensitivity (true/false)
+ * - if there is a toolbar click signal handler (y/n) and it is available in
+ * the toolbar and toolbox as a button (b, implies y) if the item is
+ * available as a button but not placed in the toolbox (t, implies y)
+ * - if there is a menu activate signal handler (y/n) and it calls the
+ * toolbar click handler directly. (p, implies y)
+ * - item label as a netsurf message (identifier)
+ * - icon image name ("string")
+ */
+
+#ifndef TOOLBAR_ITEM
+#define TOOLBAR_ITEM(a, b, c, d, e, f, g)
+#define TOOLBAR_ITEM_SET
+#endif
+
+TOOLBAR_ITEM(BACK_BUTTON, back, false, b, p, gtkBack, "go-previous")
+TOOLBAR_ITEM(HISTORY_BUTTON, history, true, y, n, , "local-history")
+TOOLBAR_ITEM(FORWARD_BUTTON, forward, false, b, p, gtkForward, "go-next")
+TOOLBAR_ITEM(STOP_BUTTON, stop, false, t, p, gtkStop, NSGTK_STOCK_STOP)
+TOOLBAR_ITEM(RELOAD_BUTTON, reload, true, t, p, Reload, NSGTK_STOCK_REFRESH)
+TOOLBAR_ITEM(HOME_BUTTON, home, true, b, p, gtkHome, NSGTK_STOCK_HOME)
+TOOLBAR_ITEM(URL_BAR_ITEM, url_bar, true, n, n, , NULL)
+TOOLBAR_ITEM(WEBSEARCH_ITEM, websearch, true, n, n, , NULL)
+TOOLBAR_ITEM(THROBBER_ITEM, throbber, true, n, n, , NULL)
+TOOLBAR_ITEM(NEWWINDOW_BUTTON, newwindow, true, b, p, gtkNewWindow, "document-new")
+TOOLBAR_ITEM(NEWTAB_BUTTON, newtab, true, b, p, gtkNewTab, NSGTK_STOCK_ADD)
+TOOLBAR_ITEM(OPENFILE_BUTTON, openfile, true, b, p, gtkOpenFile, "document-open")
+TOOLBAR_ITEM(CLOSETAB_BUTTON, closetab, false, n, y, , "window-close")
+TOOLBAR_ITEM(CLOSEWINDOW_BUTTON, closewindow, true, y, p, , "window-close")
+TOOLBAR_ITEM(SAVEPAGE_BUTTON, savepage, true, b, p, gtkSavePage, "text-html")
+TOOLBAR_ITEM(PDF_BUTTON, pdf, false, y, p, , "x-office-document")
+TOOLBAR_ITEM(PLAINTEXT_BUTTON, plaintext, true, b, p, gtkPlainText, "text-x-generic")
+TOOLBAR_ITEM(DRAWFILE_BUTTON, drawfile, false, n, n, , NULL)
+TOOLBAR_ITEM(POSTSCRIPT_BUTTON, postscript, false, n, n, , NULL)
+TOOLBAR_ITEM(PRINTPREVIEW_BUTTON, printpreview, false, n, p, gtkPrintPreview, "gtk-print-preview")
+TOOLBAR_ITEM(PRINT_BUTTON, print, true, b, p, gtkPrint, "document-print")
+TOOLBAR_ITEM(QUIT_BUTTON, quit, true, b, p, gtkQuitMenu, "application-exit")
+TOOLBAR_ITEM(CUT_BUTTON, cut, true, b, p, gtkCut, "edit-cut")
+TOOLBAR_ITEM(COPY_BUTTON, copy, true, b, p, gtkCopy, "edit-copy")
+TOOLBAR_ITEM(PASTE_BUTTON, paste, true, b, p, gtkPaste, "edit-paste")
+TOOLBAR_ITEM(DELETE_BUTTON, delete, false, b, p, gtkDelete, "edit-delete")
+TOOLBAR_ITEM(SELECTALL_BUTTON, selectall, true, b, p, gtkSelectAll, "edit-select-all")
+TOOLBAR_ITEM(FIND_BUTTON, find, true, n, y, gtkFind, "edit-find")
+TOOLBAR_ITEM(PREFERENCES_BUTTON, preferences, true, b, p, gtkPreferences, "preferences-system")
+TOOLBAR_ITEM(ZOOMPLUS_BUTTON, zoomplus, true, b, p, gtkZoomPlus, "gtk-zoom-in")
+TOOLBAR_ITEM(ZOOMMINUS_BUTTON, zoomminus, true, b, p, gtkZoomMinus, "gtk-zoom-out")
+TOOLBAR_ITEM(ZOOMNORMAL_BUTTON, zoomnormal, true, b, p, gtkZoomNormal, "gtk-zoom-100")
+TOOLBAR_ITEM(FULLSCREEN_BUTTON, fullscreen, true, b, p, gtkFullScreen, "gtk-fullscreen")
+TOOLBAR_ITEM(VIEWSOURCE_BUTTON, viewsource, true, b, p, gtkPageSource, "gtk-index")
+TOOLBAR_ITEM(DOWNLOADS_BUTTON, downloads, true, b, p, gtkDownloads, NSGTK_STOCK_SAVE_AS)
+TOOLBAR_ITEM(SAVEWINDOWSIZE_BUTTON, savewindowsize, true, y, p, gtkSaveWindowSize, NULL)
+TOOLBAR_ITEM(TOGGLEDEBUGGING_BUTTON, toggledebugging, true, y, p, gtkToggleDebugging, NULL)
+TOOLBAR_ITEM(SAVEBOXTREE_BUTTON, debugboxtree, true, y, p, gtkDebugBoxTree, NULL)
+TOOLBAR_ITEM(SAVEDOMTREE_BUTTON, debugdomtree, true, y, p, gtkDebugDomTree, NULL)
+TOOLBAR_ITEM(LOCALHISTORY_BUTTON, localhistory, true, y, p, , NULL)
+TOOLBAR_ITEM(GLOBALHISTORY_BUTTON, globalhistory, true, y, p, gtkGlobalHistory, NULL)
+TOOLBAR_ITEM(ADDBOOKMARKS_BUTTON, addbookmarks, true, y, p, gtkAddBookMarks, NULL)
+TOOLBAR_ITEM(SHOWBOOKMARKS_BUTTON, showbookmarks, true, b, p, gtkShowBookMarks, "user-bookmarks")
+TOOLBAR_ITEM(SHOWCOOKIES_BUTTON, showcookies, true, b, p, gtkShowCookies, "show-cookie")
+TOOLBAR_ITEM(OPENLOCATION_BUTTON, openlocation, true, y, p, gtkOpenLocation, NULL)
+TOOLBAR_ITEM(NEXTTAB_BUTTON, nexttab, false, n, y, gtkNextTab, "media-skip-forward")
+TOOLBAR_ITEM(PREVTAB_BUTTON, prevtab, false, n, y, gtkPrevTab, "media-skip-backward")
+TOOLBAR_ITEM(CONTENTS_BUTTON, contents, true, y, p, gtkContents, "gtk-help")
+TOOLBAR_ITEM(GUIDE_BUTTON, guide, true, y, p, gtkGuide, "gtk-help")
+TOOLBAR_ITEM(INFO_BUTTON, info, true, y, p, gtkUserInformation, "dialog-information")
+TOOLBAR_ITEM(ABOUT_BUTTON, about, true, b, p, gtkAbout, "help-about")
+TOOLBAR_ITEM(OPENMENU_BUTTON, openmenu, true, b, n, gtkOpenMenu, NSGTK_STOCK_OPEN_MENU)
+TOOLBAR_ITEM(CUSTOMIZE_BUTTON, cutomize, true, y, p, , NULL)
+TOOLBAR_ITEM(RELOADSTOP_BUTTON, reloadstop, true, b, n, Reload, NSGTK_STOCK_REFRESH)
+
+#ifdef TOOLBAR_ITEM_SET
+#undef TOOLBAR_ITEM
+#undef TOOLBAR_ITEM_SET
+#endif
diff --git a/frontends/gtk/viewsource.c b/frontends/gtk/viewsource.c
index acf81018d..7c11862c6 100644
--- a/frontends/gtk/viewsource.c
+++ b/frontends/gtk/viewsource.c
@@ -34,8 +34,8 @@ nserror nsgtk_viewsource(GtkWindow *parent, struct browser_window *bw)
{
nserror ret;
struct hlcache_handle *hlcontent;
- const char *source_data;
- unsigned long source_size;
+ const uint8_t *source_data;
+ size_t source_size;
char *ndata = NULL;
size_t ndata_len;
char *filename;
@@ -52,7 +52,7 @@ nserror nsgtk_viewsource(GtkWindow *parent, struct browser_window *bw)
source_data = content_get_source_data(hlcontent, &source_size);
- ret = nsurl_nice(browser_window_get_url(bw), &filename, false);
+ ret = nsurl_nice(browser_window_access_url(bw), &filename, false);
if (ret != NSERROR_OK) {
filename = strdup(messages_get("SaveSource"));
if (filename == NULL) {
@@ -60,15 +60,16 @@ nserror nsgtk_viewsource(GtkWindow *parent, struct browser_window *bw)
}
}
- title = malloc(strlen(nsurl_access(browser_window_get_url(bw))) + SLEN("Source of - NetSurf") + 1);
+ title = malloc(strlen(nsurl_access(browser_window_access_url(bw))) + SLEN("Source of - NetSurf") + 1);
if (title == NULL) {
free(filename);
return NSERROR_NOMEM;
}
- sprintf(title, "Source of %s - NetSurf", nsurl_access(browser_window_get_url(bw)));
+ sprintf(title, "Source of %s - NetSurf", nsurl_access(browser_window_access_url(bw)));
- ret = utf8_from_enc(source_data,
- content_get_encoding(hlcontent, CONTENT_ENCODING_NORMAL),
+ ret = utf8_from_enc((const char *)source_data,
+ content_get_encoding(hlcontent,
+ CONTENT_ENCODING_NORMAL),
source_size,
&ndata,
&ndata_len);
diff --git a/frontends/gtk/window.c b/frontends/gtk/window.c
index 7f24d40ac..f5c87ef87 100644
--- a/frontends/gtk/window.c
+++ b/frontends/gtk/window.c
@@ -31,10 +31,13 @@
#include <gdk/gdkkeysyms.h>
#include <gdk-pixbuf/gdk-pixdata.h>
-#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,12 +48,13 @@
#include "desktop/searchweb.h"
#include "desktop/textinput.h"
-#include "gtk/window.h"
#include "gtk/selection.h"
#include "gtk/warn.h"
#include "gtk/compat.h"
#include "gtk/gui.h"
#include "gtk/scaffolding.h"
+#include "gtk/toolbar_items.h"
+#include "gtk/toolbar.h"
#include "gtk/local_history.h"
#include "gtk/plotters.h"
#include "gtk/schedule.h"
@@ -58,13 +62,18 @@
#include "gtk/bitmap.h"
#include "gtk/gdk.h"
#include "gtk/resources.h"
+#include "gtk/search.h"
+#include "gtk/throbber.h"
+#include "gtk/window.h"
+
+/**
+ * time (in ms) between throbber animation frame updates
+ */
+#define THROBBER_FRAME_TIME (100)
static GtkWidget *select_menu;
static struct form_control *select_menu_control;
-static void nsgtk_select_menu_clicked(GtkCheckMenuItem *checkmenuitem,
- gpointer user_data);
-
struct gui_window {
/**
* The gtk scaffold object containing menu, buttons, url bar, [tabs],
@@ -94,12 +103,21 @@ struct gui_window {
/** previous event location */
int last_x, last_y;
- /** The top level container (tabContents) */
+ /** controls toolbar context */
+ struct nsgtk_toolbar *toolbar;
+
+ /** search toolbar context */
+ struct gtk_search *search;
+
+ /** The top level container (tabBox) */
GtkWidget *container;
/** display widget for this page or frame */
GtkLayout *layout;
+ /** The container for the layout etc */
+ GtkWidget *grid;
+
/** handle to the the visible tab */
GtkWidget *tab;
@@ -112,15 +130,15 @@ struct gui_window {
/** has the status pane had its first size operation yet? */
bool paned_sized;
- /** to allow disactivation / resume of normal window behaviour */
- gulong signalhandler[NSGTK_WINDOW_SIGNAL_COUNT];
-
/** The icon this window should have */
GdkPixbuf *icon;
/** The input method to use with this window */
GtkIMContext *input_method;
+ /** current frame of throbber */
+ int throb_frame;
+
/** list for cleanup */
struct gui_window *next, *prev;
};
@@ -128,60 +146,12 @@ struct gui_window {
/**< first entry in window list */
struct gui_window *window_list = NULL;
-/** flag controlling opening of tabs in teh background */
-int temp_open_background = -1;
-
-struct nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g)
-{
- return g->scaffold;
-}
-
-GdkPixbuf *nsgtk_get_icon(struct gui_window *gw)
-{
- return gw->icon;
-}
-
-struct browser_window *nsgtk_get_browser_window(struct gui_window *g)
-{
- return g->bw;
-}
-
-unsigned long nsgtk_window_get_signalhandler(struct gui_window *g, int i)
-{
- return g->signalhandler[i];
-}
-
-GtkLayout *nsgtk_window_get_layout(struct gui_window *g)
-{
- return g->layout;
-}
-
-GtkWidget *nsgtk_window_get_tab(struct gui_window *g)
-{
- return g->tab;
-}
-
-void nsgtk_window_set_tab(struct gui_window *g, GtkWidget *w)
-{
- g->tab = w;
-}
-
-
-struct gui_window *nsgtk_window_iterate(struct gui_window *g)
-{
- return g->next;
-}
-
-float nsgtk_get_scale_for_gui(struct gui_window *g)
-{
- return browser_window_get_scale(g->bw);
-}
-
-static void nsgtk_select_menu_clicked(GtkCheckMenuItem *checkmenuitem,
- gpointer user_data)
+static void
+nsgtk_select_menu_clicked(GtkCheckMenuItem *checkmenuitem,
+ gpointer user_data)
{
form_select_process_selection(select_menu_control,
- (intptr_t)user_data);
+ (intptr_t)user_data);
}
#if GTK_CHECK_VERSION(3,0,0)
@@ -278,8 +248,10 @@ nsgtk_window_draw_event(GtkWidget *widget, GdkEventExpose *event, gpointer data)
#endif
-static gboolean nsgtk_window_motion_notify_event(GtkWidget *widget,
- GdkEventMotion *event, gpointer data)
+static gboolean
+nsgtk_window_motion_notify_event(GtkWidget *widget,
+ GdkEventMotion *event,
+ gpointer data)
{
struct gui_window *g = data;
bool shift = event->state & GDK_SHIFT_MASK;
@@ -325,15 +297,34 @@ static gboolean nsgtk_window_motion_notify_event(GtkWidget *widget,
if (g->mouse.state & BROWSER_MOUSE_MOD_2 && !ctrl)
g->mouse.state ^= BROWSER_MOUSE_MOD_2;
- browser_window_mouse_track(g->bw, g->mouse.state,
- event->x / browser_window_get_scale(g->bw),
- event->y / browser_window_get_scale(g->bw));
+ browser_window_mouse_track(g->bw, g->mouse.state, event->x, event->y);
return TRUE;
}
-static gboolean nsgtk_window_button_press_event(GtkWidget *widget,
- GdkEventButton *event, gpointer data)
+/**
+ * GTK signal handler for focus-out-event on layout
+ *
+ * when focus leaves the layout widget ensure the caret is cleared
+ */
+static gboolean
+nsgtk_window_focus_out_event(GtkWidget *widget,
+ GdkEvent *event,
+ gpointer data)
+{
+ struct gui_window *g = data;
+
+ browser_window_remove_caret(g->bw, true);
+ return FALSE;
+}
+
+/**
+ * GTK signal handler for button-press-event on layout
+ */
+static gboolean
+nsgtk_window_button_press_event(GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
{
struct gui_window *g = data;
@@ -341,8 +332,8 @@ static gboolean nsgtk_window_button_press_event(GtkWidget *widget,
gtk_widget_grab_focus(GTK_WIDGET(g->layout));
nsgtk_local_history_hide();
- g->mouse.pressed_x = event->x / browser_window_get_scale(g->bw);
- g->mouse.pressed_y = event->y / browser_window_get_scale(g->bw);
+ g->mouse.pressed_x = event->x;
+ g->mouse.pressed_y = event->y;
switch (event->button) {
case 1: /* Left button, usually. Pass to core as BUTTON 1. */
@@ -382,25 +373,43 @@ static gboolean nsgtk_window_button_press_event(GtkWidget *widget,
g->last_x = event->x;
g->last_y = event->y;
- browser_window_mouse_click(g->bw, g->mouse.state, g->mouse.pressed_x,
- g->mouse.pressed_y);
+ browser_window_mouse_click(g->bw,
+ g->mouse.state,
+ g->mouse.pressed_x,
+ g->mouse.pressed_y);
return TRUE;
}
-static gboolean nsgtk_window_button_release_event(GtkWidget *widget,
- GdkEventButton *event, gpointer data)
+
+static gboolean
+nsgtk_window_button_release_event(GtkWidget *widget,
+ GdkEventButton *event,
+ gpointer data)
{
struct gui_window *g = data;
bool shift = event->state & GDK_SHIFT_MASK;
bool ctrl = event->state & GDK_CONTROL_MASK;
+ switch (event->button) {
+ case 8:
+ nsgtk_toolbar_item_activate(g->toolbar, BACK_BUTTON);
+ break;
+ case 9:
+ nsgtk_toolbar_item_activate(g->toolbar, FORWARD_BUTTON);
+ break;
+ default:
+ NSLOG(netsurf, DEBUG, "event button %d", event->button);
+ break;
+ }
+
/* If the mouse state is PRESS then we are waiting for a release to emit
* a click event, otherwise just reset the state to nothing */
- if (g->mouse.state & BROWSER_MOUSE_PRESS_1)
+ if (g->mouse.state & BROWSER_MOUSE_PRESS_1) {
g->mouse.state ^= (BROWSER_MOUSE_PRESS_1 | BROWSER_MOUSE_CLICK_1);
- else if (g->mouse.state & BROWSER_MOUSE_PRESS_2)
+ } else if (g->mouse.state & BROWSER_MOUSE_PRESS_2) {
g->mouse.state ^= (BROWSER_MOUSE_PRESS_2 | BROWSER_MOUSE_CLICK_2);
+ }
/* Handle modifiers being removed */
if (g->mouse.state & BROWSER_MOUSE_MOD_1 && !shift)
@@ -409,19 +418,16 @@ static gboolean nsgtk_window_button_release_event(GtkWidget *widget,
g->mouse.state ^= BROWSER_MOUSE_MOD_2;
if (g->mouse.state & (BROWSER_MOUSE_CLICK_1 | BROWSER_MOUSE_CLICK_2)) {
- browser_window_mouse_click(g->bw, g->mouse.state,
- event->x / browser_window_get_scale(g->bw),
- event->y / browser_window_get_scale(g->bw));
+ browser_window_mouse_click(g->bw, g->mouse.state, event->x, event->y);
} else {
- browser_window_mouse_track(g->bw, 0,
- event->x / browser_window_get_scale(g->bw),
- event->y / browser_window_get_scale(g->bw));
+ browser_window_mouse_track(g->bw, 0, event->x, event->y);
}
g->mouse.state = 0;
return TRUE;
}
+
static gboolean
nsgtk_window_scroll_event(GtkWidget *widget,
GdkEventScroll *event,
@@ -466,9 +472,8 @@ nsgtk_window_scroll_event(GtkWidget *widget,
deltay *= nsgtk_adjustment_get_step_increment(vscroll);
if (browser_window_scroll_at_point(g->bw,
- event->x / browser_window_get_scale(g->bw),
- event->y / browser_window_get_scale(g->bw),
- deltax, deltay) != true) {
+ event->x, event->y,
+ deltax, deltay) != true) {
/* core did not handle event so change adjustments */
@@ -510,12 +515,15 @@ nsgtk_window_scroll_event(GtkWidget *widget,
return TRUE;
}
-static gboolean nsgtk_window_keypress_event(GtkWidget *widget,
- GdkEventKey *event, gpointer data)
+
+static gboolean
+nsgtk_window_keypress_event(GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer data)
{
struct gui_window *g = data;
uint32_t nskey;
-
+
if (gtk_im_context_filter_keypress(g->input_method, event))
return TRUE;
@@ -627,17 +635,22 @@ static gboolean nsgtk_window_keypress_event(GtkWidget *widget,
return TRUE;
}
-static gboolean nsgtk_window_keyrelease_event(GtkWidget *widget,
- GdkEventKey *event, gpointer data)
+
+static gboolean
+nsgtk_window_keyrelease_event(GtkWidget *widget,
+ GdkEventKey *event,
+ gpointer data)
{
struct gui_window *g = data;
-
+
return gtk_im_context_filter_keypress(g->input_method, event);
}
-static void nsgtk_window_input_method_commit(GtkIMContext *ctx,
- const gchar *str, gpointer data)
+static void
+nsgtk_window_input_method_commit(GtkIMContext *ctx,
+ const gchar *str,
+ gpointer data)
{
struct gui_window *g = data;
size_t len = strlen(str), offset = 0;
@@ -652,8 +665,10 @@ static void nsgtk_window_input_method_commit(GtkIMContext *ctx,
}
-static gboolean nsgtk_window_size_allocate_event(GtkWidget *widget,
- GtkAllocation *allocation, gpointer data)
+static gboolean
+nsgtk_window_size_allocate_event(GtkWidget *widget,
+ GtkAllocation *allocation,
+ gpointer data)
{
struct gui_window *g = data;
@@ -663,7 +678,8 @@ static gboolean nsgtk_window_size_allocate_event(GtkWidget *widget,
}
-/** when the pane position is changed update the user option
+/**
+ * when the pane position is changed update the user option
*
* The slightly awkward implementation with the first allocation flag
* is necessary because the initial window creation does not cause an
@@ -692,11 +708,15 @@ nsgtk_paned_notify__position(GObject *gobject, GParamSpec *pspec, gpointer data)
((gtk_paned_get_position(g->paned) * 10000) / (pane_alloc.width - 1)));
}
-/** Set status bar / scroll bar proportion according to user option
- * when pane is resized.
+
+/**
+ * Set status bar / scroll bar proportion according to user option
+ * when pane is resized.
*/
-static gboolean nsgtk_paned_size_allocate_event(GtkWidget *widget,
- GtkAllocation *allocation, gpointer data)
+static gboolean
+nsgtk_paned_size_allocate_event(GtkWidget *widget,
+ GtkAllocation *allocation,
+ gpointer data)
{
gtk_paned_set_position(GTK_PANED(widget),
(nsoption_int(toolbar_status_size) * allocation->width) / 10000);
@@ -704,7 +724,12 @@ static gboolean nsgtk_paned_size_allocate_event(GtkWidget *widget,
return TRUE;
}
-/* destroy the browsing context as there is nothing to display it now */
+
+/**
+ * handler for gtk destroy signal on window container
+ *
+ * destroy the browsing context as there is will be nothing to display it now
+ */
static void window_destroy(GtkWidget *widget, gpointer data)
{
struct gui_window *gw = data;
@@ -712,6 +737,66 @@ static void window_destroy(GtkWidget *widget, gpointer data)
browser_window_destroy(gw->bw);
g_object_unref(gw->input_method);
+
+ /* free any existing icon */
+ if (gw->icon != NULL) {
+ g_object_unref(gw->icon);
+ gw->icon = NULL;
+ }
+
+ free(gw);
+}
+
+
+static struct browser_window *bw_from_gw(void *data)
+{
+ struct gui_window *gw = data;
+ return gw->bw;
+}
+
+
+static bool get_tool_bar_show(void)
+{
+ const char *cur_bar_show;
+
+ cur_bar_show = nsoption_charp(bar_show);
+ if (cur_bar_show != NULL) {
+ if (strcmp(cur_bar_show, "menu/tool") == 0) {
+ return true;
+ } else if (strcmp(cur_bar_show, "tool") == 0) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/**
+ * Make the throbber advance to next frame.
+ *
+ * scheduled callback to update the throbber
+ *
+ * \param p The context passed when scheduled.
+ */
+static void next_throbber_frame(void *p)
+{
+ struct gui_window *gw = p;
+ nserror res;
+ GdkPixbuf *pixbuf;
+
+ gw->throb_frame++; /* advance to next frame */
+
+ res = nsgtk_throbber_get_frame(gw->throb_frame, &pixbuf);
+ if (res == NSERROR_BAD_SIZE) {
+ gw->throb_frame = 1;
+ res = nsgtk_throbber_get_frame(gw->throb_frame, &pixbuf);
+ }
+
+ if (res == NSERROR_OK) {
+ nsgtk_tab_set_icon(gw->container, pixbuf);
+ /* only schedule next frame if there are no errors */
+ nsgtk_schedule(THROBBER_FRAME_TIME, next_throbber_frame, p);
+ }
}
@@ -730,13 +815,17 @@ static void window_destroy(GtkWidget *widget, gpointer data)
*/
static struct gui_window *
gui_window_create(struct browser_window *bw,
- struct gui_window *existing,
- gui_window_create_flags flags)
+ struct gui_window *existing,
+ gui_window_create_flags flags)
{
struct gui_window *g; /* what is being created to return */
- bool tempback;
+ bool open_in_background = !(nsoption_bool(focus_new));
GtkBuilder* tab_builder;
+ /* If there is a foreground request, override user preference */
+ if (flags & GW_CREATE_FOREGROUND)
+ open_in_background = false;
+
nserror res;
res = nsgtk_builder_new_from_resname("tabcontents", &tab_builder);
@@ -781,12 +870,32 @@ gui_window_create(struct browser_window *bw,
}
/* Construct our primary elements */
- g->container = GTK_WIDGET(gtk_builder_get_object(tab_builder, "tabContents"));
+ g->container = GTK_WIDGET(gtk_builder_get_object(tab_builder, "tabBox"));
g->layout = GTK_LAYOUT(gtk_builder_get_object(tab_builder, "layout"));
+ g->grid = GTK_WIDGET(gtk_builder_get_object(tab_builder, "tabContents"));
g->status_bar = GTK_LABEL(gtk_builder_get_object(tab_builder, "status_bar"));
g->paned = GTK_PANED(gtk_builder_get_object(tab_builder, "hpaned1"));
g->input_method = gtk_im_multicontext_new();
+
+ /* create toolbar */
+ res = nsgtk_toolbar_create(tab_builder, bw_from_gw, g,
+ !!(flags & GW_CREATE_FOCUS_LOCATION),
+ &g->toolbar);
+ if (res != NSERROR_OK) {
+ free(g);
+ g_object_unref(tab_builder);
+ return NULL;
+ }
+
+ /* local page text search toolbar */
+ res = nsgtk_search_create(tab_builder, g->bw, &g->search);
+ if (res != NSERROR_OK) {
+ free(g);
+ g_object_unref(tab_builder);
+ return NULL;
+ }
+
/* set a default favicon */
g_object_ref(favicon_pixbuf);
g->icon = favicon_pixbuf;
@@ -816,11 +925,10 @@ gui_window_create(struct browser_window *bw,
/* set the default background colour of the drawing area to white. */
nsgtk_widget_override_background_color(GTK_WIDGET(g->layout),
- GTK_STATE_NORMAL,
+ GTK_STATE_FLAG_NORMAL,
0, 0xffff, 0xffff, 0xffff);
- g->signalhandler[NSGTK_WINDOW_SIGNAL_REDRAW] =
- nsgtk_connect_draw_event(GTK_WIDGET(g->layout),
+ nsgtk_connect_draw_event(GTK_WIDGET(g->layout),
G_CALLBACK(nsgtk_window_draw_event), g);
/* helper macro to conect signals to callbacks */
@@ -830,8 +938,7 @@ gui_window_create(struct browser_window *bw,
/* layout signals */
CONNECT(g->layout, "motion-notify-event",
nsgtk_window_motion_notify_event, g);
- g->signalhandler[NSGTK_WINDOW_SIGNAL_CLICK] =
- CONNECT(g->layout, "button-press-event",
+ CONNECT(g->layout, "button-press-event",
nsgtk_window_button_press_event, g);
CONNECT(g->layout, "button-release-event",
nsgtk_window_button_release_event, g);
@@ -843,6 +950,8 @@ gui_window_create(struct browser_window *bw,
nsgtk_window_size_allocate_event, g);
CONNECT(g->layout, "scroll-event",
nsgtk_window_scroll_event, g);
+ CONNECT(g->layout, "focus-out-event",
+ nsgtk_window_focus_out_event, g);
/* status pane signals */
CONNECT(g->paned, "size-allocate",
@@ -864,71 +973,65 @@ gui_window_create(struct browser_window *bw,
nsgtk_window_input_method_commit, g);
/* add the tab container to the scaffold notebook */
- switch (temp_open_background) {
- case -1:
- tempback = !(nsoption_bool(focus_new));
- break;
- case 0:
- tempback = false;
- break;
- default:
- tempback = true;
- break;
- }
- nsgtk_tab_add(g, g->container, tempback);
+ nsgtk_tab_add(g, g->container,
+ open_in_background,
+ messages_get("NewTab"), g->icon);
+
+ /* initialy should not be visible */
+ nsgtk_search_toggle_visibility(g->search);
+
+ /* set toolbar visibility from user option */
+ nsgtk_toolbar_show(g->toolbar, get_tool_bar_show());
/* safe to drop the reference to the tab_builder as the container is
* referenced by the notebook now.
*/
g_object_unref(tab_builder);
- return g;
-}
-
-
-
-void nsgtk_reflow_all_windows(void)
-{
- for (struct gui_window *g = window_list; g; g = g->next) {
- nsgtk_tab_options_changed(nsgtk_scaffolding_notebook(g->scaffold));
- browser_window_schedule_reformat(g->bw);
+ /* Finally we need to focus the location bar if requested */
+ if (flags & GW_CREATE_FOCUS_LOCATION) {
+ if (nsgtk_window_item_activate(g, OPENLOCATION_BUTTON) != NSERROR_OK) {
+ NSLOG(netsurf, WARNING, "Unable to focus location input");
+ }
}
+
+ return g;
}
-void nsgtk_window_destroy_browser(struct gui_window *gw)
+static void gui_window_destroy(struct gui_window *gw)
{
- /* remove tab */
- gtk_widget_destroy(gw->container);
-}
+ NSLOG(netsurf, INFO, "gui_window: %p", gw);
+ assert(gw != NULL);
+ assert(gw->bw != NULL);
+ NSLOG(netsurf, INFO, "scaffolding: %p", gw->scaffold);
-static void gui_window_destroy(struct gui_window *g)
-{
- NSLOG(netsurf, INFO, "gui_window: %p", g);
- assert(g != NULL);
- assert(g->bw != NULL);
- NSLOG(netsurf, INFO, "scaffolding: %p", g->scaffold);
+ /* kill off any throbber that might be running */
+ nsgtk_schedule(-1, next_throbber_frame, gw);
- if (g->prev) {
- g->prev->next = g->next;
+ /* remove from window list */
+ if (gw->prev) {
+ gw->prev->next = gw->next;
} else {
- window_list = g->next;
+ window_list = gw->next;
}
- if (g->next) {
- g->next->prev = g->prev;
+ if (gw->next) {
+ gw->next->prev = gw->prev;
}
NSLOG(netsurf, INFO, "window list head: %p", window_list);
}
+
/**
* favicon setting for gtk gui window.
*
* \param gw gtk gui window to set favicon on.
* \param icon A handle to the new favicon content.
*/
-static void gui_window_set_icon(struct gui_window *gw, struct hlcache_handle *icon)
+static void
+gui_window_set_icon(struct gui_window *gw, struct hlcache_handle *icon)
{
struct bitmap *icon_bitmap = NULL;
@@ -952,9 +1055,13 @@ static void gui_window_set_icon(struct gui_window *gw, struct hlcache_handle *ic
gw->icon = favicon_pixbuf;
}
- nsgtk_scaffolding_set_icon(gw);
+ /* only set icon if throbber not running */
+ if (gw->throb_frame == 0) {
+ nsgtk_tab_set_icon(gw->container, gw->icon);
+ }
}
+
static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
{
GtkAdjustment *vadj = nsgtk_layout_get_vadjustment(g->layout);
@@ -969,6 +1076,7 @@ static bool gui_window_get_scroll(struct gui_window *g, int *sx, int *sy)
return true;
}
+
static void nsgtk_redraw_caret(struct gui_window *g)
{
int sx, sy;
@@ -983,6 +1091,7 @@ static void nsgtk_redraw_caret(struct gui_window *g)
}
+
static void gui_window_remove_caret(struct gui_window *g)
{
int sx, sy;
@@ -1000,6 +1109,7 @@ static void gui_window_remove_caret(struct gui_window *g)
}
+
/**
* Invalidates an area of a GTK browser window
*
@@ -1011,7 +1121,6 @@ static nserror
nsgtk_window_invalidate_area(struct gui_window *g, const struct rect *rect)
{
int sx, sy;
- float scale;
if (rect == NULL) {
gtk_widget_queue_draw(GTK_WIDGET(g->layout));
@@ -1023,17 +1132,17 @@ nsgtk_window_invalidate_area(struct gui_window *g, const struct rect *rect)
}
gui_window_get_scroll(g, &sx, &sy);
- scale = browser_window_get_scale(g->bw);
gtk_widget_queue_draw_area(GTK_WIDGET(g->layout),
- rect->x0 * scale - sx,
- rect->y0 * scale - sy,
- (rect->x1 - rect->x0) * scale,
- (rect->y1 - rect->y0) * scale);
+ rect->x0 - sx,
+ rect->y0 - sy,
+ rect->x1 - rect->x0,
+ rect->y1 - rect->y0);
return NSERROR_OK;
}
+
static void gui_window_set_status(struct gui_window *g, const char *text)
{
assert(g);
@@ -1087,17 +1196,20 @@ gui_window_set_scroll(struct gui_window *g, const struct rect *rect)
return NSERROR_OK;
}
+
static void gui_window_update_extent(struct gui_window *g)
{
int w, h;
if (browser_window_get_extents(g->bw, true, &w, &h) == NSERROR_OK) {
gtk_layout_set_size(g->layout, w, h);
+ gtk_widget_queue_resize(g->grid);
}
}
-static void gui_window_set_pointer(struct gui_window *g,
- gui_pointer_shape shape)
+
+static void
+gui_window_set_pointer(struct gui_window *g, gui_pointer_shape shape)
{
GdkCursor *cursor = NULL;
GdkCursorType cursortype;
@@ -1182,8 +1294,10 @@ static void gui_window_set_pointer(struct gui_window *g,
}
-static void gui_window_place_caret(struct gui_window *g, int x, int y, int height,
- const struct rect *clip)
+static void
+gui_window_place_caret(struct gui_window *g,
+ int x, int y, int height,
+ const struct rect *clip)
{
nsgtk_redraw_caret(g);
@@ -1215,14 +1329,11 @@ static void gui_window_place_caret(struct gui_window *g, int x, int y, int heigh
* \param gw The gui window to measure content area of.
* \param width receives width of window
* \param height receives height of window
- * \param scaled whether to return scaled values
* \return NSERROR_OK on sucess and width and height updated
* else error code.
*/
static nserror
-gui_window_get_dimensions(struct gui_window *gw,
- int *width, int *height,
- bool scaled)
+gui_window_get_dimensions(struct gui_window *gw, int *width, int *height)
{
GtkAllocation alloc;
@@ -1232,23 +1343,19 @@ gui_window_get_dimensions(struct gui_window *gw,
*width = alloc.width;
*height = alloc.height;
- if (scaled) {
- float scale = browser_window_get_scale(gw->bw);
- *width /= scale;
- *height /= scale;
- }
- NSLOG(netsurf, INFO, "gw:%p width:%i height:%i", gw, *width, *height);
-
return NSERROR_OK;
}
+
static void gui_window_start_selection(struct gui_window *g)
{
gtk_widget_grab_focus(GTK_WIDGET(g->layout));
}
-static void gui_window_create_form_select_menu(struct gui_window *g,
- struct form_control *control)
+
+static void
+gui_window_create_form_select_menu(struct gui_window *g,
+ struct form_control *control)
{
intptr_t item;
struct form_option *option;
@@ -1295,11 +1402,15 @@ static void gui_window_create_form_select_menu(struct gui_window *g,
gtk_widget_show_all(select_menu);
- gtk_menu_popup(GTK_MENU(select_menu), NULL, NULL, NULL,
- NULL /* data */, 0, gtk_get_current_event_time());
-
+ nsgtk_menu_popup_at_pointer(GTK_MENU(select_menu), NULL);
}
+
+/**
+ * GTK window UI callback when core needs a file selection gadget
+ *
+ * \param g The gui window on which the gadget has been requested
+ */
static void
gui_window_file_gadget_open(struct gui_window *g,
struct hlcache_handle *hl,
@@ -1315,7 +1426,7 @@ gui_window_file_gadget_open(struct gui_window *g,
NULL);
NSLOG(netsurf, INFO, "*** open dialog: %p", dialog);
-
+
int ret = gtk_dialog_run(GTK_DIALOG(dialog));
NSLOG(netsurf, INFO, "*** return value: %d", ret);
if (ret == GTK_RESPONSE_ACCEPT) {
@@ -1323,7 +1434,7 @@ gui_window_file_gadget_open(struct gui_window *g,
filename = gtk_file_chooser_get_filename(
GTK_FILE_CHOOSER(dialog));
-
+
browser_window_set_gadget_filename(g->bw, gadget, filename);
g_free(filename);
@@ -1332,6 +1443,147 @@ gui_window_file_gadget_open(struct gui_window *g,
gtk_widget_destroy(dialog);
}
+
+/**
+ * handle throbber changing state
+ */
+static nserror throbber(struct gui_window *gw, bool active)
+{
+ nsgtk_toolbar_throbber(gw->toolbar, active);
+ nsgtk_scaffolding_throbber(gw, active);
+ if (active) {
+ nsgtk_schedule(THROBBER_FRAME_TIME, next_throbber_frame, gw);
+ } else {
+ nsgtk_schedule(-1, next_throbber_frame, gw);
+ gw->throb_frame = 0;
+ /* set tab back to favicon */
+ nsgtk_tab_set_icon(gw->container, gw->icon);
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * handle page info changing
+ */
+static nserror page_info_change(struct gui_window *gw)
+{
+ nsgtk_toolbar_page_info_change(gw->toolbar);
+ return NSERROR_OK;
+}
+
+/**
+ * GTK window UI callback to process miscellaneous events
+ *
+ * \param gw The window receiving the event.
+ * \param event The event code.
+ * \return NSERROR_OK when processed ok
+ */
+static nserror
+gui_window_event(struct gui_window *gw, enum gui_window_event event)
+{
+ switch (event) {
+ case GW_EVENT_UPDATE_EXTENT:
+ gui_window_update_extent(gw);
+ break;
+
+ case GW_EVENT_REMOVE_CARET:
+ gui_window_remove_caret(gw);
+ break;
+
+ case GW_EVENT_START_SELECTION:
+ gui_window_start_selection(gw);
+ break;
+
+ case GW_EVENT_START_THROBBER:
+ throbber(gw, true);
+ break;
+
+ case GW_EVENT_STOP_THROBBER:
+ throbber(gw, false);
+ break;
+
+ case GW_EVENT_PAGE_INFO_CHANGE:
+ page_info_change(gw);
+ break;
+
+ default:
+ break;
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * GTK window UI callback when core changes the current url
+ *
+ * \param gw The gui window on which the url has been set.
+ * \param url The new url.
+ */
+static nserror gui_window_set_url(struct gui_window *gw, nsurl *url)
+{
+ return nsgtk_toolbar_set_url(gw->toolbar, 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.
+ *
+ * \param name The providers name.
+ * \param bitmap The bitmap representing the provider.
+ * \return NSERROR_OK on success else error code.
+ */
+static nserror
+gui_search_web_provider_update(const char *name, struct bitmap *bitmap)
+{
+ struct gui_window *gw;
+ GdkPixbuf *pixbuf = NULL;
+
+ if (bitmap != NULL) {
+ pixbuf = nsgdk_pixbuf_get_from_surface(bitmap->surface, 32, 32);
+ }
+
+ for (gw = window_list; gw != NULL; gw = gw->next) {
+ nsgtk_toolbar_set_websearch_image(gw->toolbar, pixbuf);
+ }
+
+ if (pixbuf != NULL) {
+ g_object_unref(pixbuf);
+ }
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * GTK frontend web search operation table
+ */
+static struct gui_search_web_table search_web_table = {
+ .provider_update = gui_search_web_provider_update,
+};
+
+struct gui_search_web_table *nsgtk_search_web_table = &search_web_table;
+
+
+/**
+ * GTK frontend browser window operation table
+ */
static struct gui_window_table window_table = {
.create = gui_window_create,
.destroy = gui_window_destroy,
@@ -1339,22 +1591,115 @@ static struct gui_window_table window_table = {
.get_scroll = gui_window_get_scroll,
.set_scroll = gui_window_set_scroll,
.get_dimensions = gui_window_get_dimensions,
- .update_extent = gui_window_update_extent,
+ .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,
- .remove_caret = gui_window_remove_caret,
.create_form_select_menu = gui_window_create_form_select_menu,
.file_gadget_open = gui_window_file_gadget_open,
- .start_selection = gui_window_start_selection,
-
- /* from scaffold */
- .set_title = nsgtk_window_set_title,
.set_url = gui_window_set_url,
- .start_throbber = gui_window_start_throbber,
- .stop_throbber = gui_window_stop_throbber,
+
+
};
struct gui_window_table *nsgtk_window_table = &window_table;
+
+
+/* exported interface documented in window.h */
+struct nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g)
+{
+ return g->scaffold;
+}
+
+
+/* exported interface documented in window.h */
+struct browser_window *nsgtk_get_browser_window(struct gui_window *g)
+{
+ return g->bw;
+}
+
+
+/* exported interface documented in window.h */
+GtkLayout *nsgtk_window_get_layout(struct gui_window *g)
+{
+ return g->layout;
+}
+
+
+/* exported interface documented in window.h */
+nserror
+nsgtk_window_search_toggle(struct gui_window *gw)
+{
+ return nsgtk_search_toggle_visibility(gw->search);
+}
+
+
+/* exported interface documented in window.h */
+nserror
+nsgtk_window_item_activate(struct gui_window *gw, nsgtk_toolbar_button itemid)
+{
+ return nsgtk_toolbar_item_activate(gw->toolbar, itemid);
+}
+
+
+/* exported interface documented in window.h */
+void nsgtk_window_destroy_browser(struct gui_window *gw)
+{
+ /* remove tab */
+ gtk_widget_destroy(gw->container);
+}
+
+
+/* exported interface documented in window.h */
+nserror nsgtk_window_update_all(void)
+{
+ struct gui_window *gw;
+ for (gw = window_list; gw != NULL; gw = gw->next) {
+ nsgtk_tab_options_changed(nsgtk_scaffolding_notebook(gw->scaffold));
+ nsgtk_toolbar_restyle(gw->toolbar);
+ nsgtk_search_restyle(gw->search);
+ browser_window_schedule_reformat(gw->bw);
+ }
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in window.h */
+nserror nsgtk_window_toolbar_show(struct nsgtk_scaffolding *gs, bool show)
+{
+ struct gui_window *gw;
+ for (gw = window_list; gw != NULL; gw = gw->next) {
+ if (gw->scaffold == gs) {
+ nsgtk_toolbar_show(gw->toolbar, show);
+ }
+ }
+ return NSERROR_OK;
+}
+
+
+/* exported interface documented in window.h */
+nserror nsgtk_window_toolbar_update(void)
+{
+ struct gui_window *gw;
+ for (gw = window_list; gw != NULL; gw = gw->next) {
+ nsgtk_toolbar_update(gw->toolbar);
+
+ }
+ return NSERROR_OK;
+}
+
+/* exported interface documented in window.h */
+nserror nsgtk_window_position_page_info(struct gui_window *gw,
+ struct nsgtk_pi_window *win)
+{
+ return nsgtk_toolbar_position_page_info(gw->toolbar, win);
+}
+
+/* exported interface documented in window.h */
+nserror nsgtk_window_position_local_history(struct gui_window *gw)
+{
+ return nsgtk_toolbar_position_local_history(gw->toolbar);
+}
diff --git a/frontends/gtk/window.h b/frontends/gtk/window.h
index 7e46a7c60..a43e0b197 100644
--- a/frontends/gtk/window.h
+++ b/frontends/gtk/window.h
@@ -19,28 +19,98 @@
#ifndef NETSURF_GTK_WINDOW_H
#define NETSURF_GTK_WINDOW_H 1
-extern struct gui_window_table *nsgtk_window_table;
+struct nsgtk_pi_window;
-typedef enum nsgtk_window_signals {
- NSGTK_WINDOW_SIGNAL_CLICK,
- NSGTK_WINDOW_SIGNAL_REDRAW,
- NSGTK_WINDOW_SIGNAL_COUNT
-} nsgtk_window_signal;
+extern struct gui_window_table *nsgtk_window_table;
+extern struct gui_search_web_table *nsgtk_search_web_table;
extern struct gui_window *window_list;
-extern int temp_open_background;
-
-struct browser_window *nsgtk_get_browser_window(struct gui_window *g);
-struct nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *g);
-GdkPixbuf *nsgtk_get_icon(struct gui_window *gw);
-void nsgtk_reflow_all_windows(void);
-float nsgtk_get_scale_for_gui(struct gui_window *g);
-int nsgtk_gui_window_update_targets(struct gui_window *g);
-void nsgtk_window_destroy_browser(struct gui_window *g);
-unsigned long nsgtk_window_get_signalhandler(struct gui_window *g, int i);
-GtkLayout *nsgtk_window_get_layout(struct gui_window *g);
-struct gui_window *nsgtk_window_iterate(struct gui_window *g);
-GtkWidget *nsgtk_window_get_tab(struct gui_window *g);
-void nsgtk_window_set_tab(struct gui_window *g, GtkWidget *w);
+
+/**
+ * get core browsing context from gui window handle
+ *
+ * \param gw gui window handle
+ */
+struct browser_window *nsgtk_get_browser_window(struct gui_window *gw);
+
+/**
+ * get containing nsgtk scaffolding handle from gui window handle
+ *
+ * \param gw gui window handle
+ */
+struct nsgtk_scaffolding *nsgtk_get_scaffold(struct gui_window *gw);
+
+/**
+ * Every window will have its tab, toolbar and drawing area updated
+ *
+ * The update will ensure the correct tab options are used, the
+ * toolbar size and style is changed and the browser window contents
+ * redrawn.
+ */
+nserror nsgtk_window_update_all(void);
+
+/**
+ * every window will have its toolbar updated to reflect user settings
+ */
+nserror nsgtk_window_toolbar_update(void);
+
+/**
+ * Windows associated with a scaffold will have their toolbar show state set
+ */
+nserror nsgtk_window_toolbar_show(struct nsgtk_scaffolding *gs, bool show);
+
+/**
+ * update targets
+ *
+ * \param gw gui window handle
+ */
+int nsgtk_gui_window_update_targets(struct gui_window *gw);
+
+/**
+ * destroy browsing context
+ *
+ * \param gw gui window handle
+ */
+void nsgtk_window_destroy_browser(struct gui_window *gw);
+
+
+/**
+ * toggle search visibility
+ *
+ * \param gw gui window handle
+ */
+nserror nsgtk_window_search_toggle(struct gui_window *gw);
+
+/**
+ * get gtk layout from gui handle
+ *
+ * \param gw gui window handle
+ */
+GtkLayout *nsgtk_window_get_layout(struct gui_window *gw);
+
+
+/**
+ * activate the handler for a item in a toolbar of a gui window
+ *
+ * \param gw The gui window handle
+ * \param itemid The id of the item to activate
+ */
+nserror nsgtk_window_item_activate(struct gui_window *gw, nsgtk_toolbar_button itemid);
+
+/**
+ * position page_info appropriately
+ *
+ * \param gw The gui window handle to position relative to
+ * \param win The page-info window to position
+ */
+nserror nsgtk_window_position_page_info(struct gui_window *gw,
+ struct nsgtk_pi_window *win);
+
+/**
+ * position local_history appropriately
+ *
+ * \param gw The gui window handle to position relative to
+ */
+nserror nsgtk_window_position_local_history(struct gui_window *gw);
#endif /* NETSURF_GTK_WINDOW_H */