diff options
| -rw-r--r-- | FAQ.md | 10 | ||||
| -rw-r--r-- | Makefile | 94 | ||||
| -rw-r--r-- | common.c | 15 | ||||
| -rw-r--r-- | common.h | 3 | ||||
| -rw-r--r-- | config.h | 16 | ||||
| -rw-r--r-- | config.mk | 23 | ||||
| -rw-r--r-- | libsurf-webext.c | 123 | ||||
| -rw-r--r-- | surf.c | 214 | 
8 files changed, 350 insertions, 148 deletions
| @@ -1,10 +1,10 @@  # Frequently Asked Questions -## Surf is starting up slowly. What might happen? +## Surf is starting up slowly. What might be causing this? -The  first suspect for such a behaviour is the plugin handling. Run surf -on the commandline and see if there are errors because of »nspluginwrap‐ -per«  or  failed RPCs to them. If that is true, go to ~/.mozilla/plugins -and try removing stale links to plugins not on your system anymore. This +The first suspect for such behaviour is the plugin handling. Run surf on +the commandline and see if there are errors because of “nspluginwrapper” +or failed RPCs to them. If that is true, go to ~/.mozilla/plugins and +try removing stale links to plugins not on your system anymore. This  will stop surf from trying to load them. @@ -4,72 +4,72 @@  include config.mk -SRC = surf.c +SRC = surf.c common.c  OBJ = $(SRC:.c=.o) +WEBEXTSRC = libsurf-webext.c +WEBEXTOBJ = $(WEBEXTSRC:.c=.o) -all: options surf +all: options libsurf-webext.so surf  options:  	@echo surf build options: -	@echo "CFLAGS   = $(SURF_CFLAGS)" -	@echo "LDFLAGS  = $(SURF_LDFLAGS)" -	@echo "CC       = $(CC)" +	@echo "CC            = $(CC)" +	@echo "CFLAGS        = $(SURFCFLAGS) $(CFLAGS)" +	@echo "WEBEXTCFLAGS  = $(WEBEXTCFLAGS) $(CFLAGS)" +	@echo "LDFLAGS       = $(LDFLAGS)"  .c.o: -	@echo CC -c $< -	@$(CC) $(SURF_CFLAGS) -c $< - -$(OBJ): config.h config.mk +	$(CC) $(SURFCFLAGS) $(CFLAGS) -c $<  config.h: -	@echo creating $@ from config.def.h -	@cp config.def.h $@ +	cp config.def.h $@ + +$(OBJ): config.h common.h config.mk + +$(WEBEXTOBJ): $(WEBEXTSRC) config.h common.h config.mk +	$(CC) $(WEBEXTCFLAGS) $(CFLAGS) -c $(WEBEXTSRC) + +libsurf-webext.so: $(WEBEXTOBJ) +	$(CC) -shared -Wl,-soname,$@ $(LDFLAGS) -o $@ $< $(WEBEXTLIBS) -lc  surf: $(OBJ) -	@echo CC -o $@ -	@$(CC) $(SURF_CFLAGS) -o $@ $(OBJ) $(SURF_LDFLAGS) +	$(CC) $(SURFLDLAGS) $(LDFLAGS) -o $@ $(OBJ) $(LIBS)  clean: -	@echo cleaning -	@rm -f surf $(OBJ) +	rm -f surf $(OBJ) +	rm -f libsurf-webext.so $(WEBEXTOBJ)  distclean: clean -	@echo cleaning dist -	@rm -f config.h surf-$(VERSION).tar.gz +	rm -f config.h surf-$(VERSION).tar.gz  dist: distclean -	@echo creating dist tarball -	@mkdir -p surf-$(VERSION) -	@cp -R LICENSE Makefile config.mk config.def.h README \ +	mkdir -p surf-$(VERSION) +	cp -R LICENSE Makefile config.mk config.def.h README \  	    surf-open.sh arg.h TODO.md surf.png \ -	    surf.1 $(SRC) surf-$(VERSION) -	@tar -cf surf-$(VERSION).tar surf-$(VERSION) -	@gzip surf-$(VERSION).tar -	@rm -rf surf-$(VERSION) +	    surf.1 $(SRC) $(WEBEXTSRC) surf-$(VERSION) +	tar -cf surf-$(VERSION).tar surf-$(VERSION) +	gzip surf-$(VERSION).tar +	rm -rf surf-$(VERSION)  install: all -	@echo installing executable file to $(DESTDIR)$(PREFIX)/bin -	@mkdir -p $(DESTDIR)$(PREFIX)/bin -	@cp -f surf $(DESTDIR)$(PREFIX)/bin -	@chmod 755 $(DESTDIR)$(PREFIX)/bin/surf -	@echo installing surf-menu to $(DESTDIR)$(PREFIX)/bin -	@cp -f surf-menu $(DESTDIR)$(PREFIX)/bin -	@chmod 755 $(DESTDIR)$(PREFIX)/bin/surf-menu -	@echo installing manual page to $(DESTDIR)$(MANPREFIX)/man1 -	@mkdir -p $(DESTDIR)$(MANPREFIX)/man1 -	@sed "s/VERSION/$(VERSION)/g" < surf.1 > $(DESTDIR)$(MANPREFIX)/man1/surf.1 -	@chmod 644 $(DESTDIR)$(MANPREFIX)/man1/surf.1 -	@echo installing desktop file to $(DESTDIR)/usr/share/applications -	@mkdir -p $(DESTDIR)/usr/share/applications -	@cp -f surf.desktop $(DESTDIR)/usr/share/applications/surf.desktop +	mkdir -p $(DESTDIR)$(PREFIX)/bin +	cp -f surf $(DESTDIR)$(PREFIX)/bin +	chmod 755 $(DESTDIR)$(PREFIX)/bin/surf +	cp -f surf-menu $(DESTDIR)$(PREFIX)/bin +	chmod 755 $(DESTDIR)$(PREFIX)/bin/surf-menu +	mkdir -p $(DESTDIR)$(LIBDIR) +	cp -f libsurf-webext.so $(DESTDIR)$(LIBDIR) +	chmod 644 $(DESTDIR)$(LIBDIR)/libsurf-webext.so +	mkdir -p $(DESTDIR)$(MANPREFIX)/man1 +	sed "s/VERSION/$(VERSION)/g" < surf.1 > $(DESTDIR)$(MANPREFIX)/man1/surf.1 +	chmod 644 $(DESTDIR)$(MANPREFIX)/man1/surf.1  uninstall: -	@echo removing executable file from $(DESTDIR)$(PREFIX)/bin -	@rm -f $(DESTDIR)$(PREFIX)/bin/surf -	@rm -f $(DESTDIR)$(PREFIX)/bin/surf-menu -	@echo removing manual page from $(DESTDIR)$(MANPREFIX)/man1 -	@rm -f $(DESTDIR)$(MANPREFIX)/man1/surf.1 -	@echo removing desktop page from $(DESTDIR)/usr/share/applications -	@rm -f $(DESTDIR)/usr/share/applications/surf.desktop - -.PHONY: all options clean dist install uninstall +	rm -f $(DESTDIR)$(PREFIX)/bin/surf +	rm -f $(DESTDIR)$(PREFIX)/bin/surf-menu +	rm -f $(DESTDIR)$(MANPREFIX)/man1/surf.1 +	rm -f $(DESTDIR)$(LIBDIR)/libsurf-webext.so +	- rmdir $(DESTDIR)$(LIBDIR) + +.SUFFIXES: .so .o .c +.PHONY: all options clean-dist clean dist install uninstall diff --git a/common.c b/common.c new file mode 100644 index 0000000..42662ed --- /dev/null +++ b/common.c @@ -0,0 +1,15 @@ +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> + +void +die(const char *errstr, ...) +{ +	va_list ap; + +	va_start(ap, errstr); +	vfprintf(stderr, errstr, ap); +	va_end(ap); +	exit(1); +} + diff --git a/common.h b/common.h new file mode 100644 index 0000000..527c4f7 --- /dev/null +++ b/common.h @@ -0,0 +1,3 @@ +#define MSGBUFSZ 32 + +void die(char *, ...); @@ -147,15 +147,13 @@ static Key keys[] = {  	{ MODKEY,                GDK_KEY_l,      navigate,   { .i = +1 } },  	{ MODKEY,                GDK_KEY_h,      navigate,   { .i = -1 } }, -	/* Currently we have to use scrolling steps that WebKit2GTK+ gives us -	 * d: step down, u: step up, r: step right, l:step left -	 * D: page down, U: page up */ -	{ MODKEY,                GDK_KEY_j,      scroll,     { .i = 'd' } }, -	{ MODKEY,                GDK_KEY_k,      scroll,     { .i = 'u' } }, -	{ MODKEY,                GDK_KEY_b,      scroll,     { .i = 'U' } }, -	{ MODKEY,                GDK_KEY_space,  scroll,     { .i = 'D' } }, -	{ MODKEY,                GDK_KEY_i,      scroll,     { .i = 'r' } }, -	{ MODKEY,                GDK_KEY_u,      scroll,     { .i = 'l' } }, +	/* vertical and horizontal scrolling, in viewport percentage */ +	{ MODKEY,                GDK_KEY_j,      scrollv,    { .i = +10 } }, +	{ MODKEY,                GDK_KEY_k,      scrollv,    { .i = -10 } }, +	{ MODKEY,                GDK_KEY_b,      scrollv,    { .i = +50 } }, +	{ MODKEY,                GDK_KEY_space,  scrollv,    { .i = -50 } }, +	{ MODKEY,                GDK_KEY_i,      scrollh,    { .i = +10 } }, +	{ MODKEY,                GDK_KEY_u,      scrollh,    { .i = -10 } },  	{ MODKEY|GDK_SHIFT_MASK, GDK_KEY_j,      zoom,       { .i = -1 } }, @@ -6,27 +6,26 @@ PKG_CONFIG ?= pkg-config  # paths  PREFIX = /usr  MANPREFIX = $(PREFIX)/share/man -LIBPREFIX = $(PREFIX)/lib/surf +LIBPREFIX = $(PREFIX)/lib +LIBDIR = $(LIBPREFIX)/surf  X11INC = $(shell $(PKG_CONFIG) --cflags x11)  X11LIB = $(shell $(PKG_CONFIG) --libs x11) -GTKINC = $(shell $(PKG_CONFIG) --cflags gtk+-3.0  gthread-2.0 gcr-3 webkit2gtk-4.0) -GTKLIB = $(shell $(PKG_CONFIG) --libs gtk+-3.0  gthread-2.0 gcr-3 webkit2gtk-4.0) +GTKINC = $(shell $(PKG_CONFIG) --cflags gtk+-3.0 gcr-3 webkit2gtk-4.0) +GTKLIB = $(shell $(PKG_CONFIG) --libs gtk+-3.0 gcr-3 webkit2gtk-4.0) +WEBEXTINC = $(shell $(PKG_CONFIG) --cflags webkit2gtk-4.0 webkit2gtk-web-extension-4.0) +WEBEXTLIBS = $(shell $(PKG_CONFIG) --libs webkit2gtk-4.0 webkit2gtk-web-extension-4.0)  # includes and libs  INCS = $(X11INC) $(GTKINC) -LIBS = $(X11LIB) $(GTKLIB) +LIBS = $(X11LIB) $(GTKLIB) -lgthread-2.0  # flags -CPPFLAGS = -DVERSION=\"${VERSION}\" -DWEBEXTDIR=\"${LIBPREFIX}\" \ +CPPFLAGS = -DVERSION=\"$(VERSION)\" -DWEBEXTDIR=\"$(LIBDIR)\" \             -D_DEFAULT_SOURCE -DGCR_API_SUBJECT_TO_CHANGE -SURF_CFLAGS = $(INCS) $(CPPFLAGS) $(CFLAGS) -SURF_LDFLAGS = $(LIBS) $(LDFLAGS) +SURFCFLAGS = $(INCS) $(CPPFLAGS) +WEBEXTCFLAGS = -fPIC $(WEBEXTINC) -# Solaris -#CFLAGS = -fast $(INCS) -DVERSION=\"$(VERSION)\" -#LDFLAGS = $(LIBS) - -# compiler and linker +# compiler  #CC = c99 diff --git a/libsurf-webext.c b/libsurf-webext.c new file mode 100644 index 0000000..684d4a5 --- /dev/null +++ b/libsurf-webext.c @@ -0,0 +1,123 @@ +#include <sys/stat.h> +#include <fcntl.h> +#include <limits.h> +#include <stdlib.h> + +#include <gio/gio.h> +#include <webkit2/webkit-web-extension.h> +#include <webkitdom/webkitdom.h> +#include <webkitdom/WebKitDOMDOMWindowUnstable.h> + +#include "common.h" + +#define LENGTH(x)   (sizeof(x) / sizeof(x[0])) + +typedef struct Page { +	guint64 id; +	WebKitWebPage *webpage; +	struct Page *next; +} Page; + +static int pipein, pipeout; +static Page *pages; + +Page * +newpage(WebKitWebPage *page) +{ +	Page *p; + +	if (!(p = calloc(1, sizeof(Page)))) +		die("Cannot malloc!\n"); + +	p->next = pages; +	pages = p; + +	p->id = webkit_web_page_get_id(page); +	p->webpage = page; + +	return p; +} + +static void +msgsurf(Page *p, const char *s) +{ +	char msg[MSGBUFSZ]; +	int ret; + +	msg[0] = p ? p->id : 0; +	ret = snprintf(&msg[1], sizeof(msg) - 1, "%s", s); +	if (ret >= sizeof(msg)) { +		fprintf(stderr, "webext: message too long: %d\n", ret); +		return; +	} + +	if (pipeout) { +		if (write(pipeout, msg, sizeof(msg)) < 0) +			fprintf(stderr, "webext: error sending: %s\n", msg); +	} +} + +static gboolean +readpipe(GIOChannel *s, GIOCondition c, gpointer unused) +{ +	char msg[MSGBUFSZ]; +	gsize msgsz; +	WebKitDOMDOMWindow *view; +	GError *gerr = NULL; +	glong wh, ww; +	Page *p; + +	if (g_io_channel_read_chars(s, msg, LENGTH(msg), &msgsz, &gerr) != +	    G_IO_STATUS_NORMAL) { +		fprintf(stderr, "webext: error reading pipe: %s\n", +		        gerr->message); +		g_error_free(gerr); +		return TRUE; +	} +	msg[msgsz] = '\0'; + +	for (p = pages; p; p = p->next) { +		if (p->id == msg[0]) +			break; +	} +	if (!p || !(view = webkit_dom_document_get_default_view( +	            webkit_web_page_get_dom_document(p->webpage)))) +		return TRUE; + +	switch (msg[1]) { +	case 'h': +		ww = webkit_dom_dom_window_get_inner_width(view); +		webkit_dom_dom_window_scroll_by(view, +		                                (ww / 100) * msg[2], 0); +		break; +	case 'v': +		wh = webkit_dom_dom_window_get_inner_height(view); +		webkit_dom_dom_window_scroll_by(view, +		                                0, (wh / 100) * msg[2]); +		break; +	} + +	return TRUE; +} + +static void +webpagecreated(WebKitWebExtension *e, WebKitWebPage *wp, gpointer unused) +{ +	Page *p = newpage(wp); +} + +G_MODULE_EXPORT void +webkit_web_extension_initialize_with_user_data(WebKitWebExtension *e, GVariant *gv) +{ +	GIOChannel *gchanpipe; + +	g_signal_connect(e, "page-created", G_CALLBACK(webpagecreated), NULL); + +	g_variant_get(gv, "(ii)", &pipein, &pipeout); +	msgsurf(NULL, "i"); + +	gchanpipe = g_io_channel_unix_new(pipein); +	g_io_channel_set_encoding(gchanpipe, NULL, NULL); +	g_io_channel_set_close_on_unref(gchanpipe, TRUE); +	g_io_add_watch(gchanpipe, G_IO_IN, readpipe, NULL); +} @@ -11,7 +11,6 @@  #include <pwd.h>  #include <regex.h>  #include <signal.h> -#include <stdarg.h>  #include <stdio.h>  #include <stdlib.h>  #include <string.h> @@ -28,8 +27,10 @@  #include <webkit2/webkit2.h>  #include <X11/X.h>  #include <X11/Xatom.h> +#include <glib.h>  #include "arg.h" +#include "common.h"  #define LENGTH(x)               (sizeof(x) / sizeof(x[0]))  #define CLEANMASK(mask)         (mask & (MODKEY|GDK_SHIFT_MASK)) @@ -104,6 +105,7 @@ typedef struct Client {  	GTlsCertificate *cert, *failedcert;  	GTlsCertificateFlags tlserr;  	Window xid; +	unsigned long pageid;  	int progress, fullscreen, https, insecure, errorpage;  	const char *title, *overtitle, *targeturi;  	const char *needle; @@ -140,12 +142,12 @@ typedef struct {  /* Surf */  static void usage(void); -static void die(const char *errstr, ...);  static void setup(void);  static void sigchld(int unused);  static void sighup(int unused);  static char *buildfile(const char *path);  static char *buildpath(const char *path); +static char *untildepath(const char *path);  static const char *getuserhomedir(const char *user);  static const char *getcurrentuserhomedir(void);  static Client *newclient(Client *c); @@ -170,6 +172,7 @@ static void updatewinid(Client *c);  static void handleplumb(Client *c, const char *uri);  static void newwindow(Client *c, const Arg *a, int noembed);  static void spawn(Client *c, const Arg *a); +static void msgext(Client *c, char type, const Arg *a);  static void destroyclient(Client *c);  static void cleanup(void); @@ -182,6 +185,7 @@ static gboolean buttonreleased(GtkWidget *w, GdkEvent *e, Client *c);  static GdkFilterReturn processx(GdkXEvent *xevent, GdkEvent *event,                                  gpointer d);  static gboolean winevent(GtkWidget *w, GdkEvent *e, Client *c); +static gboolean readpipe(GIOChannel *s, GIOCondition ioc, gpointer unused);  static void showview(WebKitWebView *v, Client *c);  static GtkWidget *createwindow(Client *c);  static gboolean loadfailedtls(WebKitWebView *v, gchar *uri, @@ -205,6 +209,9 @@ static void downloadstarted(WebKitWebContext *wc, WebKitDownload *d,                              Client *c);  static void responsereceived(WebKitDownload *d, GParamSpec *ps, Client *c);  static void download(Client *c, WebKitURIResponse *r); +static void webprocessterminated(WebKitWebView *v, +                                 WebKitWebProcessTerminationReason r, +                                 Client *c);  static void closeview(WebKitWebView *v, Client *c);  static void destroywin(GtkWidget* w, Client *c); @@ -215,7 +222,8 @@ static void print(Client *c, const Arg *a);  static void showcert(Client *c, const Arg *a);  static void clipboard(Client *c, const Arg *a);  static void zoom(Client *c, const Arg *a); -static void scroll(Client *c, const Arg *a); +static void scrollv(Client *c, const Arg *a); +static void scrollh(Client *c, const Arg *a);  static void navigate(Client *c, const Arg *a);  static void stop(Client *c, const Arg *a);  static void toggle(Client *c, const Arg *a); @@ -243,6 +251,7 @@ static char *stylefile;  static const char *useragent;  static Parameter *curconfig;  static int modparams[ParameterLast]; +static int pipein[2], pipeout[2];  char *argv0;  static ParamName loadtransient[] = { @@ -301,19 +310,9 @@ usage(void)  }  void -die(const char *errstr, ...) -{ -	va_list ap; - -	va_start(ap, errstr); -	vfprintf(stderr, errstr, ap); -	va_end(ap); -	exit(1); -} - -void  setup(void)  { +	GIOChannel *gchanin;  	GdkDisplay *gdpy;  	int i, j; @@ -344,6 +343,16 @@ setup(void)  	gdkkb = gdk_seat_get_keyboard(gdk_display_get_default_seat(gdpy)); +	if (pipe(pipeout) < 0 || pipe(pipein) < 0) { +		fputs("Unable to create pipes\n", stderr); +	} else { +		gchanin = g_io_channel_unix_new(pipein[0]); +		g_io_channel_set_encoding(gchanin, NULL, NULL); +		g_io_channel_set_close_on_unref(gchanin, TRUE); +		g_io_add_watch(gchanin, G_IO_IN, readpipe, NULL); +	} + +  	for (i = 0; i < LENGTH(certs); ++i) {  		if (!regcomp(&(certs[i].re), certs[i].regex, REG_EXTENDED)) {  			certs[i].file = g_strconcat(certdir, "/", certs[i].file, @@ -470,26 +479,12 @@ getcurrentuserhomedir(void)  char *  buildpath(const char *path)  { -	char *apath, *name, *p, *fpath; -	const char *homedir; +	char *apath, *fpath; -	if (path[0] == '~') { -		if (path[1] == '/' || path[1] == '\0') { -			p = (char *)&path[1]; -			homedir = getcurrentuserhomedir(); -		} else { -			if ((p = strchr(path, '/'))) -				name = g_strndup(&path[1], --p - path); -			else -				name = g_strdup(&path[1]); - -			homedir = getuserhomedir(name); -			g_free(name); -		} -		apath = g_build_filename(homedir, p, NULL); -	} else { +	if (path[0] == '~') +		apath = untildepath(path); +	else  		apath = g_strdup(path); -	}  	/* creating directory */  	if (g_mkdir_with_parents(apath, 0700) < 0) @@ -501,6 +496,28 @@ buildpath(const char *path)  	return fpath;  } +char * +untildepath(const char *path) +{ +       char *apath, *name, *p; +       const char *homedir; + +       if (path[1] == '/' || path[1] == '\0') { +               p = (char *)&path[1]; +               homedir = getcurrentuserhomedir(); +       } else { +               if ((p = strchr(path, '/'))) +                       name = g_strndup(&path[1], p - (path + 1)); +               else +                       name = g_strdup(&path[1]); + +               homedir = getuserhomedir(name); +               g_free(name); +       } +       apath = g_build_filename(homedir, p, NULL); +       return apath; +} +  Client *  newclient(Client *rc)  { @@ -522,7 +539,7 @@ void  loaduri(Client *c, const Arg *a)  {  	struct stat st; -	char *url, *path; +	char *url, *path, *apath;  	const char *uri = a->v;  	if (g_strcmp0(uri, "") == 0) @@ -533,11 +550,19 @@ loaduri(Client *c, const Arg *a)  	    g_str_has_prefix(uri, "file://")  ||  	    g_str_has_prefix(uri, "about:")) {  		url = g_strdup(uri); -	} else if (!stat(uri, &st) && (path = realpath(uri, NULL))) { -		url = g_strdup_printf("file://%s", path); -		free(path);  	} else { -		url = g_strdup_printf("http://%s", uri); +		if (uri[0] == '~') +			apath = untildepath(uri); +		else +			apath = (char *)uri; +		if (!stat(apath, &st) && (path = realpath(apath, NULL))) { +			url = g_strdup_printf("file://%s", path); +			free(path); +		} else { +			url = g_strdup_printf("http://%s", uri); +		} +		if (apath != uri) +			free(apath);  	}  	setatom(c, AtomUri, url); @@ -1013,6 +1038,8 @@ spawn(Client *c, const Arg *a)  	if (fork() == 0) {  		if (dpy)  			close(ConnectionNumber(dpy)); +		close(pipein[0]); +		close(pipeout[1]);  		setsid();  		execvp(((char **)a->v)[0], (char **)a->v);  		fprintf(stderr, "%s: execvp %s", argv0, ((char **)a->v)[0]); @@ -1045,6 +1072,9 @@ cleanup(void)  {  	while (clients)  		destroyclient(clients); + +	close(pipein[0]); +	close(pipeout[1]);  	g_free(cookiefile);  	g_free(scriptfile);  	g_free(stylefile); @@ -1057,13 +1087,13 @@ newview(Client *c, WebKitWebView *rv)  {  	WebKitWebView *v;  	WebKitSettings *settings; -	WebKitUserContentManager *contentmanager;  	WebKitWebContext *context; +	WebKitCookieManager *cookiemanager; +	WebKitUserContentManager *contentmanager;  	/* Webview */  	if (rv) { -		v = WEBKIT_WEB_VIEW( -		    webkit_web_view_new_with_related_view(rv)); +		v = WEBKIT_WEB_VIEW(webkit_web_view_new_with_related_view(rv));  	} else {  		settings = webkit_settings_new_with_settings(  		   "allow-file-access-from-file-urls", curconfig[FileURLsCrossAccess].val.i, @@ -1105,6 +1135,8 @@ newview(Client *c, WebKitWebView *rv)  		          "base-data-directory", cachedir,  		          NULL)); +		cookiemanager = webkit_web_context_get_cookie_manager(context); +  		/* rendering process model, can be a shared unique one  		 * or one for each view */  		webkit_web_context_set_process_model(context, @@ -1119,12 +1151,10 @@ newview(Client *c, WebKitWebView *rv)  		    WEBKIT_CACHE_MODEL_DOCUMENT_VIEWER);  		/* Currently only works with text file to be compatible with curl */ -		webkit_cookie_manager_set_persistent_storage( -		    webkit_web_context_get_cookie_manager(context), cookiefile, -		    WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT); +		webkit_cookie_manager_set_persistent_storage(cookiemanager, +		    cookiefile, WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT);  		/* cookie policy */ -		webkit_cookie_manager_set_accept_policy( -		    webkit_web_context_get_cookie_manager(context), +		webkit_cookie_manager_set_accept_policy(cookiemanager,  		    cookiepolicy_get());  		/* languages */  		webkit_web_context_set_preferred_languages(context, @@ -1170,13 +1200,49 @@ newview(Client *c, WebKitWebView *rv)  			 G_CALLBACK(permissionrequested), c);  	g_signal_connect(G_OBJECT(v), "ready-to-show",  			 G_CALLBACK(showview), c); +	g_signal_connect(G_OBJECT(v), "web-process-terminated", +			 G_CALLBACK(webprocessterminated), c);  	return v;  } +static gboolean +readpipe(GIOChannel *s, GIOCondition ioc, gpointer unused) +{ +	char msg[MSGBUFSZ]; +	gsize msgsz; +	GError *gerr = NULL; + +	if (g_io_channel_read_chars(s, msg, sizeof(msg), &msgsz, &gerr) != +	    G_IO_STATUS_NORMAL) { +		fprintf(stderr, "surf: error reading pipe: %s\n", +		        gerr->message); +		g_error_free(gerr); +		return TRUE; +	} +	msg[msgsz] = '\0'; + +	switch (msg[1]) { +	case 'i': +		close(pipein[1]); +		close(pipeout[0]); +		break; +	} + +	return TRUE; +} +  void  initwebextensions(WebKitWebContext *wc, Client *c)  { +	GVariant *gv; + +	if (!pipeout[0] || !pipein[1]) +		return; + +	gv = g_variant_new("(ii)", pipeout[0], pipein[1]); + +	webkit_web_context_set_web_extensions_initialization_user_data(wc, gv);  	webkit_web_context_set_web_extensions_directory(wc, WEBEXTDIR);  } @@ -1303,6 +1369,7 @@ showview(WebKitWebView *v, Client *c)  	c->finder = webkit_web_view_get_find_controller(c->view);  	c->inspector = webkit_web_view_get_inspector(c->view); +	c->pageid = webkit_web_view_get_page_id(c->view);  	c->win = createwindow(c);  	gtk_container_add(GTK_CONTAINER(c->win), GTK_WIDGET(c->view)); @@ -1352,8 +1419,7 @@ createwindow(Client *c)  		gtk_window_set_wmclass(GTK_WINDOW(w), wmstr, "Surf");  		g_free(wmstr); -		wmstr = g_strdup_printf("%s[%lu]", "Surf", -		        webkit_web_view_get_page_id(c->view)); +		wmstr = g_strdup_printf("%s[%lu]", "Surf", c->pageid);  		gtk_window_set_role(GTK_WINDOW(w), wmstr);  		g_free(wmstr); @@ -1675,6 +1741,15 @@ download(Client *c, WebKitURIResponse *r)  }  void +webprocessterminated(WebKitWebView *v, WebKitWebProcessTerminationReason r, +                     Client *c) +{ +	fprintf(stderr, "web process terminated: %s\n", +	        r == WEBKIT_WEB_PROCESS_CRASHED ? "crashed" : "no memory"); +	closeview(v, c); +} + +void  closeview(WebKitWebView *v, Client *c)  {  	gtk_widget_destroy(c->win); @@ -1765,38 +1840,27 @@ zoom(Client *c, const Arg *a)  	curconfig[ZoomLevel].val.f = webkit_web_view_get_zoom_level(c->view);  } -void -scroll(Client *c, const Arg *a) +static void +msgext(Client *c, char type, const Arg *a)  { -	GdkEvent *ev = gdk_event_new(GDK_KEY_PRESS); - -	gdk_event_set_device(ev, gdkkb); -	ev->key.window = gtk_widget_get_window(GTK_WIDGET(c->win)); -	ev->key.state = GDK_CONTROL_MASK; -	ev->key.time = GDK_CURRENT_TIME; +	char msg[MSGBUFSZ] = { c->pageid, type, a->i, '\0' }; -	switch (a->i) { -	case 'd': -		ev->key.keyval = GDK_KEY_Down; -		break; -	case 'D': -		ev->key.keyval = GDK_KEY_Page_Down; -		break; -	case 'l': -		ev->key.keyval = GDK_KEY_Left; -		break; -	case 'r': -		ev->key.keyval = GDK_KEY_Right; -		break; -	case 'U': -		ev->key.keyval = GDK_KEY_Page_Up; -		break; -	case 'u': -		ev->key.keyval = GDK_KEY_Up; -		break; +	if (pipeout[1]) { +		if (write(pipeout[1], msg, sizeof(msg)) < 0) +			fprintf(stderr, "surf: error sending: %s\n", msg);  	} +} + +void +scrollv(Client *c, const Arg *a) +{ +	msgext(c, 'v', a); +} -	gdk_event_put(ev); +void +scrollh(Client *c, const Arg *a) +{ +	msgext(c, 'h', a);  }  void | 
