Plugins for VCL
Project Owner: Philipp Lohmann, last change: 2004/01/28
Currently only available for Unix platforms: plugins move the whole platform dependent part of VCL(Unix) into an own library. At runtime OOo decides what plugin would suit the current desktop environment best; e.g. it uses a gtk based plugin on GNOME desktops or a generic (plain Xlib based) plugin on CDE. The foundation for this the pure abstraction of all Sal interfaces (Sal: System Abstraction Layer – the name is sadly coincidental with the sal project; the Sal layer in vcl existed first historically).
Why plugins ?
For better system integration it is necessary to run the system's toolkit inside the OOo process space. E.g. to use toolkit themes for drawing controls it is imperative to be able to ask the native toolkit to draw OOo's controls. Also toolkits know how to access system features like recent document lists, file dialogues, etc..
What are the basics for writing a VCL(Unix) plugin ?
The starting point for a new VCL plugin is SalInstance. This is a factory interface the implementation of which produces instances of all other Sal interfaces. At startup the independent part of vcl tries to determine the correct plugin (desktop autodetection) and then tries to load that library and ask it for a SalInstance object. Every other Sal interface implentation is produced via the corresponding method of SalInstance (see vcl/inc/salinst.hxx for details).
The first step is to create an
"C" function named create_SalInstance which
returns the SalInstance of your plugin. For many plugins it is
advantageous to inherit their SalInstance from the SalInstance of the
generic implementation so the new plugin can reuse the generic
implementation where appropriate; good examples for implementations
that can be inherited are SalSound, SalBitmap, SalGraphics and
SalPrinter. Especially SalGraphics should be used from the generic
implementation as it contains really difficult stuff like drawing
text with complex text layout (CTL) that would be a real pain to
implement with little gain since the result should still look like
the result of the generic SalGraphics. Still, if you want to
implement every Sal interface on your own there is of course nothing
to stop you from doing that.
SalInstance is also responsible for the application main loop and the SolarMutex (the mutex vcl gets its thread awareness from). Since toolkits tend to be nonfunctional without their own main loop, this is the first feature you should implement. The methods GetYieldMutex, ReleaseYieldMutex and AcquireYieldMutex must return a vos::IMutex interface (see vos/inc/vos/mutex.hxx) that synchronizes to the mutex of your special toolkit. Then Yield must be implemented. Yield is VCL's interface to the system main loop; when called it should look for all kinds of events (e.g. X events) and dispatch them appropriately. If called with parameter bWait set to TRUE it should wait until an event is available and then dispatch it. If bWait is FALSE Yield should dispatch all events already available and then return immediately.
Please note that this may be far from trivial to implement depending on your toolkit since so much depends on the main loop. Unless you implement every Sal interface yourself it is basically necessary to inherit from the SalDisplay, SalXLib and SalData classes of the generic implementation since these lay the groundwork for most other generic implementations (X11SalFrame, X11SalTimer, etc.). E.g. SalData adds file descriptors to be watched for events in the main loop. To make this feasible the corresponding methods on the SalXLib, SalData and SalDisplay are virtual so a new implementation can overload these and still use the generic implementation.
The next step is most likely implementing the SalFrame interface. This is necessary for the following reasons:
If you want to use any window inside your toolkit you most likely need a parent that already is a such a toolkit window; e.g. if you want to have native file dialogues you'll want to have a document window as their “parent”(or rather make the dialogue window make transient for the document window in X speak).
SalFrame reads the native system settings, so if you want to have OOo's UI using the correct colors and fonts you'll need to implement at least the UpdateSettings method.
When implementing SalFrame you must overcome the following problems:
SalFrame produces a SalGraphics; here you most likely want to inherit from the generic implementation. The X11SalGraphics for a frame needs to be initialized with a native X drawable, so you need to get the Xlib Window from your native top-level widget. You also need the Xlib Window to implement the GetSystemData method.
SalFrame needs to process internationalized input; there is most likely an abstraction inside your toolkit you'll want to use, so be prepared to send VCL's abstracted input method (IM) events instead of simple key events.
SalFrame can be constructed as a child window of a native window (this is used e.g. in the SDK's java bean where you plug OOo into another application). You'll need to find an appropriate widget to do that with your toolkit (e.g. like a GtkPlug in gtk).
You must prevent you frame widget from drawing its own background as this would interfere with VCL's controls which draw themselves directly onto the window without being known to your toolkit.
If you have implemented SalFrame, you'll need to implement SalObject, too. SalObject is a child window of a SalFrame guaranteed to be a native system window (that is in Xtoolkit terms a widget rather than a gadget). This is needed for plugins and java applets inside documents. There are only two obstacles doing this as SalObject is really rather boring:
You need to find an appropriate widget (a drawing area will generally do)
Since the SalObject is embedded into a lot of gadgets (which is what VCL's controls are from a toolkit standpoint), a real widget will overlap them if any geometry is shared. This would e.g. lead to a plugin drawing over OOo's toolbars if you scroll the corresponding document down slowly. To avoid this SalObject windows need to be shaped using the X SHAPE extension.
While implementing your own plugin you may find it necessary to change something inside the generic plugin. Please do so if it suits you, but contact one of the vcl team (e.g. The author of this document) to check whether your change does not break anything for other implementations.
In general it may be a good idea to contact the vcl developers before and during the implementation on the email@example.com mailinglist as all kinds of questions may arise (especially considering that VCL is largely undocumented code up today).