On 2/28/07, Travis Watkins <[EMAIL PROTECTED]> wrote:
Alright, here is my patch. A couple issues:
  * It doesn't seem to register any options for core,
dbusGetOptionsFromPath is failing for some reason
  * it doesn't include introspection for signals as I wasn't quite
sure where they belong
  * It doesn't register/unregister plugins and their screens/options
when you change active_plugins, it should do so
  * It probably leaks like a sieve :)

Also, it needs libxml2 but I wasn't sure how to include this in the
build system. I was doing my work with the standalone Makefile we use
for ported beryl plugins.


Updated patch to latest git. It now handles action and match types
correctly and does introspection for the signals. It also checks for
changes to active_plugins and reregisters everything. A better
solution would be to find out what plugin(s) were added and just
register them. It also doesn't unregister unloaded plugins. Trying to
register something that is already registered spits out a warning on
the console but otherwise is fine.

Remaining problems:
 * need to figure out what to do with activate/deactivate
 * core doesn't get any options registered

--
Travis Watkins
http://www.realistanew.com
diff --git a/configure.ac b/configure.ac
index 4d71729..7010690 100644
--- a/configure.ac
+++ b/configure.ac
@@ -171,7 +171,7 @@ AC_ARG_ENABLE(dbus,
   [use_dbus=$enableval], [use_dbus=yes])
 
 if test "x$use_dbus" = "xyes"; then
-  PKG_CHECK_MODULES(DBUS, dbus-1, [use_dbus=yes], [use_dbus=no])
+  PKG_CHECK_MODULES(DBUS, dbus-1 libxml-2.0, [use_dbus=yes], [use_dbus=no])
 fi
 
 AM_CONDITIONAL(DBUS_PLUGIN, test "x$use_dbus" = "xyes")
diff --git a/plugins/dbus.c b/plugins/dbus.c
index 782ad24..d5f50a3 100644
--- a/plugins/dbus.c
+++ b/plugins/dbus.c
@@ -29,10 +29,13 @@
 
 #define DBUS_API_SUBJECT_TO_CHANGE
 #include <dbus/dbus.h>
+#include <libxml/xmlwriter.h>
 
 #include <compiz.h>
 
 #define COMPIZ_DBUS_SERVICE_NAME	            "org.freedesktop.compiz"
+#define COMPIZ_DBUS_INTERFACE			    "org.freedesktop.compiz"
+#define COMPIZ_DBUS_ROOT_PATH			    "/org/freedesktop/compiz"
 
 #define COMPIZ_DBUS_ACTIVATE_MEMBER_NAME            "activate"
 #define COMPIZ_DBUS_DEACTIVATE_MEMBER_NAME          "deactivate"
@@ -78,6 +81,15 @@ typedef struct _DbusScreen {
     SetScreenOptionForPluginProc setScreenOptionForPlugin;
 } DbusScreen;
 
+static DBusHandlerResult dbusHandleMessage (DBusConnection *,
+					    DBusMessage *,
+					    void *);
+
+static DBusObjectPathVTable dbus_messages_vtable = {
+        NULL, dbusHandleMessage, /* handler function */
+        NULL, NULL, NULL, NULL
+};
+
 #define GET_DBUS_DISPLAY(d)				     \
     ((DbusDisplay *) (d)->privates[displayPrivateIndex].ptr)
 
@@ -150,6 +162,587 @@ dbusGetOptionsFromPath (CompDisplay *d,
     return NULL;
 }
 
+/* functions to create introspection XML */
+static void
+dbusIntrospectStartInterface (xmlTextWriterPtr writer)
+{
+	xmlTextWriterStartElement (writer, BAD_CAST "interface");
+	xmlTextWriterWriteAttribute (writer, BAD_CAST "name",
+								 BAD_CAST COMPIZ_DBUS_SERVICE_NAME);
+}
+
+static void
+dbusIntrospectEndInterface (xmlTextWriterPtr writer)
+{
+    xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectAddArgument (xmlTextWriterPtr writer, char *type, char *direction)
+{
+    xmlTextWriterStartElement (writer, BAD_CAST "arg");
+    xmlTextWriterWriteAttribute (writer, BAD_CAST "type", BAD_CAST type);
+    xmlTextWriterWriteAttribute (writer, BAD_CAST "direction",
+				 BAD_CAST direction);
+    xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectAddMethod (xmlTextWriterPtr writer, char *name, int nArgs, ...)
+{
+    va_list var_args;
+    char *type, *direction;
+
+    xmlTextWriterStartElement (writer, BAD_CAST "method");
+    xmlTextWriterWriteAttribute (writer, BAD_CAST "name", BAD_CAST name);
+
+    va_start (var_args, nArgs);
+    while (nArgs)
+    {
+	type = va_arg (var_args, char *);
+	direction = va_arg (var_args, char *);
+	dbusIntrospectAddArgument (writer, type, direction);
+	nArgs--;
+    }
+    va_end (var_args);
+
+    xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectAddSignal (xmlTextWriterPtr writer, char *name, int nArgs, ...)
+{
+    va_list var_args;
+    char *type;
+
+    xmlTextWriterStartElement (writer, BAD_CAST "signal");
+    xmlTextWriterWriteAttribute (writer, BAD_CAST "name", BAD_CAST name);
+
+    va_start (var_args, nArgs);
+    while (nArgs)
+    {
+	type = va_arg (var_args, char *);
+	dbusIntrospectAddArgument (writer, type, "out");
+	nArgs--;
+    }
+    va_end (var_args);
+
+    xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectAddNode (xmlTextWriterPtr writer, char *name)
+{
+    xmlTextWriterStartElement (writer, BAD_CAST "node");
+    xmlTextWriterWriteAttribute (writer, BAD_CAST "name", BAD_CAST name);
+    xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectStartRoot (xmlTextWriterPtr writer)
+{
+    xmlTextWriterStartElement (writer, BAD_CAST "node");
+
+    xmlTextWriterStartElement (writer, BAD_CAST "interface");
+    xmlTextWriterWriteAttribute (writer, BAD_CAST "name",
+				 BAD_CAST "org.freedesktop.DBus.Introspectable");
+
+    dbusIntrospectAddMethod (writer, "Introspect", 1, "s", "out");
+
+    xmlTextWriterEndElement (writer);
+}
+
+static void
+dbusIntrospectEndRoot (xmlTextWriterPtr writer)
+{
+    xmlTextWriterEndDocument (writer);
+}
+
+/* introspection handlers */
+static Bool
+dbusHandleRootIntrospectMessage (DBusConnection *connection,
+				 DBusMessage    *message,
+				 CompDisplay	*d)
+{
+    char **plugins, **plugin_name;
+    int nPlugins;
+
+    xmlTextWriterPtr writer;
+    xmlBufferPtr buf;
+
+    buf = xmlBufferCreate ();
+    writer = xmlNewTextWriterMemory (buf, 0);
+
+    dbusIntrospectStartRoot (writer);
+    dbusIntrospectStartInterface (writer);
+
+    dbusIntrospectAddMethod (writer, COMPIZ_DBUS_GET_PLUGINS_MEMBER_NAME, 1,
+			     "as", "out");
+    dbusIntrospectAddMethod (writer,
+			     COMPIZ_DBUS_GET_PLUGIN_METADATA_MEMBER_NAME, 7,
+			     "s", "in", "s", "out", "s", "out", "s", "out",
+			     "b", "out", "as", "out", "as", "out");
+    dbusIntrospectAddSignal (writer,
+			     COMPIZ_DBUS_PLUGINS_CHANGED_SIGNAL_NAME, 0);
+
+    dbusIntrospectEndInterface (writer);
+
+    plugins = availablePlugins (&nPlugins);
+    if (plugins)
+    {
+	plugin_name = plugins;
+
+	while (nPlugins--)
+	{
+	    dbusIntrospectAddNode (writer, *plugin_name);
+	    free (*plugin_name);
+	    plugin_name++;
+	}
+
+	free (plugins);
+    }
+    else
+    {
+	xmlFreeTextWriter (writer);
+	xmlBufferFree (buf);
+	return FALSE;
+    }
+
+    dbusIntrospectAddNode (writer, "core");
+
+    dbusIntrospectEndRoot (writer);
+
+    xmlFreeTextWriter (writer);
+
+    DBusMessage *reply = dbus_message_new_method_return (message);
+    if (!reply)
+    {
+	xmlBufferFree (buf);
+	return FALSE;
+    }
+
+    DBusMessageIter args;
+    dbus_message_iter_init_append (reply, &args);
+
+    if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING,
+					 &buf->content))
+    {
+	xmlBufferFree (buf);
+	return FALSE;
+    }
+
+    xmlBufferFree (buf);
+
+    if (!dbus_connection_send (connection, reply, NULL))
+    {
+	return FALSE;
+    }
+
+    dbus_connection_flush (connection);
+    dbus_message_unref (reply);
+
+    return TRUE;
+}
+
+static Bool
+dbusHandlePluginIntrospectMessage (DBusConnection *connection,
+				    DBusMessage   *message,
+				    CompDisplay	  *d,
+				    char          **path)
+{
+    CompScreen *s;
+    CompPlugin *p;
+    char screen_name[256];
+
+    xmlTextWriterPtr writer;
+    xmlBufferPtr buf;
+
+    buf = xmlBufferCreate ();
+    writer = xmlNewTextWriterMemory (buf, 0);
+
+    dbusIntrospectStartRoot (writer);
+
+    p = findActivePlugin (path[0]);
+
+    if (path[0] && (strcmp (path[0], "core") == 0 || p))
+    {
+	if ((strcmp (path[0], "core") == 0) || p->vTable->getDisplayOptions)
+	    dbusIntrospectAddNode (writer, "allscreens");
+
+	if ((strcmp (path[0], "core") == 0) || p->vTable->getScreenOptions)
+	{
+	    for (s = d->screens; s; s = s->next)
+	    {
+		sprintf (screen_name, "screen%d", s->screenNum);
+		dbusIntrospectAddNode (writer, screen_name);
+	    }
+	}
+    }
+
+    dbusIntrospectEndRoot (writer);
+
+    xmlFreeTextWriter (writer);
+
+    DBusMessage *reply = dbus_message_new_method_return (message);
+    if (!reply)
+    {
+	xmlBufferFree (buf);
+	return FALSE;
+    }
+
+    DBusMessageIter args;
+    dbus_message_iter_init_append (reply, &args);
+
+    if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING,
+					 &buf->content))
+    {
+	xmlBufferFree (buf);
+	return FALSE;
+    }
+
+    xmlBufferFree (buf);
+
+    if (!dbus_connection_send (connection, reply, NULL))
+    {
+	return FALSE;
+    }
+
+    dbus_connection_flush (connection);
+    dbus_message_unref (reply);
+
+    return TRUE;
+}
+
+static Bool
+dbusHandleScreenIntrospectMessage (DBusConnection *connection,
+				    DBusMessage   *message,
+				    CompDisplay	  *d,
+				    char          **path)
+{
+    CompOption *option = NULL;
+    int nOptions;
+
+    xmlTextWriterPtr writer;
+    xmlBufferPtr buf;
+
+    buf = xmlBufferCreate ();
+    writer = xmlNewTextWriterMemory (buf, 0);
+
+    dbusIntrospectStartRoot (writer);
+    dbusIntrospectStartInterface (writer);
+
+    dbusIntrospectAddMethod (writer, COMPIZ_DBUS_LIST_MEMBER_NAME, 1,
+			     "as", "out");
+
+    dbusIntrospectEndInterface (writer);
+
+    option = dbusGetOptionsFromPath (d, path, NULL, &nOptions);
+    if (!option)
+    {
+	xmlFreeTextWriter (writer);
+	xmlBufferFree (buf);
+	return FALSE;
+    }
+
+    while (nOptions--)
+    {
+	dbusIntrospectAddNode (writer, option->name);
+	option++;
+    }
+
+    dbusIntrospectEndRoot (writer);
+
+    xmlFreeTextWriter (writer);
+
+    DBusMessage *reply = dbus_message_new_method_return (message);
+    if (!reply)
+    {
+	xmlBufferFree (buf);
+	return FALSE;
+    }
+
+    DBusMessageIter args;
+    dbus_message_iter_init_append (reply, &args);
+
+    if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING,
+					 &buf->content))
+    {
+	xmlBufferFree (buf);
+	return FALSE;
+    }
+
+    xmlBufferFree (buf);
+
+    if (!dbus_connection_send (connection, reply, NULL))
+    {
+	return FALSE;
+    }
+
+    dbus_connection_flush (connection);
+    dbus_message_unref (reply);
+
+    return TRUE;
+}
+
+static Bool
+dbusHandleOptionIntrospectMessage (DBusConnection *connection,
+				    DBusMessage   *message,
+				    CompDisplay	  *d,
+				    char          **path)
+{
+    CompOption *option;
+    int nOptions;
+    CompOptionType restrictionType;
+    xmlTextWriterPtr writer;
+    xmlBufferPtr buf;
+    Bool is_list = FALSE;
+
+    buf = xmlBufferCreate ();
+    writer = xmlNewTextWriterMemory (buf, 0);
+
+    dbusIntrospectStartRoot (writer);
+    dbusIntrospectStartInterface (writer);
+
+    option = dbusGetOptionsFromPath (d, path, NULL, &nOptions);
+    if (!option)
+    {
+	xmlFreeTextWriter (writer);
+	xmlBufferFree (buf);
+	return FALSE;
+    }
+
+    while (nOptions--)
+    {
+	if (strcmp (option->name, path[2]) == 0)
+	{
+	    restrictionType = option->type;
+	    if (restrictionType == CompOptionTypeList)
+	    {
+		restrictionType = option->value.list.type;
+		is_list = TRUE;
+	    }
+
+	    switch (restrictionType)
+	    {
+	    case CompOptionTypeInt:
+		if (is_list)
+		{
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+					     "ai", "out");
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+					     "ai", "in");
+		    dbusIntrospectAddSignal (writer,
+					     COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+					     "ai", "out");
+		}
+		else
+		{
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+					     "i", "out");
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+					     "i", "in");
+		    dbusIntrospectAddSignal (writer,
+					     COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+					     "i", "out");
+		}
+
+		dbusIntrospectAddMethod (writer,
+					 COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+					 6, "s", "out", "s", "out",
+					 "b", "out", "s", "out",
+					 "i", "out", "i", "out");
+		break;
+	    case CompOptionTypeFloat:
+		if (is_list)
+		{
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+					     "ad", "out");
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+					     "ad", "in");
+		    dbusIntrospectAddSignal (writer,
+					     COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+					     "ad", "out");
+		}
+		else
+		{
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+					     "d", "out");
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+					     "d", "in");
+		    dbusIntrospectAddSignal (writer,
+					     COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+					     "d", "out");
+		}
+
+		dbusIntrospectAddMethod (writer,
+					 COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+					 7, "s", "out", "s", "out",
+					 "b", "out", "s", "out",
+					 "d", "out", "d", "out",
+					 "d", "out");
+		break;
+	    case CompOptionTypeString:
+		if (is_list)
+		{
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+					     "as", "out");
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+					     "as", "in");
+		    dbusIntrospectAddSignal (writer,
+					     COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+					     "as", "out");
+		}
+		else
+		{
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+					     "s", "out");
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+					     "s", "in");
+		    dbusIntrospectAddSignal (writer,
+					     COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+					     "s", "out");
+		}
+
+		dbusIntrospectAddMethod (writer,
+					 COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+					 5, "s", "out", "s", "out",
+					 "b", "out", "s", "out",
+					 "as", "out");
+		break;
+	    case CompOptionTypeBool:
+		if (is_list)
+		{
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+					     "ab", "out");
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+					     "ab", "in");
+		    dbusIntrospectAddSignal (writer,
+					     COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+					     "ab", "out");
+		}
+		else
+		{
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+					     "b", "out");
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+					     "b", "in");
+		    dbusIntrospectAddSignal (writer,
+					     COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+					     "b", "out");
+		}
+
+		dbusIntrospectAddMethod (writer,
+					 COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+					 4, "s", "out", "s", "out",
+					 "b", "out", "s", "out");
+		break;
+	    case CompOptionTypeAction:
+		dbusIntrospectAddMethod (writer, COMPIZ_DBUS_GET_MEMBER_NAME,
+					    5, "s", "out", "s", "out",
+					    "b", "out", "s", "out", "i", "out");
+		dbusIntrospectAddMethod (writer, COMPIZ_DBUS_SET_MEMBER_NAME,
+					    5, "s", "in", "s", "in",
+					    "b", "in", "s", "in", "i", "in");
+		dbusIntrospectAddSignal (writer,
+					 COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 5,
+					 "s", "out", "s", "out", "b", "out",
+					 "s", "out", "i", "out");
+
+		dbusIntrospectAddMethod (writer,
+					 COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+					 4, "s", "out", "s", "out",
+					 "b", "out", "s", "out");
+		break;
+	    case CompOptionTypeColor:
+	    case CompOptionTypeMatch:
+		if (is_list)
+		{
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+					     "as", "out");
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+					     "as", "in");
+		    dbusIntrospectAddSignal (writer,
+					     COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+					     "as", "out");
+		}
+		else
+		{
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+					     "s", "out");
+		    dbusIntrospectAddMethod (writer,
+					     COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+					     "s", "in");
+		    dbusIntrospectAddSignal (writer,
+					     COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+					     "s", "out");
+		}
+
+		dbusIntrospectAddMethod (writer,
+					 COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+					 4, "s", "out", "s", "out",
+					 "b", "out", "s", "out");
+		break;
+	    }
+	}
+
+	option++;
+    }
+
+    dbusIntrospectEndInterface (writer);
+    dbusIntrospectEndRoot (writer);
+
+    xmlFreeTextWriter (writer);
+
+    DBusMessage *reply = dbus_message_new_method_return (message);
+    if (!reply)
+    {
+	xmlBufferFree (buf);
+	return FALSE;
+    }
+
+    DBusMessageIter args;
+    dbus_message_iter_init_append (reply, &args);
+
+    if (!dbus_message_iter_append_basic (&args, DBUS_TYPE_STRING,
+					 &buf->content))
+    {
+	xmlBufferFree (buf);
+	return FALSE;
+    }
+
+    xmlBufferFree (buf);
+
+    if (!dbus_connection_send (connection, reply, NULL))
+    {
+	return FALSE;
+    }
+
+    dbus_connection_flush (connection);
+    dbus_message_unref (reply);
+
+    return TRUE;
+}
+
+
 /*
  * Activate can be used to trigger any existing action. Arguments
  * should be a pair of { string, bool|int32|double|string }.
@@ -1212,20 +1805,6 @@ dbusHandleMessage (DBusConnection *connection,
     CompDisplay *d = (CompDisplay *) userData;
     Bool	status = FALSE;
     char	**path;
-    const char  *service, *interface, *member;
-
-    service   = dbus_message_get_destination (message);
-    interface = dbus_message_get_interface (message);
-    member    = dbus_message_get_member (message);
-
-    if (!service || !interface || !member)
-	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-    if (!dbus_message_is_method_call (message, interface, member))
-	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-    if (!dbus_message_has_destination (message, COMPIZ_DBUS_SERVICE_NAME))
-	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
 
     if (!dbus_message_get_path_decomposed (message, &path))
 	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -1236,75 +1815,105 @@ dbusHandleMessage (DBusConnection *connection,
 	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
     }
 
-    if (strcmp (path[0], "org")	        ||
-	strcmp (path[1], "freedesktop") ||
-	strcmp (path[2], "compiz"))
+    //root messages
+    if (!path[3])
     {
-	dbus_free_string_array (path);
-	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-    }
-
-    if (dbus_message_has_member (message,
+	if (dbus_message_is_method_call (message, DBUS_INTERFACE_INTROSPECTABLE,
+					 "Introspect"))
+	{
+	    if (dbusHandleRootIntrospectMessage (connection, message, d))
+	    {
+		dbus_free_string_array (path);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	    }
+	}
+	else if (dbus_message_is_method_call (message, COMPIZ_DBUS_INTERFACE,
 				 COMPIZ_DBUS_GET_PLUGIN_METADATA_MEMBER_NAME))
-    {
-	if (dbusHandleGetPluginMetadataMessage (connection, message, d))
 	{
-	    dbus_free_string_array (path);
-	    return DBUS_HANDLER_RESULT_HANDLED;
+	    if (dbusHandleGetPluginMetadataMessage (connection, message, d))
+	    {
+		dbus_free_string_array (path);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	    }
 	}
-    }
-    else if (dbus_message_has_member (message,
-				      COMPIZ_DBUS_GET_PLUGINS_MEMBER_NAME))
-    {
-	if (dbusHandleGetPluginsMessage (connection, message, d))
+	else if (dbus_message_is_method_call (message, COMPIZ_DBUS_INTERFACE,
+					  COMPIZ_DBUS_GET_PLUGINS_MEMBER_NAME))
 	{
-	    dbus_free_string_array (path);
-	    return DBUS_HANDLER_RESULT_HANDLED;
+	    if (dbusHandleGetPluginsMessage (connection, message, d))
+	    {
+		dbus_free_string_array (path);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	    }
 	}
     }
-
-    if (!path[3] || !path[4])
+    //plugin message
+    else if (!path[4])
     {
-	dbus_free_string_array (path);
-	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+	if (dbus_message_is_method_call (message, DBUS_INTERFACE_INTROSPECTABLE,
+					 "Introspect"))
+	{
+	    if (dbusHandlePluginIntrospectMessage (connection, message, d,
+						   &path[3]))
+	    {
+		dbus_free_string_array (path);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	    }
+	}
     }
-
-    if (dbus_message_has_member (message, COMPIZ_DBUS_LIST_MEMBER_NAME))
+    //screen message
+    else if (!path[5])
     {
-	if (dbusHandleListMessage (connection, message, d, &path[3]))
+	if (dbus_message_is_method_call (message, DBUS_INTERFACE_INTROSPECTABLE,
+					 "Introspect"))
+	{
+	    if (dbusHandleScreenIntrospectMessage (connection, message, d,
+						   &path[3]))
+	    {
+		dbus_free_string_array (path);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	    }
+	}
+	else if (dbus_message_is_method_call (message, COMPIZ_DBUS_INTERFACE,
+					      COMPIZ_DBUS_LIST_MEMBER_NAME))
 	{
-	    dbus_free_string_array (path);
-	    return DBUS_HANDLER_RESULT_HANDLED;
+	    if (dbusHandleListMessage (connection, message, d, &path[3]))
+	    {
+		dbus_free_string_array (path);
+		return DBUS_HANDLER_RESULT_HANDLED;
+	    }
 	}
     }
-
-    if (!path[5])
+    //option message
+    if (dbus_message_is_method_call (message, DBUS_INTERFACE_INTROSPECTABLE,
+				     "Introspect"))
     {
-	dbus_free_string_array (path);
-	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+	status = dbusHandleOptionIntrospectMessage (connection, message, d,
+						    &path[3]);
     }
-
-    if (dbus_message_has_member (message, COMPIZ_DBUS_ACTIVATE_MEMBER_NAME))
+    else if (dbus_message_is_method_call (message, COMPIZ_DBUS_INTERFACE,
+					  COMPIZ_DBUS_ACTIVATE_MEMBER_NAME))
     {
 	status = dbusHandleActionMessage (connection, message, d, &path[3],
 					  TRUE);
     }
-    else if (dbus_message_has_member (message,
-				      COMPIZ_DBUS_DEACTIVATE_MEMBER_NAME))
+    else if (dbus_message_is_method_call (message, COMPIZ_DBUS_INTERFACE,
+					  COMPIZ_DBUS_DEACTIVATE_MEMBER_NAME))
     {
 	status = dbusHandleActionMessage (connection, message, d, &path[3],
 					  FALSE);
     }
-    else if (dbus_message_has_member (message, COMPIZ_DBUS_SET_MEMBER_NAME))
+    else if (dbus_message_is_method_call (message, COMPIZ_DBUS_INTERFACE,
+					  COMPIZ_DBUS_SET_MEMBER_NAME))
     {
 	status = dbusHandleSetOptionMessage (connection, message, d, &path[3]);
     }
-    else if (dbus_message_has_member (message, COMPIZ_DBUS_GET_MEMBER_NAME))
+    else if (dbus_message_is_method_call (message, COMPIZ_DBUS_INTERFACE,
+					  COMPIZ_DBUS_GET_MEMBER_NAME))
     {
 	status = dbusHandleGetOptionMessage (connection, message, d, &path[3]);
     }
-    else if (dbus_message_has_member (message,
-				      COMPIZ_DBUS_GET_METADATA_MEMBER_NAME))
+    else if (dbus_message_is_method_call (message, COMPIZ_DBUS_INTERFACE,
+					  COMPIZ_DBUS_GET_METADATA_MEMBER_NAME))
     {
 	status = dbusHandleGetMetadataMessage (connection, message, d,
 					       &path[3]);
@@ -1367,7 +1976,7 @@ dbusSendChangeSignalForDisplayOption (CompDisplay *d,
 
     if (o)
     {
-	sprintf (path, "/org/freedesktop/compiz/%s/allscreens/%s",
+	sprintf (path, "%s/%s/allscreens/%s", COMPIZ_DBUS_ROOT_PATH,
 		 plugin, o->name);
 	dbusSendChangeSignalForOption (d, o->type, &o->value, path);
     }
@@ -1382,12 +1991,168 @@ dbusSendChangeSignalForScreenOption (CompScreen *s,
 
     if (o)
     {
-	sprintf (path, "/org/freedesktop/compiz/%s/screens%d/%s",
+	sprintf (path, "%s/%s/screens%d/%s", COMPIZ_DBUS_ROOT_PATH,
 		 plugin, s->screenNum, o->name);
 	dbusSendChangeSignalForOption (s->display, o->type, &o->value, path);
     }
 }
 
+/* dbus registration */
+static Bool
+dbusRegisterOptions (DBusConnection *connection,
+		     CompDisplay    *d,
+		     char           *screen_path,
+		     char           *plugin_name,
+		     CompScreen     *s)
+{
+    CompPlugin *p;
+    CompOption *option = NULL;
+    int nOptions, size;
+    char *option_path;
+
+    if (strcmp (plugin_name, "core") == 0)
+    {
+	if (s)
+	    option = compGetScreenOptions (s, &nOptions);
+	else
+	    option = compGetDisplayOptions (d, &nOptions);
+    }
+    else
+    {
+	p = findActivePlugin (plugin_name);
+	if (p)
+	{
+	    if (s)
+	    {
+		if (p->vTable->getScreenOptions)
+		    option = (*p->vTable->getScreenOptions) (s, &nOptions);
+	    }
+	    else
+	    {
+		if (p->vTable->getDisplayOptions)
+		    option = (*p->vTable->getDisplayOptions) (d, &nOptions);
+	    }
+	}
+	else
+	{
+	    return FALSE;
+	}
+    }
+
+    if (!option)
+	return FALSE;
+
+    while (nOptions--)
+    {
+	size = strlen (screen_path) + strlen (option->name) + 2;
+	option_path = malloc (size);
+	snprintf (option_path, size, "%s/%s", screen_path, option->name);
+	dbus_connection_register_object_path (connection, option_path,
+					      &dbus_messages_vtable, d);
+	free (option_path);
+	option++;
+    }
+
+    return TRUE;
+}
+
+static Bool
+dbusRegisterScreens (DBusConnection *connection,
+		     CompDisplay    *d,
+		     char           *plugin_name)
+{
+    CompScreen *s;
+    CompPlugin *p;
+    char *screen_path;
+    int size;
+
+    //we only want to register these if they have options under them
+    p = findActivePlugin (plugin_name);
+
+    if ((strcmp (plugin_name, "core") == 0) || p->vTable->getDisplayOptions)
+    {
+	//root path + plugin name + "allscreens" + separators + \0
+	size = strlen (COMPIZ_DBUS_ROOT_PATH) + strlen (plugin_name) + 13;
+	screen_path = malloc (size);
+	snprintf (screen_path, size, "%s/%s/%s",
+		  COMPIZ_DBUS_ROOT_PATH, plugin_name, "allscreens");
+	dbus_connection_register_object_path (connection, screen_path,
+					      &dbus_messages_vtable, d);
+	dbusRegisterOptions (connection, d, screen_path, plugin_name, NULL);
+	free (screen_path);
+    }
+
+    if ((strcmp (plugin_name, "core") == 0) || p->vTable->getScreenOptions)
+    {
+	for (s = d->screens; s; s = s->next)
+	{
+	    //root path + plugin name + "screen" + screen number + separators + \0
+	    size = strlen (COMPIZ_DBUS_ROOT_PATH) + strlen (plugin_name) + 10;
+	    screen_path = malloc (size);
+	    snprintf (screen_path, size, "%s/%s/screen%d",
+		      COMPIZ_DBUS_ROOT_PATH, plugin_name, s->screenNum);
+	    dbus_connection_register_object_path (connection, screen_path,
+						  &dbus_messages_vtable, d);
+	    dbusRegisterOptions (connection, d, screen_path, plugin_name, s);
+	    free (screen_path);
+	}
+    }
+
+    return TRUE;
+}
+
+static void
+dbusRegisterPlugin (DBusConnection *connection,
+		    CompDisplay    *d,
+		    char *plugin_name)
+{
+    int size;
+    char *plugin_path;
+
+    //root path + plugin name + separator + \0
+    size = strlen (COMPIZ_DBUS_ROOT_PATH) + strlen (plugin_name) + 2;
+    plugin_path = malloc (size);
+    snprintf (plugin_path, size, "%s/%s", COMPIZ_DBUS_ROOT_PATH, plugin_name);
+    dbus_connection_register_object_path (connection, plugin_path,
+					  &dbus_messages_vtable, d);
+
+    //if plugin is loaded we need to register screens for it
+    if (findActivePlugin (plugin_name))
+	dbusRegisterScreens (connection, d, plugin_name);
+
+    free (plugin_path);
+}
+
+
+static Bool
+dbusRegisterPlugins (DBusConnection *connection,
+		     CompDisplay    *d)
+{
+    int nPlugins;
+    char **plugins, **plugin_name;
+
+    //register core 'plugin'
+    dbusRegisterPlugin (connection, d, "core");
+
+    plugins = availablePlugins (&nPlugins);
+    if (plugins)
+    {
+	plugin_name = plugins;
+	while (nPlugins--)
+	{
+		dbusRegisterPlugin (connection, d, *plugin_name);
+		free (*plugin_name);
+		plugin_name++;
+	}
+
+	free (plugins);
+	return TRUE;
+    }
+
+    return FALSE;
+}
+
+
 static Bool
 dbusSetDisplayOption (CompDisplay     *d,
 		      char	      *name,
@@ -1403,6 +2168,9 @@ dbusSetDisplayOption (CompDisplay     *d,
 
     if (status)
     {
+	if (strcmp (name, "active_plugins") == 0)
+	    dbusRegisterPlugins (dd->connection, d);
+
 	CompOption *option;
 	int	   nOption;
 
@@ -1526,7 +2294,7 @@ dbusSendPluginsChangedSignal (const char *name,
 
     DBUS_DISPLAY (d);
 
-    signal = dbus_message_new_signal ("/org/freedesktop/compiz",
+    signal = dbus_message_new_signal (COMPIZ_DBUS_ROOT_PATH,
 				      COMPIZ_DBUS_SERVICE_NAME,
 				      COMPIZ_DBUS_PLUGINS_CHANGED_SIGNAL_NAME);
 
@@ -1602,19 +2370,12 @@ dbusInitDisplay (CompPlugin  *p,
 	return FALSE;
     }
 
-    status = dbus_connection_add_filter (dd->connection,
-					 dbusHandleMessage,
-					 d, NULL);
-    if (!status)
-    {
-	fprintf (stderr, "%s: dbus_connection_add_filter failed\n",
-		 programName);
+    //register the objects
+    dbus_connection_register_object_path (dd->connection,
+					  COMPIZ_DBUS_ROOT_PATH,
+					  &dbus_messages_vtable, d);
 
-	/* dbus_connection_unref (dd->connection); */
-	free (dd);
-
-	return FALSE;
-    }
+    dbusRegisterPlugins (dd->connection, d);
 
     status = dbus_connection_get_unix_fd (dd->connection, &fd);
     if (!status)
_______________________________________________
compiz mailing list
compiz@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/compiz

Reply via email to