2 * TazWeb is a radically simple web browser providing a single window
3 * with a single toolbar with buttons, an URL entry and search as well
4 * as a contextual menu, but no menu bar or tabs. Commented line code
5 * starts with // and comments are between * *
7 * Copyright (C) 2011 SliTaz GNU/Linux - BSD License
8 * See AUTHORS and LICENSE for detailed information
13 #include <webkit/webkit.h>
15 #define CONFIG g_strdup_printf("%s/.config/tazweb", g_get_home_dir())
16 #define START "http://www.bing.com"
17 #define SEARCH "http://www.bing.com/search?q=%s&go=&qs=n&sk=&sc=7-5&form=QBLH"
19 /* Needs AppleWebKit/531.2+ to handle all sites ? */
20 static gchar
*useragent
= "TazWeb (X11; SliTaz GNU/Linux; U; en_US)";
22 static GtkWidget
* create_window(WebKitWebView
** newwebview
);
23 static GtkWidget
*mainwindow
, *vbox
, *browser
, *toolbar
;
24 static WebKitWebView
*webview
;
25 static WebKitWebFrame
*frame
;
26 static gint count
= 0;
31 create_pixbuf(const gchar
* image
)
34 pixbuf
= gdk_pixbuf_new_from_file(image
, NULL
);
38 /* Can be: http://hg.slitaz.org or hg.slitaz.org */
42 uri
= g_strrstr(uri
, "://") ? g_strdup(uri
)
43 : g_strdup_printf("http://%s", uri
);
48 update_title(GtkWindow
* window
, WebKitWebView
* webview
)
54 string
= g_string_new(webkit_web_view_get_title(webview
));
55 progress
= webkit_web_view_get_progress(webview
) * 100;
57 g_string_append_printf(string
, " [ %f%% ] ", progress
);
59 title
= g_string_free(string
, FALSE
);
60 gtk_window_set_title(window
, title
);
64 /* Get the page title */
66 notify_title_cb(WebKitWebView
* webview
, GParamSpec
* pspec
, GtkWidget
* window
)
68 update_title(GTK_WINDOW(window
), webview
);
71 /* Request progress in window title */
73 notify_progress_cb(WebKitWebView
* webview
, GParamSpec
* pspec
, GtkWidget
* window
)
75 update_title(GTK_WINDOW(window
), webview
);
78 /* Notify url entry */
80 notify_load_status_cb(WebKitWebView
* webview
, GParamSpec
* pspec
, GtkWidget
* urientry
)
82 if (webkit_web_view_get_load_status(webview
) == WEBKIT_LOAD_COMMITTED
) {
83 frame
= webkit_web_view_get_main_frame(webview
);
84 uri
= webkit_web_frame_get_uri(frame
);
86 gtk_entry_set_text(GTK_ENTRY(urientry
), uri
);
90 /* Destroy the window */
92 destroy_cb(GtkWidget
* widget
, GtkWindow
* window
)
94 if (g_atomic_int_dec_and_test(&count
))
98 /* Show page source */
100 view_source_cb(GtkWidget
* widget
, WebKitWebView
* webview
)
104 frame
= webkit_web_view_get_main_frame(webview
);
105 uri
= webkit_web_frame_get_uri(frame
);
106 source
= webkit_web_view_get_view_source_mode(webview
);
108 webkit_web_view_set_view_source_mode(webview
, !source
);
109 webkit_web_view_reload(webview
);
112 /* URL entry callback function */
114 uri_entry_cb(GtkWidget
* urientry
, WebKitWebView
* webview
)
116 uri
= gtk_entry_get_text(GTK_ENTRY(urientry
));
118 check_requested_uri();
119 webkit_web_view_load_uri(webview
, uri
);
122 /* Search entry and icon callback function */
124 search_web(GtkWidget
* search
, WebKitWebView
* webview
)
126 uri
= g_strdup_printf(SEARCH
, gtk_entry_get_text(GTK_ENTRY(search
)));
128 webkit_web_view_load_uri(webview
, uri
);
132 search_entry_cb(GtkWidget
* search
, WebKitWebView
* webview
)
134 search_web(search
, webview
);
138 search_icon_press_cb(GtkWidget
*search
, GtkEntryIconPosition pos
,
139 GdkEvent
*event
, WebKitWebView
* webview
)
141 search_web(search
, webview
);
144 /* Navigation button function */
146 go_home_cb(GtkWidget
* widget
, WebKitWebView
* webview
)
148 uri
= g_strdup_printf("file://%s/home.html", CONFIG
);
150 webkit_web_view_load_uri(webview
, uri
);
154 go_back_cb(GtkWidget
* widget
, WebKitWebView
* webview
)
156 webkit_web_view_go_back(webview
);
160 go_forward_cb(GtkWidget
* widget
, WebKitWebView
* webview
)
162 webkit_web_view_go_forward(webview
);
165 /* Fullscreen and unfullscreen callback function */
167 //fullscreen_cb(GtkWindow* window, gpointer data)
169 //GdkWindowState state;
170 //state = gdk_window_get_state(gtk_widget_get_window(GTK_WIDGET(mainwindow)));
172 //if(state & GDK_WINDOW_STATE_FULLSCREEN)
173 //gtk_window_unfullscreen(GTK_WINDOW(mainwindow));
175 //gtk_window_fullscreen(GTK_WINDOW(mainwindow));
178 /* TazWeb doc callback function */
180 tazweb_doc_cb(GtkWidget
* widget
, WebKitWebView
*webview
)
182 uri
= ("file:///usr/share/doc/tazweb/tazweb.html");
184 webkit_web_view_load_uri(webview
, uri
);
187 /* Download function */
189 download_requested_cb(WebKitWebView
*webview
, WebKitDownload
*download
,
193 uri
= webkit_download_get_uri(download
);
194 asprintf(&buffer
, "xterm -T 'Download' -geom 72x10+0-24 -e \
195 'mkdir -p $HOME/Downloads && cd $HOME/Downloads && \
196 wget -c %s; sleep 2' &", uri
);
200 /* Zoom out and in callback function */
202 zoom_out_cb(GtkWidget
*widget
, WebKitWebView
* webview
)
204 webkit_web_view_zoom_out(webview
);
208 zoom_in_cb(GtkWidget
*widget
, WebKitWebView
* webview
)
210 webkit_web_view_zoom_in(webview
);
213 /* Printing callback function */
215 print_page_cb (GtkWidget
*widget
, gpointer data
)
217 webkit_web_frame_print (webkit_web_view_get_main_frame (
218 WEBKIT_WEB_VIEW (webview
)));
221 /* New webview callbacks */
222 static WebKitWebView
*
223 create_web_view_cb(WebKitWebView
* webview
, WebKitWebFrame
* web_frame
,
226 WebKitWebView
*newview
;
227 create_window(&newview
);
232 webview_ready_cb(WebKitWebView
* webview
, GtkWidget
* window
)
234 gtk_widget_grab_focus(GTK_WIDGET(webview
));
235 gtk_widget_show_all(window
);
240 close_webview_cb(WebKitWebView
* webview
, GtkWidget
* window
)
242 gtk_widget_destroy(window
);
246 /* Add a bookmark to home.html */
248 add_bookmark_cb(GtkWidget
*widget
, gpointer data
)
253 title
= webkit_web_view_get_title(WEBKIT_WEB_VIEW (webview
));
254 uri
= webkit_web_view_get_uri(WEBKIT_WEB_VIEW (webview
));
256 asprintf(&buffer
, "sed -i \
257 -e '/<!-- end:bookmarks -->/ i <li><a href=\"%s\">%s</a></li>' \
258 -e s'/^<li>/ <li>/' $HOME/.config/tazweb/home.html &",
263 /* Add items to WebKit contextual menu */
265 populate_menu_cb(WebKitWebView
*webview
, GtkMenu
*menu
, gpointer data
)
270 item
= gtk_separator_menu_item_new();
271 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
274 item
= gtk_image_menu_item_new_with_label("Zoom in");
275 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item
),
276 gtk_image_new_from_stock(GTK_STOCK_ZOOM_IN
, GTK_ICON_SIZE_MENU
));
277 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
278 g_signal_connect(item
, "activate", G_CALLBACK(zoom_in_cb
), webview
);
281 item
= gtk_image_menu_item_new_with_label("Zoom out");
282 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item
),
283 gtk_image_new_from_stock(GTK_STOCK_ZOOM_OUT
, GTK_ICON_SIZE_MENU
));
284 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
285 g_signal_connect(item
, "activate", G_CALLBACK(zoom_out_cb
), webview
);
288 item
= gtk_separator_menu_item_new();
289 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
291 /* Add to bookmarks */
292 item
= gtk_image_menu_item_new_with_label("Add a bookmark");
293 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item
),
294 gtk_image_new_from_stock(GTK_STOCK_ADD
, GTK_ICON_SIZE_MENU
));
295 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
296 g_signal_connect(item
, "activate", G_CALLBACK(add_bookmark_cb
), webview
);
299 item
= gtk_separator_menu_item_new();
300 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
302 /* View source mode */
303 item
= gtk_image_menu_item_new_with_label("View source mode");
304 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item
),
305 gtk_image_new_from_stock(GTK_STOCK_PROPERTIES
, GTK_ICON_SIZE_MENU
));
306 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
307 g_signal_connect(item
, "activate", G_CALLBACK(view_source_cb
), webview
);
310 item
= gtk_image_menu_item_new_with_label("Print this page");
311 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item
),
312 gtk_image_new_from_stock(GTK_STOCK_PRINT
, GTK_ICON_SIZE_MENU
));
313 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
314 g_signal_connect(item
, "activate", G_CALLBACK(print_page_cb
), webview
);
317 item
= gtk_separator_menu_item_new();
318 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
320 /* TazWeb documentation */
321 item
= gtk_image_menu_item_new_with_label("TazWeb manual");
322 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item
),
323 gtk_image_new_from_stock(GTK_STOCK_HELP
, GTK_ICON_SIZE_MENU
));
324 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
325 g_signal_connect(item
, "activate", G_CALLBACK(tazweb_doc_cb
), webview
);
327 gtk_widget_show_all(GTK_WIDGET(menu
));
330 /* Scrolled window for the webview */
332 create_browser(GtkWidget
* window
, GtkWidget
* urientry
, GtkWidget
* search
,
333 WebKitWebView
* webview
)
335 WebKitWebSettings
*settings
;
337 browser
= gtk_scrolled_window_new(NULL
, NULL
);
338 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(browser
),
339 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
341 gtk_container_add(GTK_CONTAINER(browser
), GTK_WIDGET(webview
));
344 settings
= webkit_web_view_get_settings (webview
);
345 g_object_set(G_OBJECT(settings
), "user-agent", useragent
, NULL
);
347 /* Connect WebKit events */
348 g_signal_connect(webview
, "notify::title",
349 G_CALLBACK(notify_title_cb
), window
);
350 g_signal_connect(webview
, "notify::progress",
351 G_CALLBACK(notify_progress_cb
), window
);
352 g_signal_connect(webview
, "notify::load-status",
353 G_CALLBACK(notify_load_status_cb
), urientry
);
354 g_signal_connect(webview
, "download-requested",
355 G_CALLBACK(download_requested_cb
), NULL
);
356 g_signal_connect(webview
, "create-web-view",
357 G_CALLBACK(create_web_view_cb
), window
);
358 g_signal_connect(webview
, "web-view-ready",
359 G_CALLBACK(webview_ready_cb
), window
);
360 g_signal_connect(webview
, "close-web-view",
361 G_CALLBACK(close_webview_cb
), window
);
363 /* Connect WebKit contextual menu items */
364 g_object_connect(G_OBJECT(webview
), "signal::populate-popup",
365 G_CALLBACK(populate_menu_cb
), webview
, NULL
);
371 create_toolbar(GtkWidget
* urientry
, GtkWidget
* search
, WebKitWebView
* webview
)
375 toolbar
= gtk_toolbar_new();
376 gtk_toolbar_set_orientation(GTK_TOOLBAR(toolbar
),
377 GTK_ORIENTATION_HORIZONTAL
);
378 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar
),
379 GTK_TOOLBAR_BOTH_HORIZ
);
381 /* The back button */
382 item
= gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK
);
383 g_signal_connect(G_OBJECT(item
), "clicked",
384 G_CALLBACK(go_back_cb
), webview
);
385 gtk_toolbar_insert(GTK_TOOLBAR(toolbar
), item
, -1);
387 /* The forward button */
388 item
= gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD
);
389 g_signal_connect(G_OBJECT(item
), "clicked",
390 G_CALLBACK(go_forward_cb
), webview
);
391 gtk_toolbar_insert(GTK_TOOLBAR(toolbar
), item
, -1);
394 item
= gtk_tool_button_new_from_stock(GTK_STOCK_HOME
);
395 g_signal_connect(G_OBJECT(item
), "clicked",
396 G_CALLBACK(go_home_cb
), webview
);
397 gtk_toolbar_insert(GTK_TOOLBAR(toolbar
), item
, -1);
400 item
= gtk_tool_item_new();
401 gtk_tool_item_set_expand(item
, TRUE
);
402 gtk_widget_set_size_request(urientry
, 0, 33);
403 gtk_container_add(GTK_CONTAINER(item
), urientry
);
404 gtk_toolbar_insert(GTK_TOOLBAR(toolbar
), item
, -1);
405 g_signal_connect(G_OBJECT(urientry
), "activate",
406 G_CALLBACK(uri_entry_cb
), webview
);
409 item
= gtk_separator_tool_item_new();
410 gtk_toolbar_insert(GTK_TOOLBAR(toolbar
), item
, -1);
413 item
= gtk_tool_item_new();
414 gtk_widget_set_size_request(search
, 300, 33);
415 gtk_container_add(GTK_CONTAINER(item
), search
);
416 gtk_toolbar_insert(GTK_TOOLBAR(toolbar
), item
, -1);
417 gtk_entry_set_icon_from_stock(GTK_ENTRY(search
),
418 GTK_ENTRY_ICON_SECONDARY
, GTK_STOCK_FIND
);
419 g_signal_connect(GTK_ENTRY(search
), "icon-press",
420 G_CALLBACK(search_icon_press_cb
), webview
);
421 g_signal_connect(G_OBJECT(search
), "activate",
422 G_CALLBACK(search_entry_cb
), webview
);
424 /* The Fullscreen button */
425 //item = gtk_tool_button_new_from_stock(GTK_STOCK_FULLSCREEN);
426 //g_signal_connect(G_OBJECT(item), "clicked",
427 //G_CALLBACK(fullscreen_cb), NULL);
428 //gtk_toolbar_insert(GTK_TOOLBAR(toolbar), item, -1);
435 create_window(WebKitWebView
** newwebview
)
441 g_atomic_int_inc(&count
);
443 /* Default TazWeb window */
444 window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
445 gtk_window_set_default_size(GTK_WINDOW(window
), 1280, 1024);
446 gtk_window_set_icon(GTK_WINDOW(window
),
447 create_pixbuf("/usr/share/pixmaps/tazweb.png"));
448 gtk_widget_set_name(window
, "TazWeb");
449 g_signal_connect(window
, "destroy", G_CALLBACK(destroy_cb
), NULL
);
451 /* Webview and widgets */
452 webview
= WEBKIT_WEB_VIEW(webkit_web_view_new());
453 urientry
= gtk_entry_new();
454 search
= gtk_entry_new();
455 vbox
= gtk_vbox_new(FALSE
, 0);
457 /* Pack box and container */
458 gtk_box_pack_start(GTK_BOX(vbox
),
459 create_browser(window
, urientry
, search
, webview
), TRUE
, TRUE
, 0);
460 gtk_box_pack_start(GTK_BOX(vbox
),
461 create_toolbar(urientry
, search
, webview
), FALSE
, FALSE
, 0);
462 gtk_container_add(GTK_CONTAINER(window
), vbox
);
465 *newwebview
= webview
;
471 main(int argc
, char* argv
[])
473 gtk_init(NULL
, NULL
);
474 if (!g_thread_supported())
477 /* Get a default home.html if missing */
478 if (! g_file_test(CONFIG
, G_FILE_TEST_EXISTS
))
479 system("cp -r /usr/share/tazweb $HOME/.config/tazweb");
481 /* Load the start page file or the url in argument */
482 uri
=(char*)(argc
> 1 ? argv
[1] : START
);
484 check_requested_uri();
486 mainwindow
= create_window(&webview
);
488 gtk_widget_show_all(mainwindow
);
489 webkit_web_view_load_uri(webview
, uri
);
490 gtk_widget_grab_focus(GTK_WIDGET(webview
));