X-Git-Url: https://git.danieliu.xyz/?a=blobdiff_plain;f=surf.c;h=b2e7f20e1abaa02ba45e094bcdc3156cd01f157e;hb=54df4608668bb5d71ba9e89ba46995bbf5ac6602;hp=3ac76650e82ed1ea9c3b3cf002b8accd7bbe597b;hpb=168da3730fcaabf56f9cb7508cbff1699e5b33b1;p=surf.git diff --git a/surf.c b/surf.c index 3ac7665..b2e7f20 100644 --- a/surf.c +++ b/surf.c @@ -23,6 +23,8 @@ #define LENGTH(x) (sizeof x / sizeof x[0]) #define CLEANMASK(mask) (mask & ~(GDK_MOD2_MASK)) +enum { AtomFind, AtomGo, AtomUri, AtomLast }; + typedef union Arg Arg; union Arg { gboolean b; @@ -32,9 +34,7 @@ union Arg { typedef struct Client { GtkWidget *win, *scroll, *vbox, *indicator; - GtkWidget **items; WebKitWebView *view; - WebKitDownload *download; char *title, *linkhover; const char *uri, *needle; gint progress; @@ -56,11 +56,10 @@ typedef struct { } Key; static Display *dpy; -static Atom uriprop, findprop; +static Atom atoms[AtomLast]; static Client *clients = NULL; static GdkNativeWindow embed = 0; static gboolean showxid = FALSE; -static int ignorexprop = 0; static char winid[64]; static char *progname; static gboolean loadimage = 1, plugin = 1, script = 1; @@ -68,7 +67,6 @@ static gboolean loadimage = 1, plugin = 1, script = 1; static char *buildpath(const char *path); static void cleanup(void); static void clipboard(Client *c, const Arg *arg); -static void context(WebKitWebView *v, GtkMenu *m, Client *c); static char *copystr(char **str, const char *src); static WebKitWebView *createwindow(WebKitWebView *v, WebKitWebFrame *f, Client *c); static gboolean decidedownload(WebKitWebView *v, WebKitWebFrame *f, WebKitNetworkRequest *r, gchar *m, WebKitWebPolicyDecision *p, Client *c); @@ -76,16 +74,14 @@ static gboolean decidewindow(WebKitWebView *v, WebKitWebFrame *f, WebKitNetworkR static void destroyclient(Client *c); static void destroywin(GtkWidget* w, Client *c); static void die(char *str); -static void download(Client *c, const Arg *arg); static void drawindicator(Client *c); static gboolean exposeindicator(GtkWidget *w, GdkEventExpose *e, Client *c); static void find(Client *c, const Arg *arg); -static const char *getatom(Client *c, Atom a); +static const char *getatom(Client *c, int a); static const char *getcookies(SoupURI *uri); static char *geturi(Client *c); void gotheaders(SoupMessage *msg, gpointer user_data); static gboolean initdownload(WebKitWebView *v, WebKitDownload *o, Client *c); -static void itemclick(GtkMenuItem *mi, 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 loadstatuschange(WebKitWebView *view, GParamSpec *pspec, Client *c); @@ -101,7 +97,7 @@ static void progresschange(WebKitWebView *view, GParamSpec *pspec, Client *c); static void reload(Client *c, const Arg *arg); static void resize(GtkWidget *w, GtkAllocation *a, Client *c); static void scroll(Client *c, const Arg *arg); -static void setatom(Client *c, Atom a, const char *v); +static void setatom(Client *c, int a, const char *v); static void setcookie(SoupCookie *c); static void setup(void); static void sigchld(int unused); @@ -110,7 +106,6 @@ static void spawn(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 update(Client *c); -static void updatedownload(WebKitDownload *o, GParamSpec *pspec, Client *c); static void updatewinid(Client *c); static void usage(void); static void windowobjectcleared(GtkWidget *w, WebKitWebFrame *frame, JSContextRef js, JSObjectRef win, Client *c); @@ -135,7 +130,7 @@ buildpath(const char *path) { *p = '/'; } /* creating file (gives error when apath ends with "/") */ - if((f = g_fopen(apath, "a"))) + if((f = fopen(apath, "a"))) fclose(f); return apath; } @@ -145,7 +140,6 @@ cleanup(void) { while(clients) destroyclient(clients); g_free(cookiefile); - g_free(dldir); g_free(scriptfile); g_free(stylefile); } @@ -173,22 +167,6 @@ clipboard(Client *c, const Arg *arg) { gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), c->linkhover ? c->linkhover : geturi(c), -1); } -void -context(WebKitWebView *v, GtkMenu *m, Client *c) { - int i; - GtkContainer *parent; - - gtk_widget_hide_all(GTK_WIDGET(m)); - gtk_widget_show(GTK_WIDGET(m)); - for(i = 0; i < LENGTH(items); i++) { - parent = GTK_CONTAINER(gtk_widget_get_parent(c->items[i])); - if(parent) - gtk_container_remove(parent, c->items[i]); - gtk_menu_shell_append(GTK_MENU_SHELL(m), c->items[i]); - gtk_widget_show(c->items[i]); - } -} - char * copystr(char **str, const char *src) { char *tmp; @@ -231,7 +209,6 @@ decidewindow(WebKitWebView *view, WebKitWebFrame *f, WebKitNetworkRequest *r, We void destroyclient(Client *c) { - int i; Client *p; gtk_widget_destroy(c->indicator); @@ -239,9 +216,6 @@ destroyclient(Client *c) { gtk_widget_destroy(c->scroll); gtk_widget_destroy(c->vbox); gtk_widget_destroy(c->win); - for(i = 0; i < LENGTH(items); i++) - gtk_widget_destroy(c->items[i]); - free(c->items); for(p = clients; p && p->next != c; p = p->next); if(p) @@ -264,22 +238,6 @@ die(char *str) { exit(EXIT_FAILURE); } -void -download(Client *c, const Arg *arg) { - char *uri; - WebKitNetworkRequest *r; - WebKitDownload *dl; - - if(arg->v) - uri = (char *)arg->v; - else - uri = c->linkhover ? c->linkhover : geturi(c); - r = webkit_network_request_new(uri); - dl = webkit_download_new(r); - initdownload(c->view, dl, c); - webkit_download_start(c->download); -} - void drawindicator(Client *c) { gint width; @@ -288,7 +246,7 @@ drawindicator(Client *c) { GdkGC *gc; GdkColor fg; - uri = getatom(c, uriprop); + uri = geturi(c); w = c->indicator; width = c->progress * w->allocation.width / 100; gc = gdk_gc_new(w->window); @@ -313,7 +271,7 @@ void find(Client *c, const Arg *arg) { const char *s; - s = getatom(c, findprop); + s = getatom(c, AtomFind); gboolean forward = *(gboolean *)arg; webkit_web_view_search_text(c->view, s, FALSE, forward, TRUE); } @@ -328,7 +286,7 @@ getcookies(SoupURI *uri) { } const char * -getatom(Client *c, Atom a) { +getatom(Client *c, int a) { static char buf[BUFSIZ]; Atom adummy; int idummy; @@ -336,7 +294,7 @@ getatom(Client *c, Atom a) { unsigned char *p = NULL; XGetWindowProperty(dpy, GDK_WINDOW_XID(GTK_WIDGET(c->win)->window), - a, 0L, BUFSIZ, False, XA_STRING, + atoms[a], 0L, BUFSIZ, False, XA_STRING, &adummy, &idummy, &ldummy, &ldummy, &p); if(p) strncpy(buf, (char *)p, LENGTH(buf)-1); @@ -370,38 +328,12 @@ gotheaders(SoupMessage *msg, gpointer v) { gboolean initdownload(WebKitWebView *view, WebKitDownload *o, Client *c) { - const char *filename; - char *uri; - WebKitWebBackForwardList *h; - WebKitWebHistoryItem *i; - - c->download = o; - filename = webkit_download_get_suggested_filename(o); - if(!strcmp("", filename)) - filename = "index.html"; - uri = g_strconcat("file://", dldir, "/", filename, NULL); - webkit_download_set_destination_uri(c->download, uri); - c->progress = 0; - h = webkit_web_view_get_back_forward_list(c->view); - i = webkit_web_history_item_new_with_data(webkit_download_get_uri(c->download), filename); - webkit_web_back_forward_list_add_item(h, i); - g_signal_connect(c->download, "notify::progress", G_CALLBACK(updatedownload), c); - g_signal_connect(c->download, "notify::status", G_CALLBACK(updatedownload), c); - - c->title = copystr(&c->title, filename); - update(c); - return TRUE; -} - -void -itemclick(GtkMenuItem *mi, Client *c) { - int i; - const char *label; + Arg arg; - label = gtk_menu_item_get_label(mi); - for(i = 0; i < LENGTH(items); i++) - if(!strcmp(items[i].label, label)) - items[i].func(c, &(items[i].arg)); + updatewinid(c); + arg = (Arg)DOWNLOAD((char *)webkit_download_get_uri(o)); + spawn(c, &arg); + return FALSE; } gboolean @@ -423,8 +355,9 @@ keypress(GtkWidget* w, GdkEventKey *ev, Client *c) { void linkhover(WebKitWebView *v, const char* t, const char* l, Client *c) { - if(l) + if(l) { c->linkhover = copystr(&c->linkhover, l); + } else if(c->linkhover) { free(c->linkhover); c->linkhover = NULL; @@ -434,11 +367,9 @@ linkhover(WebKitWebView *v, const char* t, const char* l, Client *c) { void loadstatuschange(WebKitWebView *view, GParamSpec *pspec, Client *c) { - if(c->download) - stop(c, NULL); switch(webkit_web_view_get_load_status (c->view)) { case WEBKIT_LOAD_COMMITTED: - setatom(c, uriprop, geturi(c)); + setatom(c, AtomUri, geturi(c)); break; case WEBKIT_LOAD_FINISHED: c->progress = 0; @@ -480,7 +411,6 @@ navigate(Client *c, const Arg *arg) { Client * newclient(void) { - int i; Client *c; WebKitWebSettings *settings; WebKitWebFrame *frame; @@ -514,16 +444,6 @@ newclient(void) { g_signal_connect(G_OBJECT(c->win), "key-press-event", G_CALLBACK(keypress), c); g_signal_connect(G_OBJECT(c->win), "size-allocate", G_CALLBACK(resize), c); - if(!(c->items = calloc(1, sizeof(GtkWidget *) * LENGTH(items)))) - die("Cannot malloc!\n"); - - /* contextmenu */ - for(i = 0; i < LENGTH(items); i++) { - c->items[i] = gtk_menu_item_new_with_label(items[i].label); - g_signal_connect(G_OBJECT(c->items[i]), "activate", - G_CALLBACK(itemclick), c); - } - /* VBox */ c->vbox = gtk_vbox_new(FALSE, 0); @@ -539,11 +459,10 @@ newclient(void) { g_signal_connect(G_OBJECT(c->view), "create-web-view", G_CALLBACK(createwindow), c); g_signal_connect(G_OBJECT(c->view), "new-window-policy-decision-requested", G_CALLBACK(decidewindow), c); g_signal_connect(G_OBJECT(c->view), "mime-type-policy-decision-requested", G_CALLBACK(decidedownload), c); - g_signal_connect(G_OBJECT(c->view), "download-requested", G_CALLBACK(initdownload), c); g_signal_connect(G_OBJECT(c->view), "window-object-cleared", G_CALLBACK(windowobjectcleared), c); - g_signal_connect(G_OBJECT(c->view), "populate-popup", G_CALLBACK(context), c); g_signal_connect(G_OBJECT(c->view), "notify::load-status", G_CALLBACK(loadstatuschange), c); g_signal_connect(G_OBJECT(c->view), "notify::progress", G_CALLBACK(progresschange), c); + g_signal_connect(G_OBJECT(c->view), "download-requested", G_CALLBACK(initdownload), c); /* Indicator */ c->indicator = gtk_drawing_area_new(); @@ -581,11 +500,15 @@ newclient(void) { g_object_set(G_OBJECT(settings), "auto-load-images", loadimage, NULL); g_object_set(G_OBJECT(settings), "enable-plugins", plugin, NULL); g_object_set(G_OBJECT(settings), "enable-scripts", script, NULL); + g_object_set(G_OBJECT(settings), "enable-spatial-navigation", true, NULL); + g_free(uri); - setatom(c, findprop, ""); - setatom(c, uriprop, ""); - c->download = NULL; + setatom(c, AtomFind, ""); + setatom(c, AtomUri, "about:blank"); + if(NOBACKGROUND) + webkit_web_view_set_transparent(c->view, TRUE); + c->title = NULL; c->next = clients; clients = c; @@ -605,9 +528,8 @@ newrequest(SoupSession *s, SoupMessage *msg, gpointer v) { soup_message_headers_remove(h, "Cookie"); uri = soup_message_get_uri(msg); - if((c = getcookies(uri))) { + if((c = getcookies(uri))) soup_message_headers_append(h, "Cookie", c); - } g_signal_connect_after(G_OBJECT(msg), "got-headers", G_CALLBACK(gotheaders), NULL); } @@ -660,18 +582,17 @@ processx(GdkXEvent *e, GdkEvent *event, gpointer d) { if(((XEvent *)e)->type == PropertyNotify) { ev = &((XEvent *)e)->xproperty; - if(ignorexprop) - ignorexprop--; - else if(ev->state == PropertyNewValue) { - if(ev->atom == uriprop) { - arg.v = getatom(c, uriprop); - loaduri(c, &arg); - } - else if(ev->atom == findprop) { + if(ev->state == PropertyNewValue) { + if(ev->atom == atoms[AtomFind]) { arg.b = TRUE; find(c, &arg); + 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_REMOVE; } } return GDK_FILTER_CONTINUE; @@ -727,7 +648,7 @@ setcookie(SoupCookie *c) { SoupDate *e; SoupCookieJar *j = soup_cookie_jar_text_new(cookiefile, FALSE); c = soup_cookie_copy(c); - if(c->expires == NULL) { + if(c->expires == NULL && sessiontime) { e = soup_date_new_from_time_t(time(NULL) + sessiontime); soup_cookie_set_expires(c, e); } @@ -738,10 +659,9 @@ setcookie(SoupCookie *c) { } void -setatom(Client *c, Atom a, const char *v) { +setatom(Client *c, int a, const char *v) { XSync(dpy, False); - ignorexprop++; - XChangeProperty(dpy, GDK_WINDOW_XID(GTK_WIDGET(c->win)->window), a, + XChangeProperty(dpy, GDK_WINDOW_XID(GTK_WIDGET(c->win)->window), atoms[a], XA_STRING, 8, PropModeReplace, (unsigned char *)v, strlen(v) + 1); } @@ -761,12 +681,14 @@ setup(void) { dpy = GDK_DISPLAY(); s = webkit_get_default_session(); - uriprop = XInternAtom(dpy, "_SURF_URI", False); - findprop = XInternAtom(dpy, "_SURF_FIND", False); + + /* 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 = buildpath(cookiefile); - dldir = buildpath(dldir); scriptfile = buildpath(scriptfile); stylefile = buildpath(stylefile); @@ -776,12 +698,10 @@ setup(void) { soup_session_remove_feature_by_type(s, soup_cookie_jar_get_type()); g_signal_connect_after(G_OBJECT(s), "request-started", G_CALLBACK(newrequest), NULL); - /* proxy */ if((proxy = getenv("http_proxy")) && strcmp(proxy, "")) { new_proxy = g_strrstr(proxy, "http://") ? g_strdup(proxy) : g_strdup_printf("http://%s", proxy); - puri = soup_uri_new(new_proxy); g_object_set(G_OBJECT(s), "proxy-uri", puri, NULL); soup_uri_free(puri); @@ -821,11 +741,7 @@ spawn(Client *c, const Arg *arg) { void stop(Client *c, const Arg *arg) { - if(c->download) - webkit_download_cancel(c->download); - else - webkit_web_view_stop_loading(c->view); - c->download = NULL; + webkit_web_view_stop_loading(c->view); } void @@ -849,19 +765,6 @@ update(Client *c) { g_free(t); } -void -updatedownload(WebKitDownload *o, GParamSpec *pspec, Client *c) { - WebKitDownloadStatus status; - - status = webkit_download_get_status(c->download); - if(status == WEBKIT_DOWNLOAD_STATUS_STARTED || status == WEBKIT_DOWNLOAD_STATUS_CREATED) { - c->progress = (gint)(webkit_download_get_progress(c->download)*100); - } - else - stop(c, NULL); - update(c); -} - void updatewinid(Client *c) { snprintf(winid, LENGTH(winid), "%u",