// SPDX-License-Identifier: GPL-2.0-or-later /* * This is where Inkscape connects to the DBus when it starts and * registers the main interface. * * Also where new interfaces are registered when a new document is created. * (Not called directly by application-interface but called indirectly.) * * Authors: * Soren Berg * * Copyright (C) 2009 Soren Berg * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ #include // this is required so that giomm headers won't barf #undef DBUS_MESSAGE_TYPE_INVALID #include "dbus-init.h" #include "application-interface.h" #include "application-server-glue.h" #include "document-interface.h" #include "document-server-glue.h" #include "inkscape.h" #include "document.h" #include "desktop.h" #include "file.h" #include "verbs.h" #include "helper/action.h" #include #include #include namespace { // This stores the bus name to use for this app instance. By default, it // will be set to org.inkscape. However, users may provide other names by // setting command-line parameters when starting Inkscape, so that more // than one instance of Inkscape may be used by external scripts. gchar *instance_bus_name = NULL; } namespace Inkscape { namespace Extension { namespace Dbus { /* PRIVATE get a connection to the session bus */ DBusGConnection * dbus_get_connection() { GError *error = NULL; DBusGConnection *connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); if (error) { fprintf(stderr, "Failed to get connection"); return NULL; } else return connection; } /* PRIVATE create a proxy object for a bus.*/ DBusGProxy * dbus_get_proxy(DBusGConnection *connection) { return dbus_g_proxy_new_for_name (connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); } /* PRIVATE register an object on a bus */ static gpointer dbus_register_object (DBusGConnection *connection, DBusGProxy *proxy, GType object_type, const DBusGObjectInfo *info, const gchar *path) { GObject *object = (GObject*)g_object_new (object_type, NULL); dbus_g_object_type_install_info (object_type, info); dbus_g_connection_register_g_object (connection, path, object); return object; } /* * PRIVATE register a document interface for the document in the given ActionContext, if none exists. * Return the DBus path to the interface (something like /org/inkscape/document_0). * Note that while a DocumentInterface could be used either for a document with no desktop, or a * document with a desktop, this function is only used for creating interfaces in the former case. * Desktop-associated DocumentInterfaces are named /org/inkscape/desktop_0, etc. * FIXME: This state of affairs probably needs tidying up at some point in the future. */ static gchar * dbus_register_document(Inkscape::ActionContext const & target) { SPDocument *doc = target.getDocument(); g_assert(doc != NULL); // Document name is not suitable for DBus name, as it might contain invalid chars std::string name("/org/inkscape/document_"); std::stringstream ss; ss << doc->serial(); name.append(ss.str()); DBusGConnection *connection = dbus_get_connection(); DBusGProxy *proxy = dbus_get_proxy(connection); // Has the document already been registered? if (!dbus_g_connection_lookup_g_object(connection, name.c_str())) { // No - register it DocumentInterface *doc_interface = (DocumentInterface*) dbus_register_object (connection, proxy, TYPE_DOCUMENT_INTERFACE, &dbus_glib_document_interface_object_info, name.c_str()); // Set the document info for this interface doc_interface->target = target; } return strdup(name.c_str()); } /* Initialize a Dbus service */ void init (void) { if (instance_bus_name == NULL) { // Set the bus name to the default instance_bus_name = strdup("org.inkscape"); } guint result; GError *error = NULL; DBusGConnection *connection; DBusGProxy *proxy; connection = dbus_get_connection(); proxy = dbus_get_proxy(connection); org_freedesktop_DBus_request_name (proxy, instance_bus_name, DBUS_NAME_FLAG_DO_NOT_QUEUE, &result, &error); //create interface for application dbus_register_object (connection, proxy, TYPE_APPLICATION_INTERFACE, &dbus_glib_application_interface_object_info, DBUS_APPLICATION_INTERFACE_PATH); } gchar * init_document (void) { // This is for command-line use only g_assert(!INKSCAPE.use_gui()); // Create a blank document and get its selection model etc in an ActionContext SPDocument *doc = SPDocument::createNewDoc(NULL, 1, TRUE); INKSCAPE.add_document(doc); return dbus_register_document(INKSCAPE.action_context_for_document(doc)); } gchar * init_active_document() { SPDocument *doc = INKSCAPE.active_document(); if (!doc) { return NULL; } return dbus_register_document(INKSCAPE.active_action_context()); } gchar * dbus_init_desktop_interface (SPDesktop * dt) { DBusGConnection *connection; DBusGProxy *proxy; std::string name("/org/inkscape/desktop_"); std::stringstream out; out << dt->dkey; name.append(out.str()); //printf("DKEY: %d\n, NUMBER %d\n NAME: %s\n", dt->dkey, dt->number, name.c_str()); connection = dbus_get_connection(); proxy = dbus_get_proxy(connection); if (!dbus_g_connection_lookup_g_object(connection, name.c_str())) { DocumentInterface *doc_interface = (DocumentInterface*) dbus_register_object (connection, proxy, TYPE_DOCUMENT_INTERFACE, &dbus_glib_document_interface_object_info, name.c_str()); // Set the document info for this interface doc_interface->target = Inkscape::ActionContext(dt); doc_interface->updates = TRUE; dt->dbus_document_interface=doc_interface; } return strdup(name.c_str()); } gchar * init_desktop (void) { //this function will create a new desktop and call //dbus_init_desktop_interface. SPDesktop * dt = sp_file_new_default(); std::string name("/org/inkscape/desktop_"); std::stringstream out; out << dt->dkey; name.append(out.str()); return strdup(name.c_str()); } void dbus_set_bus_name(gchar const * bus_name) { g_assert(bus_name != NULL); g_assert(instance_bus_name == NULL); instance_bus_name = strdup(bus_name); } gchar * dbus_get_bus_name() { g_assert(instance_bus_name != NULL); return instance_bus_name; } } } } /* namespace Inkscape::Extension::Dbus */