#include #include #include #include #include #include "browser.h" static void load_modules(void) { scm_c_use_module("ice-9 threads"); scm_c_use_module("ice-9 atomic"); scm_c_use_module("ice-9 hash-table"); } static gboolean eventCallback(void *data) { struct QueueData *qdata = data; struct BrowserMessage *msg = g_async_queue_timeout_pop(qdata->gtk_qu, 10); if (msg != NULL) { switch (msg->event) { case LOAD: printf("Got a load event\n"); printf("Messaging Guile\n"); printf(msg->data); qu_push(msg->event, msg->data, qdata->guile_qu); webkit_web_view_load_uri(qdata->webView, msg->data); break; case CLOSE: printf("Got a close event\n"); break; default: printf("Got an unknown event\n"); break; } free(msg); } return TRUE; } static int qu_push(enum BrowserEvent msg_type, char *message, GAsyncQueue *g_queue) { struct BrowserMessage *msg = malloc( sizeof(*msg) ); msg->data = message; switch (msg_type) { case LOAD: msg->event = LOAD; break; case CLOSE: msg->event = CLOSE; break; default: msg->event = EMPTY; break; } g_async_queue_push(g_queue, msg); return 1; } static SCM scm_qu_push(SCM scm_msg_type, SCM scm_message, SCM scm_qu) { enum BrowserEvent msg_type = scm_to_int(scm_msg_type); char *data = scm_to_locale_string(scm_message); GAsyncQueue *g_queue = scm_to_pointer(scm_qu); qu_push(msg_type, data, g_queue); return SCM_BOOL_T; } static int conf_val(char * const key) { /* Lookup a key value in a Scheme hash-table */ SCM config = scm_ref("config"); SCM scm_key = scm_from_locale_string(key); SCM result = scm_hash_ref(config, scm_key, NULL); if (result != NULL) { return scm_to_int(result); } else { /* TODO check the key and then do an intelligent default? */ /* For now, default to 1 = ON */ return 1; } } static SCM scm_ref(const char *var_name) { /* Lookup and de-reference a Scheme value */ return scm_variable_ref(scm_c_lookup(var_name)); } static WebKitWebView* make_webview() { WebKitSettings *settings = webkit_settings_new(); WebKitHardwareAccelerationPolicy hw_policy; /* Disable hardware acceleration by default */ /* It seems to be causing issues */ if (conf_val("hw-acceleration")) { hw_policy = WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS; } else { hw_policy = WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER; } webkit_settings_set_hardware_acceleration_policy(settings, hw_policy); webkit_settings_set_enable_webgl(settings, conf_val("webgl")); webkit_settings_set_enable_accelerated_2d_canvas(settings, conf_val("2d-canvas")); webkit_settings_set_enable_write_console_messages_to_stdout(settings, conf_val("console-log")); webkit_settings_set_media_playback_requires_user_gesture(settings, conf_val("media-gestures")); webkit_settings_set_enable_media_stream(settings, conf_val("media-stream")); webkit_settings_set_enable_encrypted_media(settings, conf_val("encrypted-media")); webkit_settings_set_enable_media_capabilities(settings, conf_val("media-capabilities")); webkit_settings_set_enable_mediasource(settings, conf_val("media-source")); webkit_settings_set_enable_dns_prefetching(settings, conf_val("dns-prefetching")); webkit_settings_set_enable_javascript(settings, conf_val("javascript")); webkit_settings_set_enable_page_cache(settings, conf_val("page-cache")); webkit_settings_set_enable_developer_extras(settings, conf_val("dev-extras")); webkit_settings_set_draw_compositing_indicators(settings, conf_val("compositing-indicators")); webkit_settings_set_enable_smooth_scrolling(settings, conf_val("smooth-scrolling")); webkit_settings_set_enable_hyperlink_auditing(settings, conf_val("hyperlink-auditing")); webkit_settings_set_enable_java(settings, FALSE); return WEBKIT_WEB_VIEW(webkit_web_view_new_with_settings(settings)); } /* GTK callbacks */ static void destroyWindowCb(GtkWidget *widget, GtkWidget *window); static gboolean closeWebViewCb(WebKitWebView *webView, GtkWidget *window); static void destroyWindowCb(GtkWidget *widget, GtkWidget *window) { gtk_main_quit(); } static gboolean closeWebViewCb(WebKitWebView *webView, GtkWidget *window) { gtk_widget_destroy(window); return TRUE; } SCM launch_webkit(SCM scm_gtk_qu, SCM scm_guile_qu) { WebKitWebView *webView = make_webview(); GAsyncQueue *gtk_qu = scm_to_pointer(scm_gtk_qu); GAsyncQueue *guile_qu = scm_to_pointer(scm_guile_qu); /* Get a default webkit context for modifying the cache policy */ WebKitWebContext *webkit_ctx = webkit_web_context_get_default(); WebKitProcessModel process_model = WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES; webkit_web_context_set_process_model(webkit_ctx, process_model); webkit_web_context_set_cache_model(webkit_ctx, WEBKIT_CACHE_MODEL_WEB_BROWSER); /* Initialize GTK+ */ gtk_init(0, NULL); struct QueueData queue_data; queue_data.gtk_qu = gtk_qu; queue_data.guile_qu = guile_qu; queue_data.webView = webView; g_idle_add(eventCallback, &queue_data); /* Create an 800x600 window that will contain the browser instance */ GtkWidget *main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(main_window), 800, 600); /* Put the browser area into the main window */ gtk_container_add(GTK_CONTAINER(main_window), GTK_WIDGET(webView)); /* Set up callbacks so that if either the main window or the browser instance is */ /* closed, the program will exit */ g_signal_connect(main_window, "destroy", G_CALLBACK(destroyWindowCb), NULL); g_signal_connect(webView, "close", G_CALLBACK(closeWebViewCb), main_window); /* Load a web page into the browser instance */ webkit_web_view_load_uri(webView, "http://google.com/"); /* Make sure that when the browser area becomes visible, it will get mouse */ /* and keyboard events */ gtk_widget_grab_focus(GTK_WIDGET(webView)); /* Make sure the main window and all its contents are visible */ gtk_widget_show_all(main_window); /* Run the main GTK+ event loop */ gtk_main(); return SCM_BOOL_T; } static void run_repl(void *data, int argc, char **argv) { load_modules(); SCM current_module = scm_current_module(); GAsyncQueue *browser_event_qu = g_async_queue_new(); GAsyncQueue *guile_event_qu = g_async_queue_new(); /* Used for passing messages to the GTK thread */ scm_c_define("gtk-qu", scm_from_pointer(browser_event_qu, NULL)); /* Used for passing messages back to the Guile thread */ scm_c_define("guile-qu", scm_from_pointer(guile_event_qu, NULL)); scm_c_define_gsubr("launch-webkit-blocking", 2, 0, 0, launch_webkit); scm_c_define_gsubr("qu-push", 3, 0, 0, scm_qu_push); scm_c_primitive_load("./schemekit.scm"); scm_shell(argc, argv); } int main(int argc, char *argv[]) { /* Set environment variables relevant to webgtk */ /* Initialize Guile */ scm_boot_guile(argc, argv, run_repl, 0); return 0; }