On 3/1/07, Travis Watkins <[EMAIL PROTECTED]> wrote:
Remaining problems:
  * need to figure out what to do with activate/deactivate
  * core doesn't get any options registered


Updated the patch. It now registers/unregisters plugins on load/unload
by wrapping initPluginForDisplay and friends. I also cleaned the code
up a bit.

Known problems:
 * still don't know what to do with activate/deactivate
 * had to comment out a couple free()s in my added code to make it
work, dunno why

Please comment.

--
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..40ffdf1 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"
@@ -71,13 +74,28 @@ typedef struct _DbusDisplay {
 
     SetDisplayOptionProc	  setDisplayOption;
     SetDisplayOptionForPluginProc setDisplayOptionForPlugin;
+
+    InitPluginForDisplayProc initPluginForDisplay;
+    FiniPluginForDisplayProc finiPluginForDisplay;
 } DbusDisplay;
 
 typedef struct _DbusScreen {
     SetScreenOptionProc		 setScreenOption;
     SetScreenOptionForPluginProc setScreenOptionForPlugin;
+
+    InitPluginForScreenProc initPluginForScreen;
+    FiniPluginForScreenProc finiPluginForScreen;
 } 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)
 
@@ -104,7 +122,7 @@ dbusGetOptionsFromPath (CompDisplay *d,
 	int screenNum;
 
 	if (sscanf (path[1], "screen%d", &screenNum) != 1)
-	    return FALSE;
+	    return NULL;
 
 	for (s = d->screens; s; s = s->next)
 	    if (s->screenNum == screenNum)
@@ -150,6 +168,487 @@ 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;
+    char screen_name[256];
+
+    xmlTextWriterPtr writer;
+    xmlBufferPtr buf;
+
+    buf = xmlBufferCreate ();
+    writer = xmlNewTextWriterMemory (buf, 0);
+
+    dbusIntrospectStartRoot (writer);
+
+    dbusIntrospectAddNode (writer, "allscreens");
+
+    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)
+    {
+	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;
+    Bool getHandled, metadataHandled;
+    char *type;
+    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;
+	    }
+
+	    getHandled = metadataHandled = FALSE;
+	    switch (restrictionType)
+	    {
+	    case CompOptionTypeInt:
+		if (is_list)
+		    type = "ai";
+		else
+		    type = "i";
+
+		dbusIntrospectAddMethod (writer,
+					 COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+					 6, "s", "out", "s", "out",
+					 "b", "out", "s", "out",
+					 "i", "out", "i", "out");
+		metadataHandled = TRUE;
+		break;
+	    case CompOptionTypeFloat:
+		if (is_list)
+		    type = "ad";
+		else
+		    type = "d";
+
+		dbusIntrospectAddMethod (writer,
+					 COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+					 7, "s", "out", "s", "out",
+					 "b", "out", "s", "out",
+					 "d", "out", "d", "out",
+					 "d", "out");
+		metadataHandled = TRUE;
+		break;
+	    case CompOptionTypeString:
+		if (is_list)
+		    type = "as";
+		else
+		    type = "s";
+
+		dbusIntrospectAddMethod (writer,
+					 COMPIZ_DBUS_GET_METADATA_MEMBER_NAME,
+					 5, "s", "out", "s", "out",
+					 "b", "out", "s", "out",
+					 "as", "out");
+		metadataHandled = TRUE;
+		break;
+	    case CompOptionTypeBool:
+		if (is_list)
+		    type = "ab";
+		else
+		    type = "b";
+
+		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");
+		getHandled = TRUE;
+		break;
+	    case CompOptionTypeColor:
+	    case CompOptionTypeMatch:
+		if (is_list)
+		    type = "as";
+		else
+		    type = "s";
+
+		break;
+	    }
+
+	    if (!getHandled)
+	    {
+		dbusIntrospectAddMethod (writer,
+					 COMPIZ_DBUS_GET_MEMBER_NAME, 1,
+					 type, "out");
+		dbusIntrospectAddMethod (writer,
+					 COMPIZ_DBUS_SET_MEMBER_NAME, 1,
+					 type, "in");
+		dbusIntrospectAddSignal (writer,
+					 COMPIZ_DBUS_CHANGED_SIGNAL_NAME, 1,
+					 type, "out");
+	    }
+
+	    if (!metadataHandled)
+		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 +1711,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 +1721,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"))
 	{
-	    dbus_free_string_array (path);
-	    return DBUS_HANDLER_RESULT_HANDLED;
+	    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))
+	{
+	    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 +1882,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,13 +1897,243 @@ 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);
     }
 }
 
 static Bool
+dbusGetPathDecomposed (char *data,
+		       char ***path)
+{
+    char **retval;
+    char *temp;
+    char *token;
+    int nComponents;
+    int i;
+
+    nComponents = 0;
+    if (strlen (data) > 1)
+    {
+	i = 0;
+	while (i < strlen (data))
+	{
+            if (data[i] == '/')
+		nComponents += 1;
+	    ++i;
+	}
+    }
+  
+    retval = malloc (sizeof (char*) * nComponents + 1);
+
+    if (nComponents == 0)
+    {
+	retval[0] = malloc (1);
+	retval[0][0] = '\0';
+	*path = retval;
+	return TRUE;
+    }
+
+    temp = strdup (data);
+
+    i = 0;
+    token = strtok (temp, "/");
+    while (token != NULL)
+    {
+	retval[i] = strdup (token);
+	token = strtok (NULL, "/");
+	i++;
+    }
+    free (temp);
+
+    *path = retval;
+    return TRUE;
+}
+
+/* dbus registration */
+static Bool
+dbusRegisterOptions (DBusConnection *connection,
+		     CompDisplay    *d,
+		     char           *screen_path)
+{
+    CompOption *option = NULL;
+    int nOptions, size;
+    char *option_path;
+    char **path;
+
+    dbusGetPathDecomposed (screen_path, &path);
+
+    option = dbusGetOptionsFromPath (d, &path[3], NULL, &nOptions);
+
+    int pos = 0;
+    while (path[pos])
+	free (path[pos++]);
+    free (path);
+
+    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
+dbusUnregisterOptions (DBusConnection *connection,
+		       CompDisplay    *d,
+		       char           *screen_path)
+{
+    CompOption *option = NULL;
+    int nOptions, size;
+    char *option_path;
+    char **path;
+
+    dbusGetPathDecomposed (screen_path, &path);
+
+    option = dbusGetOptionsFromPath (d, &path[3], NULL, &nOptions);
+
+//    int pos = 0;
+//    while (path[pos])
+//	free (path[pos++]);
+//    free (path);
+
+    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_unregister_object_path (connection, option_path);
+	free (option_path);
+	option++;
+    }
+
+    return TRUE;
+}
+
+static void
+dbusRegisterScreen (DBusConnection *connection,
+		    CompDisplay   *d,
+		    char          *plugin_name,
+		    char          *screen_name)
+{
+    char *screen_path;
+    int  size;
+
+    size = strlen (COMPIZ_DBUS_ROOT_PATH) + strlen (plugin_name) +
+		strlen (screen_name) + 3;
+
+    screen_path = malloc (size);
+    snprintf (screen_path, size, "%s/%s/%s", COMPIZ_DBUS_ROOT_PATH,
+	      plugin_name, screen_name);
+    dbus_connection_register_object_path (connection, screen_path,
+					  &dbus_messages_vtable, d);
+    dbusRegisterOptions (connection, d, screen_path);
+    free (screen_path);
+}
+
+static void
+dbusUnregisterScreen (DBusConnection *connection,
+		      CompDisplay   *d,
+		      char          *plugin_name,
+		      char          *screen_name)
+{
+    char *screen_path;
+    int  size;
+
+    size = strlen (COMPIZ_DBUS_ROOT_PATH) + strlen (plugin_name) +
+		strlen (screen_name) + 3;
+
+    screen_path = malloc (size);
+    snprintf (screen_path, size, "%s/%s/%s", COMPIZ_DBUS_ROOT_PATH,
+	      plugin_name, screen_name);
+
+    dbusUnregisterOptions (connection, d, screen_path);
+    free (screen_path);
+}
+
+static Bool
+dbusRegisterScreens (DBusConnection *connection,
+		     CompDisplay    *d,
+		     char           *plugin_name)
+{
+    CompScreen *s;
+
+    dbusRegisterScreen (connection, d, plugin_name, "allscreens");
+
+    for (s = d->screens; s; s = s->next)
+    {
+	char screen_name[256];
+	sprintf (screen_name, "screen%d", s->screenNum);
+	dbusRegisterScreen (connection, d, plugin_name, screen_name);
+    }
+
+    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);
+
+    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,
 		      CompOptionValue *value)
@@ -1526,7 +2271,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);
 
@@ -1537,6 +2282,76 @@ dbusSendPluginsChangedSignal (const char *name,
 }
 
 static Bool
+dbusInitPluginForDisplay (CompPlugin  *p,
+			  CompDisplay *d)
+{
+    DBUS_DISPLAY (d);
+    Bool status;
+
+    UNWRAP (dd, d, initPluginForDisplay);
+    status = (*d->initPluginForDisplay) (p, d);
+    WRAP (dd, d, initPluginForDisplay, dbusInitPluginForDisplay);
+
+    if (status)
+	dbusRegisterScreen (dd->connection, d, p->vTable->name, "allscreens");
+
+    return status;
+}
+
+static void
+dbusFiniPluginForDisplay (CompPlugin  *p,
+			  CompDisplay *d)
+{
+    DBUS_DISPLAY (d);
+
+    dbusUnregisterScreen (dd->connection, d, p->vTable->name, "allscreens");
+
+    UNWRAP (dd, d, finiPluginForDisplay);
+    (*d->finiPluginForDisplay) (p, d);
+    WRAP (dd, d, finiPluginForDisplay, dbusFiniPluginForDisplay);
+}
+
+static Bool
+dbusInitPluginForScreen (CompPlugin *p,
+			 CompScreen *s)
+{
+    DBUS_SCREEN (s);
+    DBUS_DISPLAY (s->display);
+    Bool status;
+    char screen_name[256];
+
+    UNWRAP (ds, s, initPluginForScreen);
+    status = (*s->initPluginForScreen) (p, s);
+    WRAP (ds, s, initPluginForScreen, dbusInitPluginForScreen);
+
+    if (status)
+    {
+	sprintf (screen_name, "screen%d", s->screenNum);
+	dbusRegisterScreen (dd->connection, s->display, p->vTable->name,
+			    screen_name);
+    }
+
+    return status;
+}
+
+static void
+dbusFiniPluginForScreen (CompPlugin *p,
+			 CompScreen *s)
+{
+    DBUS_SCREEN (s);
+    DBUS_DISPLAY (s->display);
+    char screen_name[256];
+
+    sprintf (screen_name, "screen%d", s->screenNum);
+    dbusUnregisterScreen (dd->connection, s->display, p->vTable->name,
+			  screen_name);
+
+    UNWRAP (ds, s, finiPluginForScreen);
+    (*s->finiPluginForScreen) (p, s);
+    WRAP (ds, s, finiPluginForScreen, dbusFiniPluginForScreen);
+}
+
+static Bool
 dbusInitDisplay (CompPlugin  *p,
 		 CompDisplay *d)
 {
@@ -1602,19 +2417,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);
-
-	/* dbus_connection_unref (dd->connection); */
-	free (dd);
+    //register the objects
+    dbus_connection_register_object_path (dd->connection,
+					  COMPIZ_DBUS_ROOT_PATH,
+					  &dbus_messages_vtable, d);
 
-	return FALSE;
-    }
+    dbusRegisterPlugins (dd->connection, d);
 
     status = dbus_connection_get_unix_fd (dd->connection, &fd);
     if (!status)
@@ -1670,6 +2478,8 @@ dbusInitDisplay (CompPlugin  *p,
 
     WRAP (dd, d, setDisplayOption, dbusSetDisplayOption);
     WRAP (dd, d, setDisplayOptionForPlugin, dbusSetDisplayOptionForPlugin);
+    WRAP (dd, d, initPluginForDisplay, dbusInitPluginForDisplay);
+    WRAP (dd, d, finiPluginForDisplay, dbusFiniPluginForDisplay);
 
     d->privates[displayPrivateIndex].ptr = dd;
 
@@ -1700,6 +2510,8 @@ dbusFiniDisplay (CompPlugin  *p,
 
     UNWRAP (dd, d, setDisplayOption);
     UNWRAP (dd, d, setDisplayOptionForPlugin);
+    UNWRAP (dd, d, initPluginForDisplay);
+    UNWRAP (dd, d, finiPluginForDisplay);
 
     free (dd);
 }
@@ -1718,6 +2530,8 @@ dbusInitScreen (CompPlugin *p,
 
     WRAP (ds, s, setScreenOption, dbusSetScreenOption);
     WRAP (ds, s, setScreenOptionForPlugin, dbusSetScreenOptionForPlugin);
+    WRAP (ds, s, initPluginForScreen, dbusInitPluginForScreen);
+    WRAP (ds, s, finiPluginForScreen, dbusFiniPluginForScreen);
 
     s->privates[dd->screenPrivateIndex].ptr = ds;
 
@@ -1732,6 +2546,8 @@ dbusFiniScreen (CompPlugin *p,
 
     UNWRAP (ds, s, setScreenOption);
     UNWRAP (ds, s, setScreenOptionForPlugin);
+    UNWRAP (ds, s, initPluginForScreen);
+    UNWRAP (ds, s, finiPluginForScreen);
 
     free (ds);
 }
_______________________________________________
compiz mailing list
compiz@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/compiz

Reply via email to