// needs this in gobjecttypes.d public typedef extern(C) void function () GCallback; // what we want to do.. // adding as signal does: // a) binds our generic callback for that type of callback.. // b) stores the specific callback somewhere. with details of scope and function. // then when we callback.. // loop through the registered callbacks, and call them with the args. class Listeners { Dobject funcs[]; CallContext* ccs[]; Dobject owner; this(Dobject owner) { this.owner = owner; } void add(Dobject func, CallContext* cc) { this.funcs ~= func; this.ccs ~= cc; } bool Call(Value[] arglist) { Value ret; foreach(i,f;funcs) { f.Call(ccs[i], owner, &ret, arglist); if (ret.toBoolean() == true) { return true; } } } } Listeners[char[]] connectedSignals; void registerSignal(char[] signal) { GCallback cb = null; if (signal in connectedSignals) { return; } switch(signal) { case "delete-event": cb = cast(GCallback)&callBackDelete; break; default: // except for top level, that should throw an excpetion... super.registerSignal(char[]); } g_signal_connect_data( getStruct(), // which returns void anyway.. std.string.toStringz(signal), cb, cast(void*)this, null, cast(ConnectFlags)0); connectedSignals[signal] = new Listener(this); } static void* on( Dobject pthis, CallContext* cc, Dobject othis, Value* ret, Value[] arglist) { (cast(dsWrapped_GtkWindow)othis).registerSignals(arglist[0].toString()); cast(dsWrapped_GtkWindow)othis).connectedSignals[arglist[0].toString()].add(arglist[1].toObject(), cc); return null; } extern(C) static void callBackDelete(GtkWidget* widgetStruct, GdkEvent* event, Dobject dobj) { //bit consumed = false; Value[] arglist = new Value[1]; //arglist[0] = new dsEvent(event); arglist[0].putVobject(dobj); // not needed really!!!.? Value ret; return (cast(dsWrapped_GtkWindow)dobj).connectedSignals["delete-event"].Call(arglist); //return consumed; }