Mercurial > emacs
diff src/dbusbind.c @ 87175:30175fd3b679
* dbusbind.c (xd_read_message): Generate an event for every
registered handler. There might be several handlers registered
for the same signal.
(Fdbus_register_signal): Don't overwrite a registration for the
same signal. Add a new registration if handlers are different.
(Vdbus_registered_functions_table): Rework doc string.
author | Michael Albinus <michael.albinus@gmx.de> |
---|---|
date | Sat, 08 Dec 2007 12:53:37 +0000 |
parents | e0ab56e63db8 |
children | e0d7140e5b0e |
line wrap: on
line diff
--- a/src/dbusbind.c Sat Dec 08 09:55:50 2007 +0000 +++ b/src/dbusbind.c Sat Dec 08 12:53:37 2007 +0000 @@ -543,14 +543,14 @@ xd_read_message (bus) Lisp_Object bus; { - Lisp_Object key; + Lisp_Object args, key, value; struct gcpro gcpro1; static struct input_event event; DBusConnection *connection; DBusMessage *dmessage; DBusMessageIter iter; uint dtype; - char service[DBUS_MAXIMUM_NAME_LENGTH]; + char uname[DBUS_MAXIMUM_NAME_LENGTH]; char path[DBUS_MAXIMUM_MATCH_RULE_LENGTH]; /* Unlimited in D-Bus spec. */ char interface[DBUS_MAXIMUM_NAME_LENGTH]; char member[DBUS_MAXIMUM_NAME_LENGTH]; @@ -566,16 +566,11 @@ if (dmessage == NULL) return; - /* There is a message in the queue. Construct the D-Bus event. */ XD_DEBUG_MESSAGE ("Event received"); - EVENT_INIT (event); - - event.kind = DBUS_EVENT; - event.frame_or_window = Qnil; /* Collect the parameters. */ - event.arg = Qnil; - GCPRO1 (event.arg); + args = Qnil; + GCPRO1 (args); if (!dbus_message_iter_init (dmessage, &iter)) { @@ -587,44 +582,59 @@ /* Loop over the resulting parameters. Construct a list. */ while ((dtype = dbus_message_iter_get_arg_type (&iter)) != DBUS_TYPE_INVALID) { - event.arg = Fcons (xd_retrieve_arg (dtype, &iter), event.arg); + args = Fcons (xd_retrieve_arg (dtype, &iter), args); dbus_message_iter_next (&iter); } /* The arguments are stored in reverse order. Reorder them. */ - event.arg = Fnreverse (event.arg); + args = Fnreverse (args); - /* Read service, object path, interface and member from the message. - The service is always the unique name of the sending object. */ - strcpy (service, dbus_message_get_sender (dmessage)); + /* Read unique name, object path, interface and member from the + message. */ + strcpy (uname, dbus_message_get_sender (dmessage)); strcpy (path, dbus_message_get_path (dmessage)); strcpy (interface, dbus_message_get_interface (dmessage)); strcpy (member, dbus_message_get_member (dmessage)); - /* Add the registered function of the message. */ - key = list5 (bus, - (service == NULL ? Qnil : build_string (service)), - (path == NULL ? Qnil : build_string (path)), - (interface == NULL ? Qnil : build_string (interface)), - (member == NULL ? Qnil : build_string (member))); - event.arg = Fcons (Fgethash (key, Vdbus_registered_functions_table, Qnil), - event.arg); + /* Search for a registered function of the message. */ + key = list3 (bus, build_string (interface), build_string (member)); + value = Fgethash (key, Vdbus_registered_functions_table, Qnil); + + /* Loop over the registered functions. Construct an event. */ + while (!NILP (value)) + { + key = XCAR (value); + /* key has the structure (SERVICE UNAME PATH HANDLER). */ + if (((uname == NULL) || (NILP (XCAR (XCDR (key)))) || + (strcmp (uname, SDATA (XCAR (XCDR (key)))) == 0)) && + ((path == NULL) || (NILP (XCAR (XCDR (XCDR (key))))) || + (strcmp (path, SDATA (XCAR (XCDR (XCDR (key))))) == 0)) && + (!NILP (XCAR (XCDR (XCDR (XCDR (key))))))) + { + EVENT_INIT (event); + event.kind = DBUS_EVENT; + event.frame_or_window = Qnil; + event.arg = Fcons (XCAR (XCDR (XCDR (XCDR (key)))), args); - /* Add service, path, interface and member to the event. */ - event.arg = Fcons ((member == NULL ? Qnil : build_string (member)), - event.arg); - event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)), - event.arg); - event.arg = Fcons ((path == NULL ? Qnil : build_string (path)), - event.arg); - event.arg = Fcons ((service == NULL ? Qnil : build_string (service)), - event.arg); + /* Add uname, path, interface and member to the event. */ + event.arg = Fcons ((member == NULL ? Qnil : build_string (member)), + event.arg); + event.arg = Fcons ((interface == NULL + ? Qnil : build_string (interface)), + event.arg); + event.arg = Fcons ((path == NULL ? Qnil : build_string (path)), + event.arg); + event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)), + event.arg); - /* Add the bus symbol to the event. */ - event.arg = Fcons (bus, event.arg); + /* Add the bus symbol to the event. */ + event.arg = Fcons (bus, event.arg); - /* Store it into the input event queue. */ - kbd_buffer_store_event (&event); + /* Store it into the input event queue. */ + kbd_buffer_store_event (&event); + } + value = XCDR (value); + } /* Cleanup. */ dbus_message_unref (dmessage); @@ -683,7 +693,7 @@ (bus, service, path, interface, signal, handler) Lisp_Object bus, service, path, interface, signal, handler; { - Lisp_Object unique_name, key; + Lisp_Object unique_name, key, value; DBusConnection *connection; char rule[DBUS_MAXIMUM_MATCH_RULE_LENGTH]; DBusError derror; @@ -701,6 +711,7 @@ are sent always with the unique name as sender. Note: the unique name of "org.freedesktop.DBus" is that string itself. */ if ((!NILP (service)) && + (strlen (SDATA (service)) > 0) && (strcmp (SDATA (service), DBUS_SERVICE_DBUS) != 0) && (strncmp (SDATA (service), ":", 1) != 0)) unique_name = call2 (intern ("dbus-get-name-owner"), bus, service); @@ -732,16 +743,22 @@ XD_DEBUG_MESSAGE ("Matching rule \"%s\" created", rule); /* Create a hash table entry. */ - key = list5 (bus, unique_name, path, interface, signal); - Fputhash (key, handler, Vdbus_registered_functions_table); - XD_DEBUG_MESSAGE ("\"%s\" registered with handler \"%s\"", - SDATA (format2 ("%s", key, Qnil)), - SDATA (format2 ("%s", handler, Qnil))); + key = list3 (bus, interface, signal); + value = Fgethash (key, Vdbus_registered_functions_table, Qnil); + + if (NILP (Fmember (list4 (service, unique_name, path, handler), value))) + Fputhash (key, + Fcons (list4 (service, unique_name, path, handler), value), + Vdbus_registered_functions_table); /* Return key. */ return key; } +/* The current implementation removes ALL registered functions for a + given signal. Shouldn't be a problem in general, but there might + be cases it is not desired. Maybe we can refine the + implementation. */ DEFUN ("dbus-unregister-signal", Fdbus_unregister_signal, Sdbus_unregister_signal, 1, 1, 0, doc: /* Unregister OBJECT from the D-Bus. @@ -797,15 +814,19 @@ DEFVAR_LISP ("dbus-registered-functions-table", &Vdbus_registered_functions_table, doc: /* Hash table of registered functions for D-Bus. -The key in the hash table is the list (BUS SERVICE PATH MEMBER INTERFACE). -BUS is either the symbol `:system' or the symbol `:session'. SERVICE -and PATH are the unique name and the object path of the sending object. -INTERFACE is a string which denotes a D-Bus interface, and MEMBER, -also a string, is either a method or a signal INTERFACE is offering. -All arguments but BUS can be nil, which means a wild card then. +The key in the hash table is the list (BUS MEMBER INTERFACE). BUS is +either the symbol `:system' or the symbol `:session'. INTERFACE is a +string which denotes a D-Bus interface, and MEMBER, also a string, is +either a method or a signal INTERFACE is offering. All arguments but +BUS must not be nil. -The value in the hash table a the function to be called when a D-Bus -message, which matches the key criteria, arrives. */); +The value in the hash table is a list of triple lists +\((SERVICE UNAME PATH HANDLER) (SERVICE UNAME PATH HANDLER) ...). +SERVICE is the service name as registered, UNAME is the corresponding +unique name. PATH is the object path of the sending object. All of +them be nil, which means a wildcard then. HANDLER is the function to +be called when a D-Bus message, which matches the key criteria, +arrives. */); /* We initialize Vdbus_registered_functions_table in dbus.el, because we need to define a hash table function first. */ Vdbus_registered_functions_table = Qnil;