Introduction
Introduction Statistics Contact Development Disclaimer Help
Communicate with webextension via a pipe - surf - surf browser, a WebKit based …
git clone git://git.suckless.org/surf
Log
Files
Refs
README
LICENSE
---
commit 7ea0c2f7f8c5cc4616d8dc0676f7b4b59351667b
parent 1bd6d201020f67160872c28534edff532b5198b9
Author: Quentin Rameau <[email protected]>
Date: Mon, 7 Dec 2015 15:50:00 +0100
Communicate with webextension via a pipe
Diffstat:
M Makefile | 2 +-
M config.def.h | 16 +++++++---------
M libsurf-webext.c | 128 +++++++++++++++++++++++++++++…
M surf.c | 114 +++++++++++++++++++++--------…
4 files changed, 213 insertions(+), 47 deletions(-)
---
diff --git a/Makefile b/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
diff --git a/config.def.h b/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 } },
diff --git a/libsurf-webext.c b/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…
{
- 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);
}
diff --git a/surf.c b/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, 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].fil…
@@ -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[FileURLsCross…
@@ -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);
}
+}
+
+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
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.