diff options
-rw-r--r-- | src/js.c | 17 | ||||
-rw-r--r-- | src/js.h | 2 | ||||
-rw-r--r-- | src/scratchpad.c | 35 | ||||
-rw-r--r-- | src/scripts.c | 49 | ||||
-rw-r--r-- | src/scripts.h | 2 |
5 files changed, 100 insertions, 5 deletions
@@ -120,6 +120,23 @@ js_string_to_char(JSContextRef ctx, JSStringRef jsstring, size_t size) { return ret; }/*}}}*/ +JSValueRef +js_context_change(JSContextRef source_ctx, JSContextRef dest_ctx, JSValueRef val, JSValueRef *exc) { + char *c_val = js_value_to_json(source_ctx, val, -1, exc); + if (c_val == NULL) + return JSValueMakeNull(dest_ctx); + + JSStringRef json = JSStringCreateWithUTF8CString(c_val); + JSValueRef ret = JSValueMakeFromJSONString(dest_ctx, json); + + g_free(c_val); + JSStringRelease(json); + + if (ret == NULL) + return JSValueMakeNull(dest_ctx); + return ret; +} + /* js_create_object(WebKitWebFrame *frame, const char *) * * Executes a script in a function scope, should return an object with @@ -18,6 +18,7 @@ #ifndef JS_H #define JS_H +#include <JavaScriptCore/JavaScript.h> void js_make_exception(JSContextRef ctx, JSValueRef *exception, const gchar *format, ...); char * js_string_to_char(JSContextRef ctx, JSStringRef jsstring, size_t ); @@ -36,6 +37,7 @@ JSValueRef js_execute(JSContextRef ctx, const char *, JSValueRef *exc); gboolean js_print_exception(JSContextRef ctx, JSValueRef exception); JSObjectRef js_make_function(JSContextRef ctx, const char *script); JSValueRef js_json_to_value(JSContextRef ctx, const char *text); +JSValueRef js_context_change(JSContextRef, JSContextRef, JSValueRef, JSValueRef *); typedef struct _js_array_iterator { JSContextRef ctx; diff --git a/src/scratchpad.c b/src/scratchpad.c index 4ae25848..00fc0974 100644 --- a/src/scratchpad.c +++ b/src/scratchpad.c @@ -17,6 +17,9 @@ */ #include "dwb.h" +#include "js.h" +#include "scripts.h" +#include <JavaScriptCore/JavaScript.h> GtkWidget *g_scratchpad; static gboolean @@ -30,6 +33,32 @@ navigation_cb(WebKitWebView *wv, WebKitWebFrame *frame, WebKitNetworkRequest *re return false; } + +static JSValueRef +sp_send(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argc, const JSValueRef argv[], JSValueRef* exception) { + if (argc > 0) + scripts_scratchpad_send(ctx, argv[0]); + return JSValueMakeUndefined(ctx); +} + +static JSValueRef +sp_get(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc) { + scripts_scratchpad_get(ctx, function, this, argc, argv, exc); + return JSValueMakeUndefined(ctx); +} + +static void +window_object_cb(WebKitWebView *wv, WebKitWebFrame *frame, JSContextRef ctx, JSObjectRef window) { + if (frame == webkit_web_view_get_main_frame(wv)) { + JSObjectRef func = JSObjectMakeFunctionWithCallback(ctx, NULL, sp_get); + js_set_property(ctx, window, "dwbGet", func, + kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, NULL); + func = JSObjectMakeFunctionWithCallback(ctx, NULL, sp_send); + js_set_property(ctx, window, "dwbSend", func, + kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly, NULL); + } +} + void scratchpad_load(const char *text) { if (g_str_has_prefix(text, "file://")) @@ -43,22 +72,24 @@ scratchpad_show(void) { gtk_widget_show(g_scratchpad); gtk_widget_grab_focus(g_scratchpad); } + void scratchpad_hide(void) { gtk_widget_hide(g_scratchpad); dwb_focus_scroll(dwb.state.fview); } + static void scratchpad_init(void) { g_scratchpad = webkit_web_view_new(); g_signal_connect(g_scratchpad, "navigation-policy-decision-requested", G_CALLBACK(navigation_cb), NULL); + g_signal_connect(g_scratchpad, "window-object-cleared", G_CALLBACK(window_object_cb), NULL); gtk_widget_set_size_request(g_scratchpad, -1, 200); } + GtkWidget * scratchpad_get(void) { if (g_scratchpad == NULL) scratchpad_init(); return g_scratchpad; } - - diff --git a/src/scripts.c b/src/scripts.c index 5fdeae85..669de66e 100644 --- a/src/scripts.c +++ b/src/scripts.c @@ -125,6 +125,8 @@ static JSStaticValue message_values[] = { static JSValueRef sp_show(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc); static JSValueRef sp_hide(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc); static JSValueRef sp_load(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc); +static JSValueRef sp_get(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc); +static JSValueRef sp_send(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc); static JSValueRef frame_inject(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc); static JSStaticFunction frame_functions[] = { @@ -165,6 +167,8 @@ static JSClassRef m_webview_class, m_frame_class, m_download_class, m_default_cl static gboolean m_commandline = false; static JSObjectRef m_array_contructor; static JSObjectRef m_completion_callback; +static JSObjectRef m_sp_scripts_cb; +static JSObjectRef m_sp_scratchpad_cb; static GQuark ref_quark; /* MISC {{{*/ @@ -491,10 +495,47 @@ sp_load(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, c g_free(text); } return JSValueMakeUndefined(ctx); - } - - +static JSObjectRef +sp_callback_create(JSContextRef ctx, size_t argc, const JSValueRef argv[], JSValueRef *exc) { + JSObjectRef ret = NULL; + if (argc > 0) { + ret = JSValueToObject(ctx, argv[0], exc); + if (ret == NULL || !JSObjectIsFunction(ctx, ret)) + ret = NULL; + } + return ret; +} +static JSValueRef +sp_get(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc) { + m_sp_scripts_cb = sp_callback_create(ctx, argc, argv, exc); + return JSValueMakeUndefined(ctx); +} +void +scripts_scratchpad_get(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc) { + m_sp_scratchpad_cb = sp_callback_create(ctx, argc, argv, exc); +} +void +sp_context_change(JSContextRef src_ctx, JSContextRef dest_ctx, JSObjectRef func, JSValueRef val) { + if (func != NULL) { + JSValueRef val_changed = js_context_change(src_ctx, dest_ctx, val, NULL); + JSValueRef argv[] = { val_changed == 0 ? JSValueMakeNull(dest_ctx) : val_changed }; + JSObjectCallAsFunction(dest_ctx, func, NULL, 1, argv, NULL); + } +} +// send from scripts context to scratchpad context +static JSValueRef +sp_send(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc) { + if (argc > 0) { + sp_context_change(m_global_context, webkit_web_frame_get_global_context(webkit_web_view_get_main_frame(WEBKIT_WEB_VIEW(scratchpad_get()))), m_sp_scratchpad_cb, argv[0]); + } + return JSValueMakeUndefined(ctx); +} +// send from scratchpad context to script context +void +scripts_scratchpad_send(JSContextRef ctx, JSValueRef val) { + sp_context_change(ctx, m_global_context, m_sp_scripts_cb, val); +} /* SOUP_MESSAGE {{{*/ /* soup_uri_to_js_object {{{*/ @@ -1853,6 +1894,8 @@ create_global_object() { { "show", sp_show, kJSDefaultAttributes }, { "hide", sp_hide, kJSDefaultAttributes }, { "load", sp_load, kJSDefaultAttributes }, + { "get", sp_get, kJSDefaultAttributes }, + { "send", sp_send, kJSDefaultAttributes }, { 0, 0, 0 }, }; cd.className = "Scratchpad"; diff --git a/src/scripts.h b/src/scripts.h index f1beb70f..a6ab6244 100644 --- a/src/scripts.h +++ b/src/scripts.h @@ -69,6 +69,8 @@ void scripts_execute_scripts(char **scripts); DwbStatus scripts_eval_key(KeyMap *m, Arg *arg); gboolean scripts_execute_one(const char *script); void scripts_completion_activate(void); +void scripts_scratchpad_send(JSContextRef ctx, JSValueRef val); +void scripts_scratchpad_get(JSContextRef, JSObjectRef, JSObjectRef, size_t, const JSValueRef[], JSValueRef* ); #define EMIT_SCRIPT(sig) ((dwb.misc.script_signals & (1<<SCRIPTS_SIG_##sig))) #define SCRIPTS_EMIT_RETURN(signal, json) G_STMT_START \ |