Desktop scripting with DCOP

From LXF Wiki

Desktop scripting

(Original version written by Neil Bothwick for LXF issue 79.)

Original article (PDF) (http://www.linuxformat.co.uk/wikipdfs/LXF79.tut_dcop.pdf)

Add features to KDE apps or control them remotely – it’s easy with DCOP. Neil Bothwick shows you how.

Despite the power that DCOP gives you over your system, you’ve probably never even heard of it, aside from perhaps seeing the name flash past in obscure messages when starting a KDE program from a terminal. The average KDE user is sadly unaware of the Desktop Communication Protocol, but it is a fundamental part of KDE, and I think you’ll enjoy exploring it in this tutorial.

DCOP is an interprocess communication protocol, which means that it enables different KDE programs to talk to each other. This is how you can run KMail and KAddressBook inside Kontact, for example. What I want to show you is how we can use DCOP to interrogate and control KDE programs from the command line or a script, adding features or automating processes that would not otherwise be possible.

Someone once defined a macro as “a series of keystrokes used to simulate a missing but essential command”. DCOP provides the same for KDE: the ability to add options not provided by default. To show you what I mean, here is an example of a simple use of DCOP:

rm -i $(dcop kdesktop KBackgroundIface currentWallpaper 0)

I have this in an alias in my shell profile, and use it to delete my desktop’s current wallpaper file. I have a habit of collecting all sorts of image files and dropping them into the folder where KDE gets its wallpapers from, changing them at regular intervals. Very often I decide I don’t like the picture once it’s on the desktop. This command uses the dcop command-line program to find out the current wallpaper file and delete it.

In this script, the dcop command requests the name of the current background wallpaper from Kdesktop. The 0 refers to the current desktop; you can also use 1 for the first desktop and so on. The result of the dcop command is evaluated and passed to rm, and the ugly wallpaper is gone.

Table of contents

An easy way into DCOP

Thumb_kdcop.png (http://linuxformat.co.uk/wiki/images/5/5e/Kdcop.png)
KDCOP provides a simple way to browse the available dcop commands for an application and see what they do.

How do you know what dcop can do with a program like Kdesktop and which arguments to use? One way would be to read through the source code of the program and try to understand how its DCOP interface (the means by which programs send each other DCOP communications) is implemented. Fortunately, there’s an easier way: KDCOP. This is a GUI program that lists in a tree all the applications with DCOP interfaces. Opening out an application in the tree shows the various interfaces of the program, each of which contains a number of functions. You can ignore most of interfaces; the one you want is usually MainApplication-Interface.

To test a function, double-click on it. You can see the results in your application or view the output from the command. For example, double-click on Kdesktop > KbackgroundIface > ChangeWallpaper and the desktop will switch to the next wallpaper image in its list, assuming you have KDE set up to use a slideshow for the desktop wallpaper.

The bottom of the KDCOP window shows the DCOP call that you have just executed. To use this with the dcop program, simply replace the dots with spaces, thus
DCOP call kdesktop.KBackgroundIface.changeWallpaper()

becomes

dcop kdesktop KBackgroundIface changeWallpaper

If the function requires any arguments, drop the parentheses and separate them with spaces in standard shell script style.

You can also use the command-line program to see the available options for an application. For example,

dcop kdesktop KBackgroundIface

shows the options for Kdesktop, including CurrentWallpaper.

You will notice that some of the top-level entries in the KDCOP tree contain a number as well as the application’s name. This is a process ID (PID), and is included whenever it is possible to have more than one copy or instance of the app running at once. For example, each Konqueror window has its own process, so all Konqueror entries in KDCOP have a PID even if there is only one instance running. On the other hand, it is only possible to run one instance of Amarok (trying to run it again merely closes or opens the window of the instance that’s already running) so it has no number.

You can only use a DCOP interface that matches the specific PID you’re running, and there are a number of ways to determine which of the numbered interfaces is the correct one from a script. If you are running the application from the script itself, you already have the PID; it is stored in the variable $!.

konqueror http://www.site1.com &
dcop konqueror-$! konqueror-mainwindow#1 newTab http://www.site2.net
dcop konqueror-$! konqueror-mainwindow#1 newTab http://www.site3.org
dcop konqueror-$! konqueror-mainwindow#1 newTab http://www.site4.co.uk

The first line opens a Konqueror window and loads a web page. $! contains the PID of the last background process run from the shell, so the next three lines can use this to load three more pages into new tabs in the same Konqueror window.

Another way is to use shell-like name globbing to get a list of all potential interfaces, thus:

dcop konqueror-*

This returns all Konqueror instances. Or, if you are running the command, or the script containing it, from a hotkey, you can check whether the application’s window is active, like so:

for IFACE in $(dcop konqueror-*)
do
  if [ $(dcop ${IFACE} konqueror-mainwindow#1 isActiveWindow) == “true” ]
  then
    MYIFACE=${IFACE}
    break
  fi
done

This will run through all instances of Konqueror to see which, if any, are active. You will need to use KDCOP to see which command you use for this, as it is not constant across all apps.

Shell scripting

Knowledge of shell scripting is not essential to use dcop to control KDE, it certainly helps. At its most basic a shell script is a text file like this:

#!/bin/sh
command1
command2
...

The first line identifies it as a shell script (as opposed to any other form of script or executable), and the rest is a list of commands to be run, just as if you had typed them at a command prompt. After creating the text file, you need to mark it as executable with

chmod +x yourscript

GUI to shell

Now that you’ve got the hang of DCOP, let me show you a couple of neat uses for it. Ask most reasonably experienced Linux users whether they prefer a GUI or the shell and they will say they use both, switching between them as suits their needs. Here’s a quick DCOP command to make this easier. I would save it as a script and bind it to a hotkey if I were you so that you can execute it while using Konqueror as a file manager.

#!/bin/sh
#include the above code to find the Konqueror interface
if [ -n “${MYIFACE}” ];
then
  konsole --workdir $(dcop ${MYIFACE} konqueror-mainwindow#1 currentURL | cut -c 8-)
fi

Konqueror returns the file path as a full URL, but Konsole does not like the leading ‘file://’, so the cut command removes it.

Let’s try the second example. I am writing this in Kate, the KDE text editor. On the whole I like Kate, but the lack of a word count feature is a serious omission (don’t tell me that it’s a programmer’s editor: it has a spellchecker, doesn’t it?). Adding a word count function is a simple task, thanks to DCOP.

#!/bin/sh
for IFACE in $(dcop kate-*)
do
  if [ $(dcop ${IFACE} __KateMainWindow#1 isActiveWindow) == “true” ]
  then
    MYIFACE=${IFACE}
    break
  fi
done
if [ -z “${MYIFACE}” ]
then
  RESULT=”No active Kate window found”
else
  ALL=$(dcop ${MYIFACE} EditInterface#1 text | wc -w)
  SELECT=$(dcop ${MYIFACE} SelectionInterface#1 selection | wc -w)
  RESULT=”All text: ${ALL} words\nSelected: ${SELECT} words”
fi
kdialog --title “Kate word count” --msgbox “$RESULT”

This script finds the current Kate DCOP interface (if there is one), then uses EditInterface and SelectionInterface to grab the full text and any selected text respectively. The dcop call sends the text to standard output, so the script pipes it to wc to get the number of words. Again, the easiest way to run this is to attach it to a hotkey.

Other languages

We have only looked at using the dcop client to control KDE applications from the command line, shell scripts or KDE hotkeys. But DCOP was created to make it possible to access one program from another, so it can be used from most programming languages and embedded in your own applications. The KDCOP GUI can show the syntax for Python and C++ as well as the shell program. If you want to use DCOP in your program, either to control another or to give users access to your program’s features, try exploring the official documentation, which offers plenty of examples, at http://developer.kde.org/documentation/other/dcop.html.

Another set of possibilities opens up if you have a remote controller, say for a TV card and lirc. KDE makes actions for a few applications, mainly media players, available directly through the KDE Control Centre. It also has an option for the KDE Program Launcher, which would allow you to run a dcop command and control programs remotely.

KDE is sometimes criticised for having too many options. But no matter how many options a program’s authors provide, there always seems to be one thing you want that isn’t there. Now, with KDE at least, you have the chance to add it yourself, thanks to DCOP.

Binding commands to Hotkeys

Thumb_input_actions.png (http://linuxformat.co.uk/wiki/images/9/92/Input_actions.png)
The Input Actions section of the KDE Control Centre lets you run any command from any key.

KDE’s KHotKeys allows you to bind commands to keys or mouse gestures. This can be any command you care to run, be it a dcop call or a script containing several commands. Start the KDE Control Centre and go to Regional & Accessibility > Input Actions, select the Commands group and click New Action. Pick a key, give the path to your script and you’re away. There are plenty of examples, set up but disabled, so you can see what is possible.

Quick tips

  • Test your commands from KDCOP first, then the command line before trying from a hotkey.
  • If your script or command requires an active window, test it from the shell with
sleep 3; ./scriptname

This gives you three seconds to switch focus to the window you want.

  • Some interfaces have a lot of functions – the Konqueror main window has over 150. Running dcop with insufficient arguments shows the options available, and you can use this to search for a function. Thus
dcop konqueror-$!
konqueror-mainwindow#1 | grep -i url

shows all commands with ‘url’ or ‘URL’ in the name.