Difference between revisions of "DBus"

From Inkscape Wiki
Jump to navigation Jump to search
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:


Inkscape has supported a DBus interface for some time.... but information on how to use it is limited. It is also not clear how to use Gio::Actions which are suppose to work with DBus. This page is an investigation into using DBus with Inkscape.
== DBus support 1.2 ==


It would be very useful if anyone who has experience with using the DBus interface add information here!
Inkscape now supports DBus natively (as of v1.2), that is through GTK. The legacy DBus support has been removed.
 
Gtk::Application and Gtk::ApplicationWindow groups are exported automatically as ''/org/inkscape/Inkscape'' and ''/org/inkscape/Inkscape/window/#'' respectively, where '#' is the window number, starting at one. Document actions are export as ''/org/inkscape/Inkscape/document/#'' where '#' is the same number as used by the window they have been opened inside (as a document may be opened in more than one window, there may be more than one path to the same document).
 
To facilitate running more than one Inkscape instance at the same time, one can change the "App ID" (nominally ''org.inkscape.Inkscape'') by either adding a tag, via the ''INKSCAPE_APP_ID_TAG'' environment variable or ''--inkscape-app-tag'' command line argument. The App ID will then be ''org.inkscape.Inkscape.TAG'' where "TAG" is replaced by the specified tag. One can also use the GTK command line argument ''--gapplication-app-id'' to change the entire App ID. Note, that when running without a GUI, the App ID is changed automatically to ''org.inkscape.Inkscape.p#'' where '#" is the process id number. This is to avoid having command-line instance of Inkscape interfere with all-ready open Inkscape instances.
 
Here is a sample python program showing how to utilize the DBus interface:
 
<pre>
<nowiki>#</nowiki>!/usr/bin/env python
 
<nowiki>#</nowiki>  Start after inkscape is running.
print ("DBus test")
 
import gi
gi.require_version("Gio", "2.0")
from gi.repository import Gio, GLib
 
try:
   bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
 
except BaseException:
   print("No DBus bus")
   exit()
 
print ("Got DBus bus")
 
proxy = Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None,
                              'org.freedesktop.DBus',
                              '/org/freedesktop/DBus',
                              'org.freedesktop.DBus', None)
 
names_list = proxy.call_sync('ListNames', None, Gio.DBusCallFlags.NO_AUTO_START, 500, None)
 
<nowiki>#</nowiki> names_list is a GVariant, must unpack
 
names = names_list.unpack()[0]
 
<nowiki>#</nowiki> Look for Inkscape; names is a tuple.
 
for name in names:
   if ('org.inkscape.Inkscape' in name):
       print ("Found: " + name)
       break
 
print ("Name: " + name)
 
appGroupName = "/org/inkscape/Inkscape"
winGroupName = appGroupName + "/window/1"
docGroupName = appGroupName + "/document/1"
 
applicationGroup = Gio.DBusActionGroup.get( bus, name, appGroupName)
windowGroup = Gio.DBusActionGroup.get(bus, name, winGroupName)
documentGroup = Gio.DBusActionGroup.get(bus, name, docGroupName)
 
<nowiki>#</nowiki> Activate actions. Draw a few objects first.
 
applicationGroup.activate_action('select-all', GLib.Variant.new_string('all'))
applicationGroup.activate_action('object-rotate-90-cw', None)
 
windowGroup.activate_action('tool-switch', GLib.Variant.new_string('Arc'))
windowGroup.activate_action('canvas-zoom-page', None)
 
<nowiki>#</nowiki> documentGroup.activate_action('undo', None)
</pre>
 
== DBus 1.1 and earlier. ==
Inkscape has supported a DBus interface for some time.... but information on how to use it is limited. It would be very useful if anyone who has experience with using the DBus interface add information here!


=== DBus Support in Inkscape ===
=== DBus Support in Inkscape ===
Line 10: Line 77:


=== Use with Python ===
=== Use with Python ===
There is some Python documentation in the ''src/extension/dbus/doc'' directory. It's in DocBook format and incomplete. Here is a simple python program for interfacing with a running Inkscape program that has been compiled with DBUS support:<blockquote>#!/usr/bin/env python
There is some Python documentation in the ''src/extension/dbus/doc'' directory. It's in DocBook format and incomplete. Here is a simple python program for interfacing with a running Inkscape program that has been compiled with DBUS support:
<pre>
#!/usr/bin/env python


# Adapted from documentation in the src/extension/dbus/doc directory.
# Adapted from documentation in the src/extension/dbus/doc directory.


print("Inkscape DBus Interface Test")
print("Inkscape DBus Interface Test")
Line 21: Line 89:


# Get the session bus.
# Get the session bus.
try:
try:
   bus = dbus.SessionBus()
   bus = dbus.SessionBus()
except BaseException:
except BaseException:
   print("No bus")
   print("No bus")
   exit()
   exit()
print("Got DBus bus")
print("Got DBus bus")


# Get the object for the application.
# Get the object for the application.
try:
try:
   inkapp = bus.get_object('org.inkscape',
   inkapp = bus.get_object('org.inkscape',
                           '/org/inkscape/application')
                           '/org/inkscape/application')
except BaseException:
except BaseException:
   print("No Inkscape application found")
   print("No Inkscape application found")
   exit();
   exit();
print("Got connection to Inkscape application")
print("Got connection to Inkscape application")


# Request a new desktop.
# Request a new desktop.
desk = inkapp.desktop_new(dbus_interface='org.inkscape.application')
desk = inkapp.desktop_new(dbus_interface='org.inkscape.application')


# Get the object for that desktop.
# Get the object for that desktop.
inkdoc = bus.get_object('org.inkscape', desk)
inkdoc = bus.get_object('org.inkscape', desk)


# Tell it what interface it is using so we don't have to type it for every method.
# Tell it what interface it is using so we don't have to type it for every method.
doc = dbus.Interface(inkdoc, dbus_interface="org.inkscape.document")
doc = dbus.Interface(inkdoc, dbus_interface="org.inkscape.document")


# Use!
# Use!


doc.document_set_css ("fill:#ff0000;stroke:#000000")
doc.document_set_css ("fill:#ff0000;stroke:#000000")
rect = doc.rectangle (25,  25, 50, 50)
rect = doc.rectangle (25,  25, 50, 50)
#                      x    y   w   h
#                      x    y   w   h


 
doc.document_set_css ("fill:#0000ff;stroke:#000000;stroke-width:3px")
doc.document_set_css("fill:#0000ff;stroke:#000000;stroke-width:3px")
 
circle = doc.ellipse (125, 25, 50, 50)
circle = doc.ellipse (125, 25, 50, 50)
#                      x    y   w   h
#                      x    y   w   h


 
doc.document_set_css ("fill:#ffff00;stroke:#000000;stroke-width:5px")
doc.document_set_css("fill:#ffff00;stroke:#000000;stroke-width:5px")
 
star = doc.star (50, 150, 40, 16,   0, -0.314,     5, 0.314)
star = doc.star (50, 150, 40, 16,   0, -0.314,     5, 0.314)
 
#                cx   cy  r1  r2 rand   arg1  sides   arg2
#                cx   cy  r1  r2 rand   arg1  sides   arg2</blockquote>
</pre>


=== Use with Emacs ===
=== Use with Emacs ===

Latest revision as of 11:17, 28 January 2022

DBus support 1.2

Inkscape now supports DBus natively (as of v1.2), that is through GTK. The legacy DBus support has been removed.

Gtk::Application and Gtk::ApplicationWindow groups are exported automatically as /org/inkscape/Inkscape and /org/inkscape/Inkscape/window/# respectively, where '#' is the window number, starting at one. Document actions are export as /org/inkscape/Inkscape/document/# where '#' is the same number as used by the window they have been opened inside (as a document may be opened in more than one window, there may be more than one path to the same document).

To facilitate running more than one Inkscape instance at the same time, one can change the "App ID" (nominally org.inkscape.Inkscape) by either adding a tag, via the INKSCAPE_APP_ID_TAG environment variable or --inkscape-app-tag command line argument. The App ID will then be org.inkscape.Inkscape.TAG where "TAG" is replaced by the specified tag. One can also use the GTK command line argument --gapplication-app-id to change the entire App ID. Note, that when running without a GUI, the App ID is changed automatically to org.inkscape.Inkscape.p# where '#" is the process id number. This is to avoid having command-line instance of Inkscape interfere with all-ready open Inkscape instances.

Here is a sample python program showing how to utilize the DBus interface:

#!/usr/bin/env python

#  Start after inkscape is running.
print ("DBus test")

import gi
gi.require_version("Gio", "2.0")
from gi.repository import Gio, GLib

try:
   bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)

except BaseException:
   print("No DBus bus")
   exit()

print ("Got DBus bus")

proxy = Gio.DBusProxy.new_sync(bus, Gio.DBusProxyFlags.NONE, None,
                              'org.freedesktop.DBus',
                              '/org/freedesktop/DBus',
                              'org.freedesktop.DBus', None)

names_list = proxy.call_sync('ListNames', None, Gio.DBusCallFlags.NO_AUTO_START, 500, None)

# names_list is a GVariant, must unpack

names = names_list.unpack()[0]

# Look for Inkscape; names is a tuple.

for name in names:
   if ('org.inkscape.Inkscape' in name):
       print ("Found: " + name)
       break

print ("Name: " + name)

appGroupName = "/org/inkscape/Inkscape"
winGroupName = appGroupName + "/window/1"
docGroupName = appGroupName + "/document/1"

applicationGroup = Gio.DBusActionGroup.get( bus, name, appGroupName)
windowGroup = Gio.DBusActionGroup.get(bus, name, winGroupName)
documentGroup = Gio.DBusActionGroup.get(bus, name, docGroupName)

# Activate actions. Draw a few objects first.

applicationGroup.activate_action('select-all', GLib.Variant.new_string('all'))
applicationGroup.activate_action('object-rotate-90-cw', None)

windowGroup.activate_action('tool-switch', GLib.Variant.new_string('Arc'))
windowGroup.activate_action('canvas-zoom-page', None)

# documentGroup.activate_action('undo', None)

DBus 1.1 and earlier.

Inkscape has supported a DBus interface for some time.... but information on how to use it is limited. It would be very useful if anyone who has experience with using the DBus interface add information here!

DBus Support in Inkscape

Inkscape must be compiled with DBus support. Most available pre-built versions of Inkscape do NOT include DBus support. To enable DBus support, use: cmake -DWITH_DBUS=ON path_to_source

Inkscape is using a deprecated library for DBus support. See: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=955903

Use with Python

There is some Python documentation in the src/extension/dbus/doc directory. It's in DocBook format and incomplete. Here is a simple python program for interfacing with a running Inkscape program that has been compiled with DBUS support:

#!/usr/bin/env python

# Adapted from documentation in the src/extension/dbus/doc directory.

print("Inkscape DBus Interface Test")

import dbus


# Get the session bus.
try:
   bus = dbus.SessionBus()
except BaseException:
   print("No bus")
   exit()
print("Got DBus bus")

# Get the object for the application.
try:
   inkapp = bus.get_object('org.inkscape',
                           '/org/inkscape/application')
except BaseException:
   print("No Inkscape application found")
   exit();
print("Got connection to Inkscape application")

# Request a new desktop.
desk = inkapp.desktop_new(dbus_interface='org.inkscape.application')

# Get the object for that desktop.
inkdoc = bus.get_object('org.inkscape', desk)

# Tell it what interface it is using so we don't have to type it for every method.
doc = dbus.Interface(inkdoc, dbus_interface="org.inkscape.document")

# Use!

doc.document_set_css ("fill:#ff0000;stroke:#000000")
rect = doc.rectangle (25,  25, 50, 50)
#                      x    y   w   h

doc.document_set_css ("fill:#0000ff;stroke:#000000;stroke-width:3px")
circle = doc.ellipse (125, 25, 50, 50)
#                      x    y   w   h

doc.document_set_css ("fill:#ffff00;stroke:#000000;stroke-width:5px")
star = doc.star (50, 150, 40, 16,   0, -0.314,     5, 0.314)
#                cx   cy  r1  r2 rand    arg1  sides   arg2

Use with Emacs

Verification that DBus actually still works (on Fedora):

  • Start Inkscape.
  • Open an Emacs window.
  • Type:

    (message "%s on board." (cond   ((dbus-ping :session "org.inkscape" 100) "Inkscape")   (t "No")))

    Put the cursor at the very end of the function (just after ')))') and type Ctrl-X Ctrl-E.
  • The Emacs 'Message" buffer should show "Inkscape on board" if you have successfully connected to the running Inkscape app.

Open a New Inkscape Window:

  • Type:

    (dbus-call-method               :session "org.inkscape" "/org/inkscape/application"               "org.inkscape.application" "desktop_new")

    Put the cursor at the very end of the function and type Ctrl-X Ctrl-E.
  • The Emacs "Message" buffer should show "/org/inkscape/desktop_1" and a new window should have opened.

Add a rectangle:

  • Type:

    (dbus-call-method               :session "org.inkscape" "/org/inkscape/desktop_1"               "org.inkscape.document" "rectangle" :int32 100 :int32  100 :int32  100 :int32  100)

    Put the cursor at the very end of the function and type Ctrl-X Ctrl-E.
  • A rectangle should appear in the new Inkscape drawing.

Notes

Command line arguments:

  • --dbus-listen
  • --dbus-name=BUS-NAME
  • --display=DISPLAY

How to use these? At least the --dbus-name does not seem to work (bus name is always "org.inkscape").

Useful links: