]> git.armaanb.net Git - chorizo.git/blob - sn.c
Support XEMBED
[chorizo.git] / sn.c
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include <gtk/gtk.h>
5 #include <gtk/gtkx.h>
6 #include <webkit/webkit.h>
7
8
9 #define DOWNLOAD_DIR "/tmp/tmp"
10
11
12 static void sn_destroy_client(GtkWidget *, gpointer);
13 static gboolean sn_do_download(WebKitWebView *, WebKitDownload *, gpointer);
14 static gboolean sn_download_request(WebKitWebView *, WebKitWebFrame *,
15                                     WebKitNetworkRequest *, gchar *,
16                                     WebKitWebPolicyDecision *, gpointer);
17 static void sn_new_client(const gchar *uri);
18 static gboolean sn_new_client_request(WebKitWebView *, WebKitWebFrame *,
19                                       WebKitNetworkRequest *,
20                                       WebKitWebNavigationAction *,
21                                       WebKitWebPolicyDecision *, gpointer);
22 static void sn_title_changed(GObject *, GParamSpec *, gpointer);
23
24
25 static Window embed = 0;
26 static int clients = 0;
27 static double global_zoom = 1.0;
28
29
30 struct Client
31 {
32         GtkWidget *win;
33         GtkWidget *scroll;
34         GtkWidget *web_view;
35 };
36
37
38 void
39 sn_destroy_client(GtkWidget *obj, gpointer data)
40 {
41         struct Client *c = (struct Client *)data;
42
43         (void)obj;
44
45         webkit_web_view_stop_loading(WEBKIT_WEB_VIEW(c->web_view));
46         gtk_widget_destroy(c->web_view);
47         gtk_widget_destroy(c->scroll);
48         gtk_widget_destroy(c->win);
49         free(c);
50
51         clients--;
52         if (clients == 0)
53                 gtk_main_quit();
54 }
55
56 gboolean
57 sn_do_download(WebKitWebView *web_view, WebKitDownload *download, gpointer data)
58 {
59         const gchar *uri;
60
61         (void)web_view;
62         (void)data;
63
64         uri = webkit_download_get_uri(download);
65         if (fork() == 0)
66         {
67                 chdir(DOWNLOAD_DIR);
68                 if (execlp("xterm", "xterm", "-hold", "-e", "wget", uri, NULL) == -1)
69                 {
70                         fprintf(stderr, "sn: exec'ing xterm for download");
71                         perror(" failed");
72                         exit(EXIT_FAILURE);
73                 }
74         }
75
76         return FALSE;
77 }
78
79 gboolean
80 sn_download_request(WebKitWebView *web_view, WebKitWebFrame *frame,
81                     WebKitNetworkRequest *request, gchar *mime_type,
82                     WebKitWebPolicyDecision *policy_decision,
83                     gpointer data)
84 {
85         (void)frame;
86         (void)request;
87         (void)data;
88
89         if (!webkit_web_view_can_show_mime_type(web_view, mime_type))
90         {
91                 webkit_web_policy_decision_download(policy_decision);
92                 return TRUE;
93         }
94         return FALSE;
95 }
96
97 void
98 sn_new_client(const gchar *uri)
99 {
100         struct Client *c = malloc(sizeof(struct Client));
101         if (!c)
102         {
103                 fprintf(stderr, "sn: fatal: malloc failed\n");
104                 exit(EXIT_FAILURE);
105         }
106
107         if (embed == 0)
108         {
109                 c->win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
110         }
111         else
112         {
113                 c->win = gtk_plug_new(embed);
114         }
115
116         g_signal_connect(G_OBJECT(c->win), "destroy", G_CALLBACK(sn_destroy_client),
117                          c);
118         gtk_window_set_has_resize_grip(GTK_WINDOW(c->win), FALSE);
119         gtk_window_set_title(GTK_WINDOW(c->win), "sn");
120
121         c->web_view = webkit_web_view_new();
122         webkit_web_view_set_full_content_zoom(WEBKIT_WEB_VIEW(c->web_view), TRUE);
123         webkit_web_view_set_zoom_level(WEBKIT_WEB_VIEW(c->web_view), global_zoom);
124         g_signal_connect(G_OBJECT(c->web_view), "notify::title",
125                          G_CALLBACK(sn_title_changed), c->win);
126         g_signal_connect(G_OBJECT(c->web_view),
127                          "new-window-policy-decision-requested",
128                          G_CALLBACK(sn_new_client_request), NULL);
129         g_signal_connect(G_OBJECT(c->web_view), "mime-type-policy-decision-requested",
130                          G_CALLBACK(sn_download_request), NULL);
131         g_signal_connect(G_OBJECT(c->web_view), "download-requested",
132                          G_CALLBACK(sn_do_download), NULL);
133
134         c->scroll = gtk_scrolled_window_new(NULL, NULL);
135
136         gtk_container_add(GTK_CONTAINER(c->scroll), c->web_view);
137         gtk_container_add(GTK_CONTAINER(c->win), c->scroll);
138
139         gtk_widget_show_all(c->win);
140
141         webkit_web_view_load_uri(WEBKIT_WEB_VIEW(c->web_view), uri);
142
143         clients++;
144 }
145
146 gboolean
147 sn_new_client_request(WebKitWebView *web_view, WebKitWebFrame *frame,
148                       WebKitNetworkRequest *request,
149                       WebKitWebNavigationAction *navigation_action,
150                       WebKitWebPolicyDecision *policy_decision,
151                       gpointer user_data)
152 {
153         (void)web_view;
154         (void)frame;
155         (void)navigation_action;
156         (void)user_data;
157
158         webkit_web_policy_decision_ignore(policy_decision);
159         sn_new_client(webkit_network_request_get_uri(request));
160
161         return TRUE;
162 }
163
164 void
165 sn_title_changed(GObject *obj, GParamSpec *pspec, gpointer data)
166 {
167         const gchar *t;
168         WebKitWebView *view = WEBKIT_WEB_VIEW(obj);
169         GtkWindow *win = GTK_WINDOW(data);
170
171         (void)pspec;
172
173         t = webkit_web_view_get_title(view);
174         gtk_window_set_title(win, (t == NULL ? "sn" : t));
175 }
176
177 int
178 main(int argc, char **argv)
179 {
180         int opt;
181
182         gtk_init(&argc, &argv);
183
184         while ((opt = getopt(argc, argv, "z:e:")) != -1)
185         {
186                 switch (opt)
187                 {
188                         case 'z':
189                                 global_zoom = atof(optarg);
190                                 break;
191                         case 'e':
192                                 embed = atol(optarg);
193                                 break;
194                 }
195         }
196
197         if (optind >= argc)
198         {
199                 fprintf(stderr, "Usage: sn [OPTIONS] <URI>\n");
200                 exit(EXIT_FAILURE);
201         }
202
203         sn_new_client(argv[optind]);
204         gtk_main();
205         exit(EXIT_SUCCESS);
206 }