Introduction
Introduction Statistics Contact Development Disclaimer Help
tStyle change in functions ordering - surf - customized build of surf, the suck…
git clone git://src.adamsgaard.dk/surf
Log
Files
Refs
README
LICENSE
---
commit 432f3c6b53cf47db3141a3e9b8b5aec2152f9aae
parent 7e9a85a5cb31a2ddefd06498eff33df724bdc6cf
Author: Quentin Rameau <[email protected]>
Date: Sat, 21 Nov 2015 19:14:08 +0100
Style change in functions ordering
Try to group and order functions in a logical manner.
Same thing for config keybindings.
Diffstat:
M config.def.h | 40 ++++++++++++++++-------------…
M surf.c | 1738 +++++++++++++++--------------…
2 files changed, 889 insertions(+), 889 deletions(-)
---
diff --git a/config.def.h b/config.def.h
t@@ -84,18 +84,15 @@ static SiteStyle styles[] = {
*/
static Key keys[] = {
/* modifier keyval function arg */
- { MODKEY|GDK_SHIFT_MASK, GDK_KEY_r, reload, { .b = TRUE } },
- { MODKEY, GDK_KEY_r, reload, { .b = FALSE } },
- { MODKEY|GDK_SHIFT_MASK, GDK_KEY_p, print, { 0 } },
+ { MODKEY, GDK_KEY_g, spawn, SETPROP("_SURF_UR…
+ { MODKEY, GDK_KEY_f, spawn, SETPROP("_SURF_FI…
+ { MODKEY, GDK_KEY_slash, spawn, SETPROP("_SURF_FI…
- { MODKEY, GDK_KEY_p, clipboard, { .b = TRUE } },
- { MODKEY, GDK_KEY_y, clipboard, { .b = FALSE } },
+ { 0, GDK_KEY_Escape, stop, { 0 } },
+ { MODKEY, GDK_KEY_c, stop, { 0 } },
- { MODKEY|GDK_SHIFT_MASK, GDK_KEY_j, zoom, { .i = -1 } },
- { MODKEY|GDK_SHIFT_MASK, GDK_KEY_k, zoom, { .i = +1 } },
- { MODKEY|GDK_SHIFT_MASK, GDK_KEY_q, zoom, { .i = 0 } },
- { MODKEY, GDK_KEY_minus, zoom, { .i = -1 } },
- { MODKEY, GDK_KEY_plus, zoom, { .i = +1 } },
+ { MODKEY|GDK_SHIFT_MASK, GDK_KEY_r, reload, { .b = TRUE } },
+ { MODKEY, GDK_KEY_r, reload, { .b = FALSE } },
{ MODKEY, GDK_KEY_l, navigate, { .i = +1 } },
{ MODKEY, GDK_KEY_h, navigate, { .i = -1 } },
t@@ -108,17 +105,25 @@ static Key keys[] = {
{ MODKEY, GDK_KEY_i, scroll_h, { .i = +10 } },
{ MODKEY, GDK_KEY_u, scroll_h, { .i = -10 } },
- { 0, GDK_KEY_F11, togglefullscreen, { 0 } },
- { 0, GDK_KEY_Escape, stop, { 0 } },
- { MODKEY|GDK_SHIFT_MASK, GDK_KEY_o, toggleinspector, { 0 } },
+ { MODKEY|GDK_SHIFT_MASK, GDK_KEY_j, zoom, { .i = -1 } },
+ { MODKEY|GDK_SHIFT_MASK, GDK_KEY_k, zoom, { .i = +1 } },
+ { MODKEY|GDK_SHIFT_MASK, GDK_KEY_q, zoom, { .i = 0 } },
+ { MODKEY, GDK_KEY_minus, zoom, { .i = -1 } },
+ { MODKEY, GDK_KEY_plus, zoom, { .i = +1 } },
- { MODKEY, GDK_KEY_g, spawn, SETPROP("_SURF_UR…
- { MODKEY, GDK_KEY_f, spawn, SETPROP("_SURF_FI…
- { MODKEY, GDK_KEY_slash, spawn, SETPROP("_SURF_FI…
+ { MODKEY, GDK_KEY_p, clipboard, { .b = TRUE } },
+ { MODKEY, GDK_KEY_y, clipboard, { .b = FALSE } },
{ MODKEY, GDK_KEY_n, find, { .i = +1 } },
{ MODKEY|GDK_SHIFT_MASK, GDK_KEY_n, find, { .i = -1 } },
+ { MODKEY|GDK_SHIFT_MASK, GDK_KEY_p, print, { 0 } },
+
+ { MODKEY|GDK_SHIFT_MASK, GDK_KEY_a, togglecookiepolicy, { 0 } },
+ { 0, GDK_KEY_F11, togglefullscreen, { 0 } },
+ { MODKEY|GDK_SHIFT_MASK, GDK_KEY_o, toggleinspector, { 0 } },
+ { MODKEY|GDK_SHIFT_MASK, GDK_KEY_m, togglestyle, { 0 } },
+
{ MODKEY|GDK_SHIFT_MASK, GDK_KEY_c, toggle, { .i = CaretBrows…
{ MODKEY|GDK_SHIFT_MASK, GDK_KEY_f, toggle, { .i = FrameFlatt…
{ MODKEY|GDK_SHIFT_MASK, GDK_KEY_g, toggle, { .i = Geolocatio…
t@@ -126,9 +131,6 @@ static Key keys[] = {
{ MODKEY|GDK_SHIFT_MASK, GDK_KEY_i, toggle, { .i = LoadImages…
{ MODKEY|GDK_SHIFT_MASK, GDK_KEY_v, toggle, { .i = Plugins } …
{ MODKEY|GDK_SHIFT_MASK, GDK_KEY_b, toggle, { .i = ScrollBars…
-
- { MODKEY|GDK_SHIFT_MASK, GDK_KEY_a, togglecookiepolicy, { 0 } },
- { MODKEY|GDK_SHIFT_MASK, GDK_KEY_m, togglestyle, { 0 } },
};
/* button definitions */
diff --git a/surf.c b/surf.c
t@@ -29,14 +29,22 @@
#include "arg.h"
-char *argv0;
-
#define LENGTH(x) (sizeof(x) / sizeof(x[0]))
#define CLEANMASK(mask) (mask & (MODKEY|GDK_SHIFT_MASK))
enum { AtomFind, AtomGo, AtomUri, AtomLast };
enum {
+ CaretBrowsing,
+ FrameFlattening,
+ Geolocation,
+ JavaScript,
+ LoadImages,
+ Plugins,
+ ScrollBars,
+};
+
+enum {
OnDoc = WEBKIT_HIT_TEST_RESULT_CONTEXT_DOCUMENT,
OnLink = WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK,
OnImg = WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE,
t@@ -47,42 +55,31 @@ enum {
OnAny = OnDoc | OnLink | OnImg | OnMedia | OnEdit | OnBar | OnSel,
};
-enum {
- CaretBrowsing,
- FrameFlattening,
- Geolocation,
- JavaScript,
- LoadImages,
- Plugins,
- ScrollBars,
-};
-
-typedef union Arg Arg;
-union Arg {
+typedef union {
gboolean b;
gint i;
const void *v;
-};
+} Arg;
typedef struct Client {
GtkWidget *win;
- Window xid;
WebKitWebView *view;
WebKitWebInspector *inspector;
WebKitFindController *finder;
WebKitHitTestResult *mousepos;
GTlsCertificateFlags tlsflags;
+ Window xid;
+ gint progress;
+ gboolean fullscreen;
const char *title, *targeturi;
const char *needle;
- gint progress;
struct Client *next;
- gboolean fullscreen;
} Client;
typedef struct {
guint mod;
guint keyval;
- void (*func)(Client *c, const Arg *arg);
+ void (*func)(Client *c, const Arg *a);
const Arg arg;
} Key;
t@@ -101,114 +98,168 @@ typedef struct {
regex_t re;
} SiteStyle;
-static Display *dpy;
-static Atom atoms[AtomLast];
-static Client *clients = NULL;
-static Window embed = 0;
-static gboolean showxid = FALSE;
-static char winid[64];
-static char togglestats[10];
-static char pagestats[2];
-static int cookiepolicy;
-static char *stylefile = NULL;
-static const char *useragent;
-
-static void addaccelgroup(Client *c);
+/* Surf */
+static void usage(void);
+static void die(const char *errstr, ...);
+static void setup(void);
+static void sigchld(int unused);
static char *buildfile(const char *path);
static char *buildpath(const char *path);
-static gboolean buttonreleased(GtkWidget *w, GdkEventKey *e, Client *c);
-static void cleanup(void);
-static void clipboard(Client *c, const Arg *a);
-
+static Client *newclient(Client *c);
+static void addaccelgroup(Client *c);
+static void loaduri(Client *c, const Arg *a);
+static char *geturi(Client *c);
+static void setatom(Client *c, int a, const char *v);
+static const char *getatom(Client *c, int a);
+static void updatetitle(Client *c);
+static void gettogglestats(Client *c);
+static void getpagestats(Client *c);
static WebKitCookieAcceptPolicy cookiepolicy_get(void);
static char cookiepolicy_set(const WebKitCookieAcceptPolicy p);
+static const gchar *getstyle(const char *uri);
+static void setstyle(Client *c, const char *stylefile);
+static void runscript(Client *c);
+static void evalscript(Client *c, const char *jsstr, ...);
+static void updatewinid(Client *c);
+static void handleplumb(Client *c, const gchar *uri);
+static void newwindow(Client *c, const Arg *arg, gboolean noembed);
+static void spawn(Client *c, const Arg *a);
+static void destroyclient(Client *c);
+static void cleanup(void);
+/* GTK/WebKit */
+static WebKitWebView *newview(Client *c, WebKitWebView *rv);
static GtkWidget *createview(WebKitWebView *v, WebKitNavigationAction *a,
Client *c);
+static gboolean buttonreleased(GtkWidget *w, GdkEventKey *e, Client *c);
+static gboolean keypress(GtkAccelGroup *group, GObject *obj, guint key,
+ GdkModifierType mods, Client *c);
+static GdkFilterReturn processx(GdkXEvent *xevent, GdkEvent *event,
+ gpointer d);
+static gboolean winevent(GtkWidget *w, GdkEvent *e, Client *c);
+static void showview(WebKitWebView *v, Client *c);
+static GtkWidget *createwindow(Client *c);
+static void loadchanged(WebKitWebView *v, WebKitLoadEvent e, Client *c);
+static void progresschanged(WebKitWebView *v, GParamSpec *ps, Client *c);
+static void titlechanged(WebKitWebView *view, GParamSpec *ps, Client *c);
+static void mousetargetchanged(WebKitWebView *v, WebKitHitTestResult *h,
+ guint modifiers, Client *c);
+static gboolean permissionrequested(WebKitWebView *v,
+ WebKitPermissionRequest *r, Client *c);
static gboolean decidepolicy(WebKitWebView *v, WebKitPolicyDecision *d,
WebKitPolicyDecisionType dt, Client *c);
static void decidenavigation(WebKitPolicyDecision *d, Client *c);
static void decidenewwindow(WebKitPolicyDecision *d, Client *c);
static void decideresource(WebKitPolicyDecision *d, Client *c);
-static void closeview(WebKitWebView *v, Client *c);
-static void destroyclient(Client *c);
-static void destroywin(GtkWidget* w, Client *c);
-static void die(const char *errstr, ...);
-static void evalscript(Client *c, const char *jsstr, ...);
-static void runscript(Client *c);
-static void find(Client *c, const Arg *a);
-static void togglefullscreen(Client *c, const Arg *a);
-static gboolean permissionrequested(WebKitWebView *v,
- WebKitPermissionRequest *r, Client *c);
-static const char *getatom(Client *c, int a);
-static void gettogglestats(Client *c);
-static void getpagestats(Client *c);
-static char *geturi(Client *c);
-static const gchar *getstyle(const char *uri);
-static void setstyle(Client *c, const char *stylefile);
-
-static void handleplumb(Client *c, const gchar *uri);
-
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 closeview(WebKitWebView *v, Client *c);
+static void destroywin(GtkWidget* w, Client *c);
-static void toggleinspector(Client *c, const Arg *a);
-
-static gboolean keypress(GtkAccelGroup *group, GObject *obj, guint key,
- GdkModifierType mods, Client *c);
-static void mousetargetchanged(WebKitWebView *v, WebKitHitTestResult *h,
- guint modifiers, Client *c);
-static void loadchanged(WebKitWebView *v, WebKitLoadEvent e, Client *c);
-static void loaduri(Client *c, const Arg *a);
-static void navigate(Client *c, const Arg *a);
-static void clicknavigate(Client *c, const Arg *a, WebKitHitTestResult *h);
-static Client *newclient(Client *c);
-static WebKitWebView *newview(Client *c, WebKitWebView *rv);
-static void showview(WebKitWebView *v, Client *c);
-static void newwindow(Client *c, const Arg *arg, gboolean noembed);
-static GtkWidget *createwindow(Client *c);
+/* Hotkeys */
static void pasteuri(GtkClipboard *clipboard, const char *text, gpointer d);
-static void print(Client *c, const Arg *a);
-static GdkFilterReturn processx(GdkXEvent *xevent, GdkEvent *event,
- gpointer d);
-static gboolean winevent(GtkWidget *w, GdkEvent *e, Client *c);
-static void progresschanged(WebKitWebView *v, GParamSpec *ps, Client *c);
-static void clicknewwindow(Client *c, const Arg *a, WebKitHitTestResult *h);
static void reload(Client *c, const Arg *arg);
-static void scroll_h(Client *c, const Arg *a);
+static void print(Client *c, const Arg *a);
+static void clipboard(Client *c, const Arg *a);
+static void zoom(Client *c, const Arg *a);
static void scroll_v(Client *c, const Arg *a);
-static void setatom(Client *c, int a, const char *v);
-static void setup(void);
-static void sigchld(int unused);
-static void spawn(Client *c, const Arg *arg);
+static void scroll_h(Client *c, const Arg *a);
+static void navigate(Client *c, const Arg *a);
static void stop(Client *c, const Arg *arg);
-static void titlechanged(WebKitWebView *view, GParamSpec *ps, Client *c);
static void toggle(Client *c, const Arg *a);
+static void togglefullscreen(Client *c, const Arg *a);
static void togglecookiepolicy(Client *c, const Arg *arg);
static void togglestyle(Client *c, const Arg *arg);
-static void updatetitle(Client *c);
-static void updatewinid(Client *c);
-static void usage(void);
-static void zoom(Client *c, const Arg *a);
+static void toggleinspector(Client *c, const Arg *a);
+static void find(Client *c, const Arg *a);
+
+/* Buttons */
+static void clicknavigate(Client *c, const Arg *a, WebKitHitTestResult *h);
+static void clicknewwindow(Client *c, const Arg *a, WebKitHitTestResult *h);
+
+static char winid[64];
+static char togglestats[10];
+static char pagestats[2];
+static Atom atoms[AtomLast];
+static Window embed;
+static gboolean showxid = FALSE;
+static int cookiepolicy;
+static Display *dpy;
+static Client *clients;
+static char *stylefile;
+static const char *useragent;
+char *argv0;
/* configuration, allows nested code to access above variables */
#include "config.h"
void
-addaccelgroup(Client *c)
+usage(void)
+{
+ die("usage: %s [-bBdDfFgGiIkKmMnNpPsSvx] [-a cookiepolicies ] "
+ "[-c cookiefile] [-e xid] [-r scriptfile] [-t stylefile] "
+ "[-u useragent] [-z zoomlevel] [uri]\n", basename(argv0));
+}
+
+void
+die(const char *errstr, ...)
+{
+ va_list ap;
+
+ va_start(ap, errstr);
+ vfprintf(stderr, errstr, ap);
+ va_end(ap);
+ exit(EXIT_FAILURE);
+}
+
+void
+setup(void)
{
int i;
- GtkAccelGroup *group = gtk_accel_group_new();
- GClosure *closure;
- for (i = 0; i < LENGTH(keys); i++) {
- closure = g_cclosure_new(G_CALLBACK(keypress), c, NULL);
- gtk_accel_group_connect(group, keys[i].keyval, keys[i].mod, 0,
- closure);
+ /* clean up any zombies immediately */
+ sigchld(0);
+ gtk_init(NULL, NULL);
+
+ dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
+
+ /* atoms */
+ atoms[AtomFind] = XInternAtom(dpy, "_SURF_FIND", False);
+ atoms[AtomGo] = XInternAtom(dpy, "_SURF_GO", False);
+ atoms[AtomUri] = XInternAtom(dpy, "_SURF_URI", False);
+
+ /* dirs and files */
+ cookiefile = buildfile(cookiefile);
+ scriptfile = buildfile(scriptfile);
+ cachedir = buildpath(cachedir);
+
+ if (stylefile == NULL) {
+ styledir = buildpath(styledir);
+ for (i = 0; i < LENGTH(styles); i++) {
+ if (regcomp(&(styles[i].re), styles[i].regex,
+ REG_EXTENDED)) {
+ fprintf(stderr,
+ "Could not compile regex: %s\n",
+ styles[i].regex);
+ styles[i].regex = NULL;
+ }
+ styles[i].style = g_strconcat(styledir, "/",
+ styles[i].style, NULL);
+ }
+ g_free(styledir);
+ } else {
+ stylefile = buildfile(stylefile);
}
- gtk_window_add_accel_group(GTK_WINDOW(c->win), group);
+}
+
+void
+sigchld(int unused)
+{
+ if (signal(SIGCHLD, sigchld) == SIG_ERR)
+ die("Can't install SIGCHLD handler");
+ while (0 < waitpid(-1, NULL, WNOHANG));
}
char *
t@@ -273,37 +324,161 @@ buildpath(const char *path)
return fpath;
}
-gboolean
-buttonreleased(GtkWidget *w, GdkEventKey *e, Client *c)
+Client *
+newclient(Client *rc)
{
- WebKitHitTestResultContext element;
- GdkEventButton *eb = (GdkEventButton*)e;
- int i;
+ Client *c;
- element = webkit_hit_test_result_get_context(c->mousepos);
+ if (!(c = calloc(1, sizeof(Client))))
+ die("Cannot malloc!\n");
- for (i = 0; i < LENGTH(buttons); ++i) {
- if (element & buttons[i].target &&
- eb->button == buttons[i].button &&
- CLEANMASK(eb->state) == CLEANMASK(buttons[i].mask) &&
- buttons[i].func) {
- buttons[i].func(c, &buttons[i].arg, c->mousepos);
- return buttons[i].stopevent;
- }
- }
+ c->title = NULL;
+ c->progress = 100;
- return FALSE;
+ c->next = clients;
+ clients = c;
+
+ c->view = newview(c, rc ? rc->view : NULL);
+ c->tlsflags = G_TLS_CERTIFICATE_VALIDATE_ALL + 1;
+
+ return c;
}
void
-cleanup(void)
+addaccelgroup(Client *c)
{
- while (clients)
- destroyclient(clients);
- g_free(cookiefile);
- g_free(scriptfile);
- g_free(stylefile);
- g_free(cachedir);
+ int i;
+ GtkAccelGroup *group = gtk_accel_group_new();
+ GClosure *closure;
+
+ for (i = 0; i < LENGTH(keys); i++) {
+ closure = g_cclosure_new(G_CALLBACK(keypress), c, NULL);
+ gtk_accel_group_connect(group, keys[i].keyval, keys[i].mod, 0,
+ closure);
+ }
+ gtk_window_add_accel_group(GTK_WINDOW(c->win), group);
+}
+
+void
+loaduri(Client *c, const Arg *a)
+{
+ struct stat st;
+ char *url, *path;
+ const char *uri = (char *)a->v;
+
+ if (g_strcmp0(uri, "") == 0)
+ return;
+
+ if (g_strrstr(uri, "://") || 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);
+ }
+
+ setatom(c, AtomUri, url);
+
+ if (strcmp(url, geturi(c)) == 0) {
+ reload(c, a);
+ } else {
+ webkit_web_view_load_uri(c->view, url);
+ c->title = geturi(c);
+ updatetitle(c);
+ }
+
+ g_free(url);
+}
+
+char *
+geturi(Client *c)
+{
+ char *uri;
+
+ if (!(uri = (char *)webkit_web_view_get_uri(c->view)))
+ uri = "about:blank";
+ return uri;
+}
+
+void
+setatom(Client *c, int a, const char *v)
+{
+ XSync(dpy, False);
+ XChangeProperty(dpy, c->xid,
+ atoms[a], XA_STRING, 8, PropModeReplace,
+ (unsigned char *)v, strlen(v) + 1);
+}
+
+const char *
+getatom(Client *c, int a)
+{
+ static char buf[BUFSIZ];
+ Atom adummy;
+ int idummy;
+ unsigned long ldummy;
+ unsigned char *p = NULL;
+
+ XGetWindowProperty(dpy, c->xid,
+ atoms[a], 0L, BUFSIZ, False, XA_STRING,
+ &adummy, &idummy, &ldummy, &ldummy, &p);
+ if (p)
+ strncpy(buf, (char *)p, LENGTH(buf)-1);
+ else
+ buf[0] = '\0';
+ XFree(p);
+
+ return buf;
+}
+
+void
+updatetitle(Client *c)
+{
+ char *title;
+
+ if (showindicators) {
+ gettogglestats(c);
+ getpagestats(c);
+
+ if (c->progress != 100) {
+ title = g_strdup_printf("[%i%%] %s:%s | %s",
+ c->progress, togglestats, pagestats,
+ c->targeturi ? c->targeturi : c->title);
+ } else {
+ title = g_strdup_printf("%s:%s | %s",
+ togglestats, pagestats,
+ c->targeturi ? c->targeturi : c->title);
+ }
+
+ gtk_window_set_title(GTK_WINDOW(c->win), title);
+ g_free(title);
+ } else {
+ gtk_window_set_title(GTK_WINDOW(c->win), c->title ?
+ c->title : "");
+ }
+}
+
+void
+gettogglestats(Client *c)
+{
+ togglestats[0] = cookiepolicy_set(cookiepolicy_get());
+ togglestats[1] = enablecaretbrowsing ? 'C' : 'c';
+ togglestats[2] = allowgeolocation ? 'G' : 'g';
+ togglestats[3] = enablecache ? 'D' : 'd';
+ togglestats[4] = loadimages ? 'I' : 'i';
+ togglestats[5] = enablescripts ? 'S': 's';
+ togglestats[6] = enableplugins ? 'V' : 'v';
+ togglestats[7] = enablestyle ? 'M' : 'm';
+ togglestats[8] = enableframeflattening ? 'F' : 'f';
+ togglestats[9] = '\0';
+}
+
+void
+getpagestats(Client *c)
+{
+ pagestats[0] = c->tlsflags > G_TLS_CERTIFICATE_VALIDATE_ALL ? '-' :
+ c->tlsflags > 0 ? 'U' : 'T';
+ pagestats[1] = '\0';
}
WebKitCookieAcceptPolicy
t@@ -338,18 +513,41 @@ cookiepolicy_set(const WebKitCookieAcceptPolicy ep)
return 'A';
}
+const gchar *
+getstyle(const char *uri)
+{
+ int i;
+
+ if (stylefile != NULL)
+ return stylefile;
+
+ for (i = 0; i < LENGTH(styles); i++) {
+ if (styles[i].regex && !regexec(&(styles[i].re), uri, 0,
+ NULL, 0))
+ return styles[i].style;
+ }
+
+ return "";
+}
+
void
-evalscript(Client *c, const char *jsstr, ...)
+setstyle(Client *c, const char *stylefile)
{
- va_list ap;
- gchar *script;
+ gchar *style;
- va_start(ap, jsstr);
- script = g_strdup_vprintf(jsstr, ap);
- va_end(ap);
+ if (!g_file_get_contents(stylefile, &style, NULL, NULL)) {
+ fprintf(stderr, "Could not read style file: %s\n", stylefile);
+ return;
+ }
- webkit_web_view_run_javascript(c->view, script, NULL, NULL, NULL);
- g_free(script);
+ webkit_user_content_manager_add_style_sheet(
+ webkit_web_view_get_user_content_manager(c->view),
+ webkit_user_style_sheet_new(style,
+ WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
+ WEBKIT_USER_STYLE_LEVEL_USER,
+ NULL, NULL));
+
+ g_free(style);
}
void
t@@ -364,517 +562,129 @@ runscript(Client *c)
}
void
-clipboard(Client *c, const Arg *a)
-{
- if (a->b) { /* load clipboard uri */
- gtk_clipboard_request_text(gtk_clipboard_get(
- GDK_SELECTION_PRIMARY),
- pasteuri, c);
- } else { /* copy uri */
- gtk_clipboard_set_text(gtk_clipboard_get(
- GDK_SELECTION_PRIMARY), c->targeturi
- ? c->targeturi : geturi(c), -1);
- }
-}
-
-GtkWidget *
-createview(WebKitWebView *v, WebKitNavigationAction *a, Client *c)
+evalscript(Client *c, const char *jsstr, ...)
{
- Client *n;
+ va_list ap;
+ gchar *script;
- switch (webkit_navigation_action_get_navigation_type(a)) {
- case WEBKIT_NAVIGATION_TYPE_OTHER: /* fallthrough */
- /*
- * popup windows of type “other” are almost always trigger…
- * by user gesture, so inverse the logic here
- */
-/* instead of this, compare destination uri to mouse-over uri for validating w…
- if (webkit_navigation_action_is_user_gesture(a)) {
- return NULL;
- break;
- }
- case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_BACK_FORWARD: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_RELOAD: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED:
- n = newclient(c);
- break;
- default:
- return NULL;
- break;
- }
+ va_start(ap, jsstr);
+ script = g_strdup_vprintf(jsstr, ap);
+ va_end(ap);
- return GTK_WIDGET(n->view);
+ webkit_web_view_run_javascript(c->view, script, NULL, NULL, NULL);
+ g_free(script);
}
-gboolean
-decidepolicy(WebKitWebView *v, WebKitPolicyDecision *d,
- WebKitPolicyDecisionType dt, Client *c)
+void
+updatewinid(Client *c)
{
- switch (dt) {
- case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION:
- decidenavigation(d, c);
- break;
- case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION:
- decidenewwindow(d, c);
- break;
- case WEBKIT_POLICY_DECISION_TYPE_RESPONSE:
- decideresource(d, c);
- break;
- default:
- webkit_policy_decision_ignore(d);
- break;
- }
- return TRUE;
+ snprintf(winid, LENGTH(winid), "%lu", c->xid);
}
void
-decidenavigation(WebKitPolicyDecision *d, Client *c)
+handleplumb(Client *c, const gchar *uri)
{
- WebKitNavigationAction *a;
+ Arg arg;
- a = webkit_navigation_policy_decision_get_navigation_action(
- WEBKIT_NAVIGATION_POLICY_DECISION(d));
-
- switch (webkit_navigation_action_get_navigation_type(a)) {
- case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_BACK_FORWARD: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_RELOAD: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED:
- case WEBKIT_NAVIGATION_TYPE_OTHER: /* fallthrough */
- default:
- /* Do not navigate to links with a "_blank" target (popup) */
- if (webkit_navigation_policy_decision_get_frame_name(
- WEBKIT_NAVIGATION_POLICY_DECISION(d))) {
- webkit_policy_decision_ignore(d);
- } else {
- /* Filter out navigation to different domain ? */
- /* get action→urirequest, copy and load in new windo…
- * on Ctrl+Click ? */
- webkit_policy_decision_use(d);
- }
- break;
- }
-}
-
-void
-decidenewwindow(WebKitPolicyDecision *d, Client *c)
-{
- WebKitNavigationAction *a;
- Arg arg;
-
- a = webkit_navigation_policy_decision_get_navigation_action(
- WEBKIT_NAVIGATION_POLICY_DECISION(d));
-
- switch (webkit_navigation_action_get_navigation_type(a)) {
- case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_BACK_FORWARD: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_RELOAD: /* fallthrough */
- case WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED:
- /* Filter domains here */
-/* If the value of “mouse-button” is not 0, then the navigation was trigge…
- * test for link clicked but no button ? */
- arg.v = webkit_uri_request_get_uri(
- webkit_navigation_action_get_request(a));
- newwindow(c, &arg, 0);
- break;
- case WEBKIT_NAVIGATION_TYPE_OTHER: /* fallthrough */
- default:
- break;
- }
-
- webkit_policy_decision_ignore(d);
-}
-
-void
-decideresource(WebKitPolicyDecision *d, Client *c)
-{
- const gchar *uri;
- int i, isascii = 1;
- WebKitResponsePolicyDecision *r = WEBKIT_RESPONSE_POLICY_DECISION(d);
- WebKitURIResponse *res;
-
- res = webkit_response_policy_decision_get_response(r);
- uri = webkit_uri_response_get_uri(res);
-
- if (g_str_has_suffix(uri, "/favicon.ico"))
- webkit_uri_request_set_uri(
- webkit_response_policy_decision_get_request(r),
- "about:blank");
-
- if (!g_str_has_prefix(uri, "http://")
- && !g_str_has_prefix(uri, "https://")
- && !g_str_has_prefix(uri, "about:")
- && !g_str_has_prefix(uri, "file://")
- && !g_str_has_prefix(uri, "data:")
- && !g_str_has_prefix(uri, "blob:")
- && strlen(uri) > 0) {
- for (i = 0; i < strlen(uri); i++) {
- if (!g_ascii_isprint(uri[i])) {
- isascii = 0;
- break;
- }
- }
- if (isascii) {
- handleplumb(c, uri);
- webkit_policy_decision_ignore(d);
- }
- }
-
- if (webkit_response_policy_decision_is_mime_type_supported(r)) {
- webkit_policy_decision_use(d);
- } else {
- webkit_policy_decision_ignore(d);
- download(c, res);
- }
-}
-
-void
-destroyclient(Client *c)
-{
- Client *p;
-
- webkit_web_view_stop_loading(c->view);
- /* Not needed, has already been called
- gtk_widget_destroy(c->win);
- */
-
- for (p = clients; p && p->next != c; p = p->next)
- ;
- if (p)
- p->next = c->next;
- else
- clients = c->next;
- free(c);
-}
-
-void
-closeview(WebKitWebView *v, Client *c)
-{
- gtk_widget_destroy(c->win);
-}
-
-void
-destroywin(GtkWidget* w, Client *c)
-{
- destroyclient(c);
- if (clients == NULL)
- gtk_main_quit();
-}
-
-void
-die(const char *errstr, ...)
-{
- va_list ap;
-
- va_start(ap, errstr);
- vfprintf(stderr, errstr, ap);
- va_end(ap);
- exit(EXIT_FAILURE);
-}
-
-void
-find(Client *c, const Arg *a)
-{
- const char *s, *f;
-
- if (a && a->i) {
- if (a->i > 0)
- webkit_find_controller_search_next(c->finder);
- else
- webkit_find_controller_search_previous(c->finder);
- } else {
- s = getatom(c, AtomFind);
- f = webkit_find_controller_get_search_text(c->finder);
-
- if (g_strcmp0(f, s) == 0) /* reset search */
- webkit_find_controller_search(c->finder, "", findopts,…
-
- webkit_find_controller_search(c->finder, s, findopts, G_MAXUIN…
-
- if (strcmp(s, "") == 0)
- webkit_find_controller_search_finish(c->finder);
- }
-}
-
-void
-togglefullscreen(Client *c, const Arg *a)
-{
- /* toggling value is handled in winevent() */
- if (c->fullscreen)
- gtk_window_unfullscreen(GTK_WINDOW(c->win));
- else
- gtk_window_fullscreen(GTK_WINDOW(c->win));
-}
-
-gboolean
-permissionrequested(WebKitWebView *v, WebKitPermissionRequest *r, Client *c)
-{
- if (WEBKIT_IS_GEOLOCATION_PERMISSION_REQUEST(r)) {
- if (allowgeolocation)
- webkit_permission_request_allow(r);
- else
- webkit_permission_request_deny(r);
- return TRUE;
- }
-
- return FALSE;
-}
-
-const char *
-getatom(Client *c, int a)
-{
- static char buf[BUFSIZ];
- Atom adummy;
- int idummy;
- unsigned long ldummy;
- unsigned char *p = NULL;
-
- XGetWindowProperty(dpy, c->xid,
- atoms[a], 0L, BUFSIZ, False, XA_STRING,
- &adummy, &idummy, &ldummy, &ldummy, &p);
- if (p)
- strncpy(buf, (char *)p, LENGTH(buf)-1);
- else
- buf[0] = '\0';
- XFree(p);
-
- return buf;
-}
-
-char *
-geturi(Client *c)
-{
- char *uri;
-
- if (!(uri = (char *)webkit_web_view_get_uri(c->view)))
- uri = "about:blank";
- return uri;
-}
-
-const gchar *
-getstyle(const char *uri)
-{
- int i;
-
- if (stylefile != NULL)
- return stylefile;
-
- for (i = 0; i < LENGTH(styles); i++) {
- if (styles[i].regex && !regexec(&(styles[i].re), uri, 0,
- NULL, 0))
- return styles[i].style;
- }
-
- return "";
-}
+ arg = (Arg)PLUMB(uri);
+ spawn(c, &arg);
+}
void
-setstyle(Client *c, const char *stylefile)
-{
- gchar *style;
-
- if (!g_file_get_contents(stylefile, &style, NULL, NULL)) {
- fprintf(stderr, "Could not read style file: %s\n", stylefile);
- return;
- }
-
- webkit_user_content_manager_add_style_sheet(
- webkit_web_view_get_user_content_manager(c->view),
- webkit_user_style_sheet_new(style,
- WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
- WEBKIT_USER_STYLE_LEVEL_USER,
- NULL, NULL));
-
- g_free(style);
-}
-
-void
-handleplumb(Client *c, const gchar *uri)
-{
- Arg arg;
-
- arg = (Arg)PLUMB(uri);
- spawn(c, &arg);
-}
-
-void
-downloadstarted(WebKitWebContext *wc, WebKitDownload *d, Client *c)
-{
- g_signal_connect(G_OBJECT(d), "notify::response",
- G_CALLBACK(responsereceived), c);
-}
-
-void
-responsereceived(WebKitDownload *d, GParamSpec *ps, Client *c)
-{
- download(c, webkit_download_get_response(d));
- webkit_download_cancel(d);
-}
-
-void
-download(Client *c, WebKitURIResponse *r)
+newwindow(Client *c, const Arg *a, int noembed)
{
- Arg a;
-
- a = (Arg)DOWNLOAD(webkit_uri_response_get_uri(r), geturi(c));
- spawn(c, &a);
-}
+ int i = 0;
+ char tmp[64];
+ const char *cmd[26], *uri;
+ const Arg arg = { .v = cmd };
-void
-toggleinspector(Client *c, const Arg *a)
-{
- if (enableinspector) {
- if (webkit_web_inspector_is_attached(c->inspector))
- webkit_web_inspector_close(c->inspector);
- else
- webkit_web_inspector_show(c->inspector);
+ cmd[i++] = argv0;
+ cmd[i++] = "-a";
+ cmd[i++] = cookiepolicies;
+ cmd[i++] = enablescrollbars ? "-B" : "-b";
+ if (cookiefile && g_strcmp0(cookiefile, "")) {
+ cmd[i++] = "-c";
+ cmd[i++] = cookiefile;
}
-}
-
-gboolean
-keypress(GtkAccelGroup *group, GObject *obj, guint key, GdkModifierType mods,
- Client *c)
-{
- guint i;
- gboolean processed = FALSE;
-
- mods = CLEANMASK(mods);
- key = gdk_keyval_to_lower(key);
- updatewinid(c);
- for (i = 0; i < LENGTH(keys); i++) {
- if (key == keys[i].keyval
- && mods == keys[i].mod
- && keys[i].func) {
- keys[i].func(c, &(keys[i].arg));
- processed = TRUE;
- }
+ cmd[i++] = enablecache ? "-D" : "-d";
+ if (embed && !noembed) {
+ cmd[i++] = "-e";
+ snprintf(tmp, LENGTH(tmp), "%lu", embed);
+ cmd[i++] = tmp;
}
-
- return processed;
-}
-
-void
-mousetargetchanged(WebKitWebView *v, WebKitHitTestResult *h, guint modifiers,
- Client *c)
-{
- WebKitHitTestResultContext hc;
-
- /* Keep the hit test to know where is the pointer on the next click */
- c->mousepos = h;
-
- hc = webkit_hit_test_result_get_context(h);
-
- if (hc & OnLink)
- c->targeturi = webkit_hit_test_result_get_link_uri(h);
- else if (hc & OnImg)
- c->targeturi = webkit_hit_test_result_get_image_uri(h);
- else if (hc & OnMedia)
- c->targeturi = webkit_hit_test_result_get_media_uri(h);
- else
- c->targeturi = NULL;
- updatetitle(c);
-}
-
-void
-loadchanged(WebKitWebView *v, WebKitLoadEvent e, Client *c)
-{
- switch (e) {
- case WEBKIT_LOAD_STARTED:
- c->tlsflags = G_TLS_CERTIFICATE_VALIDATE_ALL + 1;
- break;
- case WEBKIT_LOAD_REDIRECTED:
- setatom(c, AtomUri, geturi(c));
- break;
- case WEBKIT_LOAD_COMMITTED:
- if (!webkit_web_view_get_tls_info(c->view, NULL, &(c->tlsflags…
- c->tlsflags = G_TLS_CERTIFICATE_VALIDATE_ALL + 1;
-
- setatom(c, AtomUri, geturi(c));
-
- if (enablestyle)
- setstyle(c, getstyle(geturi(c)));
- break;
- case WEBKIT_LOAD_FINISHED:
- /* Disabled until we write some WebKitWebExtension for
- * manipulating the DOM directly.
- evalscript(c, "document.documentElement.style.overflow = '%s'",
- enablescrollbars ? "auto" : "hidden");
- */
- runscript(c);
- break;
+ cmd[i++] = runinfullscreen ? "-F" : "-f";
+ cmd[i++] = allowgeolocation ? "-G" : "-g";
+ cmd[i++] = loadimages ? "-I" : "-i";
+ cmd[i++] = kioskmode ? "-K" : "-k";
+ cmd[i++] = enablestyle ? "-M" : "-m";
+ cmd[i++] = enableinspector ? "-N" : "-n";
+ cmd[i++] = enableplugins ? "-P" : "-p";
+ if (scriptfile && g_strcmp0(scriptfile, "")) {
+ cmd[i++] = "-r";
+ cmd[i++] = scriptfile;
}
- updatetitle(c);
-}
-
-void
-loaduri(Client *c, const Arg *a)
-{
- struct stat st;
- char *url, *path;
- const char *uri = (char *)a->v;
-
- if (g_strcmp0(uri, "") == 0)
- return;
-
- if (g_strrstr(uri, "://") || 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);
+ cmd[i++] = enablescripts ? "-S" : "-s";
+ if (stylefile && g_strcmp0(stylefile, "")) {
+ cmd[i++] = "-t";
+ cmd[i++] = stylefile;
}
-
- setatom(c, AtomUri, url);
-
- if (strcmp(url, geturi(c)) == 0) {
- reload(c, a);
- } else {
- webkit_web_view_load_uri(c->view, url);
- c->title = geturi(c);
- updatetitle(c);
+ if (fulluseragent && g_strcmp0(fulluseragent, "")) {
+ cmd[i++] = "-u";
+ cmd[i++] = fulluseragent;
}
-
- g_free(url);
-}
-
-void
-navigate(Client *c, const Arg *a)
-{
- if (a->i < 0)
- webkit_web_view_go_back(c->view);
- else if (a->i > 0)
- webkit_web_view_go_forward(c->view);
+ if (showxid)
+ cmd[i++] = "-x";
+ /* do not keep zoom level */
+ cmd[i++] = "--";
+ if ((uri = a->v))
+ cmd[i++] = uri;
+ cmd[i] = NULL;
+
+ spawn(c, &arg);
}
void
-clicknavigate(Client *c, const Arg *a, WebKitHitTestResult *h)
+spawn(Client *c, const Arg *arg)
{
- navigate(c, a);
+ if (fork() == 0) {
+ if (dpy)
+ close(ConnectionNumber(dpy));
+ setsid();
+ execvp(((char **)arg->v)[0], (char **)arg->v);
+ fprintf(stderr, "surf: execvp %s", ((char **)arg->v)[0]);
+ perror(" failed");
+ exit(0);
+ }
}
-Client *
-newclient(Client *rc)
+void
+destroyclient(Client *c)
{
- Client *c;
-
- if (!(c = calloc(1, sizeof(Client))))
- die("Cannot malloc!\n");
-
- c->title = NULL;
- c->progress = 100;
+ Client *p;
- c->next = clients;
- clients = c;
+ webkit_web_view_stop_loading(c->view);
+ /* Not needed, has already been called
+ gtk_widget_destroy(c->win);
+ */
- c->view = newview(c, rc ? rc->view : NULL);
- c->tlsflags = G_TLS_CERTIFICATE_VALIDATE_ALL + 1;
+ for (p = clients; p && p->next != c; p = p->next)
+ ;
+ if (p)
+ p->next = c->next;
+ else
+ clients = c->next;
+ free(c);
+}
- return c;
+void
+cleanup(void)
+{
+ while (clients)
+ destroyclient(clients);
+ g_free(cookiefile);
+ g_free(scriptfile);
+ g_free(stylefile);
+ g_free(cachedir);
}
WebKitWebView *
t@@ -983,109 +793,178 @@ newview(Client *c, WebKitWebView *rv)
return v;
}
-void
-showview(WebKitWebView *v, Client *c)
+GtkWidget *
+createview(WebKitWebView *v, WebKitNavigationAction *a, Client *c)
{
- GdkGeometry hints = { 1, 1 };
- GdkRGBA bgcolor = { 0 };
- GdkWindow *gwin;
+ Client *n;
- c->win = createwindow(c);
+ switch (webkit_navigation_action_get_navigation_type(a)) {
+ case WEBKIT_NAVIGATION_TYPE_OTHER: /* fallthrough */
+ /*
+ * popup windows of type “other” are almost always trigger…
+ * by user gesture, so inverse the logic here
+ */
+/* instead of this, compare destination uri to mouse-over uri for validating w…
+ if (webkit_navigation_action_is_user_gesture(a)) {
+ return NULL;
+ break;
+ }
+ case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_BACK_FORWARD: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_RELOAD: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED:
+ n = newclient(c);
+ break;
+ default:
+ return NULL;
+ break;
+ }
- if (enableinspector)
- c->inspector = webkit_web_view_get_inspector(c->view);
+ return GTK_WIDGET(n->view);
+}
- c->finder = webkit_web_view_get_find_controller(c->view);
+gboolean
+buttonreleased(GtkWidget *w, GdkEventKey *e, Client *c)
+{
+ WebKitHitTestResultContext element;
+ GdkEventButton *eb = (GdkEventButton*)e;
+ int i;
- if (!kioskmode)
- addaccelgroup(c);
+ element = webkit_hit_test_result_get_context(c->mousepos);
- /* Arranging */
- gtk_container_add(GTK_CONTAINER(c->win), GTK_WIDGET(c->view));
+ for (i = 0; i < LENGTH(buttons); ++i) {
+ if (element & buttons[i].target &&
+ eb->button == buttons[i].button &&
+ CLEANMASK(eb->state) == CLEANMASK(buttons[i].mask) &&
+ buttons[i].func) {
+ buttons[i].func(c, &buttons[i].arg, c->mousepos);
+ return buttons[i].stopevent;
+ }
+ }
- /* Setup */
- gtk_widget_grab_focus(GTK_WIDGET(c->view));
- gtk_widget_show(GTK_WIDGET(c->view));
- gtk_widget_show(c->win);
- gwin = gtk_widget_get_window(GTK_WIDGET(c->win));
- c->xid = gdk_x11_window_get_xid(gwin);
- gtk_window_set_geometry_hints(GTK_WINDOW(c->win), NULL, &hints,
- GDK_HINT_MIN_SIZE);
- gdk_window_set_events(gwin, GDK_ALL_EVENTS_MASK);
- gdk_window_add_filter(gwin, processx, c);
+ return FALSE;
+}
- if (zoomlevel != 1.0)
- webkit_web_view_set_zoom_level(c->view, zoomlevel);
+gboolean
+keypress(GtkAccelGroup *group, GObject *obj, guint key, GdkModifierType mods,
+ Client *c)
+{
+ guint i;
+ gboolean processed = FALSE;
- if (runinfullscreen)
- togglefullscreen(c, NULL);
+ mods = CLEANMASK(mods);
+ key = gdk_keyval_to_lower(key);
+ updatewinid(c);
+ for (i = 0; i < LENGTH(keys); i++) {
+ if (key == keys[i].keyval
+ && mods == keys[i].mod
+ && keys[i].func) {
+ keys[i].func(c, &(keys[i].arg));
+ processed = TRUE;
+ }
+ }
- setatom(c, AtomFind, "");
- setatom(c, AtomUri, "about:blank");
- if (hidebackground)
- webkit_web_view_set_background_color(c->view, &bgcolor);
+ return processed;
+}
- if (showxid) {
- gdk_display_sync(gtk_widget_get_display(c->win));
- printf("%lu\n", c->xid);
- fflush(NULL);
- if (fclose(stdout) != 0) {
- die("Error closing stdout");
- }
+GdkFilterReturn
+processx(GdkXEvent *e, GdkEvent *event, gpointer d)
+{
+ Client *c = (Client *)d;
+ XPropertyEvent *ev;
+ Arg arg;
+
+ if (((XEvent *)e)->type == PropertyNotify) {
+ ev = &((XEvent *)e)->xproperty;
+ if (ev->state == PropertyNewValue) {
+ if (ev->atom == atoms[AtomFind]) {
+ find(c, NULL);
+
+ return GDK_FILTER_REMOVE;
+ } else if (ev->atom == atoms[AtomGo]) {
+ arg.v = getatom(c, AtomGo);
+ loaduri(c, &arg);
+
+ return GDK_FILTER_REMOVE;
+ }
+ }
+ }
+ return GDK_FILTER_CONTINUE;
+}
+
+gboolean
+winevent(GtkWidget *w, GdkEvent *e, Client *c)
+{
+ switch (e->type) {
+ case GDK_LEAVE_NOTIFY:
+ c->targeturi = NULL;
+ updatetitle(c);
+ break;
+ case GDK_WINDOW_STATE: /* fallthrough */
+ if (e->window_state.changed_mask ==
+ GDK_WINDOW_STATE_FULLSCREEN) {
+ c->fullscreen = e->window_state.new_window_state &
+ GDK_WINDOW_STATE_FULLSCREEN;
+ break;
+ }
+ default:
+ return FALSE;
}
+
+ return TRUE;
}
void
-newwindow(Client *c, const Arg *a, int noembed)
+showview(WebKitWebView *v, Client *c)
{
- int i = 0;
- char tmp[64];
- const char *cmd[26], *uri;
- const Arg arg = { .v = cmd };
+ GdkGeometry hints = { 1, 1 };
+ GdkRGBA bgcolor = { 0 };
+ GdkWindow *gwin;
- cmd[i++] = argv0;
- cmd[i++] = "-a";
- cmd[i++] = cookiepolicies;
- cmd[i++] = enablescrollbars ? "-B" : "-b";
- if (cookiefile && g_strcmp0(cookiefile, "")) {
- cmd[i++] = "-c";
- cmd[i++] = cookiefile;
- }
- cmd[i++] = enablecache ? "-D" : "-d";
- if (embed && !noembed) {
- cmd[i++] = "-e";
- snprintf(tmp, LENGTH(tmp), "%lu", embed);
- cmd[i++] = tmp;
- }
- cmd[i++] = runinfullscreen ? "-F" : "-f";
- cmd[i++] = allowgeolocation ? "-G" : "-g";
- cmd[i++] = loadimages ? "-I" : "-i";
- cmd[i++] = kioskmode ? "-K" : "-k";
- cmd[i++] = enablestyle ? "-M" : "-m";
- cmd[i++] = enableinspector ? "-N" : "-n";
- cmd[i++] = enableplugins ? "-P" : "-p";
- if (scriptfile && g_strcmp0(scriptfile, "")) {
- cmd[i++] = "-r";
- cmd[i++] = scriptfile;
- }
- cmd[i++] = enablescripts ? "-S" : "-s";
- if (stylefile && g_strcmp0(stylefile, "")) {
- cmd[i++] = "-t";
- cmd[i++] = stylefile;
- }
- if (fulluseragent && g_strcmp0(fulluseragent, "")) {
- cmd[i++] = "-u";
- cmd[i++] = fulluseragent;
- }
- if (showxid)
- cmd[i++] = "-x";
- /* do not keep zoom level */
- cmd[i++] = "--";
- if ((uri = a->v))
- cmd[i++] = uri;
- cmd[i] = NULL;
+ c->win = createwindow(c);
+
+ if (enableinspector)
+ c->inspector = webkit_web_view_get_inspector(c->view);
+
+ c->finder = webkit_web_view_get_find_controller(c->view);
+
+ if (!kioskmode)
+ addaccelgroup(c);
- spawn(c, &arg);
+ /* Arranging */
+ gtk_container_add(GTK_CONTAINER(c->win), GTK_WIDGET(c->view));
+
+ /* Setup */
+ gtk_widget_grab_focus(GTK_WIDGET(c->view));
+ gtk_widget_show(GTK_WIDGET(c->view));
+ gtk_widget_show(c->win);
+ gwin = gtk_widget_get_window(GTK_WIDGET(c->win));
+ c->xid = gdk_x11_window_get_xid(gwin);
+ gtk_window_set_geometry_hints(GTK_WINDOW(c->win), NULL, &hints,
+ GDK_HINT_MIN_SIZE);
+ gdk_window_set_events(gwin, GDK_ALL_EVENTS_MASK);
+ gdk_window_add_filter(gwin, processx, c);
+
+ if (zoomlevel != 1.0)
+ webkit_web_view_set_zoom_level(c->view, zoomlevel);
+
+ if (runinfullscreen)
+ togglefullscreen(c, NULL);
+
+ setatom(c, AtomFind, "");
+ setatom(c, AtomUri, "about:blank");
+ if (hidebackground)
+ webkit_web_view_set_background_color(c->view, &bgcolor);
+
+ if (showxid) {
+ gdk_display_sync(gtk_widget_get_display(c->win));
+ printf("%lu\n", c->xid);
+ fflush(NULL);
+ if (fclose(stdout) != 0) {
+ die("Error closing stdout");
+ }
+ }
}
GtkWidget *
t@@ -1126,60 +1005,254 @@ createwindow(Client *c)
}
void
-pasteuri(GtkClipboard *clipboard, const char *text, gpointer d)
+loadchanged(WebKitWebView *v, WebKitLoadEvent e, Client *c)
{
- Arg arg = {.v = text };
- if (text != NULL)
- loaduri((Client *) d, &arg);
+ switch (e) {
+ case WEBKIT_LOAD_STARTED:
+ c->tlsflags = G_TLS_CERTIFICATE_VALIDATE_ALL + 1;
+ break;
+ case WEBKIT_LOAD_REDIRECTED:
+ setatom(c, AtomUri, geturi(c));
+ break;
+ case WEBKIT_LOAD_COMMITTED:
+ if (!webkit_web_view_get_tls_info(c->view, NULL, &(c->tlsflags…
+ c->tlsflags = G_TLS_CERTIFICATE_VALIDATE_ALL + 1;
+
+ setatom(c, AtomUri, geturi(c));
+
+ if (enablestyle)
+ setstyle(c, getstyle(geturi(c)));
+ break;
+ case WEBKIT_LOAD_FINISHED:
+ /* Disabled until we write some WebKitWebExtension for
+ * manipulating the DOM directly.
+ evalscript(c, "document.documentElement.style.overflow = '%s'",
+ enablescrollbars ? "auto" : "hidden");
+ */
+ runscript(c);
+ break;
+ }
+ updatetitle(c);
}
void
-print(Client *c, const Arg *a)
+progresschanged(WebKitWebView *v, GParamSpec *ps, Client *c)
{
- webkit_print_operation_run_dialog(webkit_print_operation_new(c->view),
- GTK_WINDOW(c->win));
+ c->progress = webkit_web_view_get_estimated_load_progress(c->view) *
+ 100;
+ updatetitle(c);
}
-GdkFilterReturn
-processx(GdkXEvent *e, GdkEvent *event, gpointer d)
+void
+titlechanged(WebKitWebView *view, GParamSpec *ps, Client *c)
{
- Client *c = (Client *)d;
- XPropertyEvent *ev;
+ c->title = webkit_web_view_get_title(c->view);
+ updatetitle(c);
+}
+
+void
+mousetargetchanged(WebKitWebView *v, WebKitHitTestResult *h, guint modifiers,
+ Client *c)
+{
+ WebKitHitTestResultContext hc;
+
+ /* Keep the hit test to know where is the pointer on the next click */
+ c->mousepos = h;
+
+ hc = webkit_hit_test_result_get_context(h);
+
+ if (hc & OnLink)
+ c->targeturi = webkit_hit_test_result_get_link_uri(h);
+ else if (hc & OnImg)
+ c->targeturi = webkit_hit_test_result_get_image_uri(h);
+ else if (hc & OnMedia)
+ c->targeturi = webkit_hit_test_result_get_media_uri(h);
+ else
+ c->targeturi = NULL;
+ updatetitle(c);
+}
+
+gboolean
+permissionrequested(WebKitWebView *v, WebKitPermissionRequest *r, Client *c)
+{
+ if (WEBKIT_IS_GEOLOCATION_PERMISSION_REQUEST(r)) {
+ if (allowgeolocation)
+ webkit_permission_request_allow(r);
+ else
+ webkit_permission_request_deny(r);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+gboolean
+decidepolicy(WebKitWebView *v, WebKitPolicyDecision *d,
+ WebKitPolicyDecisionType dt, Client *c)
+{
+ switch (dt) {
+ case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION:
+ decidenavigation(d, c);
+ break;
+ case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION:
+ decidenewwindow(d, c);
+ break;
+ case WEBKIT_POLICY_DECISION_TYPE_RESPONSE:
+ decideresource(d, c);
+ break;
+ default:
+ webkit_policy_decision_ignore(d);
+ break;
+ }
+ return TRUE;
+}
+
+void
+decidenavigation(WebKitPolicyDecision *d, Client *c)
+{
+ WebKitNavigationAction *a;
+
+ a = webkit_navigation_policy_decision_get_navigation_action(
+ WEBKIT_NAVIGATION_POLICY_DECISION(d));
+
+ switch (webkit_navigation_action_get_navigation_type(a)) {
+ case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_BACK_FORWARD: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_RELOAD: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED:
+ case WEBKIT_NAVIGATION_TYPE_OTHER: /* fallthrough */
+ default:
+ /* Do not navigate to links with a "_blank" target (popup) */
+ if (webkit_navigation_policy_decision_get_frame_name(
+ WEBKIT_NAVIGATION_POLICY_DECISION(d))) {
+ webkit_policy_decision_ignore(d);
+ } else {
+ /* Filter out navigation to different domain ? */
+ /* get action→urirequest, copy and load in new windo…
+ * on Ctrl+Click ? */
+ webkit_policy_decision_use(d);
+ }
+ break;
+ }
+}
+
+void
+decidenewwindow(WebKitPolicyDecision *d, Client *c)
+{
+ WebKitNavigationAction *a;
Arg arg;
- if (((XEvent *)e)->type == PropertyNotify) {
- ev = &((XEvent *)e)->xproperty;
- if (ev->state == PropertyNewValue) {
- if (ev->atom == atoms[AtomFind]) {
- find(c, NULL);
+ a = webkit_navigation_policy_decision_get_navigation_action(
+ WEBKIT_NAVIGATION_POLICY_DECISION(d));
+
+ switch (webkit_navigation_action_get_navigation_type(a)) {
+ case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_BACK_FORWARD: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_RELOAD: /* fallthrough */
+ case WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED:
+ /* Filter domains here */
+/* If the value of “mouse-button” is not 0, then the navigation was trigge…
+ * test for link clicked but no button ? */
+ arg.v = webkit_uri_request_get_uri(
+ webkit_navigation_action_get_request(a));
+ newwindow(c, &arg, 0);
+ break;
+ case WEBKIT_NAVIGATION_TYPE_OTHER: /* fallthrough */
+ default:
+ break;
+ }
+
+ webkit_policy_decision_ignore(d);
+}
+
+void
+decideresource(WebKitPolicyDecision *d, Client *c)
+{
+ const gchar *uri;
+ int i, isascii = 1;
+ WebKitResponsePolicyDecision *r = WEBKIT_RESPONSE_POLICY_DECISION(d);
+ WebKitURIResponse *res;
+
+ res = webkit_response_policy_decision_get_response(r);
+ uri = webkit_uri_response_get_uri(res);
+
+ if (g_str_has_suffix(uri, "/favicon.ico"))
+ webkit_uri_request_set_uri(
+ webkit_response_policy_decision_get_request(r),
+ "about:blank");
+
+ if (!g_str_has_prefix(uri, "http://")
+ && !g_str_has_prefix(uri, "https://")
+ && !g_str_has_prefix(uri, "about:")
+ && !g_str_has_prefix(uri, "file://")
+ && !g_str_has_prefix(uri, "data:")
+ && !g_str_has_prefix(uri, "blob:")
+ && strlen(uri) > 0) {
+ for (i = 0; i < strlen(uri); i++) {
+ if (!g_ascii_isprint(uri[i])) {
+ isascii = 0;
+ break;
+ }
+ }
+ if (isascii) {
+ handleplumb(c, uri);
+ webkit_policy_decision_ignore(d);
+ }
+ }
+
+ if (webkit_response_policy_decision_is_mime_type_supported(r)) {
+ webkit_policy_decision_use(d);
+ } else {
+ webkit_policy_decision_ignore(d);
+ download(c, res);
+ }
+}
+
+void
+downloadstarted(WebKitWebContext *wc, WebKitDownload *d, Client *c)
+{
+ g_signal_connect(G_OBJECT(d), "notify::response",
+ G_CALLBACK(responsereceived), c);
+}
+
+void
+responsereceived(WebKitDownload *d, GParamSpec *ps, Client *c)
+{
+ download(c, webkit_download_get_response(d));
+ webkit_download_cancel(d);
+}
- return GDK_FILTER_REMOVE;
- } else if (ev->atom == atoms[AtomGo]) {
- arg.v = getatom(c, AtomGo);
- loaduri(c, &arg);
+void
+download(Client *c, WebKitURIResponse *r)
+{
+ Arg a;
- return GDK_FILTER_REMOVE;
- }
- }
- }
- return GDK_FILTER_CONTINUE;
+ a = (Arg)DOWNLOAD(webkit_uri_response_get_uri(r), geturi(c));
+ spawn(c, &a);
}
void
-progresschanged(WebKitWebView *v, GParamSpec *ps, Client *c)
+closeview(WebKitWebView *v, Client *c)
{
- c->progress = webkit_web_view_get_estimated_load_progress(c->view) *
- 100;
- updatetitle(c);
+ gtk_widget_destroy(c->win);
}
void
-clicknewwindow(Client *c, const Arg *a, WebKitHitTestResult *h)
+destroywin(GtkWidget* w, Client *c)
{
- Arg arg;
+ destroyclient(c);
+ if (clients == NULL)
+ gtk_main_quit();
+}
- arg.v = webkit_hit_test_result_get_link_uri(h);
- newwindow(c, &arg, a->b);
+void
+pasteuri(GtkClipboard *clipboard, const char *text, gpointer d)
+{
+ Arg arg = {.v = text };
+ if (text != NULL)
+ loaduri((Client *) d, &arg);
}
void
t@@ -1193,88 +1266,60 @@ reload(Client *c, const Arg *arg)
}
void
-scroll_h(Client *c, const Arg *a)
+print(Client *c, const Arg *a)
{
- evalscript(c, "window.scrollBy(%d * (window.innerWidth / 100), 0)",
- a->i);
+ webkit_print_operation_run_dialog(webkit_print_operation_new(c->view),
+ GTK_WINDOW(c->win));
}
void
-scroll_v(Client *c, const Arg *a)
+clipboard(Client *c, const Arg *a)
{
- evalscript(c, "window.scrollBy(0, %d * (window.innerHeight / 100))",
- a->i);
+ if (a->b) { /* load clipboard uri */
+ gtk_clipboard_request_text(gtk_clipboard_get(
+ GDK_SELECTION_PRIMARY),
+ pasteuri, c);
+ } else { /* copy uri */
+ gtk_clipboard_set_text(gtk_clipboard_get(
+ GDK_SELECTION_PRIMARY), c->targeturi
+ ? c->targeturi : geturi(c), -1);
+ }
}
void
-setatom(Client *c, int a, const char *v)
+zoom(Client *c, const Arg *a)
{
- XSync(dpy, False);
- XChangeProperty(dpy, c->xid,
- atoms[a], XA_STRING, 8, PropModeReplace,
- (unsigned char *)v, strlen(v) + 1);
+ if (a->i > 0)
+ webkit_web_view_set_zoom_level(c->view, zoomlevel + 0.1);
+ else if (a->i < 0)
+ webkit_web_view_set_zoom_level(c->view, zoomlevel - 0.1);
+ else
+ webkit_web_view_set_zoom_level(c->view, 1.0);
+
+ zoomlevel = webkit_web_view_get_zoom_level(c->view);
}
void
-setup(void)
+scroll_v(Client *c, const Arg *a)
{
- int i;
-
- /* clean up any zombies immediately */
- sigchld(0);
- gtk_init(NULL, NULL);
-
- dpy = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
-
- /* atoms */
- atoms[AtomFind] = XInternAtom(dpy, "_SURF_FIND", False);
- atoms[AtomGo] = XInternAtom(dpy, "_SURF_GO", False);
- atoms[AtomUri] = XInternAtom(dpy, "_SURF_URI", False);
-
- /* dirs and files */
- cookiefile = buildfile(cookiefile);
- scriptfile = buildfile(scriptfile);
- cachedir = buildpath(cachedir);
-
- if (stylefile == NULL) {
- styledir = buildpath(styledir);
- for (i = 0; i < LENGTH(styles); i++) {
- if (regcomp(&(styles[i].re), styles[i].regex,
- REG_EXTENDED)) {
- fprintf(stderr,
- "Could not compile regex: %s\n",
- styles[i].regex);
- styles[i].regex = NULL;
- }
- styles[i].style = g_strconcat(styledir, "/",
- styles[i].style, NULL);
- }
- g_free(styledir);
- } else {
- stylefile = buildfile(stylefile);
- }
+ evalscript(c, "window.scrollBy(0, %d * (window.innerHeight / 100))",
+ a->i);
}
void
-sigchld(int unused)
+scroll_h(Client *c, const Arg *a)
{
- if (signal(SIGCHLD, sigchld) == SIG_ERR)
- die("Can't install SIGCHLD handler");
- while (0 < waitpid(-1, NULL, WNOHANG));
+ evalscript(c, "window.scrollBy(%d * (window.innerWidth / 100), 0)",
+ a->i);
}
void
-spawn(Client *c, const Arg *arg)
+navigate(Client *c, const Arg *a)
{
- if (fork() == 0) {
- if (dpy)
- close(ConnectionNumber(dpy));
- setsid();
- execvp(((char **)arg->v)[0], (char **)arg->v);
- fprintf(stderr, "surf: execvp %s", ((char **)arg->v)[0]);
- perror(" failed");
- exit(0);
- }
+ if (a->i < 0)
+ webkit_web_view_go_back(c->view);
+ else if (a->i > 0)
+ webkit_web_view_go_forward(c->view);
}
void
t@@ -1284,35 +1329,6 @@ stop(Client *c, const Arg *arg)
}
void
-titlechanged(WebKitWebView *view, GParamSpec *ps, Client *c)
-{
- c->title = webkit_web_view_get_title(c->view);
- updatetitle(c);
-}
-
-gboolean
-winevent(GtkWidget *w, GdkEvent *e, Client *c)
-{
- switch (e->type) {
- case GDK_LEAVE_NOTIFY:
- c->targeturi = NULL;
- updatetitle(c);
- break;
- case GDK_WINDOW_STATE: /* fallthrough */
- if (e->window_state.changed_mask ==
- GDK_WINDOW_STATE_FULLSCREEN) {
- c->fullscreen = e->window_state.new_window_state &
- GDK_WINDOW_STATE_FULLSCREEN;
- break;
- }
- default:
- return FALSE;
- }
-
- return TRUE;
-}
-
-void
toggle(Client *c, const Arg *a)
{
WebKitSettings *s;
t@@ -1363,6 +1379,16 @@ toggle(Client *c, const Arg *a)
}
void
+togglefullscreen(Client *c, const Arg *a)
+{
+ /* toggling value is handled in winevent() */
+ if (c->fullscreen)
+ gtk_window_unfullscreen(GTK_WINDOW(c->win));
+ else
+ gtk_window_fullscreen(GTK_WINDOW(c->win));
+}
+
+void
togglecookiepolicy(Client *c, const Arg *arg)
{
++cookiepolicy;
t@@ -1387,80 +1413,53 @@ togglestyle(Client *c, const Arg *arg)
}
void
-gettogglestats(Client *c)
+toggleinspector(Client *c, const Arg *a)
{
- togglestats[0] = cookiepolicy_set(cookiepolicy_get());
- togglestats[1] = enablecaretbrowsing ? 'C' : 'c';
- togglestats[2] = allowgeolocation ? 'G' : 'g';
- togglestats[3] = enablecache ? 'D' : 'd';
- togglestats[4] = loadimages ? 'I' : 'i';
- togglestats[5] = enablescripts ? 'S': 's';
- togglestats[6] = enableplugins ? 'V' : 'v';
- togglestats[7] = enablestyle ? 'M' : 'm';
- togglestats[8] = enableframeflattening ? 'F' : 'f';
- togglestats[9] = '\0';
+ if (enableinspector) {
+ if (webkit_web_inspector_is_attached(c->inspector))
+ webkit_web_inspector_close(c->inspector);
+ else
+ webkit_web_inspector_show(c->inspector);
+ }
}
void
-getpagestats(Client *c)
+find(Client *c, const Arg *a)
{
- pagestats[0] = c->tlsflags > G_TLS_CERTIFICATE_VALIDATE_ALL ? '-' :
- c->tlsflags > 0 ? 'U' : 'T';
- pagestats[1] = '\0';
-}
+ const char *s, *f;
-void
-updatetitle(Client *c)
-{
- char *title;
+ if (a && a->i) {
+ if (a->i > 0)
+ webkit_find_controller_search_next(c->finder);
+ else
+ webkit_find_controller_search_previous(c->finder);
+ } else {
+ s = getatom(c, AtomFind);
+ f = webkit_find_controller_get_search_text(c->finder);
- if (showindicators) {
- gettogglestats(c);
- getpagestats(c);
+ if (g_strcmp0(f, s) == 0) /* reset search */
+ webkit_find_controller_search(c->finder, "", findopts,…
- if (c->progress != 100) {
- title = g_strdup_printf("[%i%%] %s:%s | %s",
- c->progress, togglestats, pagestats,
- c->targeturi ? c->targeturi : c->title);
- } else {
- title = g_strdup_printf("%s:%s | %s",
- togglestats, pagestats,
- c->targeturi ? c->targeturi : c->title);
- }
+ webkit_find_controller_search(c->finder, s, findopts, G_MAXUIN…
- gtk_window_set_title(GTK_WINDOW(c->win), title);
- g_free(title);
- } else {
- gtk_window_set_title(GTK_WINDOW(c->win), c->title ?
- c->title : "");
+ if (strcmp(s, "") == 0)
+ webkit_find_controller_search_finish(c->finder);
}
}
void
-updatewinid(Client *c)
-{
- snprintf(winid, LENGTH(winid), "%lu", c->xid);
-}
-
-void
-usage(void)
+clicknavigate(Client *c, const Arg *a, WebKitHitTestResult *h)
{
- die("usage: %s [-bBdDfFgGiIkKmMnNpPsSvx] [-a cookiepolicies ] "
- "[-c cookiefile] [-e xid] [-r scriptfile] [-t stylefile] "
- "[-u useragent] [-z zoomlevel] [uri]\n", basename(argv0));
+ navigate(c, a);
}
void
-zoom(Client *c, const Arg *a)
+clicknewwindow(Client *c, const Arg *a, WebKitHitTestResult *h)
{
- if (a->i > 0)
- webkit_web_view_set_zoom_level(c->view, zoomlevel + 0.1);
- else if (a->i < 0)
- webkit_web_view_set_zoom_level(c->view, zoomlevel - 0.1);
- else
- webkit_web_view_set_zoom_level(c->view, 1.0);
+ Arg arg;
- zoomlevel = webkit_web_view_get_zoom_level(c->view);
+ arg.v = webkit_hit_test_result_get_link_uri(h);
+ newwindow(c, &arg, a->b);
}
int
t@@ -1579,4 +1578,3 @@ main(int argc, char *argv[])
return EXIT_SUCCESS;
}
-
You are viewing proxied material from mx1.adamsgaard.dk. 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.