summaryrefslogtreecommitdiff
path: root/frontends/gtk
diff options
context:
space:
mode:
Diffstat (limited to 'frontends/gtk')
-rw-r--r--frontends/gtk/Makefile36
-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/completion.c2
-rw-r--r--frontends/gtk/cookies.c10
-rw-r--r--frontends/gtk/cookies.h2
-rw-r--r--frontends/gtk/corewindow.c90
-rw-r--r--frontends/gtk/corewindow.h6
-rw-r--r--frontends/gtk/download.c7
-rw-r--r--frontends/gtk/fetch.c1
-rw-r--r--frontends/gtk/gdk.c2
-rw-r--r--frontends/gtk/global_history.c9
-rw-r--r--frontends/gtk/gui.c1367
-rw-r--r--frontends/gtk/hotlist.c5
-rw-r--r--frontends/gtk/layout_pango.c20
-rw-r--r--frontends/gtk/local_history.c38
-rw-r--r--frontends/gtk/local_history.h5
-rw-r--r--frontends/gtk/misc.c192
-rw-r--r--frontends/gtk/misc.h24
-rw-r--r--frontends/gtk/options.h6
-rw-r--r--frontends/gtk/page_info.c196
-rw-r--r--frontends/gtk/page_info.h10
-rw-r--r--frontends/gtk/plotters.c4
-rw-r--r--frontends/gtk/preferences.c67
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.ui (renamed from frontends/gtk/res/netsurf.gtk2.ui)0
-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.ui (renamed from frontends/gtk/res/tabcontents.gtk2.ui)0
-rw-r--r--frontends/gtk/res/gtk2/toolbar.ui (renamed from frontends/gtk/res/toolbar.gtk2.ui)0
-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.ui (renamed from frontends/gtk/res/netsurf.gtk3.ui)0
-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.ui (renamed from frontends/gtk/res/tabcontents.gtk3.ui)0
-rw-r--r--frontends/gtk/res/gtk3/toolbar.ui (renamed from frontends/gtk/res/toolbar.gtk3.ui)0
-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
l---------frontends/gtk/res/maps.html1
-rw-r--r--frontends/gtk/res/messages.gresource.xml1
-rw-r--r--frontends/gtk/res/netsurf.gresource.xml33
-rw-r--r--frontends/gtk/res/ssl.gtk2.ui202
-rw-r--r--frontends/gtk/res/ssl.gtk3.ui181
-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.c10
-rw-r--r--frontends/gtk/scaffolding.c39
-rw-r--r--frontends/gtk/scaffolding.h17
-rw-r--r--frontends/gtk/search.c3
-rw-r--r--frontends/gtk/toolbar.c168
-rw-r--r--frontends/gtk/toolbar.h21
-rw-r--r--frontends/gtk/window.c72
-rw-r--r--frontends/gtk/window.h18
72 files changed, 1664 insertions, 1869 deletions
diff --git a/frontends/gtk/Makefile b/frontends/gtk/Makefile
index ec9889ea0..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=700 \
- -D_POSIX_C_SOURCE=200809L \
-D_NETBSD_SOURCE \
-DGTK_RESPATH=\"$(NETSURF_GTK_RES_PATH)\"
@@ -103,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
@@ -112,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: $<"
@@ -158,11 +174,11 @@ 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 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 \
+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
@@ -177,15 +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 \
+ 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/completion.c b/frontends/gtk/completion.c
index 1a765416b..585a9e511 100644
--- a/frontends/gtk/completion.c
+++ b/frontends/gtk/completion.c
@@ -21,6 +21,8 @@
* Implementation of url entry completion.
*/
+#include <stdlib.h>
+
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/nsoption.h"
diff --git a/frontends/gtk/cookies.c b/frontends/gtk/cookies.c
index 1f7833cca..fef7e06d7 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;
}
@@ -288,8 +292,7 @@ static nserror nsgtk_cookies_init(void)
return res;
}
- res = cookie_manager_init(ncwin->core.cb_table,
- (struct core_window *)ncwin);
+ res = cookie_manager_init((struct core_window *)ncwin);
if (res != NSERROR_OK) {
free(ncwin);
return res;
@@ -305,13 +308,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 cb78212dd..fe2ffd087 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;
}
@@ -610,18 +615,20 @@ static nserror
nsgtk_cw_set_scroll(struct core_window *cw, int x, int y)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
- GtkAdjustment *vadj;
- GtkAdjustment *hadj;
- vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
- hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
+ if (nsgtk_cw->scrolled != NULL) {
+ GtkAdjustment *vadj;
+ GtkAdjustment *hadj;
- assert(vadj != NULL);
- assert(hadj != NULL);
+ vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
+ hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
- gtk_adjustment_set_value(vadj, y);
- gtk_adjustment_set_value(hadj, x);
+ assert(vadj != NULL);
+ assert(hadj != NULL);
+ gtk_adjustment_set_value(vadj, y);
+ gtk_adjustment_set_value(hadj, x);
+ }
return NSERROR_OK;
}
@@ -633,21 +640,26 @@ nsgtk_cw_set_scroll(struct core_window *cw, int x, int y)
* \param r rectangle that needs scrolling.
*/
static nserror
-nsgtk_cw_get_scroll(struct core_window *cw, int *x, int *y)
+nsgtk_cw_get_scroll(const struct core_window *cw, int *x, int *y)
{
struct nsgtk_corewindow *nsgtk_cw = (struct nsgtk_corewindow *)cw;
- GtkAdjustment *vadj;
- GtkAdjustment *hadj;
- vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
- hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
+ if (nsgtk_cw->scrolled != NULL) {
+ GtkAdjustment *vadj;
+ GtkAdjustment *hadj;
- assert(vadj != NULL);
- assert(hadj != NULL);
+ vadj = gtk_scrolled_window_get_vadjustment(nsgtk_cw->scrolled);
+ hadj = gtk_scrolled_window_get_hadjustment(nsgtk_cw->scrolled);
- *y = (int)(gtk_adjustment_get_value(vadj));
- *x = (int)(gtk_adjustment_get_value(hadj));
+ assert(vadj != NULL);
+ assert(hadj != NULL);
+ *y = (int)(gtk_adjustment_get_value(vadj));
+ *x = (int)(gtk_adjustment_get_value(hadj));
+ } else {
+ *x = 0;
+ *y = 0;
+ }
return NSERROR_OK;
}
@@ -660,21 +672,29 @@ nsgtk_cw_get_scroll(struct core_window *cw, int *x, int *y)
* \param[out] height to be set to viewport height in px
*/
static nserror
-nsgtk_cw_get_window_dimensions(struct core_window *cw, int *width, int *height)
+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;
}
@@ -698,20 +718,20 @@ nsgtk_cw_drag_status(struct core_window *cw, core_window_drag_status ds)
/**
* core window callback table for nsgtk
*/
-static struct core_window_callback_table nsgtk_cw_cb_table = {
+static struct core_window_table nsgtk_cw_cb_table = {
.invalidate = nsgtk_cw_invalidate_area,
- .update_size = nsgtk_cw_update_size,
+ .set_extent = nsgtk_cw_update_size,
.set_scroll = nsgtk_cw_set_scroll,
.get_scroll = nsgtk_cw_get_scroll,
- .get_window_dimensions = nsgtk_cw_get_window_dimensions,
+ .get_dimensions = nsgtk_cw_get_window_dimensions,
.drag_status = nsgtk_cw_drag_status
};
+struct core_window_table *nsgtk_core_window_table = &nsgtk_cw_cb_table;
/* exported function documented gtk/corewindow.h */
nserror nsgtk_corewindow_init(struct nsgtk_corewindow *nsgtk_cw)
{
- nsgtk_cw->cb_table = &nsgtk_cw_cb_table;
nsgtk_cw->drag_status = CORE_WINDOW_DRAG_NONE;
/* input method setup */
@@ -756,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/corewindow.h b/frontends/gtk/corewindow.h
index 6100e67ae..2640e3bab 100644
--- a/frontends/gtk/corewindow.h
+++ b/frontends/gtk/corewindow.h
@@ -21,6 +21,8 @@
#include "netsurf/core_window.h"
+extern struct core_window_table *nsgtk_core_window_table;
+
/**
* nsgtk core window mouse state
*/
@@ -46,10 +48,10 @@ struct nsgtk_corewindow {
/* private variables */
/** Input method */
GtkIMContext *input_method;
- /** table of callbacks for core window operations */
- struct core_window_callback_table *cb_table;
+
/** mouse state */
struct nsgtk_corewindow_mouse mouse_state;
+
/** drag status set by core */
core_window_drag_status drag_status;
diff --git a/frontends/gtk/download.c b/frontends/gtk/download.c
index 173d2e46e..d1231634d 100644
--- a/frontends/gtk/download.c
+++ b/frontends/gtk/download.c
@@ -432,7 +432,7 @@ static gboolean nsgtk_download_update(gboolean force_update)
switch (dl->status) {
case NSGTK_DOWNLOAD_WORKING:
pulse_mode = TRUE;
- /* Fall through */
+ fallthrough;
case NSGTK_DOWNLOAD_NONE:
dl->speed = dl->size_downloaded /
@@ -449,12 +449,13 @@ static gboolean nsgtk_download_update(gboolean force_update)
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
@@ -1022,7 +1023,7 @@ nserror nsgtk_download_init(void)
/* exported interface documented in gtk/download.h */
-void nsgtk_download_destroy ()
+void nsgtk_download_destroy(void)
{
nsgtk_download_do(nsgtk_download_store_cancel_item);
}
diff --git a/frontends/gtk/fetch.c b/frontends/gtk/fetch.c
index 58bd0b853..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");
diff --git a/frontends/gtk/gdk.c b/frontends/gtk/gdk.c
index 2912862da..fe9a0791c 100644
--- a/frontends/gtk/gdk.c
+++ b/frontends/gtk/gdk.c
@@ -73,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..703b9c498 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;
}
@@ -343,8 +349,7 @@ static nserror nsgtk_global_history_init(void)
return res;
}
- res = global_history_init(ncwin->core.cb_table,
- (struct core_window *)ncwin);
+ res = global_history_init((struct core_window *)ncwin);
if (res != NSERROR_OK) {
free(ncwin);
return res;
diff --git a/frontends/gtk/gui.c b/frontends/gtk/gui.c
index 3cfcd5cb1..644237e09 100644
--- a/frontends/gtk/gui.c
+++ b/frontends/gtk/gui.c
@@ -43,12 +43,11 @@
#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"
@@ -66,38 +65,196 @@
#include "gtk/toolbar_items.h"
#include "gtk/scaffolding.h"
#include "gtk/window.h"
+#include "gtk/corewindow.h"
#include "gtk/schedule.h"
#include "gtk/selection.h"
#include "gtk/search.h"
#include "gtk/bitmap.h"
+#include "gtk/misc.h"
#include "gtk/resources.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 */
+/** favicon default pixbuf */
+GdkPixbuf *favicon_pixbuf;
+
+/** default window icon pixbuf */
+GdkPixbuf *win_default_icon_pixbuf;
GtkBuilder *warning_builder;
-char **respaths; /** resource search path vector */
+/** resource search path vector */
+char **respaths;
-/**
- * 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)
+
+/* exported function documented in gtk/warn.h */
+nserror nsgtk_warning(const char *warning, const char *detail)
{
- fprintf(stderr, "%s", error);
- exit(EXIT_FAILURE);
+ char buf[300]; /* 300 is the size the RISC OS GUI uses */
+ static GtkWindow *nsgtk_warning_window;
+ GtkLabel *WarningLabel;
+
+ NSLOG(netsurf, INFO, "%s %s", warning, detail ? detail : "");
+ fflush(stdout);
+
+ nsgtk_warning_window = GTK_WINDOW(gtk_builder_get_object(warning_builder, "wndWarning"));
+ WarningLabel = GTK_LABEL(gtk_builder_get_object(warning_builder,
+ "labelWarning"));
+
+ snprintf(buf, sizeof(buf), "%s %s", messages_get(warning),
+ detail ? detail : "");
+ buf[sizeof(buf) - 1] = 0;
+
+ gtk_label_set_text(WarningLabel, buf);
+
+ gtk_widget_show_all(GTK_WIDGET(nsgtk_warning_window));
+
+ return NSERROR_OK;
+}
+
+
+/* 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
+ * everything that the RISC OS version does. But this will do for
+ * now. I hope.
+ */
+ switch (key->keyval) {
+
+ case GDK_KEY(Tab):
+ return NS_KEY_TAB;
+
+ 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;
+
+ case GDK_KEY(Linefeed):
+ return 13;
+
+ case GDK_KEY(Return):
+ return 10;
+
+ 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):
+ case GDK_KEY(KP_Up):
+ return NS_KEY_UP;
+
+ case GDK_KEY(Down):
+ case GDK_KEY(KP_Down):
+ return NS_KEY_DOWN;
+
+ case GDK_KEY(Home):
+ case GDK_KEY(KP_Home):
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_LINE_START;
+ else
+ return NS_KEY_TEXT_START;
+
+ case GDK_KEY(End):
+ case GDK_KEY(KP_End):
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_LINE_END;
+ else
+ return NS_KEY_TEXT_END;
+
+ case GDK_KEY(Page_Up):
+ case GDK_KEY(KP_Page_Up):
+ return NS_KEY_PAGE_UP;
+
+ case GDK_KEY(Page_Down):
+ case GDK_KEY(KP_Page_Down):
+ return NS_KEY_PAGE_DOWN;
+
+ case 'a':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_SELECT_ALL;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'u':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_DELETE_LINE;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'c':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_COPY_SELECTION;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'v':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_PASTE;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'x':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_CUT_SELECTION;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'Z':
+ case 'y':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_REDO;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case 'z':
+ if (key->state & GDK_CONTROL_MASK)
+ return NS_KEY_UNDO;
+ return gdk_keyval_to_unicode(key->keyval);
+
+ case GDK_KEY(Escape):
+ return NS_KEY_ESCAPE;
+
+ /* Modifiers - do nothing for now */
+ case GDK_KEY(Shift_L):
+ case GDK_KEY(Shift_R):
+ case GDK_KEY(Control_L):
+ case GDK_KEY(Control_R):
+ case GDK_KEY(Caps_Lock):
+ case GDK_KEY(Shift_Lock):
+ case GDK_KEY(Meta_L):
+ case GDK_KEY(Meta_R):
+ case GDK_KEY(Alt_L):
+ case GDK_KEY(Alt_R):
+ case GDK_KEY(Super_L):
+ case GDK_KEY(Super_R):
+ case GDK_KEY(Hyper_L):
+ case GDK_KEY(Hyper_R):
+ return 0;
+
+ }
+ return gdk_keyval_to_unicode(key->keyval);
}
+
/**
* Create an array of valid paths to search for resources.
*
@@ -156,6 +313,176 @@ nsgtk_init_resource_path(const char *config_home)
/**
+ * create directory name and check it is acessible and a directory.
+ */
+static nserror
+check_dirname(const char *path, const char *leaf, char **dirname_out)
+{
+ nserror ret;
+ char *dirname = NULL;
+ struct stat dirname_stat;
+
+ ret = netsurf_mkpath(&dirname, NULL, 2, path, leaf);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+
+ /* ensure access is possible and the entry is actualy
+ * a directory.
+ */
+ if (stat(dirname, &dirname_stat) == 0) {
+ if (S_ISDIR(dirname_stat.st_mode)) {
+ if (access(dirname, R_OK | W_OK) == 0) {
+ *dirname_out = dirname;
+ return NSERROR_OK;
+ } else {
+ ret = NSERROR_PERMISSION;
+ }
+ } else {
+ ret = NSERROR_NOT_DIRECTORY;
+ }
+ } else {
+ ret = NSERROR_NOT_FOUND;
+ }
+
+ free(dirname);
+
+ return ret;
+}
+
+
+/**
+ * Get the path to the config directory.
+ *
+ * @param config_home_out Path to configuration directory.
+ * @return NSERROR_OK on sucess and \a config_home_out updated else error code.
+ */
+static nserror get_config_home(char **config_home_out)
+{
+ nserror ret;
+ char *home_dir;
+ char *xdg_config_dir;
+ char *config_home;
+
+ home_dir = getenv("HOME");
+
+ /* The old $HOME/.netsurf/ directory should be used if it
+ * exists and is accessible.
+ */
+ if (home_dir != NULL) {
+ ret = check_dirname(home_dir, ".netsurf", &config_home);
+ if (ret == NSERROR_OK) {
+ NSLOG(netsurf, INFO, "\"%s\"", config_home);
+ *config_home_out = config_home;
+ return ret;
+ }
+ }
+
+ /* $XDG_CONFIG_HOME defines the base directory
+ * relative to which user specific configuration files
+ * should be stored.
+ */
+ xdg_config_dir = getenv("XDG_CONFIG_HOME");
+
+ if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
+ /* If $XDG_CONFIG_HOME is either not set or empty, a
+ * default equal to $HOME/.config should be used.
+ */
+
+ /** @todo the meaning of empty is never defined so I
+ * am assuming it is a zero length string but is it
+ * supposed to mean "whitespace" and if so what counts
+ * as whitespace? (are tabs etc. counted or should
+ * isspace() be used)
+ */
+
+ /* the HOME envvar is required */
+ if (home_dir == NULL) {
+ return NSERROR_NOT_DIRECTORY;
+ }
+
+ ret = check_dirname(home_dir, ".config/netsurf", &config_home);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ } else {
+ ret = check_dirname(xdg_config_dir, "netsurf", &config_home);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ }
+
+ NSLOG(netsurf, INFO, "\"%s\"", config_home);
+
+ *config_home_out = config_home;
+ return NSERROR_OK;
+}
+
+
+static nserror create_config_home(char **config_home_out)
+{
+ char *config_home = NULL;
+ char *home_dir;
+ char *xdg_config_dir;
+ nserror ret;
+
+ NSLOG(netsurf, INFO, "Attempting to create configuration directory");
+
+ /* $XDG_CONFIG_HOME defines the base directory
+ * relative to which user specific configuration files
+ * should be stored.
+ */
+ xdg_config_dir = getenv("XDG_CONFIG_HOME");
+
+ if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
+ home_dir = getenv("HOME");
+
+ if ((home_dir == NULL) || (*home_dir == 0)) {
+ return NSERROR_NOT_DIRECTORY;
+ }
+
+ ret = netsurf_mkpath(&config_home, NULL, 4, home_dir, ".config","netsurf", "/");
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ } else {
+ ret = netsurf_mkpath(&config_home, NULL, 3, xdg_config_dir, "netsurf", "/");
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ }
+
+ /* ensure all elements of path exist (the trailing / is required) */
+ ret = netsurf_mkdir_all(config_home);
+ if (ret != NSERROR_OK) {
+ free(config_home);
+ return ret;
+ }
+
+ /* strip the trailing separator */
+ config_home[strlen(config_home) - 1] = 0;
+
+ NSLOG(netsurf, INFO, "\"%s\"", config_home);
+
+ *config_home_out = config_home;
+
+ 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.
@@ -250,7 +577,7 @@ static nserror set_defaults(struct nsoption_s *defaults)
/* set default items in toolbar */
nsoption_set_charp(toolbar_items,
- strdup("back/history/forward/reloadstop/url_bar/websearch/openmenu"));
+ strdup("back/history/forward/reloadstop/url_bar/websearch/openmenu"));
/* set default for menu and tool bar visibility */
nsoption_set_charp(bar_show, strdup("tool"));
@@ -258,6 +585,253 @@ static nserror set_defaults(struct nsoption_s *defaults)
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.
+ *
+ * @param cache_home_out Path to cache directory.
+ * @return NSERROR_OK on sucess and \a cache_home_out updated else error code.
+ */
+static nserror get_cache_home(char **cache_home_out)
+{
+ nserror ret;
+ char *xdg_cache_dir;
+ char *cache_home;
+ char *home_dir;
+
+ /* $XDG_CACHE_HOME defines the base directory relative to
+ * which user specific non-essential data files should be
+ * stored.
+ */
+ xdg_cache_dir = getenv("XDG_CACHE_HOME");
+
+ if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
+ /* If $XDG_CACHE_HOME is either not set or empty, a
+ * default equal to $HOME/.cache should be used.
+ */
+
+ home_dir = getenv("HOME");
+
+ /* the HOME envvar is required */
+ if (home_dir == NULL) {
+ return NSERROR_NOT_DIRECTORY;
+ }
+
+ ret = check_dirname(home_dir, ".cache/netsurf", &cache_home);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ } else {
+ ret = check_dirname(xdg_cache_dir, "netsurf", &cache_home);
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ }
+
+ NSLOG(netsurf, INFO, "\"%s\"", cache_home);
+
+ *cache_home_out = cache_home;
+ return NSERROR_OK;
+}
+
+
+/**
+ * create a cache directory
+ */
+static nserror create_cache_home(char **cache_home_out)
+{
+ char *cache_home = NULL;
+ char *home_dir;
+ char *xdg_cache_dir;
+ nserror ret;
+
+ NSLOG(netsurf, INFO, "Attempting to create cache directory");
+
+ /* $XDG_CACHE_HOME defines the base directory
+ * relative to which user specific cache files
+ * should be stored.
+ */
+ xdg_cache_dir = getenv("XDG_CACHE_HOME");
+
+ if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
+ home_dir = getenv("HOME");
+
+ if ((home_dir == NULL) || (*home_dir == 0)) {
+ return NSERROR_NOT_DIRECTORY;
+ }
+
+ ret = netsurf_mkpath(&cache_home, NULL, 4, home_dir, ".cache", "netsurf", "/");
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ } else {
+ ret = netsurf_mkpath(&cache_home, NULL, 3, xdg_cache_dir, "netsurf", "/");
+ if (ret != NSERROR_OK) {
+ return ret;
+ }
+ }
+
+ /* ensure all elements of path exist (the trailing / is required) */
+ ret = netsurf_mkdir_all(cache_home);
+ if (ret != NSERROR_OK) {
+ free(cache_home);
+ return ret;
+ }
+
+ /* strip the trailing separator */
+ cache_home[strlen(cache_home) - 1] = 0;
+
+ NSLOG(netsurf, INFO, "\"%s\"", cache_home);
+
+ *cache_home_out = cache_home;
+
+ return NSERROR_OK;
+}
+
+
+/**
+ * GTK specific initialisation
+ */
+static nserror nsgtk_init(int *pargc, char ***pargv, char **cache_home)
+{
+ nserror ret;
+
+ /* Locate the correct user configuration directory path */
+ ret = get_config_home(&nsgtk_config_home);
+ if (ret == NSERROR_NOT_FOUND) {
+ /* no config directory exists yet so try to create one */
+ ret = create_config_home(&nsgtk_config_home);
+ }
+ if (ret != NSERROR_OK) {
+ NSLOG(netsurf, INFO,
+ "Unable to locate a configuration directory.");
+ nsgtk_config_home = NULL;
+ }
+
+ /* Initialise gtk */
+ 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, pargc, *pargv);
+
+ /* build the common resource path list */
+ respaths = nsgtk_init_resource_path(nsgtk_config_home);
+ if (respaths == NULL) {
+ fprintf(stderr, "Unable to locate resources\n");
+ return 1;
+ }
+
+ /* initialise the gtk resource handling */
+ ret = nsgtk_init_resources(respaths);
+ if (ret != NSERROR_OK) {
+ fprintf(stderr, "GTK resources failed to initialise (%s)\n",
+ messages_get_errorcode(ret));
+ return ret;
+ }
+
+ /* Initialise user options */
+ ret = nsgtk_option_init(pargc, *pargv);
+ if (ret != NSERROR_OK) {
+ fprintf(stderr, "Options failed to initialise (%s)\n",
+ messages_get_errorcode(ret));
+ return ret;
+ }
+
+ /* Initialise translated messages */
+ ret = nsgtk_messages_init(respaths);
+ if (ret != NSERROR_OK) {
+ fprintf(stderr, "Unable to load translated messages (%s)\n",
+ messages_get_errorcode(ret));
+ 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);
+ if (ret == NSERROR_NOT_FOUND) {
+ /* no cache directory exists yet so try to create one */
+ ret = create_cache_home(cache_home);
+ }
+ if (ret != NSERROR_OK) {
+ NSLOG(netsurf, INFO, "Unable to locate a cache directory.");
+ }
+
+
+ return NSERROR_OK;
+}
+
+
#if GTK_CHECK_VERSION(3,14,0)
/**
@@ -266,7 +840,7 @@ static nserror set_defaults(struct nsoption_s *defaults)
static nserror nsgtk_add_named_icons_to_theme(void)
{
gtk_icon_theme_add_resource_path(gtk_icon_theme_get_default(),
- "/org/netsurf/icons");
+ "/org/netsurf/icons");
return NSERROR_OK;
}
@@ -280,7 +854,7 @@ add_builtin_icon(const char *prefix, const char *name, int x, int y)
char *resname;
int resnamelen;
- /* resource name string length allowing for / .png and termination */
+ /* resource name string length allowing for / .png and termination */
resnamelen = strlen(prefix) + strlen(name) + 5 + 1 + 4 + 1;
resname = malloc(resnamelen);
if (resname == NULL) {
@@ -299,13 +873,14 @@ add_builtin_icon(const char *prefix, const char *name, int x, int y)
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
+ * gtk/res/netsurf.gresource.xml
*/
add_builtin_icon("", "local-history", 8, 32);
add_builtin_icon("", "show-cookie", 24, 24);
@@ -327,13 +902,13 @@ static nserror nsgtk_add_named_icons_to_theme(void)
/**
- * Initialize GTK specific parts of the browser.
+ * 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_init(int argc, char** argv, char **respath)
+static nserror nsgtk_setup(int argc, char** argv, char **respath)
{
char buf[PATH_MAX];
char *resource_filename;
@@ -374,7 +949,7 @@ static nserror nsgtk_init(int argc, char** argv, char **respath)
resource_filename);
free(resource_filename);
}
- search_web_select_provider(nsoption_int(search_provider));
+ search_web_select_provider(nsoption_charp(search_web_provider));
/* Default favicon */
res = nsgdk_pixbuf_new_from_resname("favicon.png", &favicon_pixbuf);
@@ -407,6 +982,11 @@ static nserror nsgtk_init(int argc, char** argv, char **respath)
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);
@@ -467,19 +1047,6 @@ static nserror nsgtk_init(int argc, char** argv, char **respath)
}
-
-/**
- * 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.
*
@@ -500,6 +1067,9 @@ static void nsgtk_main(void)
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);
@@ -537,7 +1107,10 @@ static void nsgtk_main(void)
}
-static void gui_quit(void)
+/**
+ * finalise the browser
+ */
+static void nsgtk_finalise(void)
{
nserror res;
@@ -589,630 +1162,30 @@ static void gui_quit(void)
free(nsgtk_config_home);
gtk_fetch_filetype_fin();
-}
-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;
-}
-
-/* exported function documented in gtk/warn.h */
-nserror nsgtk_warning(const char *warning, const char *detail)
-{
- char buf[300]; /* 300 is the size the RISC OS GUI uses */
- static GtkWindow *nsgtk_warning_window;
- GtkLabel *WarningLabel;
-
- NSLOG(netsurf, INFO, "%s %s", warning, detail ? detail : "");
- fflush(stdout);
-
- nsgtk_warning_window = GTK_WINDOW(gtk_builder_get_object(warning_builder, "wndWarning"));
- WarningLabel = GTK_LABEL(gtk_builder_get_object(warning_builder,
- "labelWarning"));
-
- snprintf(buf, sizeof(buf), "%s %s", messages_get(warning),
- detail ? detail : "");
- buf[sizeof(buf) - 1] = 0;
-
- gtk_label_set_text(WarningLabel, buf);
-
- gtk_widget_show_all(GTK_WIDGET(nsgtk_warning_window));
-
- return NSERROR_OK;
-}
-
-
-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));
-}
-
-
-uint32_t gtk_gui_gdkkey_to_nskey(GdkEventKey *key)
-{
- /* this function will need to become much more complex to support
- * everything that the RISC OS version does. But this will do for
- * now. I hope.
- */
- switch (key->keyval) {
-
- case GDK_KEY(Tab):
- return NS_KEY_TAB;
-
- case GDK_KEY(BackSpace):
- if (key->state & GDK_SHIFT_MASK)
- return NS_KEY_DELETE_LINE_START;
- else
- return NS_KEY_DELETE_LEFT;
-
- case GDK_KEY(Delete):
- if (key->state & GDK_SHIFT_MASK)
- return NS_KEY_DELETE_LINE_END;
- else
- return NS_KEY_DELETE_RIGHT;
-
- case GDK_KEY(Linefeed):
- return 13;
-
- case GDK_KEY(Return):
- return 10;
-
- case GDK_KEY(Left):
- case GDK_KEY(KP_Left):
- return NS_KEY_LEFT;
-
- case GDK_KEY(Right):
- case GDK_KEY(KP_Right):
- return NS_KEY_RIGHT;
-
- case GDK_KEY(Up):
- case GDK_KEY(KP_Up):
- return NS_KEY_UP;
-
- case GDK_KEY(Down):
- case GDK_KEY(KP_Down):
- return NS_KEY_DOWN;
-
- case GDK_KEY(Home):
- case GDK_KEY(KP_Home):
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_LINE_START;
- else
- return NS_KEY_TEXT_START;
-
- case GDK_KEY(End):
- case GDK_KEY(KP_End):
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_LINE_END;
- else
- return NS_KEY_TEXT_END;
-
- case GDK_KEY(Page_Up):
- case GDK_KEY(KP_Page_Up):
- return NS_KEY_PAGE_UP;
-
- case GDK_KEY(Page_Down):
- case GDK_KEY(KP_Page_Down):
- return NS_KEY_PAGE_DOWN;
-
- case 'a':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_SELECT_ALL;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'u':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_DELETE_LINE;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'c':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_COPY_SELECTION;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'v':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_PASTE;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'x':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_CUT_SELECTION;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'Z':
- case 'y':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_REDO;
- return gdk_keyval_to_unicode(key->keyval);
-
- case 'z':
- if (key->state & GDK_CONTROL_MASK)
- return NS_KEY_UNDO;
- return gdk_keyval_to_unicode(key->keyval);
-
- case GDK_KEY(Escape):
- return NS_KEY_ESCAPE;
-
- /* Modifiers - do nothing for now */
- case GDK_KEY(Shift_L):
- case GDK_KEY(Shift_R):
- case GDK_KEY(Control_L):
- case GDK_KEY(Control_R):
- case GDK_KEY(Caps_Lock):
- case GDK_KEY(Shift_Lock):
- case GDK_KEY(Meta_L):
- case GDK_KEY(Meta_R):
- case GDK_KEY(Alt_L):
- case GDK_KEY(Alt_R):
- case GDK_KEY(Super_L):
- case GDK_KEY(Super_R):
- case GDK_KEY(Hyper_L):
- case GDK_KEY(Hyper_R):
- return 0;
-
- }
- return gdk_keyval_to_unicode(key->keyval);
-}
-
-
-/**
- * create directory name and check it is acessible and a directory.
- */
-static nserror
-check_dirname(const char *path, const char *leaf, char **dirname_out)
-{
- nserror ret;
- char *dirname = NULL;
- struct stat dirname_stat;
-
- ret = netsurf_mkpath(&dirname, NULL, 2, path, leaf);
- if (ret != NSERROR_OK) {
- return ret;
- }
-
- /* ensure access is possible and the entry is actualy
- * a directory.
- */
- if (stat(dirname, &dirname_stat) == 0) {
- if (S_ISDIR(dirname_stat.st_mode)) {
- if (access(dirname, R_OK | W_OK) == 0) {
- *dirname_out = dirname;
- return NSERROR_OK;
- } else {
- ret = NSERROR_PERMISSION;
- }
- } else {
- ret = NSERROR_NOT_DIRECTORY;
- }
- } else {
- ret = NSERROR_NOT_FOUND;
- }
-
- free(dirname);
-
- return ret;
-}
-
-/**
- * Get the path to the config directory.
- *
- * @param config_home_out Path to configuration directory.
- * @return NSERROR_OK on sucess and \a config_home_out updated else error code.
- */
-static nserror get_config_home(char **config_home_out)
-{
- nserror ret;
- char *home_dir;
- char *xdg_config_dir;
- char *config_home;
-
- home_dir = getenv("HOME");
-
- /* The old $HOME/.netsurf/ directory should be used if it
- * exists and is accessible.
- */
- if (home_dir != NULL) {
- ret = check_dirname(home_dir, ".netsurf", &config_home);
- if (ret == NSERROR_OK) {
- NSLOG(netsurf, INFO, "\"%s\"", config_home);
- *config_home_out = config_home;
- return ret;
- }
- }
-
- /* $XDG_CONFIG_HOME defines the base directory
- * relative to which user specific configuration files
- * should be stored.
- */
- xdg_config_dir = getenv("XDG_CONFIG_HOME");
-
- if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
- /* If $XDG_CONFIG_HOME is either not set or empty, a
- * default equal to $HOME/.config should be used.
- */
-
- /** @todo the meaning of empty is never defined so I
- * am assuming it is a zero length string but is it
- * supposed to mean "whitespace" and if so what counts
- * as whitespace? (are tabs etc. counted or should
- * isspace() be used)
- */
-
- /* the HOME envvar is required */
- if (home_dir == NULL) {
- return NSERROR_NOT_DIRECTORY;
- }
-
- ret = check_dirname(home_dir, ".config/netsurf", &config_home);
- if (ret != NSERROR_OK) {
- return ret;
- }
- } else {
- ret = check_dirname(xdg_config_dir, "netsurf", &config_home);
- if (ret != NSERROR_OK) {
- return ret;
- }
- }
-
- NSLOG(netsurf, INFO, "\"%s\"", config_home);
-
- *config_home_out = config_home;
- return NSERROR_OK;
-}
-
-static nserror create_config_home(char **config_home_out)
-{
- char *config_home = NULL;
- char *home_dir;
- char *xdg_config_dir;
- nserror ret;
-
- NSLOG(netsurf, INFO, "Attempting to create configuration directory");
-
- /* $XDG_CONFIG_HOME defines the base directory
- * relative to which user specific configuration files
- * should be stored.
- */
- xdg_config_dir = getenv("XDG_CONFIG_HOME");
-
- if ((xdg_config_dir == NULL) || (*xdg_config_dir == 0)) {
- home_dir = getenv("HOME");
-
- if ((home_dir == NULL) || (*home_dir == 0)) {
- return NSERROR_NOT_DIRECTORY;
- }
-
- ret = netsurf_mkpath(&config_home, NULL, 4, home_dir, ".config","netsurf", "/");
- if (ret != NSERROR_OK) {
- return ret;
- }
- } else {
- ret = netsurf_mkpath(&config_home, NULL, 3, xdg_config_dir, "netsurf", "/");
- if (ret != NSERROR_OK) {
- return ret;
- }
- }
-
- /* ensure all elements of path exist (the trailing / is required) */
- ret = netsurf_mkdir_all(config_home);
- if (ret != NSERROR_OK) {
- free(config_home);
- return ret;
- }
-
- /* strip the trailing separator */
- config_home[strlen(config_home) - 1] = 0;
-
- NSLOG(netsurf, INFO, "\"%s\"", config_home);
-
- *config_home_out = config_home;
-
- return NSERROR_OK;
-}
-
-/**
- * Get the path to the cache directory.
- *
- * @param cache_home_out Path to cache directory.
- * @return NSERROR_OK on sucess and \a cache_home_out updated else error code.
- */
-static nserror get_cache_home(char **cache_home_out)
-{
- nserror ret;
- char *xdg_cache_dir;
- char *cache_home;
- char *home_dir;
-
- /* $XDG_CACHE_HOME defines the base directory relative to
- * which user specific non-essential data files should be
- * stored.
- */
- xdg_cache_dir = getenv("XDG_CACHE_HOME");
-
- if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
- /* If $XDG_CACHE_HOME is either not set or empty, a
- * default equal to $HOME/.cache should be used.
- */
-
- home_dir = getenv("HOME");
-
- /* the HOME envvar is required */
- if (home_dir == NULL) {
- return NSERROR_NOT_DIRECTORY;
- }
-
- ret = check_dirname(home_dir, ".cache/netsurf", &cache_home);
- if (ret != NSERROR_OK) {
- return ret;
- }
- } else {
- ret = check_dirname(xdg_cache_dir, "netsurf", &cache_home);
- if (ret != NSERROR_OK) {
- return ret;
- }
- }
-
- NSLOG(netsurf, INFO, "\"%s\"", cache_home);
-
- *cache_home_out = cache_home;
- return NSERROR_OK;
-}
-
-static nserror create_cache_home(char **cache_home_out)
-{
- char *cache_home = NULL;
- char *home_dir;
- char *xdg_cache_dir;
- nserror ret;
-
- NSLOG(netsurf, INFO, "Attempting to create configuration directory");
-
- /* $XDG_CACHE_HOME defines the base directory
- * relative to which user specific cache files
- * should be stored.
- */
- xdg_cache_dir = getenv("XDG_CACHE_HOME");
-
- if ((xdg_cache_dir == NULL) || (*xdg_cache_dir == 0)) {
- home_dir = getenv("HOME");
-
- if ((home_dir == NULL) || (*home_dir == 0)) {
- return NSERROR_NOT_DIRECTORY;
- }
-
- ret = netsurf_mkpath(&cache_home, NULL, 4, home_dir, ".cache", "netsurf", "/");
- if (ret != NSERROR_OK) {
- return ret;
- }
- } else {
- ret = netsurf_mkpath(&cache_home, NULL, 3, xdg_cache_dir, "netsurf", "/");
- if (ret != NSERROR_OK) {
- return ret;
- }
- }
-
- /* ensure all elements of path exist (the trailing / is required) */
- ret = netsurf_mkdir_all(cache_home);
- if (ret != NSERROR_OK) {
- free(cache_home);
- return ret;
- }
-
- /* strip the trailing separator */
- cache_home[strlen(cache_home) - 1] = 0;
-
- NSLOG(netsurf, INFO, "\"%s\"", cache_home);
-
- *cache_home_out = cache_home;
-
- 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);
+ /* common finalisation */
+ netsurf_exit();
- /* ensure all options fall within sensible bounds */
+ /* finalise options */
+ nsoption_finalise(nsoptions, nsoptions_default);
- /* 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);
- }
+ /* finalise logging */
+ nslog_finalise();
- return NSERROR_OK;
}
-static struct gui_misc_table nsgtk_misc_table = {
- .schedule = nsgtk_schedule,
-
- .quit = gui_quit,
- .launch_url = gui_launch_url,
- .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.
*/
int main(int argc, char** argv)
{
+ nserror res;
char *cache_home = NULL;
- nserror ret;
struct netsurf_table nsgtk_table = {
- .misc = &nsgtk_misc_table,
+ .misc = nsgtk_misc_table,
.window = nsgtk_window_table,
+ .corewindow = nsgtk_core_window_table,
.clipboard = nsgtk_clipboard_table,
.download = nsgtk_download_table,
.fetch = nsgtk_fetch_table,
@@ -1223,99 +1196,43 @@ int main(int argc, char** argv)
.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);
- if (ret == NSERROR_NOT_FOUND) {
- /* no config directory exists yet so try to create one */
- ret = create_config_home(&nsgtk_config_home);
- }
- if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO,
- "Unable to locate a configuration directory.");
- nsgtk_config_home = NULL;
- }
-
- /* Initialise gtk */
- gtk_init(&argc, &argv);
-
- /* initialise logging. Not fatal if it fails but not much we
- * can do about it either.
- */
- nslog_init(nslog_stream_configure, &argc, argv);
-
- /* build the common resource path list */
- respaths = nsgtk_init_resource_path(nsgtk_config_home);
- if (respaths == NULL) {
- fprintf(stderr, "Unable to locate resources\n");
- return 1;
- }
-
- /* initialise the gtk resource handling */
- ret = nsgtk_init_resources(respaths);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "GTK resources failed to initialise (%s)\n",
- messages_get_errorcode(ret));
- return 1;
- }
-
- /* Initialise user options */
- ret = nsgtk_option_init(&argc, argv);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "Options failed to initialise (%s)\n",
- messages_get_errorcode(ret));
+ res = netsurf_register(&nsgtk_table);
+ if (res != NSERROR_OK) {
+ fprintf(stderr,
+ "NetSurf operation table failed registration (%s)\n",
+ messages_get_errorcode(res));
return 1;
}
- /* Initialise translated messages */
- ret = nsgtk_messages_init(respaths);
- if (ret != NSERROR_OK) {
- fprintf(stderr, "Unable to load translated messages (%s)\n",
- messages_get_errorcode(ret));
- 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);
- if (ret == NSERROR_NOT_FOUND) {
- /* no cache directory exists yet so try to create one */
- ret = create_cache_home(&cache_home);
- }
- if (ret != NSERROR_OK) {
- NSLOG(netsurf, INFO, "Unable to locate a cache directory.");
+ /* 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 */
- ret = netsurf_init(cache_home);
+ res = netsurf_init(cache_home);
free(cache_home);
- if (ret != NSERROR_OK) {
+ if (res != NSERROR_OK) {
fprintf(stderr, "NetSurf core failed to initialise (%s)\n",
- messages_get_errorcode(ret));
- return 1;
+ messages_get_errorcode(res));
+ return 3;
}
/* 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));
- } else {
- nsgtk_main();
+ 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;
}
- /* common finalisation */
- netsurf_exit();
+ nsgtk_main();
- /* finalise options */
- nsoption_finalise(nsoptions, nsoptions_default);
-
- /* finalise logging */
- nslog_finalise();
+ nsgtk_finalise();
return 0;
}
diff --git a/frontends/gtk/hotlist.c b/frontends/gtk/hotlist.c
index 843e47736..4524f59ba 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;
}
@@ -361,8 +363,7 @@ static nserror nsgtk_hotlist_init(void)
return res;
}
- res = hotlist_manager_init(ncwin->core.cb_table,
- (struct core_window *)ncwin);
+ res = hotlist_manager_init((struct core_window *)ncwin);
if (res != NSERROR_OK) {
free(ncwin);
return res;
diff --git a/frontends/gtk/layout_pango.c b/frontends/gtk/layout_pango.c
index 9e8e94d48..a750e081e 100644
--- a/frontends/gtk/layout_pango.c
+++ b/frontends/gtk/layout_pango.c
@@ -46,7 +46,7 @@ static inline void nsfont_pango_check(void)
NSLOG(netsurf, INFO, "Creating nsfont_pango_context.");
nsfont_pango_context = gdk_pango_context_get();
}
-
+
if (nsfont_pango_layout == NULL) {
NSLOG(netsurf, INFO, "Creating nsfont_pango_layout.");
nsfont_pango_layout = pango_layout_new(nsfont_pango_context);
@@ -74,7 +74,7 @@ nsfont_width(const plot_font_style_t *fstyle,
*width = 0;
return NSERROR_OK;
}
-
+
nsfont_pango_check();
desc = nsfont_style_to_description(fstyle);
@@ -88,7 +88,7 @@ nsfont_width(const plot_font_style_t *fstyle,
NSLOG(netsurf, DEEPDEBUG,
"fstyle: %p string:\"%.*s\", length: %" PRIsizet ", width: %dpx",
fstyle, (int)length, string, length, *width);
-
+
return NSERROR_OK;
}
@@ -127,7 +127,7 @@ nsfont_position_in_string(const plot_font_style_t *fstyle,
pango_layout_set_text(nsfont_pango_layout, string, length);
if (pango_layout_xy_to_index(nsfont_pango_layout,
- x * PANGO_SCALE,
+ x * PANGO_SCALE,
0, &index, 0) == FALSE) {
index = length;
}
@@ -137,6 +137,10 @@ nsfont_position_in_string(const plot_font_style_t *fstyle,
*char_offset = index;
*actual_x = PANGO_PIXELS(pos.x);
+ NSLOG(netsurf, DEEPDEBUG,
+ "fstyle: %p string:\"%.*s\", length: %" PRIsizet ", "
+ "search_x: %dpx, offset: %" PRIsizet ", actual_x: %dpx",
+ fstyle, (int)length, string, length, x, *char_offset, *actual_x);
return NSERROR_OK;
}
@@ -198,7 +202,7 @@ nsfont_split(const plot_font_style_t *fstyle,
/* Obtain the second line of the layout (if there is one) */
line = pango_layout_get_line_readonly(layout, 1);
if (line != NULL) {
- /* Pango split the text. The line's start_index indicates the
+ /* Pango split the text. The line's start_index indicates the
* start of the character after the line break. */
index = line->start_index;
}
@@ -210,6 +214,10 @@ nsfont_split(const plot_font_style_t *fstyle,
/* Obtain the pixel offset of the split character */
nsfont_width(fstyle, string, index, actual_x);
+ NSLOG(netsurf, DEEPDEBUG,
+ "fstyle: %p string:\"%.*s\", length: %" PRIsizet ", "
+ "split_x: %dpx, offset: %" PRIsizet ", actual_x: %dpx",
+ fstyle, (int)length, string, length, x, *char_offset, *actual_x);
return NSERROR_OK;
}
@@ -291,7 +299,7 @@ nsfont_style_to_description(const plot_font_style_t *fstyle)
pango_font_description_set_size(desc, size);
if (fstyle->flags & FONTF_SMALLCAPS) {
- pango_font_description_set_variant(desc,
+ pango_font_description_set_variant(desc,
PANGO_VARIANT_SMALL_CAPS);
} else {
pango_font_description_set_variant(desc, PANGO_VARIANT_NORMAL);
diff --git a/frontends/gtk/local_history.c b/frontends/gtk/local_history.c
index 010fa3126..9303ce459 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;
@@ -182,8 +199,7 @@ nsgtk_local_history_init(struct browser_window *bw,
return res;
}
- res = local_history_init(ncwin->core.cb_table,
- (struct core_window *)ncwin,
+ res = local_history_init((struct core_window *)ncwin,
bw,
&ncwin->session);
if (res != NSERROR_OK) {
@@ -206,7 +222,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 +244,11 @@ 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);
}
@@ -269,3 +293,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/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/misc.h b/frontends/gtk/misc.h
new file mode 100644
index 000000000..3a02c2254
--- /dev/null
+++ b/frontends/gtk/misc.h
@@ -0,0 +1,24 @@
+/*
+ * 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/>.
+ */
+
+#ifndef NETSURF_GTK_MISC_H
+#define NETSURF_GTK_MISC_H 1
+
+extern struct gui_misc_table *nsgtk_misc_table;
+
+#endif
diff --git a/frontends/gtk/options.h b/frontends/gtk/options.h
index dad17f059..7fd79d7c5 100644
--- a/frontends/gtk/options.h
+++ b/frontends/gtk/options.h
@@ -23,9 +23,6 @@
#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)
diff --git a/frontends/gtk/page_info.c b/frontends/gtk/page_info.c
index adc2dfa66..f426f4708 100644
--- a/frontends/gtk/page_info.c
+++ b/frontends/gtk/page_info.c
@@ -26,10 +26,13 @@
#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/sslcert_viewer.h"
+#include "desktop/page-info.h"
+#include "desktop/gui_internal.h"
#include "gtk/plotters.h"
#include "gtk/scaffolding.h"
@@ -41,61 +44,44 @@
/**
* GTK certificate viewing window context
*/
-struct nsgtk_crtvrfy_window {
+struct nsgtk_pi_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;
+ /** GTK window being shown */
+ GtkWindow *dlg;
+ /** Core page-info window */
+ struct page_info *pi;
};
+
/**
- * destroy a previously created certificate view
+ * destroy a previously created page information window
*/
-static nserror nsgtk_crtvrfy_destroy(struct nsgtk_crtvrfy_window *crtvrfy_win)
+static gboolean
+nsgtk_pi_delete_event(GtkWidget *w, GdkEvent *event, gpointer data)
{
- 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;
-}
+ struct nsgtk_pi_window *pi_win;
+ pi_win = (struct nsgtk_pi_window *)data;
-static void
-nsgtk_crtvrfy_accept(GtkButton *w, gpointer data)
-{
- struct nsgtk_crtvrfy_window *crtvrfy_win;
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)data;
+ page_info_destroy(pi_win->pi);
- sslcert_viewer_accept(crtvrfy_win->ssl_data);
+ 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);
- nsgtk_crtvrfy_destroy(crtvrfy_win);
+ return FALSE;
}
+/**
+ * Called to cause the page-info window to close cleanly
+ */
static void
-nsgtk_crtvrfy_reject(GtkWidget *w, gpointer data)
+nsgtk_pi_close_callback(void *pw)
{
- 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;
+ nsgtk_pi_delete_event(NULL, NULL, pw);
}
/**
@@ -108,15 +94,21 @@ nsgtk_crtvrfy_delete_event(GtkWidget *w, GdkEvent *event, gpointer data)
* \return NSERROR_OK on success otherwise appropriate error code
*/
static nserror
-nsgtk_crtvrfy_mouse(struct nsgtk_corewindow *nsgtk_cw,
+nsgtk_pi_mouse(struct nsgtk_corewindow *nsgtk_cw,
browser_mouse_state mouse_state,
int x, int y)
{
- struct nsgtk_crtvrfy_window *crtvrfy_win;
+ struct nsgtk_pi_window *pi_win;
+ bool did_something = false;
/* technically degenerate container of */
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)nsgtk_cw;
+ pi_win = (struct nsgtk_pi_window *)nsgtk_cw;
- sslcert_viewer_mouse_action(crtvrfy_win->ssl_data, mouse_state, x, y);
+ 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;
}
@@ -129,14 +121,14 @@ nsgtk_crtvrfy_mouse(struct nsgtk_corewindow *nsgtk_cw,
* \return NSERROR_OK on success otherwise appropriate error code
*/
static nserror
-nsgtk_crtvrfy_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
+nsgtk_pi_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
{
- struct nsgtk_crtvrfy_window *crtvrfy_win;
+ struct nsgtk_pi_window *pi_win;
/* technically degenerate container of */
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)nsgtk_cw;
+ pi_win = (struct nsgtk_pi_window *)nsgtk_cw;
- if (sslcert_viewer_keypress(crtvrfy_win->ssl_data, nskey)) {
+ if (page_info_keypress(pi_win->pi, nskey)) {
return NSERROR_OK;
}
return NSERROR_NOT_IMPLEMENTED;
@@ -150,92 +142,88 @@ nsgtk_crtvrfy_key(struct nsgtk_corewindow *nsgtk_cw, uint32_t nskey)
* \return NSERROR_OK on success otherwise appropriate error code
*/
static nserror
-nsgtk_crtvrfy_draw(struct nsgtk_corewindow *nsgtk_cw, struct rect *r)
+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_crtvrfy_window *crtvrfy_win;
+ struct nsgtk_pi_window *pi_win;
/* technically degenerate container of */
- crtvrfy_win = (struct nsgtk_crtvrfy_window *)nsgtk_cw;
+ pi_win = (struct nsgtk_pi_window *)nsgtk_cw;
- sslcert_viewer_redraw(crtvrfy_win->ssl_data, 0, 0, r, &ctx);
+ page_info_redraw(pi_win->pi, 0, 0, r, &ctx);
return NSERROR_OK;
}
-static nserror dummy_cb(bool proceed, void *pw)
-{
- return NSERROR_OK;
-}
-
/* exported interface documented in gtk/page_info.h */
nserror nsgtk_page_info(struct browser_window *bw)
{
- struct nsgtk_crtvrfy_window *ncwin;
+ struct nsgtk_pi_window *ncwin;
nserror res;
+ GtkWindow *scaffwin = nsgtk_scaffolding_window(nsgtk_current_scaffolding());
- size_t num;
- struct ssl_cert_info *chain;
- struct nsurl *url;
-
- browser_window_get_ssl_chain(bw, &num, &chain);
- url = browser_window_access_url(bw);
-
- ncwin = malloc(sizeof(struct nsgtk_crtvrfy_window));
+ ncwin = calloc(1, sizeof(struct nsgtk_pi_window));
if (ncwin == NULL) {
return NSERROR_NOMEM;
}
- res = nsgtk_builder_new_from_resname("ssl", &ncwin->builder);
+ res = nsgtk_builder_new_from_resname("pageinfo", &ncwin->builder);
if (res != NSERROR_OK) {
- NSLOG(netsurf, INFO, "SSL UI builder init failed");
+ 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_DIALOG(gtk_builder_get_object(ncwin->builder,
- "wndSSLProblem"));
+ 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);
- /* set parent for transient dialog */
- gtk_window_set_transient_for(GTK_WINDOW(ncwin->dlg),
- nsgtk_scaffolding_window(nsgtk_current_scaffolding()));
+ gtk_window_set_screen(GTK_WINDOW(ncwin->dlg),
+ gtk_widget_get_screen(GTK_WIDGET(scaffwin)));
- ncwin->core.scrolled = GTK_SCROLLED_WINDOW(
- gtk_builder_get_object(ncwin->builder, "SSLScrolled"));
+ /* 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, "SSLDrawingArea"));
+ 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_crtvrfy_delete_event),
+ G_CALLBACK(nsgtk_pi_delete_event),
ncwin);
-
- /* accept button */
- g_signal_connect(G_OBJECT(gtk_builder_get_object(ncwin->builder,
- "sslaccept")),
- "clicked",
- G_CALLBACK(nsgtk_crtvrfy_accept),
+ /* Ditto if we lose the grab */
+ g_signal_connect(G_OBJECT(ncwin->dlg),
+ "grab-broken-event",
+ G_CALLBACK(nsgtk_pi_delete_event),
ncwin);
-
- /* reject button */
- g_signal_connect(G_OBJECT(gtk_builder_get_object(ncwin->builder,
- "sslreject")),
- "clicked",
- G_CALLBACK(nsgtk_crtvrfy_reject),
+ /* 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_crtvrfy_draw;
- ncwin->core.key = nsgtk_crtvrfy_key;
- ncwin->core.mouse = nsgtk_crtvrfy_mouse;
+ 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) {
@@ -244,18 +232,7 @@ nserror nsgtk_page_info(struct browser_window *bw)
return res;
}
- /* initialise certificate viewing interface */
- res = sslcert_viewer_create_session_data(num, url, dummy_cb, NULL, chain,
- &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);
+ res = page_info_create((struct core_window *)ncwin, bw, &ncwin->pi);
if (res != NSERROR_OK) {
g_object_unref(G_OBJECT(ncwin->dlg));
free(ncwin);
@@ -264,5 +241,16 @@ nserror nsgtk_page_info(struct browser_window *bw)
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/page_info.h b/frontends/gtk/page_info.h
index ad443fcfd..23e1e348c 100644
--- a/frontends/gtk/page_info.h
+++ b/frontends/gtk/page_info.h
@@ -27,4 +27,14 @@
*/
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 4a5ef510c..110dcffc5 100644
--- a/frontends/gtk/plotters.c
+++ b/frontends/gtk/plotters.c
@@ -432,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 3aaaa9026..26d32ee20 100644
--- a/frontends/gtk/preferences.c
+++ b/frontends/gtk/preferences.c
@@ -412,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,
@@ -481,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 */
@@ -839,15 +830,33 @@ TOGGLEBUTTON_SIGNALS(checkUrlSearch, search_url_bar)
G_MODULE_EXPORT void
nsgtk_preferences_comboSearch_changed(GtkComboBox *widget, struct ppref *priv)
{
- int provider;
+ gboolean set;
+ GtkTreeIter iter;
+ GtkTreeModel* model;
+ gchar* provider;
+ const char* defprovider;
- provider = gtk_combo_box_get_active(widget);
+ set = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter);
+ if (!set) {
+ return;
+ }
- /* set the option */
- nsoption_set_int(search_provider, provider);
+ model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
+ gtk_tree_model_get(model, &iter, 0, &provider, -1);
/* set search provider */
search_web_select_provider(provider);
+
+ /* set to default option if the default provider is selected */
+ if ((search_web_iterate_providers(-1, &defprovider) != -1) &&
+ (strcmp(provider, defprovider) == 0)) {
+ free(provider);
+ /* use default option */
+ provider = NULL;
+ }
+
+ /* set the option which takes owership of the provider allocation */
+ nsoption_set_charp(search_web_provider, provider);
}
G_MODULE_EXPORT void
@@ -855,20 +864,29 @@ nsgtk_preferences_comboSearch_realize(GtkWidget *widget, struct ppref *priv)
{
int iter;
const char *name;
- int provider = nsoption_int(search_provider);
-
- if (priv->search_providers != NULL) {
- gtk_list_store_clear(priv->search_providers);
- for (iter = search_web_iterate_providers(0, &name);
- iter != -1;
- iter = search_web_iterate_providers(iter, &name)) {
- gtk_list_store_insert_with_values(priv->search_providers,
- NULL, -1,
- 0, name, -1);
+ const char *provider;
+ int provider_idx = 0;
+
+ if (priv->search_providers == NULL) {
+ return;
+ }
+ gtk_list_store_clear(priv->search_providers);
+
+ provider = nsoption_charp(search_web_provider);
+
+ iter = search_web_iterate_providers(-1, &name);
+ while (iter != -1) {
+ gtk_list_store_insert_with_values(priv->search_providers,
+ NULL, -1,
+ 0, name, -1);
+ if ((provider != NULL) && (strcmp(name, provider) == 0)) {
+ provider_idx = iter;
}
+ iter = search_web_iterate_providers(iter, &name);
}
- gtk_combo_box_set_active(GTK_COMBO_BOX(widget), provider);
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(widget), provider_idx);
}
@@ -1012,4 +1030,3 @@ GtkWidget* nsgtk_preferences(struct browser_window *bw, GtkWindow *parent)
return GTK_WIDGET(priv->dialog);
}
-
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/netsurf.gtk2.ui b/frontends/gtk/res/gtk2/netsurf.ui
index adca54001..adca54001 100644
--- a/frontends/gtk/res/netsurf.gtk2.ui
+++ b/frontends/gtk/res/gtk2/netsurf.ui
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/tabcontents.gtk2.ui b/frontends/gtk/res/gtk2/tabcontents.ui
index c47e6a2ef..c47e6a2ef 100644
--- a/frontends/gtk/res/tabcontents.gtk2.ui
+++ b/frontends/gtk/res/gtk2/tabcontents.ui
diff --git a/frontends/gtk/res/toolbar.gtk2.ui b/frontends/gtk/res/gtk2/toolbar.ui
index 61723065b..61723065b 100644
--- a/frontends/gtk/res/toolbar.gtk2.ui
+++ b/frontends/gtk/res/gtk2/toolbar.ui
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/netsurf.gtk3.ui b/frontends/gtk/res/gtk3/netsurf.ui
index 6ea8f07a7..6ea8f07a7 100644
--- a/frontends/gtk/res/netsurf.gtk3.ui
+++ b/frontends/gtk/res/gtk3/netsurf.ui
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/tabcontents.gtk3.ui b/frontends/gtk/res/gtk3/tabcontents.ui
index b07cf92e0..b07cf92e0 100644
--- a/frontends/gtk/res/tabcontents.gtk3.ui
+++ b/frontends/gtk/res/gtk3/tabcontents.ui
diff --git a/frontends/gtk/res/toolbar.gtk3.ui b/frontends/gtk/res/gtk3/toolbar.ui
index 60452f472..60452f472 100644
--- a/frontends/gtk/res/toolbar.gtk3.ui
+++ b/frontends/gtk/res/gtk3/toolbar.ui
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/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 a81500b68..21a2e7723 100644
--- a/frontends/gtk/res/netsurf.gresource.xml
+++ b/frontends/gtk/res/netsurf.gresource.xml
@@ -1,32 +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>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>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>
@@ -40,17 +14,22 @@
<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>
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/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 61853e458..fc17f7418 100644
--- a/frontends/gtk/resources.c
+++ b/frontends/gtk/resources.c
@@ -77,7 +77,6 @@ static struct nsgtk_resource_s ui_resource[] = {
RES_ENTRY("netsurf"),
RES_ENTRY("tabcontents"),
RES_ENTRY("password"),
- RES_ENTRY("ssl"),
RES_ENTRY("toolbar"),
RES_ENTRY("downloads"),
RES_ENTRY("globalhistory"),
@@ -87,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 },
};
@@ -124,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"),
@@ -346,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;
@@ -362,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 ccf3fcb45..f9d4f6d67 100644
--- a/frontends/gtk/scaffolding.c
+++ b/frontends/gtk/scaffolding.c
@@ -18,6 +18,8 @@
#include <gtk/gtk.h>
#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
#include "utils/utils.h"
#include "utils/log.h"
@@ -191,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 {
@@ -261,9 +275,6 @@ static void scaffolding_update_context(struct nsgtk_scaffolding *g)
nsgtk_scaffolding_set_sensitivity(g);
- /* update the url bar, particularly necessary when tabbing */
- browser_window_refresh_url_bar(bw);
-
nsgtk_local_history_hide();
}
@@ -546,8 +557,6 @@ nsgtk_on_link_opentab_activate_menu(GtkMenuItem *widget, gpointer data)
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,
@@ -556,8 +565,6 @@ nsgtk_on_link_opentab_activate_menu(GtkMenuItem *widget, gpointer data)
nsgtk_warning(messages_get_errorcode(err), 0);
}
- temp_open_background = -1;
-
return TRUE;
}
@@ -1291,8 +1298,9 @@ nserror nsgtk_scaffolding_destroy_all(void)
/* iterate all scaffolding windows and destroy them */
while (gs != NULL) {
+ struct nsgtk_scaffolding *next = gs->next;
gtk_widget_destroy(GTK_WIDGET(gs->window));
- gs = gs->next;
+ gs = next;
}
return NSERROR_OK;
}
@@ -1356,7 +1364,7 @@ void nsgtk_scaffolding_set_top_level(struct gui_window *gw)
sc->top_level = gw;
- /* Synchronise the history (will also update the URL bar) */
+ /* Synchronise the history */
scaffolding_update_context(sc);
/* Ensure the window's title bar is updated */
@@ -1580,3 +1588,16 @@ struct nsgtk_scaffolding *nsgtk_new_scaffolding(struct gui_window *toplevel)
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 1fae00394..87d4f3bd6 100644
--- a/frontends/gtk/scaffolding.h
+++ b/frontends/gtk/scaffolding.h
@@ -27,6 +27,7 @@ struct hlcache_handle;
struct gui_window;
struct gui_search_web_table;
struct nsurl;
+struct nsgtk_pi_window;
/**
@@ -56,6 +57,22 @@ nserror nsgtk_scaffolding_throbber(struct gui_window* gw, bool active);
nserror nsgtk_scaffolding_toolbar_context_menu(struct nsgtk_scaffolding *gs);
/**
+ * 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
+ */
+nserror nsgtk_scaffolding_position_page_info(struct nsgtk_scaffolding *gs,
+ struct nsgtk_pi_window *win);
+
+/**
+ * Position the local-history popup in the right place
+ *
+ * \param gs The scaffolding to position relative to
+ */
+nserror nsgtk_scaffolding_position_local_history(struct nsgtk_scaffolding *gs);
+
+/**
* open the burger menu
*/
nserror nsgtk_scaffolding_burger_menu(struct nsgtk_scaffolding *gs);
diff --git a/frontends/gtk/search.c b/frontends/gtk/search.c
index 068624153..f9a509f6e 100644
--- a/frontends/gtk/search.c
+++ b/frontends/gtk/search.c
@@ -25,6 +25,7 @@
* that generally means web search and is confusing.
*/
+#include <stdlib.h>
#include <stdbool.h>
#include <gtk/gtk.h>
@@ -269,6 +270,8 @@ nserror nsgtk_search_restyle(struct gtk_search *search)
case 4: /* Text icons only */
gtk_toolbar_set_style(GTK_TOOLBAR(search->bar),
GTK_TOOLBAR_TEXT);
+ break;
+
default:
break;
}
diff --git a/frontends/gtk/toolbar.c b/frontends/gtk/toolbar.c
index f191bc174..6ec41cc1d 100644
--- a/frontends/gtk/toolbar.c
+++ b/frontends/gtk/toolbar.c
@@ -144,6 +144,25 @@ struct nsgtk_toolbar_item {
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;
/**
* control toolbar context
@@ -182,6 +201,11 @@ struct nsgtk_toolbar {
* context passed to get_bw function
*/
void *get_ctx;
+
+ /**
+ * Location focus state machine, current state
+ */
+ nsgtk_toolbar_location_focus_state loc_focus;
};
@@ -649,15 +673,22 @@ nsgtk_toolbar_customisation_save(struct nsgtk_toolbar *tb)
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;
}
- start += snprintf(start,
+ 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;
@@ -926,7 +957,7 @@ nsgtk_browser_window_create(struct browser_window *bw, bool intab)
{
nserror res = NSERROR_OK;
nsurl *url = NULL;
- int flags = BW_CREATE_HISTORY;
+ int flags = BW_CREATE_HISTORY | BW_CREATE_FOREGROUND | BW_CREATE_FOCUS_LOCATION;
if (intab) {
flags |= BW_CREATE_TAB;
@@ -1995,16 +2026,14 @@ static gboolean websearch_entry_activate_cb(GtkWidget *widget, gpointer data)
SEARCH_WEB_OMNI_SEARCHONLY,
&url);
if (res == NSERROR_OK) {
- temp_open_background = 0;
bw = tb->get_bw(tb->get_ctx);
res = browser_window_create(
- BW_CREATE_HISTORY | BW_CREATE_TAB,
+ BW_CREATE_HISTORY | BW_CREATE_TAB | BW_CREATE_FOREGROUND,
url,
NULL,
bw,
NULL);
- temp_open_background = -1;
nsurl_unref(url);
}
if (res != NSERROR_OK) {
@@ -3000,7 +3029,7 @@ static gboolean
showcookies_button_clicked_cb(GtkWidget *widget, gpointer data)
{
nserror res;
- res = nsgtk_cookies_present();
+ res = nsgtk_cookies_present(NULL);
if (res != NSERROR_OK) {
NSLOG(netsurf, INFO, "Unable to initialise cookies window.");
}
@@ -3044,7 +3073,7 @@ contents_button_clicked_cb(GtkWidget *widget, gpointer data)
struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
nserror res;
- res = toolbar_navigate_to_url(tb, "http://www.netsurf-browser.org/documentation/");
+ res = toolbar_navigate_to_url(tb, "https://www.netsurf-browser.org/documentation/");
if (res != NSERROR_OK) {
nsgtk_warning(messages_get_errorcode(res), 0);
}
@@ -3065,7 +3094,7 @@ guide_button_clicked_cb(GtkWidget *widget, gpointer data)
struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
nserror res;
- res = toolbar_navigate_to_url(tb, "http://www.netsurf-browser.org/documentation/guide");
+ res = toolbar_navigate_to_url(tb, "https://www.netsurf-browser.org/documentation/guide");
if (res != NSERROR_OK) {
nsgtk_warning(messages_get_errorcode(res), 0);
}
@@ -3087,7 +3116,7 @@ info_button_clicked_cb(GtkWidget *widget, gpointer data)
struct nsgtk_toolbar *tb = (struct nsgtk_toolbar *)data;
nserror res;
- res = toolbar_navigate_to_url(tb, "http://www.netsurf-browser.org/documentation/info");
+ res = toolbar_navigate_to_url(tb, "https://www.netsurf-browser.org/documentation/info");
if (res != NSERROR_OK) {
nsgtk_warning(messages_get_errorcode(res), 0);
}
@@ -3418,6 +3447,7 @@ 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;
@@ -3433,6 +3463,11 @@ nsgtk_toolbar_create(GtkBuilder *builder,
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);
@@ -3517,6 +3552,24 @@ 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);
@@ -3629,7 +3682,23 @@ nserror nsgtk_toolbar_set_url(struct nsgtk_toolbar *tb, nsurl *url)
url_text = nsurl_access(url);
}
- gtk_entry_set_text(url_entry, url_text);
+ 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);
@@ -3737,3 +3806,82 @@ nserror nsgtk_toolbar_update(struct nsgtk_toolbar *tb)
return res;
}
+
+/**
+ * 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
+ */
+static nserror
+nsgtk_toolbar_get_icon_window_position(struct nsgtk_toolbar *tb,
+ int item_idx,
+ int *out_x,
+ int *out_y)
+{
+ 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 9bb859be1..4ecca9f02 100644
--- a/frontends/gtk/toolbar.h
+++ b/frontends/gtk/toolbar.h
@@ -32,7 +32,11 @@ struct nsgtk_scaffolding;
* \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,struct nsgtk_toolbar **toolbar);
+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);
/**
@@ -113,6 +117,21 @@ nserror nsgtk_toolbar_item_activate(struct nsgtk_toolbar *tb, nsgtk_toolbar_butt
*/
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
diff --git a/frontends/gtk/window.c b/frontends/gtk/window.c
index 39b7413d3..f5c87ef87 100644
--- a/frontends/gtk/window.c
+++ b/frontends/gtk/window.c
@@ -115,6 +115,9 @@ struct gui_window {
/** 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;
@@ -143,9 +146,6 @@ struct gui_window {
/**< first entry in window list */
struct gui_window *window_list = NULL;
-/** flag controlling opening of tabs in the background */
-int temp_open_background = -1;
-
static void
nsgtk_select_menu_clicked(GtkCheckMenuItem *checkmenuitem,
gpointer user_data)
@@ -391,12 +391,25 @@ nsgtk_window_button_release_event(GtkWidget *widget,
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)
@@ -806,9 +819,13 @@ gui_window_create(struct browser_window *bw,
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);
@@ -855,13 +872,16 @@ gui_window_create(struct browser_window *bw,
/* Construct our primary elements */
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, &g->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);
@@ -905,7 +925,7 @@ 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);
nsgtk_connect_draw_event(GTK_WIDGET(g->layout),
@@ -953,18 +973,9 @@ 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, messages_get("NewTab"), g->icon);
+ 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);
@@ -977,6 +988,13 @@ gui_window_create(struct browser_window *bw,
*/
g_object_unref(tab_builder);
+ /* 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;
}
@@ -1185,6 +1203,7 @@ static void gui_window_update_extent(struct gui_window *g)
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);
}
}
@@ -1671,3 +1690,16 @@ nserror nsgtk_window_toolbar_update(void)
}
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 728c653a8..a43e0b197 100644
--- a/frontends/gtk/window.h
+++ b/frontends/gtk/window.h
@@ -19,11 +19,12 @@
#ifndef NETSURF_GTK_WINDOW_H
#define NETSURF_GTK_WINDOW_H 1
+struct nsgtk_pi_window;
+
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;
/**
* get core browsing context from gui window handle
@@ -96,5 +97,20 @@ GtkLayout *nsgtk_window_get_layout(struct gui_window *gw);
*/
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 */