- Slide 1 - Title |
If an application, such as XEmacs, wants to live and cooperate in a bigger framework of applications, as the 'new' desktop environments GNOME and KDE or as the 'old' ones Windows and CDE/Motif, it has to provide means of communicating data to other applications in the framework. One basic method are files, but for a quick transfer between applications another way of transfer was invented: Drag'n'Drop.
Drag'n'Drop is sort of a mouse-initiated interprocess communication to move, copy or share data between processes. It uses a metaphor which is easy to understand for the common user: (s)he can grab the thing and drop it at the place (s)he wants it to be.
One basic problem of Drag'n'Drop is the lack of one protocol used by all applications. Each of the environments listed above brings along its own protocol and there are even more 'rogue' protocols (not belonging to some bigger framework) based on X basics. In the last month, both GNOME and KDE decided to support Xdnd (actually after they cooperated with the author of Xdnd to make it do the things they need) and I think we should also support it.
MULE makes the whole thing a bit more difficult: we not only have to pick the right protocol, we should also try to provide the dragged data in a format and charset the target of the drop understands.
- Slide 2 - Current Implementation |
XEmacs currently has experimental support for CDE, OffiX V1 (a 'rogue' X protocol used by a not so widely know desktop project called OffiX), and MSWindows Drag'n'Drop (file drops only).
If the support is enabled via the '--with-offix' and '--with-cde' configure switches (for MSWindows it should be automatic), the user can use drag'n'drop (default is drag via the middle button) to copy regions between buffers or even send them to other apps using the same protocol (dtpad or TkStep's dropdemo). XEmacs also knows how to handle drops and will open files if paths are dropped onto the modeline or toolbar or inserts them into a buffer if the drop happens there.
But these are only tests and examples. The options are countless, cause the whole thing can be controlled by lisp constructs.
In case of OffiX, XEmacs looks for a ClientMessage with the OffiX atom in it. CDE defines a callback and MSWindows does whatever Johnatan Harris has done to make it work. The received message then gets converted into a misc-user-event with it's function argument set to dragdrop-drop-dispatch. The object is the data of the drop, which is currently either an URL or MIME type data. These are no new abstract types, but lists of symbols and strings. The URL data type is obsolete, cause it can be modelled via the mime type text/uri-list.
The dispatcher will look for extend properties called experimental-dragdrop-drop-functions and call each element of this list until one indicates that it could do something with the data by returning t. If no call returned true, or the property was not set a variable of the same name is searched the same way.
Drags must be initiated 'by hand'. Just define a button binding that will call offix/cde-start-drag or one of the predefined API shortcuts. These shortcuts are also experimental wrappers to the core functions (they set the right data types for the different protocols, which are currently not MIME). The data is currently converted (clobbered) into a 8bit data string, without proper MULE handling (as XSelection does).
In addition, the whole thing is rather buggy at the moment. The OffiX code only works for single display setups, cause it stores only atoms for one display. The CDE code also has it's clitches. Both don't understand MULE content.
- Slide 3 - Drag'n'Drop Protocols |
Cause unfortunately there are multiple Drag'n'Drop protocols on the X platform, and XEmacs also runs on other platforms which provide their own protocols (MSWindows), XEmacs must have support for multiple protocols to give the user the same behaviour on all platforms.
To get it worse, the right protocol must be choosen at runtime, or even changed within one d'n'd operation depending on the type of protocol the target supports. And each protocol uses a different way of doing it's job.
This is easy to determine for protocols that have methods of displaying the ability to receive drops for the specific protocol (Xdnd, Motif), but others lack this ability (the old OffiX protocol, or even no protocol -- here a paste could be used to simulate a drop) and can only be used in a fallback mode.
One solution is the total exclusion of obsolete protocols. If we look around, we find out that both qt/KDE and gtk+/GNOME support Xdnd, and the list of Xdnd supporters is growing. The architecture of this protocol is based on standart Xlib functions, avaiable on all X platforms, it uses the Selection mechanism to transfer the data, and it encodes the type of the data using mime types. I think it provides the best base for XEmacs.
To keep the compatibility with the Motif using world, this protocol should also be supported. It has not as much features as Xdnd, but it still does the job. How the mime types can be introduced here has to be examined. One may opt to leave Motif out, but I think there are two many Motif using platforms supported by XEmacs to ignore this protocol. It should be fairly easy to transparently switch between the two without user interaction, cause both tell us if the receiver supports one of them (gtk+ also supports both Xdnd and Motif).
Support for OLE/DDE is necessary for the MSWindows platform. Unfortunately I can't tell anything about this, cause it's long since I last had the joy to program on this platform. Jonathan Harris did all the black magik to make it work.
All other protcols I know have to less features, or are only used within (and between) a single application, to support the requirements of MULE and should be ignored. The inclusion would complicate the whole implementation a lot. Most older applications can also be reached by the paste selection fallback of Xdnd.
- Slide 4 - Proposed Architecture |
As Ben Wing suggests on the 'Architecturing XEmacs' pages, I strongly support the move back to seperate event types instead of merging all in misc-user-event as drag'n'drop is now handled. The new scheme to handle drag'n'drop he introduces is semiliar to the one I implemented, but much more adapted to the XEmacs way of doing such things. He proposes to define drop-handlers which can be accessed through a defined set of functions (add-drop-handler, make-drop-handler, find-drop-handler, remove-drop-handler). Each handler is characterized by a MIME-type regex and a package tag to identify which data it can handle. If the type of the dropped data is matched by the MIME regex, the handler for the data is executed.
In case of Xdnd, the whole list of MIME types must be matched against the regex, cause this protocol allows the target to pick one of multiple types the source can provide.
One thing we can not depend on is the button and the modifiers that where used during the drag. There is no defined behaviour for this and it would add extra confusion. All we can depend on is the action the drop carries with it. This might also be a context menu (as Ben suggests for right button drops) when using the Xdnd protocol or if the target decides a popup is required.
The newer protocols have the ability to display changes in the receiver while dragging something. This is done (in X) by grabbing the pointer and sending special events to possible receivers. The receiver can react to these events by changing widgets, scrolling views, collapsing or uncollapsing folders, etc. This feedback could be provided by another handler that is called while a drag is in progress. If the drop-object has no matching handler for the data the source wants to transmit, it even can tell the source if it is no valid target for this data.
As long as the source is the target everything should be done in the grab loop of the source, to save bandwidth and because the call of the main event loop of XEmacs may result in unwanted sideeffects. So any events should be translated directly into the associated function calls.
Dragging is a different story: Either we will have prebound objects which will also start a drag when triggered, or we can provide a new event called drag-event, which will be created after a button is pressed and the mouse has moved more than a few pixel (this is the standart way/feel how the user sees a drag). The movement is to make sure that the user really wants to do a drag, and is not only to clumsy. This will require a change to the events XEmacs currently provides, in the direction of FSF Emacs (with it's click and drag events).
This event again can be used to bind some widget, but it could also work like the drop: by adding drag-handlers to widgets, XEmacs automaticlly could decide wether to drag or not something from the widget.
- Slide 5 - MULE Interaction |
To enable DnD to transfer MULE data different approaches are possible:
This may be the best way to transfer the data between different XEmacs instances (or the same instance). With Xdnd a new mime type (text/x-mule-coding) is created, and a app which knows this type (an XEmacs) can pick it to get the unmodified data. With other protocols this gets difficult. As long as the transfer happens within the same XEmacs instance it can be simulated, but as soon as the data is dragged into another app (which is quite natural for DnD) we don't know if the receiver know to handle this data.
there is no such thing as a well know format. One could choose UNICODE, but there are only few apps which can handle such data.
The data gets converted via MULE into the 'natural' charset of the platform/buffer, and we hope that the receiver knows to handle it. (dragging japanese data into a kanji-term) This is the same thing XSelection does.
Clobber all extended chars. Don't care about this MULE thing.
- Slide 6 - Loose Ends |
Xdnd provides the best interface for this multiple choice conversion, by allowing the receiving application to pick from different types. The source of a drag sends a set of types with the status event. The receiver may pick the type it understands best. We can even provide an image of the selected region.
Xdnd uses mime types to specify the type of data. I have talked to John Lindal about the inclusion of the charset attribute into the text/plain mime type, and he was quite interested in this solution. The idea is to append the charset information to the actual mime type (i.e. text/plain;charset=iso8859-5) so a conforming app may pick the charset it understands best. By also providing the base text/plain type, backward compability is archived.
Cause Xdnd uses XSelection for data transfer, the current scheme of cut & paste may be used as a blueprint for the transfer. But this is only true for this protocol. We need a close examination of other protocols to evaluate which the best way is to transfer multilingual data using them.
For OLE/DDE we might use also MIME features, or we can try to use the new UNICODE support of XEmacs to transform text data into a UNICODE format (this is work still in progress, but it is in the same schedule as drag'n'drop support is). Most MSWindows Application should know UNICODE by now.
In the case of Motif, the XmString type might proof useful. But how the data is handled might be different depending on the application. Cause I'm no seasoned Motif programmer, I can'say much moe to this topic. It will work out in the implementation.
A quick and dirty protcol with a fixed set of types. In the latest version it got two new types DndMIME and DndURL to provide types for abitary data.
The basetypes are not well choosen: there are the File, Dir, Exe, Link types (mixing action and type) and a Files type, which is the only one that can list multiple files. This is rather contradictionary, cause all those types can be represented as an URL.
There is no support for user feedback while the drag is in progress. The actual drop is done blind, cause there is no way to determine if the target understands the drop.
The data is stored for transfer in a internal X atom. The source gets no feedback from the target if or if not the drop could be handled.
Properitery protocol auf gtk+. This is no longer used and was replaced by Xdnd, after the gtk+ maintainers were statisfied with the possibilities of Xdnd, by actually adding them.
The Drag'n'Drop protocol used by the well known commercial widget set. It requires lots of globally shared information and is prone to race conditions. To store drag informtaion it uses a realized but not visible window.
User feedback is possible, but not required. One can also define nice little animations which are executed depending on the result of the drag.
These are the MSWindows ways to transfer data. It provides semiliar functions as Motif and Xdnd.
A newly designed protocol which tries to fix the lacks of the other protocols.
It can savely coexist with all others, cause a target signals it's compilance through a window property (XdndAware).
See Appendix B for more information.
Xdnd was developed by John Lindal for his JX framework. Others helped to improve it and add features needed by them. It is now the main protocol of gtk+/GNOME and qt/KDE. The list of supporting applications is still growing.
It allows to source to provide multiple data formats, and lets the target pick the one it understands best. The data types used are the standart MIME types commonly used throughout the world. You can actually use any arbitary string as type, but if everyone would do so, this would be no good. There are a few predefined actions, but the protocol also allows the use of private action menus.
Feedback can be provided through the whole D'n'D process. The source always knows if the target received the data completely. The author also provides multiple examples how common D'n'D actions (dragging text and files) and targets (trashcans) should be implemented. For example, the natural action when dragging a region within the same application (or buffer if we think of XEmacs) would be a move, but as soon as we enter another application this should change to copy.
Xdnd uses the X Selection mechanism to transfer its data. So there is no requirement to implement a whole new transport scheme.
To provide backward compability to applications that don't know Xdnd or other Drag'n'Drop protocols, the data is transfered to such applications by sending middle button press/release events to the deepest target window in the hope the applications takes this as 'paste' and begins to convert the X selection. This works for most older X applications that conform to the pseudo standart xterm had set for cut&paste.
Some links to resources related to Drag'n'Drop, XEmacs, and the various toolkits involved:
My name is Oliver Graf, and I work for a local ISP and Internet newsletter (called Rhein-Zeitung in Koblenz, Germany. I also have my own small webpublishing-server-stuff-consulting company FGA (warning: both are german, so keep your babelfish handy).
I started using unix like environments after I switched from my Commodore VC-20 and C128 to a PC about 8 years ago. First contact was solaris and linux. I studied computer science and computational linguistics at Universität Koblenz-Landau for about 8 Years. I have not graduated, and I don't have any 'official' degree.
Some programs I've written include a ncurses based FIDO-client called Feddie (now Feddy), some other small useless tools (WMRack to name the most known one). I maintain TkStep (a n*xtstep lookalike version of Tk) together with Steve Murray and I've done some modifications to XEmacs (WM_COMMAND/WM_CLASS handling, OffiX Drag'n'Drop, 'fixed' CDE to work like OffiX).
My current projects include some web based project management software, making XEmacs work with Motif & Xdnd Drag'n'Drop protocols, adding FSF emacs style click events, and perhaps making a TkStep 8.1 release.
First of all I want to thank the MULE Team and the ETL Tsukuba for the invitation to m17n99. It was great to meat all those people from all around the world.
Other thanks go to Oliver Andrich, Hank Hampel, and Christof Furch for trying to fix the broken english in this document.
Copyright (c) 1999 by Oliver Graf <ograf@fga.de>