A Small DCOP Command Is a Good Test
I needed to tell a running application to refresh a document, and my first instinct was to add a socket and invent a tiny protocol. Then I remembered that a KDE session already has DCOP, including discovery, calls, and argument marshalling. It seemed wasteful to build a worse version before lunch.
The dcop command is the quickest way to see what is available:
dcop
dcop konqueror
dcop konqueror KonquerorIface
The first command lists registered applications. Supplying an application lists its objects and interfaces; adding an object shows callable functions. This is useful beyond scripting. It tells me whether the object registered under the name I expected and whether the signature exported by the program matches my mental version of it.
For a simple application object, I derive from DCOPObject and name the interface:
class RefreshIface : virtual public DCOPObject
{
K_DCOP
k_dcop:
virtual void refresh(const QString &path) = 0;
};
The implementation registers through the application’s DCOPClient. Calls are sent through the session’s DCOP server, which locates the target client and carries the serialized arguments. The caller does not need the target’s process identifier, and the receiver can expose a small interface rather than its internal objects.
I keep DCOP methods coarse. Sending refresh(QString) is reasonable; reproducing every setter on a widget is not. Once the interface mirrors the user interface, outside programs depend on details I will want to change.
There is also a choice between a call that waits for a reply and one that merely sends a message. I use a synchronous call only when the result is genuinely needed. Blocking while another desktop process opens a file or asks a question can make both programs feel frozen.
Application names need care as well. A second instance may register with a numbered name rather than replacing the first one. If the operation concerns a particular document, guessing the first process in the list is unsafe. I either arrange single-instance behavior deliberately or discover the intended application and object from information I already have. DCOP removes the need for process identifiers; it does not remove the need to choose the right process.
Failures should remain visible. A call can fail because the application exited, the object disappeared, or the signature changed. I report that to the caller instead of treating a missing reply as an empty successful result.
My rule now is to prove the exchange with the command-line client first. If dcop cannot see or call the object, another page of C++ is unlikely to improve matters. This is one of those rare debugging techniques that removes code, which makes it suspiciously pleasant.