|  | <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> | 
|  | <html> | 
|  | <head> | 
|  | <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> | 
|  | <title>SWT: The Standard Widget Toolkit</title> | 
|  | <link rel="stylesheet" href="../default_style.css"> | 
|  | </head> | 
|  | <body> | 
|  | <div align="right"> | 
|  | <font face="Times New Roman, Times, serif" size="2">Copyright | 
|  | © 2001 Object Technology International, Inc.</font> | 
|  |   | 
|  |  | 
|  | <table BORDER=0 CELLSPACING=0 CELLPADDING=2 WIDTH="100%" > | 
|  | <tr> | 
|  | <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica"><font color="#FFFFFF"> Eclipse | 
|  | Corner Article</font></font></b></td> | 
|  | </tr> | 
|  | </table> | 
|  | </div> | 
|  | <h1> | 
|  | <img SRC="idea.jpg" height=86 width=120 align=CENTER></h1> | 
|  | <center> | 
|  | <h1> | 
|  | SWT: The Standard Widget Toolkit</h1></center> | 
|  |  | 
|  | <center> | 
|  | <h3> | 
|  | PART 1: Implementation Strategy for Java™ Natives</h3></center> | 
|  |  | 
|  | <center><i>The first in a series of articles about the design ideas behind | 
|  | SWT.</i></center> | 
|  |  | 
|  | <blockquote><b>Summary</b> | 
|  | <br>SWT is the software component that delivers native widget functionality | 
|  | for the Eclipse platform in an operating system independent manner.  | 
|  | It is analogous to AWT/Swing in Java with a difference - SWT uses a rich set of native | 
|  | widgets.  Even in an ideal situation, industrial strength cross platform | 
|  | widget libraries are very difficult to write and maintain.  This is | 
|  | due to the inherent complexity of widget systems and the many subtle differences | 
|  | between platforms.  There are several basic approaches that have helped | 
|  | significantly to reduce the complexity of the problem and deliver high | 
|  | quality libraries.  This article discusses one of them, the low level | 
|  | implementation techniques used to implement SWT on different platforms.  | 
|  | Examples are drawn from the Windows® and Motif implementations. | 
|  |  | 
|  | <p><b>By Steve Northover, OTI</b> | 
|  | <br> | 
|  | <font size="-1">March 22, 2001</font> </p> | 
|  |  | 
|  | </blockquote> | 
|  |  | 
|  | <p> | 
|  | <hr WIDTH="100%"> | 
|  | <h3> | 
|  | Portable and Native - It Can't Be Done!</h3> | 
|  | Developers demand portable graphics and widgets to allow them to build | 
|  | user interfaces that are competitive with shrink-wrapped applications built | 
|  | using platform specific tools.  They need access to platform specific | 
|  | features, with well defined API boundaries. SWT delivers this functionality | 
|  | using a small and consistent API.  This API is implemented on different | 
|  | platforms using a combination of Java code and JNI natives specific to | 
|  | each platform. | 
|  | <p>SWT is implemented entirely in one language: Java.  How can this | 
|  | be true when SWT uses native widgets that provide an API in C?  The | 
|  | answer is that Java provides a native interface to C (JNI) that is used | 
|  | by SWT to invoke the operating system from Java code.  JNI is the | 
|  | standard mechanism used by all Java programs to invoke code written in | 
|  | C. SWT goes one step further by enforcing a<i> one-to-one mapping</i> between | 
|  | Java native methods and operating system calls.  The fact that this | 
|  | mapping is strictly enforced is one of the most critical factors in the | 
|  | success of SWT. | 
|  | <h3> | 
|  | A Tale of Two Implementations</h3> | 
|  | Let's take a look at the implementation of SWT <i>Text</i> widget on two | 
|  | different platforms.  The <i>Text</i> widget provides the ability | 
|  | to set the selection.  SWT application code that uses this API might | 
|  | look something like this: | 
|  | <p><tt>    /* Select positions 2 to 5 */</tt> | 
|  | <br><tt>    text.setText ("0123456780");</tt> | 
|  | <br><tt>    text.setSelection (2, 5);</tt> | 
|  | <p>The method signature for <b>setSelection</b> in class <i>Text</i> looks | 
|  | like this: | 
|  | <p><tt>    /**</tt> | 
|  | <br><tt>    * Sets the selection.</tt> | 
|  | <br><tt>    * <p></tt> | 
|  | <br><tt>    * Indexing is zero based.  The range of | 
|  | a selection is from 0..N</tt> | 
|  | <br><tt>    * where N is the number of characters in the | 
|  | widget.</tt> | 
|  | <br><tt>    */</tt> | 
|  | <br><tt>    public void setSelection (int start, int end)</tt> | 
|  | <p>Here is the Windows implementation of <b>setSelection</b>: | 
|  | <p><tt>    public void setSelection (int start, int end) | 
|  | {</tt> | 
|  | <br><tt>        OS.SendMessage (handle, | 
|  | OS.EM_SETSEL, start, end);</tt> | 
|  | <br><tt>    }</tt> | 
|  | <p>What are <b>SendMessage</b> and <b>EM_SETSEL</b>?  Windows programmers | 
|  | recognize this right away.  It's <b>SendMessage</b>, the mechanism | 
|  | that is used to talk to Windows controls. <b>EM_SETSEL</b> is the message | 
|  | that tells the text control to set the selection.  It's not easy reading, | 
|  | but it is familiar to a Windows programmer.  The rest of us get to | 
|  | read the Microsoft® Developer Network (MSDN) Library! | 
|  | <p>Here is the Java code for the SWT class <i>OS</i> on Windows: | 
|  | <p><tt>    class OS {</tt> | 
|  | <br><tt>        public static final | 
|  | int EM_SETSEL = 0xB1;</tt> | 
|  | <br><tt>        public static final | 
|  | native int SendMessage (int hWnd, int Msg, int wParam, int lParam);</tt> | 
|  | <br><tt>        ...</tt> | 
|  | <br><tt>    }</tt> | 
|  | <p>How is the <b>SendMessage</b> native implemented?  Here is the | 
|  | C code on Windows: | 
|  | <p><tt>    JNIEXPORT jint JNICALL Java_org_eclipse_swt_internal_win32_OS_SendMessage__IIII</tt> | 
|  | <br><tt>      (JNIEnv *env, jclass that, jint | 
|  | hWnd, jint Msg, jint wParam, jint lParam)</tt> | 
|  | <br><tt>    {</tt> | 
|  | <br><tt>        return (jint) SendMessage((HWND)hWnd, | 
|  | Msg, wParam, lParam);</tt> | 
|  | <br><tt>    }</tt> | 
|  | <p>Notice that <i>the only thing this native does</i> is pass the Java | 
|  | call straight on through to the Windows API. But what about other operating | 
|  | systems?  Does the fact that <b>setSelection</b> is implemented in | 
|  | terms of the Windows API mean that SWT is not portable?  While it | 
|  | is true that the Windows implementation of <i>Text</i> is not portable, | 
|  | application code that uses <i>Text</i> is.  How is this achieved?  | 
|  | SWT provides a different <i>Text</i> class for each platform, but the signature | 
|  | of every public method is the same.  Java code that calls SWT does | 
|  | not know or care which <i>Text</i> class is referenced at run time. | 
|  | <b>SendMessage</b> | 
|  | is not SWT API. | 
|  | <p>Here is the implementation of <b>setSelection</b> on Motif (Java and | 
|  | JNI C): | 
|  | <p><tt>    public void setSelection (int start, int end) | 
|  | {</tt> | 
|  | <br><tt>        int xDisplay = OS.XtDisplay | 
|  | (handle);</tt> | 
|  | <br><tt>        if (xDisplay == 0) return;</tt> | 
|  | <br><tt>        OS.XmTextSetSelection | 
|  | (handle, start, end, OS.XtLastTimestampProcessed (xDisplay));</tt> | 
|  | <br><tt>        OS.XmTextSetInsertionPosition | 
|  | (handle, end);</tt> | 
|  | <br><tt>    }</tt> | 
|  | <p><tt>    class OS {</tt> | 
|  | <br><tt>        public static final | 
|  | native void XmTextSetSelection (int widget, int first, int last, int time);</tt> | 
|  | <br><tt>        public static final | 
|  | native int XtLastTimestampProcessed (int display);</tt> | 
|  | <br><tt>        public static final | 
|  | native void XmTextSetInsertionPosition (int widget, int position);</tt> | 
|  | <br><tt>        public static final | 
|  | native int XtDisplay (int widget);</tt> | 
|  | <br><tt>        ...</tt> | 
|  | <br><tt>    }</tt> | 
|  | <p><tt>    JNIEXPORT void JNICALL Java_org_eclipse_swt_internal_motif_OS_XmTextSetSelection</tt> | 
|  | <br><tt>      (JNIEnv *env, jclass that, jint | 
|  | widget, jint first, jint last, jint time)</tt> | 
|  | <br><tt>    {</tt> | 
|  | <br><tt>        XmTextSetSelection((Widget)widget, | 
|  | first, last, time);</tt> | 
|  | <br><tt>    }</tt> | 
|  | <p><tt>    ...</tt> | 
|  | <p>What are <b>XtDisplay</b>, <b>XmTextSetSelection</b>, <b>XtLastTimestampProcessed</b> | 
|  | and <b>XmTextSetInsertionPosition</b>?  They don't mean much to a | 
|  | Windows programmer, but they are familiar to anyone who has ever programmed | 
|  | Motif.  Now it's the Windows programmer's turn to consult the Motif | 
|  | man pages! | 
|  | <p>The example code above was taken directly from SWT but has been simplified | 
|  | by removing range and error checking code for the sake of the example.  | 
|  | However, the code that is doing the real work - setting the selection - | 
|  | is identical to that found in the product. | 
|  | <h3> | 
|  | One to One Mapping - No Custom Natives</h3> | 
|  | Take a moment to review the Java and C code for <b>setSelection</b> in | 
|  | the previous section.  Wouldn't it be easier to implement one <i>Text</i> | 
|  | class for all SWT platforms and hide the platform differences in the natives?  | 
|  | Such an implementation might look like this: | 
|  | <p><tt>    public void setSelection (int start, int end) | 
|  | {</tt> | 
|  | <br><tt>        nativeSetSelection (start, | 
|  | end)</tt> | 
|  | <br><tt>    }</tt> | 
|  | <br><tt>    static final native void nativeSetSelection (int | 
|  | start, int end);</tt> | 
|  | <p><tt>    JNIEXPORT void JNICALL Java_org_eclipse_swt_widgets_text_nativeSetSelection</tt> | 
|  | <br><tt>      (JNIEnv *env, jclass that, jobject | 
|  | widget, jint first, jint last)</tt> | 
|  | <br><tt>    {</tt> | 
|  | <br><tt>    #ifdef WINDOWS</tt> | 
|  | <br><tt>        HWND hWnd = SWTGetHandleFromJavaWidget | 
|  | (widget);</tt> | 
|  | <br><tt>        SendMessage(hWnd, Msg, | 
|  | wParam, lParam);</tt> | 
|  | <br><tt>    #endif</tt> | 
|  | <br><tt>    #ifdef MOTIF</tt> | 
|  | <br><tt>        Widget *w = SWTGetHandleFromJavaWidget | 
|  | (widget);</tt> | 
|  | <br><tt>        Display xDisplay = XtDisplay | 
|  | (w);</tt> | 
|  | <br><tt>        if (xDisplay == NULL) | 
|  | return;</tt> | 
|  | <br><tt>        XmTextSetSelection (w, | 
|  | start, end, XtLastTimestampProcessed (xDisplay));</tt> | 
|  | <br><tt>        XmTextSetInsertionPosition | 
|  | (w, end);</tt> | 
|  | <br><tt>    #endif</tt> | 
|  | <br><tt>    }</tt> | 
|  | <p>Isn't this easier than having a different <i>Text</i> class on each | 
|  | platform?  The answer is a resounding "<i>No</i>".  Why?  | 
|  | In the case of the <i>Text</i> widget, the code to set the selection is | 
|  | pretty simple but even this causes problems.  Before we get into the | 
|  | discussion, consider this: | 
|  | <ul> | 
|  | <li> | 
|  | The non-public native interface must be identical on all platforms.  | 
|  | This means there needs to be an implementation of <b>nativeSetSelection</b> | 
|  | everywhere.  We also still need to provide the public SWT API.  | 
|  | So we need to implement <b>setSelection</b> everywhere. Why would we want | 
|  | to write two portable APIs instead of just one?  One API is hard enough | 
|  | to specify and maintain!</li> | 
|  |  | 
|  | <li> | 
|  | Java is a powerful high level language with features that promote robust | 
|  | code and program stability.  It contains reusable class libraries | 
|  | for high level data types such as hash tables and vectors as well as efficient | 
|  | primitive types. Why use C?</li> | 
|  | </ul> | 
|  | Calling the operating system directly from Java helps with debugging. The | 
|  | following problem occurred in an early version of SWT for Windows:  | 
|  | when the selection was set in the text widget, sometimes the widget did | 
|  | not scroll to show the i-beam.  Where was the problem?  The code | 
|  | that demonstrated the problem was complicated, but it was clear from stepping | 
|  | through the Java code and consulting the MSDN Library that the Java implementation | 
|  | of <b>setSelection</b> was correct.  In fact, because of the <i>one-to-one | 
|  | mapping</i> between our Java natives and C, it was possible to write a | 
|  | simple C example to help isolate the problem and submit a bug report to | 
|  | Microsoft.  Why was this so easy?  Because, as we have said before, | 
|  | nothing extra ever happens in an SWT native. The Java call is passed right | 
|  | on through to the operating system.  This means that C code is guaranteed | 
|  | to exhibit the same behavior.  This is great news for debugging and | 
|  | maintenance. | 
|  | <p>Performance problems are legendary in widget toolkits and finding them | 
|  | is a black art.  Where is the performance problem?  Is it in | 
|  | the Java code or the natives?  Fortunately, SWT natives can't be the | 
|  | problem. We are guaranteed that once we are in a native, the limiting factor | 
|  | is the speed of the operating system - something beyond our control.  | 
|  | This is great news for performance tuning: look at the Java code.  | 
|  | In fact, one quickly develops a sense of which operating system operations | 
|  | are expensive and which are cheap. Best of all, this knowledge is accurate.  | 
|  | A C program that makes the same sequence of operating system calls will | 
|  | exhibit the same performance characteristics.  This is a feature of | 
|  | the one-to-one mapping. | 
|  | <p>What happens when you try to debug a segment fault (or GP)?  It's | 
|  | easy enough to step into a Java method and examine arguments but not possible | 
|  | to step into a native.  Fortunately, nothing special happens in SWT | 
|  | natives so it's easy enough to isolate the code that is causing the problem.  | 
|  | While on the subject of GPs, wouldn't it make sense for SWT natives to | 
|  | check their parameters before making the operating system call?  It's | 
|  | tempting to check for NULL or -1 to avoid the crash.  On the surface, | 
|  | this seems to make sense - after all, who wants to GP?  The answer, | 
|  | of course, is that this would violate the one-to-one mapping and would | 
|  | mean that an equivalent C program would not crash in the same place.  | 
|  | That's bad news for debugging and isolating a problem. | 
|  | <p>For someone implementing and maintaining SWT, the one-to-one mapping | 
|  | is extremely valuable.  For example, a Windows programmer knows right | 
|  | away how <b>setSelection</b> works, just by looking at the Java code.  | 
|  | Everyone else needs to read the MSDN Library.  It's not light reading, | 
|  | but the information is there.  The same thing is true for a Motif | 
|  | programmer for SWT on Motif, and for the other supported operating systems.  | 
|  | In fact, it's clear exactly how existing features work and new features | 
|  | are to be implemented.  The critial point here is that the documentation | 
|  | for the operating system applies to all SWT natives because they are a | 
|  | one-to-one mapping. | 
|  | <p>Adding new native features to SWT is a straightforward and well defined | 
|  | process. For example, implementing drag and drop and integrating it with | 
|  | the widgets was not difficult, despite the fact that these are two independent | 
|  | services.  Why was this so easy?  Nothing is hidden in the C | 
|  | code.  All of the operating system resources needed to implement SWT | 
|  | are manifested as simple Java objects making it easy to understand how | 
|  | SWT works and to make changes.  This allows SWT to be customized to | 
|  | support new platform dependent widgets and operating system services as | 
|  | they become available. | 
|  | <p>One last point: JNI is rich and powerful.  It allows you to allocate | 
|  | Java objects in C, get and set Java fields, invoke new VMs and throw exceptions.  | 
|  | The operating system, on the other hand, is typically more primitive.  | 
|  | For example, most operating system calls that access memory require you | 
|  | to allocate the buffer and pass in the size.  Java arrays know their | 
|  | size, so why do we need to pass it in?  JNI allows us to allocate | 
|  | objects in C, so why not allocate buffers in the C code?  Wouldn't | 
|  | it be better to try and "fix" the operating system API to make it more | 
|  | Java friendly?  The answer again is "<i>No</i>".  Any deviation | 
|  | from the one-to-one rule means that our Java code no longer behaves the | 
|  | same as the equivalent C code.  For example, allocating objects in | 
|  | JNI could introduce a hidden performance problem for Java code inside a | 
|  | tight loop.  Also, it may make sense to allocate one large buffer | 
|  | and pass in a smaller size, or reuse a buffer.  It's tempting to use | 
|  | JNI | 
|  | features to attempt to "fix" the operating system API but this is a huge | 
|  | mistake. | 
|  | <h3> | 
|  | Conclusion</h3>All of the natives in SWT are implemented using this simple and consistent strategy.  There is no C code to hide the low level details of the operating system such as the event loop, callbacks or the thread model.  No code reaches back into Java from C to get a field or invoke a method.  Nothing is magic - everything is coded in Java using the terminology and documentation of the operating system.  Why is this such a big deal?  Some might claim that all SWT does is use JNI to invoke the operating system - nothing fancy. But that's the whole point.  Without a simple set of rules and a sense of restraint - a characteristic of SWT - it's just too easy for a widget toolkit to collapse under its own weight.<br>  | 
|  |  | 
|  | <p><small>Java and all Java-based trademarks and logos are trademarks or registered | 
|  | trademarks of Sun Microsystems, Inc. in the United States, other countries, or | 
|  | both.</small></p> | 
|  | <p><small>Microsoft, Windows, Windows NT, and the Windows logo are trademarks of Microsoft Corporation in the United States, other countries, or both.</small></p> | 
|  |  | 
|  | </body> | 
|  | </html> |