diff options
author | portix <portix@gmx.net> | 2012-12-03 00:55:55 +0100 |
---|---|---|
committer | portix <portix@gmx.net> | 2012-12-03 00:55:55 +0100 |
commit | 26b72b104a8fc439f17369c8b7982e892101f394 (patch) | |
tree | 85b92a2f915c1a57c4d866ea9428ace54950a624 /src/scripts.c | |
parent | 35c7e8147b3f8520573411fc514f40f5903737eb (diff) | |
download | dwb-26b72b104a8fc439f17369c8b7982e892101f394.zip |
Rewriting object.connect, pass parameters of GCallback to callback function
Diffstat (limited to 'src/scripts.c')
-rw-r--r-- | src/scripts.c | 153 |
1 files changed, 145 insertions, 8 deletions
diff --git a/src/scripts.c b/src/scripts.c index fb4d6239..b51be201 100644 --- a/src/scripts.c +++ b/src/scripts.c @@ -47,6 +47,7 @@ typedef struct m_Sigmap { } Sigmap; typedef struct _CallbackData CallbackData; +typedef struct _SSignal SSignal; typedef gboolean (*StopCallbackNotify)(CallbackData *); struct _CallbackData { @@ -55,6 +56,16 @@ struct _CallbackData { JSObjectRef callback; StopCallbackNotify notify; }; +struct _SSignal { + int id; + GSignalQuery *query; + GObject *object; + JSObjectRef func; + JSValueRef jsid; +}; +static GSList *m_signals; +#define S_SIGNAL(X) ((SSignal*)X->data) + static Sigmap m_sigmap[] = { { SCRIPTS_SIG_NAVIGATION, "navigation" }, @@ -308,6 +319,31 @@ callback_data_free(CallbackData *c) } }/*}}}*/ +static void +ssignal_free(SSignal *sig) +{ + if (sig != NULL) + { + JSValueUnprotect(m_global_context, sig->jsid); + g_free(sig->query); + g_free(sig); + } +} + +static SSignal * +ssignal_new() +{ + SSignal *sig = g_malloc(sizeof(SSignal)); + if (sig != NULL) + { + sig->query = g_malloc(sizeof(GSignalQuery)); + if (sig->query != NULL) + return sig; + g_free(sig); + } + return NULL; +} + /* make_callback {{{*/ static void make_callback(JSContextRef ctx, JSObjectRef this, GObject *gobject, const char *signalname, JSValueRef value, StopCallbackNotify notify, JSValueRef *exception) @@ -2050,6 +2086,16 @@ scripts_emit(ScriptSignal *sig) void object_destroy_cb(JSObjectRef o) { + GObject *go = JSObjectGetPrivate(o); + for (GSList *l = m_signals; l; l=l->next) + { + if (S_SIGNAL(l)->object == go) + { + ssignal_free(l->data); + m_signals = g_slist_delete_link(m_signals, l); + break; + } + } JSObjectSetPrivate(o, NULL); JSValueUnprotect(m_global_context, o); } @@ -2097,12 +2143,61 @@ make_object(JSContextRef ctx, GObject *o) }/*}}}*/ static gboolean -connect_callback(JSObjectRef func) +connect_callback(SSignal *sig, ...) { - JSValueRef ret = JSObjectCallAsFunction(m_global_context, func, NULL, 0, NULL, NULL); + va_list args; + JSValueRef cur; + JSValueRef argv[sig->query->n_params + 1]; + va_start(args, sig); +#define CHECK_NUMBER(GTYPE, TYPE) G_STMT_START if (gtype == G_TYPE_##GTYPE) { \ + TYPE MM_value = va_arg(args, TYPE); \ + cur = JSValueMakeNumber(m_global_context, MM_value); goto apply;} G_STMT_END + for (int i=0; i<sig->query->n_params; i++) + { + GType gtype = sig->query->param_types[i], act; + while ((act = g_type_parent(gtype))) + gtype = act; + CHECK_NUMBER(INT, gint); + CHECK_NUMBER(UINT, guint); + CHECK_NUMBER(LONG, glong); + CHECK_NUMBER(ULONG, gulong); + CHECK_NUMBER(FLOAT, gdouble); + CHECK_NUMBER(DOUBLE, gdouble); + CHECK_NUMBER(ENUM, gint); + CHECK_NUMBER(INT64, gint64); + CHECK_NUMBER(UINT64, guint64); + CHECK_NUMBER(FLAGS, guint); + if (sig->query->param_types[i] == G_TYPE_BOOLEAN) + { + gboolean value = va_arg(args, gboolean); + cur = JSValueMakeBoolean(m_global_context, value); + } + else if (sig->query->param_types[i] == G_TYPE_STRING) + { + char *value = va_arg(args, char *); + cur = js_char_to_value(m_global_context, value); + } + else if (G_TYPE_IS_CLASSED(gtype)) + { + GObject *value = va_arg(args, gpointer); + if (value != NULL) // avoid conversion to JSObjectRef + cur = make_object(m_global_context, value); + else + cur = JSValueMakeNull(m_global_context); + } + else + { + cur = JSValueMakeUndefined(m_global_context); + } + +apply: + argv[i+1] = cur; + } +#undef CHECK_NUMBER + argv[0] = make_object(m_global_context, va_arg(args, gpointer)); + JSValueRef ret = JSObjectCallAsFunction(m_global_context, sig->func, NULL, sig->query->n_params+1, argv, NULL); if (JSValueIsBoolean(m_global_context, ret)) { - printf("%d\n", JSValueToBoolean(m_global_context, ret)); return JSValueToBoolean(m_global_context, ret); } return false; @@ -2112,7 +2207,7 @@ connect_object(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t { gulong id = 0; if (argc < 2) - return JSValueMakeNumber(ctx, -1); + return JSValueMakeNumber(ctx, 0); char *name = js_value_to_char(ctx, argv[0], PROP_LENGTH, exc); if (name == NULL) @@ -2124,9 +2219,34 @@ connect_object(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t GObject *o = JSObjectGetPrivate(this); if (o == NULL) - return JSValueMakeNumber(ctx, -1); + goto error_out; + + guint signal_id = g_signal_lookup(name, G_TYPE_FROM_INSTANCE(o)); + if (signal_id == 0) + goto error_out; + + SSignal *sig = ssignal_new(); + if (sig == NULL) + goto error_out; + + g_signal_query(signal_id, sig->query); + if (sig->query->signal_id == 0) + goto error_out; + + sig->func = func; + id = g_signal_connect_swapped(o, name, G_CALLBACK(connect_callback), sig); + if (id > 0) + { + sig->id = id; + sig->object = o; + sig->jsid = argv[0]; + JSValueProtect(m_global_context, sig->jsid); + + m_signals = g_slist_prepend(m_signals, sig); + } + else + ssignal_free(sig); - id = g_signal_connect_swapped(o, name, G_CALLBACK(connect_callback), func); error_out: g_free(name); return JSValueMakeNumber(ctx, id); @@ -2135,10 +2255,19 @@ static JSValueRef disconnect_object(JSContextRef ctx, JSObjectRef function, JSObjectRef this, size_t argc, const JSValueRef argv[], JSValueRef* exc) { int id; - if (argc > 0 && (id = JSValueToNumber(ctx, argv[0], exc)) != NAN) + if (argc > 0 && JSValueIsNumber(ctx, argv[0]) && (id = JSValueToNumber(ctx, argv[0], exc)) != NAN) { + for (GSList *sigs = m_signals; sigs; sigs=sigs->next) + { + if (id == S_SIGNAL(sigs)->id) + { + ssignal_free(sigs->data); + m_signals = g_slist_delete_link(m_signals, sigs); + break; + } + } GObject *o = JSObjectGetPrivate(this); - if (o != NULL) + if (o != NULL && g_signal_handler_is_connected(o, id)) { g_signal_handler_disconnect(o, id); return JSValueMakeBoolean(ctx, true); @@ -2668,6 +2797,14 @@ scripts_end() JSClassRelease(m_download_class); JSClassRelease(m_message_class); JSGlobalContextRelease(m_global_context); + if (m_signals != NULL) + { + for (GSList *l = m_signals; l; l=l->next) + { + ssignal_free(l->data); + } + g_slist_free(m_signals); + } m_global_context = NULL; } }/*}}}*//*}}}*/ |