Abstract Window Toolkit Framework

Revision History

Disclaimer and Legal Information

About this Document

Purpose

Intended Audience

Documentation Conventions

Introduction to AWT

AWT in DRL

Event Handling

Native and AWT Events

Event Dispatch Thread

Native and AWT Events Priority

Native Events Handling

Native and AWT Event Handlers Cooperation

Focus Subsystem

Focus Dispatcher

AWT Level

DRL Focus Implementation Specifics

Visual Themes in AWT

Default Theme

Derived Themes

Implementation Specifics

Using State Interfaces in a Standard Component

Windows* Theme

Multi-threading Support

Why Synchronize

How to Synchronize

When to Synchronize

Synchronizer

References

Revision History

Version Version Information Date
Initial version Nadya Morozova, Pavel Dolgov: document created. May 10, 2006

Disclaimer and Legal Information

Copyright 2005-2006 The Apache Software Foundation or its licensors, as applicable.

Licensed under the Apache License, Version 2.0 (the License); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About This Document

Purpose

This document introduces the AWT (Abstract Window Toolkit) framework delivered as part of the DRL (Dynamic Run-time Layer) initiative. This document focuses on the characteristics of the current AWT implementation.

Intended Audience

The target audience for the document includes a wide community of engineers interested in further work with AWT to contribute to its development. The document assumes that readers are familiar with AWT and the Java* programming language.

Documentation Conventions

This document uses the unified conventions for the DRL documentation kit.

Back to Top

Introduction to AWT

As indicated in the specification [1], the Abstract Window Toolkit (AWT) is a part of the Java* Foundation Classes (JFC). AWT provides basic facilities to develop graphical user interfaces (GUI) and to draw simple graphics for platform-independent applets and applications.

In AWT, GUI consists of components, such as buttons, menus, and top-level windows. One of the main AWT features is that all its built-in components are heavy-weight, that is, every Java* component has a native GUI object behind it. The Swing library [2] is built on the basis of AWT and uses light-weight components, which do not have the 1:1 mapping with native resources.

AWT in DRL

This document describes major design features and internal specifics of the DRL AWT implementation. Further in this document, AWT denotes the DRL implementation for convenience.
To summarize, DRL AWT has the following key features:

Back to Top

Event Handling

AWT helps applications react to user's actions and traces the system state and the AWT internal state by means of events. Subsequent sections describe the AWT event handling implementation in DRL with focus on the interaction between AWT and the native system, specifically, the GUI subsystem of OS. For information on application events handling, consult the AWT specification [1].

Native and AWT Events

The DRL AWT framework deals with the following types of events:

Event Dispatch Thread

AWT has the event dispatch thread (EDT) at its basis, represented by the class java.awt.EventDispatchThread. This thread handles all generated types of events by going over the loop shown in Figure 1. EDT starts on AWT Toolkit creation and stops on application termination.

AWT and native event handling order

Figure 1: Native and AWT Events Handling

In more detail, EDT performs the following event loop:

  1. Wait for and get the native event from operating system.
  2. Decode the native event into an AWT event.
  3. Dispatch the AWT event: find the target AWT component for this event and pass it to this component through the java.awt.Dispatcher class.
  4. Push the AWT event to the event queue represented by the java.awt.EventQueue class.
  5. Pop all AWT events from the event queue.
  6. Pass the given AWT events to the appropriate AWT component by using the java.awt.Component.processXYZEvent() methods.
  7. Call the appropriate AWT component’s event listeners of the EventListener interface. Applications should implement appropriate listeners' interfaces to react to specific events.

Native and AWT Events Priority

Back to Top

Native Events Handling

This section defines native events types and the way AWT handles these events based on their type.

Native Events Classification

Figure 3 below demonstrates how native events can be classified by their role in the AWT framework.

Native events: 4 subtypes

Figure 3: Native Events Classification

Abstracting the Native Platform

Native events handling goes in two stages: the first stage depends on the native platform, and the second stage is the same on all supported platforms. Platform-dependent functionality comprises the Window Toolkit, WTK, in the org.apache.harmony.awt.wtk package. The platform-dependent and platform-independent levels cooperate via three main interfaces of this package: NativeEventListenerNativeEvent, and NativeEventQueue, as shown in Figure 2. Classes implementing the NativeEvent and NativeEventQueue interfaces are platform-specific. For example, the NativeEvent interface is implemented by the classes LinuxEvent and WinEvent for the Linux* and Windows* systems respectively.

Interfaces depending and not depending on the underlying platform

Figure 2: Interfaces for Abstracting the Native Platform

 

Classes of the NativeEvent interface convert information about native events to a platform-independent format. The NativeEventQueue interface fetches native events, and the NativeEventListener interface of the Java* EDT thread handles native events. In the DRL AWT implementation, native and AWT events are handled by the single EDT thread. See the Multi-threading Support section for more information.

Back to Top

Native Event Dispatching

The method onEvent() in the platform-dependent NativeEventListener interface processes native events. Platform-dependent classes implementing NativeEventQueue call this method to handle a relevant native event, see Figure 4.

AWT handles relevant native events by following these steps:

  1. The platform-specific implementation of the NativeEvent interface translates the event to a unified format described by the interface NativeEvent.
  2. The platform-specific implementation of NativeEventQueue calls the EDT method onEvent() and passes the decoded event as a parameter.
  3. EDT passes the event to the java.awt.Dispatcher class identifying the type of event.
  4. Depending on the event type, the dispatcher can handle the event or transmit it to a specific sub-dispatcher. For example, java.awt.MouseDispatcher works with mouse events, java.awt.Dispatcher.KeyDispatcher processes keyboard events.

The result of native event dispatching depends on the event type: state event, signal or invisible. Signal native events are translated to AWT events explicitly (Figure 4, second column). For state and invisible events, the AWT framework updates the state of the AWT object corresponding to the native object that sent the event. For state events, this implicitly generates an AWT event signaling an AWT object state change (Figure 4, third column). For invisible events, the AWT object state gets updated silently (Figure 4, fourth column).

Native events handling by the 4 subtypes

Figure 4: Native Events Handling by Type

Back to Top

Native and AWT Event Handlers Cooperation

Native events often result in new AWT events that need to be handled. This section describes when and how AWT event handlers are called for this purpose.

The Windows* OS generates synchronous and asynchronous native events, so that AWT must be ready to handle nested calls to the event handler. In this case, AWT makes an additional effort to handle AWT events one by one. DRL AWT uses the WindowProc event handler inside WTK for interaction with Windows*. The OS calls this handler for handling any native event in AWT.

The Linux* event handling mechanism is different with its own method for handling native events. In this OS, all native events are asynchronous and no nesting happens.

Handling a single event

Figure 5 is an example of mouse click event handling in AWT. In the given case, the AWT listener does not co-operate with the underlying native system, and, consequently, no other native events are produced during the listener's operation. The example demonstrates handling an event on Windows*.

Native events handling by the 4 subtypes

Figure 5: Mouse Click Event Handling

Numbers in the figure above correspond to the following steps in the event handling flow:

  1. The OS calls WindowProc to handle the native event. The type of event is determined, information about this event is gathered and passed to the onEvent() method of NativeEventListener.
  2. The java.awt.Dispatcher class finds the appropriate target for this event and posts an AWT event to the AWT event queue. In this example, it is MouseEvent.
  3. The method onEventNestingEnd() is called to handle all accumulated AWT events. MouseEvent is fetched from the event queue and finally dispatched. Listeners of the event's target are called at this point.
  4.  WindowProc returns.

Back to Top

Handling nested events

Figure 6 is an example of mouse click event handling with the event listener requests keyboard focus on the clicked component.

Nested Event handling

Figure 6: Mouse Click Event Handling with a Nested Event

Numbers in the figure above correspond to the following steps in the event handling flow:

  1. The OS calls WindowProc, the native event is transformed into an AWT event and stored in the event queue.
  2. The event listener calls requestFocus(), which indirectly results in a native API call.
  3. The OS calls WindowProc to report the focus change event. Because the previous call to WindowProc is not complete yet, the new call is recognized as nested.
  4. The dispatcher adds another AWT event, FocusEvent, to the event queue.
  5.  WindowProc returns without handling AWT events because it is a nested native event handler.
  6. The method onEventNestingEnd() is still working in the first-level WindowProc handler. This method fetches and dispatches the FocusEvent added at step 4.
  7. When the AWT event queue is empty, WindowProc returns.

This technique guarantees that AWT event handlers are called sequentially. The nested native event handler does not attempt to handle pending AWT events. Instead, these events are collected in the event queue to be handled later. The first-level native event handler dispatches all the AWT events waiting in the queue.

Back to Top

Focus Subsystem

The AWT focus subsystem is a set of classes for managing keyboard input focus responsible for:

In the DRL implementation, the focus subsystem functionality is distributed among several internal layers:

The interaction between user code and these levels of the focus subsystem is shown on Figure 7 below.

Detailed event handling schema

Figure 7. Focus Event Data Flow

The following code entities perform the major focus subsystem tasks:

Subsequent sections describe the levels of focus management in more detail and give specifics of the DRL implementation compared to the focus specification [3].

Back to Top

Focus Dispatcher

The focus dispatcher responds to native focus events and, for those relevant to AWT, sends an internal focus change event to the higher AWT level. The dispatcher skips redundant native events and handles event proxying supported on certain native platforms. The focus dispatcher in DRL is characterized by the features listed below.

Platform independence
This component is platform-independent and handles native events in a unified way. For example, when set to skip a false event, the focus dispatcher does not change its behavior on platforms where this type of event never occurs.
Internal operation only: no interaction with user code
The dispatcher does not generate AWT events and never calls client code directly, synchronously. Instead, WTK passes event information to the upper AWT level, which includes the flag indicating whether the focus is lost or gained, the source and opposite components, and the focused window.
Focus Proxying
When the focus is on an inactive window, focus proxies are used. A focus proxy is a child of an active window that has the native focus, whereas focus and key events are redirected to the Java* focused window. This way, the native decorations indicating the active state of the window are on the active window. At the same time, keyboard input and focus AWT events go to the focused window, whereas the native focused window is the focus proxy. The focus dispatcher transfers the native focus to the focus proxy and back when necessary. Events are redirected by the keyboard focus manager.

Events and Output in Event Proxying

Figure 8. Focus Proxy

If the active window is the focused window, no proxying occurs. In this case, the nearest heavyweight ancestor of the focus owner or the focus owner native window itself (if focus owner is a heavy-weight component) has native focus.

Back to Top

AWT Level

The higher level of the focus subsystem generates and posts all necessary AWT events to the event queue. This level keeps track of the following focus states:

The AWT level of the focus subsystem handles focus requests synchronously on every successful focus change request. When the method requestFocus() is called, the keyboard focus manager posts all necessary AWT events in the required order irrespective of the success or failure of the native focus request. In other words, the AWT subsystem does not wait until the native focus request gets confirmed and the corresponding native events are received.

After receiving a notification from the native system, WTK requests the AWT level to update the focus state via an internal request. For example, if the native system reports an unsuccessful focus change, a component might lose focus.

Note

Only certain native focus-related events cause a Java* focus state update. For example:

Back to Top

DRL Focus Implementation Specifics

Below, the specific features of DRL implementation are listed compared to the focus specification grouped by their function.

Replacing the DefaultKeyboardFocusManager class
The keyboard focus manager handles all events in the required order and never synthesizes window activation events. Instead, the focus manager skips the events that do not correspond to the current focus state. Such events can be generated by the private API of this class in response to native events. For example, the keyboard focus manager ignores events sent to the window that has failed to become the focused window because the corresponding AWT event was dispatched and vetoed.
When handling the WINDOW_GAINED_FOCUS event, private methods in the keyboard focus manager set focus on the appropriate child component of the window.
Programmatic Traversal
Disabling any ancestor of the focus owner, both light-weight and heavy-weight, automatically initiates a focus traversal.

Back to Top

Visual Themes in AWT

This document describes the mechanism of drawing standard AWT components with platform-independent Java* means or platform-specific native API or using both approaches.

Default theme

You can paint standard components in many ways, including drawing the component parts (text, background, shadows and all other elements) by the means of class java.awt.Graphics. Note that the framework must not paint standard components by the method java.awt.Component.paint() because it could be overridden. Instead, when processing a painting event, the framework calls the package-private method java.awt.Component.prepaint() just before calling the method paint(). The prepaint() method does the actual painting for all standard components by delegating the painting task to the theme. This approach might not seem optimal, but it works on all supported platforms without any changes.

The org.apache.harmony.awt.Theme class implements the default theme. Methods of this class do the following:

The default theme class is platform-independent, non-abstract and fully functional, and it usually works when the native theme is disabled or not available, or when the native theme re-uses functionality of the standard theme.

Back to Top

Derived themes

You can create a custom theme that inherits from the default theme and contains specific features. The current implementation contains the WinTheme class that extends the default theme as shown in Figure 9.

To use the native API in your theme, extend the default theme overriding its painting methods. In the derived theme, you can use the additional features of specific implementation of the Graphics class, and explicitly call native API functions via wrappers, see org.apache.harmony.misc package for details. Figure 9 below demonstrates theme-related classes hierarchy with methods related to the Button component as an example. A block of code for extending the drawButton() method is shown in Example 1 below.

OS specific themes as subclasses to the major theme

Figure 9: Hierarchy of Theme Classes

 

After creating a derived theme, turn it on by using the property awt.theme. This property contains the name of a subclass of default theme class used as the theme by all components. If the property points to a non-existent class or if the required native library is missing, or any other error occurs, the default theme is used. If the property is not set, the native theme of the current OS is used if it exists. If no OS theme exists, the default theme is used.

To force the default theme, set the command-line option -Dawt.theme=0. As long as zero is an invalid class name, this does the job.

Back to Top

Implementation details

Painting standard components requires access to their internal state, such as the pressed state, the focused state, the background color, and the contained text. Because not all these attributes are visible through the public API, the DRL AWT module provides a set of interfaces to allow the theme to access private and public data. The package org.apache.harmony.awt.state contains these interfaces, such as, TextStateCheckboxState, and ButtonState. Each standard component class has an inner class that implements the appropriate interface and has the state field of that class declared. The java.awt.Component class stores all functionality common for all types of standard components. Specifically, the java.awt.Component class has an inner class ComponentState that implements the org.apache.harmony.awt.state.State interface. This inner class enables implementing the state of a specific component by overriding only a few methods.

Standard components delegate the painting and size calculation to the currently active theme and pass their state field value as a parameter to every method of the theme.

Platform-specific and component-specific code is concentrated in separate helper classes, such as DefaultButton, the helper to the default theme, and WinCheckbox, the helper to the Windows* theme. The theme class contains only simple methods.

Example 1

This is an example with the Button component.

public void drawButton(Graphics g, ButtonState s) { 
    drawButtonBackground(g, s); 
    drawButtonText(g, s); 
} 
protected void drawButtonBackground(Graphics g, ButtonState s) { 
    DefaultButton.drawBackground(g, s); 
} 
protected void drawButtonText(Graphics g, ButtonState s) { 
    DefaultButton.drawText(g, s); 
}

When designing a custom theme, you may need to override some of these protected methods.

Figure 10 shows an example of component classes relation, inner states and the inheritance hierarchy of component state interfaces. The figure contains short names for convenience, for example,  Component actually means  java.awt.Component.

Methods and classes related to state change operations

Figure 10: Inheritance and Composition for Components' State

Back to Top

Using State Interfaces in a Standard Component

This section illustrates how the state interfaces are used in the Button component. In DRL AWT, all standard components follow the same model.

This is a part of the java.awt.Button code that illustrates how to use visual themes in standard components.

class State extends Component.ComponentState implements ButtonState { … } 
final transient State state = new State(); 
    
void prepaint(Graphics g) { 
    toolkit.theme.drawButton(g, state); 
}

The framework calls the prepaint() method, which paints standard components. The painting itself is done by the theme class, and all the information it requires is contained in the state variable.

Back to Top

Windows* theme

In DRL, the Windows* theme is implemented by the class org.apache.harmony.awt.theme.windows.WinTheme, which inherits from the class org.apache.harmony.awt.Theme.

The WinTheme class paints components using the Windows* API function DrawFrameControl() in the classic mode and DrawThemeBackground() in the XP mode, and basic Windows* API painting functions.

The implementation also includes several helper classes:

Note

If the Windows* theme does not support the combination of components attributes, it delegates painting to the default theme by calling the super class. For example, the default theme can be used when the background color of a push button differs from the theme setting.

Back to Top

Multi-Threading support

Complying to the specification [1], DRL AWT can work within multi-threaded applications. This implementation ensures consistency of AWT framework data when accessed by multiple threads. For that, AWT synchronizes its key classes.

Why synchronize

The main purpose of synchronization is keeping the component hierarchy consistent when component properties are queried and/or modified, so that it potentially affects other components. This includes the parent-child relationships, the child component order, inherited properties, such as the font and the background color, the size and position related properties, as well as visibility, focusable state and other conditions relevant for message handling. Concurrent modifications of these properties can make the AWT framework state inconsistent.

For example, if a thread adds a component to a list of child components for a container without updating this component’s field parent, another thread working with the same component gets the wrong value of the parent field. Moreover, the second thread may remove this component from the container children list, which makes the behavior of the first thread unpredictable. Synchronization helps avoid such problems.

Back to Top

How to synchronize

When a method or a block of code deals with the data that must not be modified concurrently, a synchronized section is used. The DRL implementation uses a special monitor AWT lock more powerful than built-in Java* synchronized blocks and methods. The AWT lock is similar to the synchronization tools provided by the java.util.concurrent package. The synchronized section using the AWT lock has its own specifics, as demonstrated by the example below.

Example 2

This example provides an excerpt of code from the Component class demonstrating a typical synchronized section in the AWT code. The methods lockAWT() and unlockAWT() are the boundaries of the critical section. The code between them is synchronized by the AWT lock.

final transient Toolkit toolkit = Toolkit.getDefaultToolkit();
…
public Color getBackground() {
    toolkit.lockAWT();
    try {
        if ((backColor == null) && (parent != null)) {
            return parent.getBackground();
        }
        return backColor;
    } finally {
        toolkit.unlockAWT();
    }
}

From the syntactical standpoint, this is a try-finally structure, which guarantees that the unlockAWT() method is always called after doing the useful work in the body of try block. Logically, it is used as an ordinary synchronized block, except when using AWT lock extended functionality.

Back to Top

When to synchronize

AWT synchronization covers the following classes:

The total number of synchronized classes nears 40.

Simple data structures, for example, Rectangle or Point, are not protected from concurrent modifications for performance reasons.

General rules on how to use synchronized sections

Exceptions

Note

In platform-specific event handling code, the event listener uses this lock by calling methods onEventBegin() and onEventEnd(). These methods call lockAWT() and unlockAWT() respectively. This is done to ensure that the dispatcher can find the event target and that the data is not modified by another thread.

Back to Top

Synchronizer

The org.apache.harmony.awt.wtk.Synchronizer class implements the AWT lock. The Toolkit class holds the reference to the synchronizer instance. In a standalone application, Toolkit and Synchronizer are singleton classes. In the multi-context mode, AWT provides independent Toolkit and Synchronizer instances per each context.

Figure 11 shows the inheritance relationship of synchronizer classes. The Linux* and Windows* operating systems have their own classes.

Windows and Linux synchronizers are subclasses of Synchronizer

Figure 11: Synchronizer Classes

The base class Synchronizer represents a mutex with a high-priority event dispatch thread. All user threads are served in the FIFO (first in first out) order, whereas EDT has higher priority and is served in the LIFO (last in first out) order.

Back to Top

Synchronizer for Linux*

AWT uses the Xlib library to access native window resources on Linux*. The Xlib library is thread-safe and all user and EDT threads can freely access the native system through the AWT interface, as shown in Figure 12. As a result, the class org.apache.harmony.awt.wtk.linux.LinuxSynchronizer contains no extensions to java.awt.Synchronizer.

user threads access native resources independently of the EDT thread

Figure 12: Access to the Native System on Linux*

Back to Top

Synchronizer for Windows*

Synchronization on Windows* is different due to Windows* libraries specifics. Firstly, changing the state of a native window usually produces a synchronous event that reports this change. Secondly, only the thread that created a window receives native events related to that window.

In DRL AWT, the event dispatch thread handles all native events and, consequently, is the only thread that can create windows. EDT also changes the window’s state to simplify the native events handling scheme. Non-EDT threads can create and manipulate native windows by giving tasks to EDT. User and EDT threads cooperation is shown in Figure 13.

user threads access native resources via of the EDT thread

Figure 13: Access to the Native System on Windows* with EDT

The org.apache.harmony.awt.wtk.windows.WinSynchronizer class, the extension of Synchronizer, implements the interface NativeServer, which enables user threads to query EDT for access to native resources.

However, delegating access to native resources to EDT requires a more complicated synchronization mechanism. Using the Synchronizer logic as is results in a potential deadlock while handling native Windows* events. Figure 14 shows the scenario of the deadlock.

thread execution flows with deadlock illustrated

Figure 14: Deadlock with the user thread and EDT

t1: The user thread starts.

t2: EDT starts.

t3: The user thread obtains the AWT lock.

t4: EDT tries to obtain the AWT lock and gets blocked.

t5: The user thread requests a service from EDT via the NativeServer interface and gets blocked forever because EDT is blocked too.

The WinSynchronizer class resolves the deadlock issue by combining the synchronizer’s protocol and the native server protocol. For that, EDT switches between handling events and providing access to native resources for other running threads, as shown in Figure 15.

EDT modes

Figure 15. EDT Operation

This algorithm enables detecting a potential deadlock and resolving it. When EDT is requested to provide access to native resources while it is waiting to obtain the AWT lock, EDT awakes, serves the request and resumes waiting. Serving the native resource request is transparent for the event-handling side of EDT because this operation is performed while EDT is inside of lockAWT() method. The deadlock is resolved, as shown in Figure 16.

Thread execution flow with no deadlock

Figure 16: Deadlock Resolution by WinSynchronizer

t1: The user thread starts.

t2: EDT starts.

t3: The user thread obtains the AWT lock.

t4: EDT tries to obtain the AWT lock and gets blocked.

t5: The user thread requests EDT service and also gets blocked. EDT starts processing the request.

t6: EDT finishes processing request. The user thread resumes.

t7: The user thread releases the AWT lock, EDT obtains it.

t8: The user thread may continue its work or exit.

t9: EDT releases the AWT lock.

t10: EDT continues operation.

Back to Top

References

[1] AWT spec, http://java.sun.com/j2se/1.5.0/docs/guide/awt/index.html

[2] Swing Library Description, http://java.sun.com/j2se/1.5.0/docs/guide/swing/index.html

[3] AWT Focus Subsystem specification, http://java.sun.com/j2se/1.5.0/docs/api/java/awt/doc-files/FocusSpec.html

 

Back to Top

* Other brands and names are the property of their respective owners.