Standard Widget Toolkit

The main idea of the SWT library is such that its internal implementation on the certain platform is made in the terms of that platform, directly using its native API through the JNI interface, so the look'n'feel comes close to the regular platform applications (i.e. usability; other important benefits of such approach are: easiness, stability, performance). This means that there is a different implementation of the basics of SWT for each supported platform; only the public interface of SWT classes is, of course, the same. So the term "porting" in this case means rewriting the most part of the internal logic from scratch (sometimes including the whole classes) rather than just correcting it for the specific OS. Therefore we have chosen to start from the very beginning and go possibly like original Eclipse developers did, from the basics (the top of the class hierarchy) to details, creating the java and the native code in parallel. The best way to do it is to divide our work into little steps (tasks): every of them is the next level of the implementation and can be tested regardless of other parts that are to be implemented on the next levels.

Brief description of SWT parts

Technically, SWT sources consist of two parts: one is written in Java, another is written in C and contains native methods that communicate with Java code through JNI.

The table below represents basic subcomponents of SWT as they were defined by the original developers. There's a separate directory for each subcomponent in the structure of the Eclipse sources. Packages with names in bold are platform specific (i.e. have their own implementation on each platform), other are common for all platforms (but may require some adaptation for a certain OS). o.e.swt here and further is a short form of org.eclipse.swt, for convenience.

Name Description Packages Prognosis
SWT Base SWT Base. Contains the major part of all public classes and interfaces. Implementations of many basic classes (Display, Widget etc.) are individual for each supported platform. o.e.swt.events
o.e.swt.graphics
o.e.swt.internal
o.e.swt.internal.image
o.e.swt.layout
o.e.swt.widgetsefwef
o.e.swt.graphics
o.e.swt.internal
o.e.swt.widgets
Platform dependent parts need to be almost fully rewritten for OS/2
SWT PI SWT Platform Implementation. Contains platform dependent internal implementations of SWT interface, including Java wrappers for platform native API data structures. o.e.swt.internal
o.e.swt.internal.<xxx>
Needs to be almost fully rewritten for OS/2
SWT AWT It's an experimental class (works currently only on Win32 and has some limitations) to make it possible to embed AWT widgets to SWT layout. o.e.s.internal.awt.<xxx> Can be implemented in the future?
SWT Accessibility Accessibility support. o.s.swt.accessibility
o.s.swt.accessibility
Is it supported natively by OS/2 or should be emulated?
SWT Custom Widgets Standard custom widgets library o.e.swt.custom Does not contain any platform dependent code?
SWT Drag and Drop Public interface for D'n'D support o.e.swt.dnd
o.e.swt.dnd
Platform dependent implementations need to be rewritten (partially ported from Win32?) for OS/2
SWT Printing SWT printing capabilities o.e.swt.printing
o.e.swt.printing
Needs to be almost fully rewritten for OS/2 (not a lot of work to do)
SWT Program OS specific program launching aspects o.e.swt.program Just one single class <)
SWT OLE OLE support o.e.swt.ole.win32
o.e.swt.internal.ole.win32
Can the similar one be implemented for OS/2 in the future?

Native methods [uncomplete]

C sources of native methods are organized in the following way:

Native methods serve as a bridge between SWT and underlying platform API. One of Eclipse principles is that such mapping should be transparent as much as it possible. It means that Java methods have exactly the same name and behavior as their native counterparts, including the type and the list of arguments and the return value. For that purposes there are Java wrappers exist for native structures used by platform API functions to exchange information with the application. These wrapper classes are defined in the SWT PI part as well as the o.e.swt.internal.OS class containing (almost?) all of native API-to-Java mappers. But due to the fact that Java semantics differ from C there cannot be the full equivalence between C and Java types, so some considerations about mapping should be taken into account.

Primitive types

Arrays

...

Pointers

There's a special case with pointers to arrays and ASCIIZ strings, which are returned by some platform API calls to represent some data of variable length. There are few situations when such data is not copied to the storage area provided by the caller, but the pointer to the internal storage area is returned. In these situations we cannot allocate the storage for that data in Java before a call to a native method, because we don't know its size. The solution can be to create the corresponding Java array object inside of the C implementation of the native method after an API call (when we already know the size of the data returned) fill it and return the reference to this object to the Java caller.

Also there are sutiations when an API call returns a pointer to a structure from its internal storage and the user should be able to access this data directly to change some value (the good example is DosGetInfoBlocks()). Since a Java structure wrapper class contains a copy of the original data it doesn't make sence to use it as a parameter to call such API -- it's better to return a pointer to the caller "as is" using a reference to one-element array of int type to use it for the direct access. But Java cannot read/write directly to the specified memory address, so we need some helper functions to copy data from a wrapper class directly to a given memory location and back. These functions are overloaded versions of o.e.swt.internal.pm.OS.objcpy(). They take two arguments: the destination (the first one) and the source (the second one) of data to be copied. One of them is a reference to a wrapper class and another is an int value containing the address of (the pointer to) the corresponding C structure. So, to the sequence of operations to get the required result can be:

  1. Call API function to get the "real" pointer through an one-element int array
  2. Use it in OS.objcpy() to copy data to the object of the wrapper class
  3. Change object's nesessary fields
  4. Use OS.objcpy() to copy data back from the object to the memory

Note. These helper functions are potentionally dangerous and should be used very carefully since there's no way to check whether a given pointer really points to the structure of the appropriate type or not. However, if zero or null is passed as one of arguments, an SWTError exception will be thrown (this behavior depends on the DEBUG_CHECK_NULL_EXCEPTIONS macro definition during compilation of the SWT DLL).

ASCIIZ strings

ASCIIZ strings are mapped using references to the special Java wrapper class: o.e.swt.internal.pm.PSZ. String data is actually stored in its bytes field which is of byte[] type. This class provides automatic appending of zero byte to the array when constructed from Java String type and removing that byte when converted back to String. Convertion between Unicode and 8-byte ASCII characters is done using the default system codepage. There are helper functions to handle this wrapper in C: getPSZArray(), getPSZBytes() and releasePSZBytes(), see their description at the top of structs.h.

Structures

C structures are mapped to Java classes (wrappers) with the same name and fields (their order and names). Primitive fields' types are mapped according to the rules above. For every structure the following C helper functions are defined: cacheXXXFids() (and the correspondig XXX_FID_CACHE structure) to cache Java field IDs, getXXXFields() to fill the native C structure with values from the Java wrapper structure before a call to platform API routine and setXXXFields() for backward operation after a call.

If some field of the structure is itself a structure or a pointer to a structure, there are two ways to handle this situation:

Some structures have the special field (cb or cbFix) that should be set to the length of the structure before passing it to a function. In Win32 version this is achieved by adding an extra field (sizeof) to Java wrapper of every structure and then assigning its value to the length field when using the structure from Java code. In OS/2, this is done not at the Java level, but in the code of the structure's getter function. Therefore, the need in the sizeof field is eliminated (tough,some strucrures will have this field because there are some cases when arrays of that structures are given us as a pointer from the C code and we need to know the address of the particular structure in the array). Also, Java wrappers in OS/2 do not contain the cb or cbFix field since it's useless from the point of view of data the structure represents.

Pointers to structures

Since it's too complicated (in particular, requires two transformations and two times more memory) to convert arrays of C structures to arrays of their Java wrappers and back, such arrays are mapped to arrays of Java int type, where every one or more elements of that array correspond to a field from the structure, consequtively. Of course, it's suitable only for structure types where all fields have the size which is multiple of 32-bit int type, such as POINTL and RECTL. This is primarily used in Gpi* API calls. Hopefully, at the present time there is no need to work with other types of structures.

For convenience, parameter names in the declaration (in Java) and in the definition (in C) of native methods should be the same as in the toolkit documentation.

SWT compilation notes

SWT compilation is driven by the build.xml located in the src\plugins\org.eclipse.swt.pm directory of the repository. It should not be used directly since there are some prerequisites that are set up from the main build file.

Ant includes in compilation every .java file it finds in the specified source directory. Since we go class by class, but use complete common source directories from the original distribution, we need a way to narrow a list of files to compile. Otherwise we will get many errors because of missing platform dependent classes (which are not yet ready) referenced from common sources during compilation. To exclude temporarily the whole common directory is not a good idea because we might need some classes from there. So, there is a special file called classes.inc in the same directory as the SWT build file that contains a list of all files to be compiled. Paths there are relative to the source directories, so every entry there is just a full name of a class but with dots replaced by slashes in the package name. Although file masks can be used there it should be done carefully because file mask will apply to every source directory (we cannot change this behavior in Ant) and unnecessary files can be included.

SWT porting roadmap

Below is the plan and the progress of the SWT porting process. Each step number and objective is a link to the corresponding step description. The names of classes here, in the step descriptions and in some other places follow the rule: the text in [square brackets] after the class name shows the name of the SWT part the class belongs to (according to the table above) and the sharp (#) sign before it means that the class is platform specific, otherwise it is common.

# Objective Started To be done Actually done
1 Initial moves. CVS setup, dummy Device [#Base] implementation. 2002-10-21 2003-01-15 2003-01-21
2 Basics of GUI, part 1. Partially implement the basic hierarchy from the Widget to Shell. 2003-01-24 2003-02-24 2003-03-11
3 Basics of GUI, part 2. Implement drawing facilities 2003-03-12 2003-04-15 2003-07-11
4 Layout basics. Implement the basics of the layout management. 2003-03-12 2003-04-15 2003-07-11
5 Font handling. Implement font handling. 2003-07-12 2003-08-01 2004-02-29
6 Image handling. Implement Image handling 2003-07-22 2003-08-15 2003-11-24
7 Buttons. Finish the implementation of the Button widget 2004-03-01 2004-03-10 2004-10-31
8 Standard dialogs. Implement standard dialogs (Dialog derivants). 2004-12-09 ??
9 Labels. Implement the Label class. 2004-12-09 ??