diff options
Diffstat (limited to 'frontends/gtk')
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"><b>Certificate chain</b></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"><b>Certificate Chain</b></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 */ |