Communicate with webextension via a pipe
This commit is contained in:
		
							parent
							
								
									1bd6d20102
								
							
						
					
					
						commit
						7ea0c2f7f8
					
				
							
								
								
									
										2
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										2
									
								
								Makefile
								
								
								
								
							| 
						 | 
				
			
			@ -29,7 +29,7 @@ options:
 | 
			
		|||
	@$(LIBTOOL) --mode compile --tag CC $(CC) $(LIBCFLAGS) -c $<
 | 
			
		||||
 | 
			
		||||
$(OBJ): config.h config.mk
 | 
			
		||||
$(LIBOBJ): config.mk
 | 
			
		||||
$(LIBOBJ): config.h config.mk
 | 
			
		||||
 | 
			
		||||
config.h:
 | 
			
		||||
	@echo creating $@ from config.def.h
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										16
									
								
								config.def.h
								
								
								
								
							
							
						
						
									
										16
									
								
								config.def.h
								
								
								
								
							| 
						 | 
				
			
			@ -143,15 +143,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 } },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										128
									
								
								libsurf-webext.c
								
								
								
								
							
							
						
						
									
										128
									
								
								libsurf-webext.c
								
								
								
								
							| 
						 | 
				
			
			@ -1,7 +1,131 @@
 | 
			
		|||
#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>
 | 
			
		||||
 | 
			
		||||
#define LENGTH(x)   (sizeof(x) / sizeof(x[0]))
 | 
			
		||||
 | 
			
		||||
#define MSGBUFSZ 32
 | 
			
		||||
 | 
			
		||||
typedef struct Page {
 | 
			
		||||
	guint64 id;
 | 
			
		||||
	WebKitWebPage *webpage;
 | 
			
		||||
	WebKitDOMDOMWindow *view;
 | 
			
		||||
	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;
 | 
			
		||||
	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 || !p->view)
 | 
			
		||||
		return TRUE;
 | 
			
		||||
 | 
			
		||||
	switch (msg[1]) {
 | 
			
		||||
	case 'h':
 | 
			
		||||
		ww = webkit_dom_dom_window_get_inner_width(p->view);
 | 
			
		||||
		webkit_dom_dom_window_scroll_by(p->view,
 | 
			
		||||
		                                (ww / 100) * msg[2], 0);
 | 
			
		||||
		break;
 | 
			
		||||
	case 'v':
 | 
			
		||||
		wh = webkit_dom_dom_window_get_inner_height(p->view);
 | 
			
		||||
		webkit_dom_dom_window_scroll_by(p->view,
 | 
			
		||||
		                                0, (wh / 100) * msg[2]);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return TRUE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
documentloaded(WebKitWebPage *wp, Page *p)
 | 
			
		||||
{
 | 
			
		||||
	p->view = webkit_dom_document_get_default_view(
 | 
			
		||||
	          webkit_web_page_get_dom_document(wp));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
webpagecreated(WebKitWebExtension *e, WebKitWebPage *wp, gpointer unused)
 | 
			
		||||
{
 | 
			
		||||
	Page *p = newpage(wp);
 | 
			
		||||
 | 
			
		||||
	g_signal_connect(wp, "document-loaded", G_CALLBACK(documentloaded), p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
G_MODULE_EXPORT void
 | 
			
		||||
webkit_web_extension_initialize(WebKitWebExtension *e)
 | 
			
		||||
webkit_web_extension_initialize_with_user_data(WebKitWebExtension *e, GVariant *gv)
 | 
			
		||||
{
 | 
			
		||||
	return;
 | 
			
		||||
	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);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										114
									
								
								surf.c
								
								
								
								
							
							
						
						
									
										114
									
								
								surf.c
								
								
								
								
							| 
						 | 
				
			
			@ -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,11 +27,13 @@
 | 
			
		|||
#include <webkit2/webkit2.h>
 | 
			
		||||
#include <X11/X.h>
 | 
			
		||||
#include <X11/Xatom.h>
 | 
			
		||||
#include <glib.h>
 | 
			
		||||
 | 
			
		||||
#include "arg.h"
 | 
			
		||||
 | 
			
		||||
#define LENGTH(x)               (sizeof(x) / sizeof(x[0]))
 | 
			
		||||
#define CLEANMASK(mask)         (mask & (MODKEY|GDK_SHIFT_MASK))
 | 
			
		||||
#define MSGBUFSZ 32
 | 
			
		||||
 | 
			
		||||
enum { AtomFind, AtomGo, AtomUri, AtomLast };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			@ -171,6 +173,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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -183,6 +186,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,
 | 
			
		||||
| 
						 | 
				
			
			@ -219,7 +223,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);
 | 
			
		||||
| 
						 | 
				
			
			@ -247,6 +252,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[] = {
 | 
			
		||||
| 
						 | 
				
			
			@ -318,6 +324,7 @@ die(const char *errstr, ...)
 | 
			
		|||
void
 | 
			
		||||
setup(void)
 | 
			
		||||
{
 | 
			
		||||
	GIOChannel *gchanin;
 | 
			
		||||
	GdkDisplay *gdpy;
 | 
			
		||||
	int i, j;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -348,6 +355,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,
 | 
			
		||||
| 
						 | 
				
			
			@ -1033,6 +1050,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]);
 | 
			
		||||
| 
						 | 
				
			
			@ -1065,6 +1084,9 @@ cleanup(void)
 | 
			
		|||
{
 | 
			
		||||
	while (clients)
 | 
			
		||||
		destroyclient(clients);
 | 
			
		||||
 | 
			
		||||
	close(pipein[0]);
 | 
			
		||||
	close(pipeout[1]);
 | 
			
		||||
	g_free(cookiefile);
 | 
			
		||||
	g_free(scriptfile);
 | 
			
		||||
	g_free(stylefile);
 | 
			
		||||
| 
						 | 
				
			
			@ -1077,14 +1099,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,
 | 
			
		||||
| 
						 | 
				
			
			@ -1197,9 +1218,43 @@ newview(Client *c, WebKitWebView *rv)
 | 
			
		|||
	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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1326,6 +1381,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));
 | 
			
		||||
| 
						 | 
				
			
			@ -1375,8 +1431,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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1797,38 +1852,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);
 | 
			
		||||
	char msg[MSGBUFSZ] = { c->pageid, type, a->i, '\0' };
 | 
			
		||||
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	gdk_event_put(ev);
 | 
			
		||||
void
 | 
			
		||||
scrollv(Client *c, const Arg *a)
 | 
			
		||||
{
 | 
			
		||||
	msgext(c, 'v', a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
scrollh(Client *c, const Arg *a)
 | 
			
		||||
{
 | 
			
		||||
	msgext(c, 'h', a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue