/**
 * _nm_dbus_signal_connect_data:
 * @proxy: a #GDBusProxy
 * @signal_name: the D-Bus signal to connect to
 * @signature: (allow-none): the signal's type signature (must be a tuple)
 * @c_handler: the signal handler function
 * @data: (allow-none): data to pass to @c_handler
 * @destroy_data: (allow-none): closure destroy notify for @data
 * @connect_flags: connection flags
 *
 * Connects to the D-Bus signal @signal_name on @proxy. @c_handler must be a
 * void function whose first argument is a #GDBusProxy, followed by arguments
 * for each element of @signature, ending with a #gpointer argument for @data.
 *
 * The argument types in @c_handler correspond to the types output by
 * g_dbus_gvariant_to_gvalue(), except for 'ay' and 'aay'. In particular:
 * - both 16-bit and 32-bit integers are passed as #gint/#guint
 * - 'as' values are passed as #GStrv (char **)
 * - all other array, tuple, and dict types are passed as #GVariant
 *
 * If @signature is %NULL, then the signal's parameters will be ignored, and
 * @c_handler should take only the #GDBusProxy and #gpointer arguments.
 *
 * Returns: the signal handler ID, which can be used with
 *   g_signal_handler_remove(). Beware that because of the way the signal is
 *   connected, you will not be able to remove it with
 *   g_signal_handlers_disconnect_by_func(), although
 *   g_signal_handlers_disconnect_by_data() will work correctly.
 */
gulong
_nm_dbus_signal_connect_data (GDBusProxy *proxy,
                              const char *signal_name,
                              const GVariantType *signature,
                              GCallback c_handler,
                              gpointer data,
                              GClosureNotify destroy_data,
                              GConnectFlags connect_flags)
{
	NMDBusSignalData *sd;
	GClosure *closure;
	gboolean swapped = !!(connect_flags & G_CONNECT_SWAPPED);
	gboolean after = !!(connect_flags & G_CONNECT_AFTER);

	g_return_val_if_fail (G_IS_DBUS_PROXY (proxy), 0);
	g_return_val_if_fail (signal_name != NULL, 0);
	g_return_val_if_fail (signature == NULL || g_variant_type_is_tuple (signature), 0);
	g_return_val_if_fail (c_handler != NULL, 0);

	sd = g_slice_new (NMDBusSignalData);
	sd->signal_name = g_strdup (signal_name);
	sd->signature = signature;

	closure = (swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data);
	g_closure_set_marshal (closure, g_cclosure_marshal_generic);
	g_closure_set_meta_marshal (closure, sd, dbus_signal_meta_marshal);
	g_closure_add_finalize_notifier (closure, sd, dbus_signal_data_free);

	return g_signal_connect_closure (proxy, "g-signal", closure, after);
}
Exemple #2
0
static inline GClosure *createCppClosure(ClosureDataBase *closureData)
{
    GClosure *closure = g_closure_new_simple(sizeof(GClosure), closureData);
    g_closure_set_marshal(closure, &c_marshaller);
    g_closure_add_finalize_notifier(closure, NULL, &closureDestroyNotify);
    g_closure_ref(closure);
    g_closure_sink(closure);
    return closure;
}
Exemple #3
0
/*
Creates a new closure which invokes callback_func with user_data as the last parameter.
创建GCClosure, 并初始化
但仍返回GClosure
*/
GClosure*
g_cclosure_new (GCallback      callback_func,
		gpointer       user_data,
		GClosureNotify destroy_data)
{
	closure = g_closure_new_simple (sizeof (GCClosure), user_data);
	g_closure_add_finalize_notifier (closure, user_data, destroy_data);
	((GCClosure*) closure)->callback = (gpointer) callback_func;
}
Exemple #4
0
GClosure*
gjs_closure_new(JSContext  *context,
                JSObject   *callable,
                const char *description,
                gboolean    root_function)
{
    Closure *c;

    c = (Closure*) g_closure_new_simple(sizeof(Closure), NULL);
    c->runtime = JS_GetRuntime(context);
    /* The saved context is used for lifetime management, so that the closure will
     * be torn down with the context that created it. The context could be attached to
     * the default context of the runtime using if we wanted the closure to survive
     * the context that created it.
     */
    c->context = context;
    JS_BeginRequest(context);

    c->obj = callable;
    c->unref_on_global_object_finalized = FALSE;

    GJS_INC_COUNTER(closure);
    /* the finalize notifier right now is purely to track the counter
     * of how many closures are alive.
     */
    g_closure_add_finalize_notifier(&c->base, NULL, closure_finalized);

    if (root_function) {
        /* Fully manage closure lifetime if so asked */
        gjs_keep_alive_add_global_child(context,
                                        global_context_finalized,
                                        c->obj,
                                        c);

        g_closure_add_invalidate_notifier(&c->base, NULL, closure_invalidated);
    } else {
        /* Only mark the closure as invalid if memory is managed
           outside (i.e. by object.c for signals) */
        g_closure_add_invalidate_notifier(&c->base, NULL, closure_set_invalid);
    }

    gjs_debug_closure("Create closure %p which calls object %p '%s'",
                      c, c->obj, description);

    JS_EndRequest(context);

    return &c->base;
}
Exemple #5
0
/**
 * g_cclosure_new: (skip)
 * @callback_func: the function to invoke
 * @user_data: user data to pass to @callback_func
 * @destroy_data: destroy notify to be called when @user_data is no longer used
 *
 * Creates a new closure which invokes @callback_func with @user_data as
 * the last parameter.
 *
 * Returns: a new #GCClosure
 */
GClosure*
g_cclosure_new (GCallback      callback_func,
		gpointer       user_data,
		GClosureNotify destroy_data)
{
  GClosure *closure;
  
  g_return_val_if_fail (callback_func != NULL, NULL);
  
  closure = g_closure_new_simple (sizeof (GCClosure), user_data);
  if (destroy_data)
    g_closure_add_finalize_notifier (closure, user_data, destroy_data);
  ((GCClosure*) closure)->callback = (gpointer) callback_func;
  
  return closure;
}
Exemple #6
0
static inline GClosure* mgtk_closure_new(gpointer callback_id) {
  GClosure *closure;

  /*    printf("register id = %i\n",(int) callback_id);
   */
  closure = g_closure_new_simple(sizeof(GClosure), 
                                 callback_id);

  g_closure_set_marshal (closure, mgtk_callback_dispatch);

  g_closure_add_finalize_notifier (closure, 
                                   callback_id, 
                                   mgtk_callback_destroy);

  return closure;
}
/**
 * Create one of our custom GClosure subclasses. To save us having to export
 * it, however, we just return the GClosure* that it extends.
 */
GClosure*
bindings_java_closure_new
(
	JNIEnv* env,
	jobject handler,
	jclass receiver,
	const gchar* name,
	guint id
)
{
	GClosure* closure;
	BindingsJavaClosure* bjc;
	
	GSignalQuery info;

	GString* buf;
	guint i;

	gchar* methodName;
	gchar* methodSignature;
	
	/*
	 * First we allocate the closure and do the footwork to tell it what
	 * its marshaller is
	 */

	closure = g_closure_new_simple(sizeof(BindingsJavaClosure), NULL);
	g_closure_add_finalize_notifier(closure, NULL, bindings_java_closure_destroy);
	g_closure_set_marshal(closure, bindings_java_marshaller);

	bjc = (BindingsJavaClosure*) closure;

	/*
	 * And now we begin the legwork of figuring out what the methodID of
	 * the callback to be invoked is and caching that in the closure. We
	 * get the GSignalQuery data for the specified signal and then use that
	 * to formulate a string that can be use to lookup the method.
	 */

	g_signal_query(id, &info);

	switch(G_TYPE_FUNDAMENTAL(info.return_type)) {
	case G_TYPE_BOOLEAN:
		bjc->returnType = 'Z';
      		break;

	case G_TYPE_INT:
		bjc->returnType = 'I';
		break;

	case G_TYPE_ENUM:
		bjc->returnType = 'E';
      		break;

	case G_TYPE_STRING:
		/*
		 * Strings are encoded as java.lang.String objects in signatures,
		 * so we use the object type marker for gchar* (only).
		 */
		bjc->returnType = 'L';
      		break;

	case G_TYPE_NONE:
		bjc->returnType = 'V';
		break;

	default:
		g_critical("Don't know what to do with signal return type %s", g_type_name(info.return_type));
		return NULL;
	}
	

	/*
	 * the name of the methods we invoke is algorithmic: "receiveName",
	 * where Name is a PascalCase version of the signal name we were
	 * passed in.
	 */

	buf = g_string_new("receive");

	gchar** tokens = g_strsplit_set(name, "_-:", -1);

	for (i = 0; i < g_strv_length(tokens); i++) {
		gchar* token = tokens[i];

		if (token[0] == '\0') {
			// skip past :: which splits signal name from "detail"
			continue;
		}

		gchar first = g_unichar_toupper(token[0]);
		g_string_append_c(buf, first);

		token++;
		g_string_append(buf, token);
	}

	methodName = buf->str;

	g_string_free(buf, FALSE);
	g_strfreev(tokens);

	/*
	 * And here is the tricky bit: formulate the method signature that goes
	 * along with this signal. A method of the signature
	 *
	 * 	boolean method(int, long, String)
	 *
	 * has a JNI encoding of
	 *
	 * 	(IJLjava/util/String;)Z
	 */

	buf = g_string_new("(Lorg/gnome/glib/Signal;J");

	// add the signature for each parameter type
	for(i = 0; i < info.n_params; i++) {
		g_string_append(buf, bindings_java_typeToSignature(info.param_types[i]));
	}

	// and the return type
	g_string_append(buf, ")");
	g_string_append(buf, bindings_java_typeToSignature(info.return_type));
	
	methodSignature = buf->str;
	g_string_free(buf, FALSE);
	
	/*
	 * Now at last we can lookup the method ID
	 */
	
//	jclass CANDIDATE = (*env)->FindClass(env, "org/gnome/gtk/GtkWidget");
//	if ((*env)->IsSameObject(env, CANDIDATE, receiver)) {
//		g_debug("Received a GtkWidget");
//	}

	bjc->receiver = receiver;
	bjc->method = (*env)->GetStaticMethodID(env, bjc->receiver, methodName, methodSignature);
	
//	g_debug("Looking for\nJava method %s\nwith signature %s\nin class %s\nto handle signal %s\n",
//			methodName, methodSignature, "FIXME", g_signal_name(id));

	// clean up	
	g_free(methodName);
	g_free(methodSignature);

	// and check for error
	if (bjc->method == NULL) {
		// Exception already thrown by GetMethodID
		return NULL;
	}

	/*
	 * Set the reference so that the marshaller can find the Signal instance.
	 */

	bjc->handler = (*env)->NewWeakGlobalRef(env, handler);

	/*
	 * And we're done!
	 */
	
	return closure;
}
 EditorClientFrameDestructionObserver(Frame* frame, GClosure* closure)
     : FrameDestructionObserver(frame)
     , m_closure(closure)
 {
     g_closure_add_finalize_notifier(m_closure, this, destroyOnClosureFinalization);
 }