#include <glib/gstdio.h>
#include <JavaScriptCore/JavaScript.h>
#include <sys/file.h>
+#include <libgen.h>
+#include <stdarg.h>
#include "arg.h"
char *argv0;
#define LENGTH(x) (sizeof x / sizeof x[0])
+#define CLEANMASK(mask) (mask & (MODKEY|GDK_SHIFT_MASK))
#define COOKIEJAR_TYPE (cookiejar_get_type ())
#define COOKIEJAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), COOKIEJAR_TYPE, CookieJar))
};
typedef struct Client {
- GtkWidget *win, *scroll, *vbox, *indicator;
+ GtkWidget *win, *scroll, *vbox, *indicator, *pane;
WebKitWebView *view;
+ WebKitWebInspector *inspector;
char *title, *linkhover;
const char *uri, *needle;
gint progress;
- gboolean sslfailed;
struct Client *next;
- gboolean zoomed, fullscreen;
+ gboolean zoomed, fullscreen, isinspecting, sslfailed;
} Client;
typedef struct {
static GdkNativeWindow embed = 0;
static gboolean showxid = FALSE;
static char winid[64];
-static gboolean loadimages = 1, enableplugins = 1, enablescripts = 1,
- usingproxy = 0;
+static gboolean usingproxy = 0;
static char togglestat[5];
static void beforerequest(WebKitWebView *w, WebKitWebFrame *f,
GList *gl);
static void cleanup(void);
static void clipboard(Client *c, const Arg *arg);
+
static void cookiejar_changed(SoupCookieJar *self, SoupCookie *old_cookie,
SoupCookie *new_cookie);
static void cookiejar_finalize(GObject *self);
static SoupCookieJar *cookiejar_new(const char *filename, gboolean read_only);
static void cookiejar_set_property(GObject *self, guint prop_id,
const GValue *value, GParamSpec *pspec);
+
static char *copystr(char **str, const char *src);
static WebKitWebView *createwindow(WebKitWebView *v, WebKitWebFrame *f,
Client *c);
WebKitWebPolicyDecision *p, Client *c);
static void destroyclient(Client *c);
static void destroywin(GtkWidget* w, Client *c);
-static void die(char *str);
+static void die(const char *errstr, ...);
static void drawindicator(Client *c);
+static void eval(Client *c, const Arg *arg);
static gboolean exposeindicator(GtkWidget *w, GdkEventExpose *e, Client *c);
static void find(Client *c, const Arg *arg);
static void fullscreen(Client *c, const Arg *arg);
static const char *getatom(Client *c, int a);
+static void gettogglestat(Client *c);
static char *geturi(Client *c);
static gboolean initdownload(WebKitWebView *v, WebKitDownload *o, Client *c);
+
+static void inspector(Client *c, const Arg *arg);
+static WebKitWebView *inspector_new(WebKitWebInspector *i, WebKitWebView *v,
+ Client *c);
+static gboolean inspector_show(WebKitWebInspector *i, Client *c);
+static gboolean inspector_close(WebKitWebInspector *i, Client *c);
+static void inspector_finished(WebKitWebInspector *i, Client *c);
+
static gboolean keypress(GtkWidget *w, GdkEventKey *ev, Client *c);
static void linkhover(WebKitWebView *v, const char* t, const char* l,
Client *c);
static void sigchld(int unused);
static void source(Client *c, const Arg *arg);
static void spawn(Client *c, const Arg *arg);
-static void eval(Client *c, const Arg *arg);
static void stop(Client *c, const Arg *arg);
static void titlechange(WebKitWebView *v, WebKitWebFrame *frame,
const char *title, Client *c);
static void toggle(Client *c, const Arg *arg);
-static void gettogglestat(Client *c);
static void update(Client *c);
static void updatewinid(Client *c);
static void usage(void);
}
static void
-die(char *str) {
- fputs(str, stderr);
+die(const char *errstr, ...) {
+ va_list ap;
+
+ va_start(ap, errstr);
+ vfprintf(stderr, errstr, ap);
+ va_end(ap);
exit(EXIT_FAILURE);
}
return FALSE;
}
+static void
+inspector(Client *c, const Arg *arg) {
+ if(c->isinspecting) {
+ webkit_web_inspector_close(c->inspector);
+ } else {
+ webkit_web_inspector_show(c->inspector);
+ }
+}
+
+static WebKitWebView *
+inspector_new(WebKitWebInspector *i, WebKitWebView *v, Client *c) {
+ return WEBKIT_WEB_VIEW(webkit_web_view_new());
+}
+
+static gboolean
+inspector_show(WebKitWebInspector *i, Client *c) {
+ WebKitWebView *w;
+
+ if(c->isinspecting)
+ return false;
+
+ w = webkit_web_inspector_get_web_view(i);
+ gtk_paned_pack2(GTK_PANED(c->pane), GTK_WIDGET(w), TRUE, TRUE);
+ gtk_widget_show(GTK_WIDGET(w));
+ c->isinspecting = true;
+
+ return true;
+}
+
+static gboolean
+inspector_close(WebKitWebInspector *i, Client *c) {
+ GtkWidget *w;
+
+ if(!c->isinspecting)
+ return false;
+
+ w = GTK_WIDGET(webkit_web_inspector_get_web_view(i));
+ gtk_widget_hide(w);
+ gtk_widget_destroy(w);
+ c->isinspecting = false;
+
+ return true;
+}
+
+static void
+inspector_finished(WebKitWebInspector *i, Client *c) {
+ g_free(c->inspector);
+}
+
static gboolean
keypress(GtkWidget* w, GdkEventKey *ev, Client *c) {
guint i;
updatewinid(c);
for(i = 0; i < LENGTH(keys); i++) {
if(gdk_keyval_to_lower(ev->keyval) == keys[i].keyval
- && (ev->state & keys[i].mod) == keys[i].mod
+ && CLEANMASK(ev->state) == keys[i].mod
&& keys[i].func) {
keys[i].func(c, &(keys[i].arg));
processed = TRUE;
"key-press-event",
G_CALLBACK(keypress), c);
+ /* Pane */
+ c->pane = gtk_vpaned_new();
+
/* VBox */
c->vbox = gtk_vbox_new(FALSE, 0);
+ gtk_paned_pack1(GTK_PANED(c->pane), c->vbox, TRUE, TRUE);
/* Scrolled Window */
c->scroll = gtk_scrolled_window_new(NULL, NULL);
/* Arranging */
gtk_container_add(GTK_CONTAINER(c->scroll), GTK_WIDGET(c->view));
- gtk_container_add(GTK_CONTAINER(c->win), c->vbox);
+ gtk_container_add(GTK_CONTAINER(c->win), c->pane);
gtk_container_add(GTK_CONTAINER(c->vbox), c->scroll);
gtk_container_add(GTK_CONTAINER(c->vbox), c->indicator);
gtk_box_set_child_packing(GTK_BOX(c->vbox), c->scroll, TRUE,
TRUE, 0, GTK_PACK_START);
gtk_widget_grab_focus(GTK_WIDGET(c->view));
+ gtk_widget_show(c->pane);
gtk_widget_show(c->vbox);
gtk_widget_show(c->scroll);
gtk_widget_show(GTK_WIDGET(c->view));
g_object_set(G_OBJECT(settings), "user-agent", ua, NULL);
uri = g_strconcat("file://", stylefile, NULL);
g_object_set(G_OBJECT(settings), "user-stylesheet-uri", uri, NULL);
- g_object_set(G_OBJECT(settings), "auto-load-images", loadimages, NULL);
- g_object_set(G_OBJECT(settings), "enable-plugins", enableplugins, NULL);
- g_object_set(G_OBJECT(settings), "enable-scripts", enablescripts, NULL);
+ g_object_set(G_OBJECT(settings), "auto-load-images", loadimages,
+ NULL);
+ g_object_set(G_OBJECT(settings), "enable-plugins", enableplugins,
+ NULL);
+ g_object_set(G_OBJECT(settings), "enable-scripts", enablescripts,
+ NULL);
g_object_set(G_OBJECT(settings), "enable-spatial-navigation",
- spatialbrowsing, NULL);
+ enablespatialbrowsing, NULL);
+ g_object_set(G_OBJECT(settings), "enable-developer-extras",
+ enableinspector, NULL);
+
+ if(enableinspector) {
+ c->inspector = WEBKIT_WEB_INSPECTOR(
+ webkit_web_view_get_inspector(c->view));
+ g_signal_connect(G_OBJECT(c->inspector), "inspect-web-view",
+ G_CALLBACK(inspector_new), c);
+ g_signal_connect(G_OBJECT(c->inspector), "show-window",
+ G_CALLBACK(inspector_show), c);
+ g_signal_connect(G_OBJECT(c->inspector), "close-window",
+ G_CALLBACK(inspector_close), c);
+ g_signal_connect(G_OBJECT(c->inspector), "finished",
+ G_CALLBACK(inspector_finished), c);
+ c->isinspecting = false;
+ }
g_free(uri);
c->title = NULL;
c->next = clients;
clients = c;
+
if(showxid) {
gdk_display_sync(gtk_widget_get_display(c->win));
printf("%u\n",
die("Error closing stdout");
}
}
+
return c;
}
/* clean up any zombies immediately */
sigchld(0);
gtk_init(NULL, NULL);
- if (!g_thread_supported())
- g_thread_init(NULL);
dpy = GDK_DISPLAY();
static void
usage(void) {
- fputs("surf - simple browser\n", stderr);
- die("usage: surf [-c cookiefile] [-e xid] [-i] [-p] [-r scriptfile]"
- " [-s] [-t stylefile] [-u useragent] [-v] [-x] [uri]\n");
+ die("usage: %s [-inpsvx] [-c cookiefile] [-e xid] [-r scriptfile]"
+ " [-t stylefile] [-u useragent] [uri]\n", basename(argv0));
}
static void
case 'i':
loadimages = 0;
break;
+ case 'n':
+ enableinspector = 0;
+ break;
case 'p':
enableplugins = 0;
break;
case 'u':
useragent = EARGF(usage());
break;
+ case 'v':
+ die("surf-"VERSION", ©2009-2012 surf engineers, "
+ "see LICENSE for details\n");
case 'x':
showxid = TRUE;
break;
- case 'v':
- die("surf-"VERSION", ©2009-2012 surf engineers, see LICENSE for details\n");
default:
usage();
} ARGEND;