org.eclipse.swt.widgets.Display.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.swt.widgets.Display.java

Source

/*******************************************************************************
 * Copyright (c) 2002, 2015 Innoopract Informationssysteme GmbH and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Innoopract Informationssysteme GmbH - initial API and implementation
 *    EclipseSource - ongoing development
 *    Frank Appel - replaced singletons and static fields (Bug 337787)
 *    Rdiger Herrmann - exception handler (bug 367773)
 ******************************************************************************/
package org.eclipse.swt.widgets;

import static org.eclipse.rap.rwt.internal.lifecycle.DisplayUtil.getId;
import static org.eclipse.rap.rwt.internal.protocol.ProtocolUtil.readPropertyValue;
import static org.eclipse.rap.rwt.remote.JsonMapping.readPoint;
import static org.eclipse.rap.rwt.remote.JsonMapping.readRectangle;

import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.eclipse.rap.json.JsonValue;
import org.eclipse.rap.rwt.Adaptable;
import org.eclipse.rap.rwt.application.ExceptionHandler;
import org.eclipse.rap.rwt.internal.application.ApplicationContextImpl;
import org.eclipse.rap.rwt.internal.lifecycle.CurrentPhase;
import org.eclipse.rap.rwt.internal.lifecycle.IUIThreadHolder;
import org.eclipse.rap.rwt.internal.lifecycle.LifeCycle;
import org.eclipse.rap.rwt.internal.lifecycle.LifeCycleUtil;
import org.eclipse.rap.rwt.internal.lifecycle.PhaseId;
import org.eclipse.rap.rwt.internal.lifecycle.ProcessActionRunner;
import org.eclipse.rap.rwt.internal.lifecycle.RemoteAdapter;
import org.eclipse.rap.rwt.internal.lifecycle.WidgetUtil;
import org.eclipse.rap.rwt.internal.serverpush.ServerPushManager;
import org.eclipse.rap.rwt.internal.service.ContextProvider;
import org.eclipse.rap.rwt.internal.service.ServletLog;
import org.eclipse.rap.rwt.internal.theme.CssColor;
import org.eclipse.rap.rwt.internal.theme.CssImage;
import org.eclipse.rap.rwt.internal.theme.CssValue;
import org.eclipse.rap.rwt.internal.theme.SimpleSelector;
import org.eclipse.rap.rwt.internal.theme.ThemeUtil;
import org.eclipse.rap.rwt.service.ServerPushSession;
import org.eclipse.rap.rwt.service.UISession;
import org.eclipse.rap.rwt.theme.BoxDimensions;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Device;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.internal.SerializableCompatibility;
import org.eclipse.swt.internal.events.EventList;
import org.eclipse.swt.internal.events.EventUtil;
import org.eclipse.swt.internal.widgets.IDisplayAdapter;
import org.eclipse.swt.internal.widgets.IdGenerator;
import org.eclipse.swt.internal.widgets.WidgetRemoteAdapter;
import org.eclipse.swt.internal.widgets.WidgetTreeUtil;
import org.eclipse.swt.internal.widgets.WidgetTreeVisitor;

/**
 * Instances of this class are responsible for managing the
 * connection between SWT and the underlying operating
 * system. Their most important function is to implement
 * the SWT event loop in terms of the platform event model.
 * They also provide various methods for accessing information
 * about the operating system, and have overall control over
 * the operating system resources which SWT allocates.
 * <p>
 * Applications which are built with SWT will <em>almost always</em>
 * require only a single display. In particular, some platforms
 * which SWT supports will not allow more than one <em>active</em>
 * display. In other words, some platforms do not support
 * creating a new display if one already exists that has not been
 * sent the <code>dispose()</code> message.
 * <p>
 * In SWT, the thread which creates a <code>Display</code>
 * instance is distinguished as the <em>user-interface thread</em>
 * for that display.
 * </p>
 * The user-interface thread for a particular display has the
 * following special attributes:
 * <ul>
 * <li>
 * The event loop for that display must be run from the thread.
 * </li>
 * <li>
 * Some SWT API methods (notably, most of the public methods in
 * <code>Widget</code> and its subclasses), may only be called
 * from the thread. (To support multi-threaded user-interface
 * applications, class <code>Display</code> provides inter-thread
 * communication methods which allow threads other than the
 * user-interface thread to request that it perform operations
 * on their behalf.)
 * </li>
 * <li>
 * The thread is not allowed to construct other
 * <code>Display</code>s until that display has been disposed.
 * (Note that, this is in addition to the restriction mentioned
 * above concerning platform support for multiple displays. Thus,
 * the only way to have multiple simultaneously active displays,
 * even on platforms which support it, is to have multiple threads.)
 * </li>
 * </ul>
 * Enforcing these attributes allows SWT to be implemented directly
 * on the underlying operating system's event model. This has
 * numerous benefits including smaller footprint, better use of
 * resources, safer memory management, clearer program logic,
 * better performance, and fewer overall operating system threads
 * required. The down side however, is that care must be taken
 * (only) when constructing multi-threaded applications to use the
 * inter-thread communication mechanisms which this class provides
 * when required.
 * </p><p>
 * All SWT API methods which may only be called from the user-interface
 * thread are distinguished in their documentation by indicating that
 * they throw the "<code>ERROR_THREAD_INVALID_ACCESS</code>"
 * SWT exception.
 * </p>
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>(none)</dd>
 * <dt><b>Events:</b></dt>
 * <dd>Close, Dispose, Skin</dd>
 * </dl>
 * <p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 * @see #syncExec
 * @see #asyncExec
 * @see #wake
 *
 * @see #readAndDispatch
 * @see #sleep
 * @see Device#dispose
 *
 * @since 1.0
 */
@SuppressWarnings("deprecation")
public class Display extends Device implements Adaptable {

    private final static String BOUNDS = "bounds";
    private final static String DPI = "dpi";
    private final static String COLOR_DEPTH = "colorDepth";
    private static final String ATTR_INVALIDATE_FOCUS = DisplayAdapter.class.getName() + "#invalidateFocus";
    private static final String APP_NAME = Display.class.getName() + "#appName";
    private static final String APP_VERSION = Display.class.getName() + "#appVersion";
    private static final int DOUBLE_CLICK_TIME = 500; // Keep in sync with client-side (EventUtil.js)
    private static final int GROW_SIZE = 1024;

    static final String PACKAGE_PREFIX = "org.eclipse.swt.widgets.";

    private static final ExceptionHandler DEFAULT_EXCEPTION_HANDLER = new ExceptionHandler() {
        @Override
        public void handleException(Throwable throwable) {
            if (throwable instanceof RuntimeException) {
                throw (RuntimeException) throwable;
            }
            if (throwable instanceof Error) {
                throw (Error) throwable;
            }
        }
    };

    /**
     * Returns the display which the currently running thread is
     * the user-interface thread for, or null if the currently
     * running thread is not a user-interface thread for any display.
     *
     * @return the current display
     */
    public static Display getCurrent() {
        Display result = LifeCycleUtil.getSessionDisplay();
        if (result != null) {
            if (result.isDisposed() || result.getThread() != Thread.currentThread()) {
                result = null;
            }
        }
        return result;
    }

    /**
     * Returns the default display. One is created if it did not already exist.
     *
     * <p><strong>Note:</strong> In RWT, a new display is only created if the
     * calling thread is the user-interface thread.
     * </p>
     *
     * @return the default display
     */
    public static Display getDefault() {
        Display display = LifeCycleUtil.getSessionDisplay();
        if (display == null || display.isDisposed()) {
            if (isUIThread()) {
                display = new Display();
            }
        }
        return display;
    }

    private static boolean isUIThread() {
        boolean result = false;
        if (ContextProvider.hasContext()) {
            IUIThreadHolder uiThreadHolder = LifeCycleUtil.getUIThread(ContextProvider.getUISession());
            Thread uiThread = uiThreadHolder == null ? null : uiThreadHolder.getThread();
            result = uiThread == Thread.currentThread();
        }
        return result;
    }

    private final List<Shell> shells;
    private transient Thread thread;
    private final UISession uiSession;
    private final Rectangle bounds;
    private final Point dpi;
    private final int depth;
    private final Point cursorLocation;
    private Shell activeShell;
    private Collection<Control> redrawControls;
    private Control focusControl;
    private EventTable filterTable;
    private EventTable eventTable;
    private transient Monitor monitor;
    private transient IDisplayAdapter displayAdapter;
    private WidgetRemoteAdapter remoteAdapter;
    private Runnable[] disposeList;
    private Composite[] layoutDeferred;
    private int layoutDeferredCount;
    private Widget[] skinList;
    private int skinCount;
    private boolean beep;

    /* Display Data */
    private Object data;
    private String[] keys;
    private Object[] values;

    private Synchronizer synchronizer;
    private TimerExecScheduler scheduler;

    /**
     * Constructs a new instance of this class.
     * <p>
     * Note: The resulting display is marked as the <em>current</em>
     * display. If this is the first display which has been
     * constructed since the application started, it is also
     * marked as the <em>default</em> display.
     * </p>
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if called from a thread that already created an existing display</li>
     *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
     * </ul>
     *
     * @see #getCurrent
     * @see #getDefault
     * @see Widget#checkSubclass
     * @see Shell
     */
    public Display() {
        if (getCurrent() != null) {
            SWT.error(SWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]");
        }
        LifeCycleUtil.setSessionDisplay(this);
        attachThread();
        uiSession = ContextProvider.getUISession();
        shells = new ArrayList<>();
        monitor = new Monitor(this);
        cursorLocation = new Point(0, 0);
        bounds = readInitialBounds();
        dpi = readDPI();
        depth = readDepth();
        synchronizer = new Synchronizer(this);
        register();
    }

    /**
     * Returns a rectangle describing the receiver's size and location.
     *
     * @return the bounding rectangle
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     */
    @Override
    public Rectangle getBounds() {
        checkDevice();
        return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
    }

    @Override
    public Point getDPI() {
        checkDevice();
        return new Point(dpi.x, dpi.y);
    }

    @Override
    public int getDepth() {
        checkDevice();
        return depth;
    }

    /**
     * Returns the control which currently has keyboard focus,
     * or null if keyboard events are not currently going to
     * any of the controls built by the currently running
     * application.
     *
     * @return the control under the cursor
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     */
    public Control getFocusControl() {
        checkDevice();
        return focusControl;
    }

    private void setFocusControl(Control focusControl, boolean fireEvents) {
        if (this.focusControl != focusControl) {
            if (this.focusControl != null && !this.focusControl.isInDispose()) {
                Control currentFocusControl = this.focusControl;
                Shell shell = currentFocusControl.getShell();
                if (fireEvents) {
                    currentFocusControl.notifyListeners(SWT.FocusOut, new Event());
                }
                shell.updateDefaultButton(currentFocusControl, false);
            }
            this.focusControl = focusControl;
            if (this.focusControl != null) {
                Control currentFocusControl = this.focusControl;
                Shell shell = currentFocusControl.getShell();
                if (fireEvents) {
                    currentFocusControl.notifyListeners(SWT.FocusIn, new Event());
                }
                shell.updateDefaultButton(currentFocusControl, true);
            }
        }
    }

    /////////////////////
    // Coordinate mapping

    /**
     * Maps a point from one coordinate system to another.
     * When the control is null, coordinates are mapped to
     * the display.
     * <p>
     * NOTE: On right-to-left platforms where the coordinate
     * systems are mirrored, special care needs to be taken
     * when mapping coordinates from one control to another
     * to ensure the result is correctly mirrored.
     *
     * Mapping a point that is the origin of a rectangle and
     * then adding the width and height is not equivalent to
     * mapping the rectangle.  When one control is mirrored
     * and the other is not, adding the width and height to a
     * point that was mapped causes the rectangle to extend
     * in the wrong direction.  Mapping the entire rectangle
     * instead of just one point causes both the origin and
     * the corner of the rectangle to be mapped.
     * </p>
     *
     * @param from the source <code>Control</code> or <code>null</code>
     * @param to the destination <code>Control</code> or <code>null</code>
     * @param point to be mapped
     * @return point with mapped coordinates
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the point is null</li>
     *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
     * </ul>
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     */
    public Point map(Control from, Control to, Point point) {
        checkDevice();
        if (point == null) {
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        }
        return map(from, to, point.x, point.y);
    }

    /**
     * Maps a point from one coordinate system to another.
     * When the control is null, coordinates are mapped to
     * the display.
     * <p>
     * NOTE: On right-to-left platforms where the coordinate
     * systems are mirrored, special care needs to be taken
     * when mapping coordinates from one control to another
     * to ensure the result is correctly mirrored.
     *
     * Mapping a point that is the origin of a rectangle and
     * then adding the width and height is not equivalent to
     * mapping the rectangle.  When one control is mirrored
     * and the other is not, adding the width and height to a
     * point that was mapped causes the rectangle to extend
     * in the wrong direction.  Mapping the entire rectangle
     * instead of just one point causes both the origin and
     * the corner of the rectangle to be mapped.
     * </p>
     *
     * @param from the source <code>Control</code> or <code>null</code>
     * @param to the destination <code>Control</code> or <code>null</code>
     * @param x coordinates to be mapped
     * @param y coordinates to be mapped
     * @return point with mapped coordinates
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
     * </ul>
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     */
    public Point map(Control from, Control to, int x, int y) {
        checkDevice();
        Rectangle rectangle = map(from, to, x, y, 0, 0);
        return new Point(rectangle.x, rectangle.y);
    }

    /**
     * Maps a point from one coordinate system to another.
     * When the control is null, coordinates are mapped to
     * the display.
     * <p>
     * NOTE: On right-to-left platforms where the coordinate
     * systems are mirrored, special care needs to be taken
     * when mapping coordinates from one control to another
     * to ensure the result is correctly mirrored.
     *
     * Mapping a point that is the origin of a rectangle and
     * then adding the width and height is not equivalent to
     * mapping the rectangle.  When one control is mirrored
     * and the other is not, adding the width and height to a
     * point that was mapped causes the rectangle to extend
     * in the wrong direction.  Mapping the entire rectangle
     * instead of just one point causes both the origin and
     * the corner of the rectangle to be mapped.
     * </p>
     *
     * @param from the source <code>Control</code> or <code>null</code>
     * @param to the destination <code>Control</code> or <code>null</code>
     * @param rectangle to be mapped
     * @return rectangle with mapped coordinates
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the rectangle is null</li>
     *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
     * </ul>
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     */
    public Rectangle map(Control from, Control to, Rectangle rectangle) {
        checkDevice();
        if (rectangle == null) {
            SWT.error(SWT.ERROR_NULL_ARGUMENT);
        }
        return map(from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
    }

    /**
     * Maps a point from one coordinate system to another.
     * When the control is null, coordinates are mapped to
     * the display.
     * <p>
     * NOTE: On right-to-left platforms where the coordinate
     * systems are mirrored, special care needs to be taken
     * when mapping coordinates from one control to another
     * to ensure the result is correctly mirrored.
     *
     * Mapping a point that is the origin of a rectangle and
     * then adding the width and height is not equivalent to
     * mapping the rectangle.  When one control is mirrored
     * and the other is not, adding the width and height to a
     * point that was mapped causes the rectangle to extend
     * in the wrong direction.  Mapping the entire rectangle
     * instead of just one point causes both the origin and
     * the corner of the rectangle to be mapped.
     * </p>
     *
     * @param from the source <code>Control</code> or <code>null</code>
     * @param to the destination <code>Control</code> or <code>null</code>
     * @param x coordinates to be mapped
     * @param y coordinates to be mapped
     * @param width coordinates to be mapped
     * @param height coordinates to be mapped
     * @return rectangle with mapped coordinates
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_INVALID_ARGUMENT - if the Control from or the Control to have been disposed</li>
     * </ul>
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     */
    public Rectangle map(Control from, Control to, int x, int y, int width, int height) {
        checkDevice();
        int newX = x;
        int newY = y;
        if (from != null) {
            Point fromOrigin = getAbsoluteOrigin(from);
            newX = fromOrigin.x + applyMirror(from, newX, width);
            newY = fromOrigin.y + newY;
        }
        if (to != null) {
            Point toOrigin = getAbsoluteOrigin(to);
            newX = applyMirror(to, newX - toOrigin.x, width);
            newY = newY - toOrigin.y;
        }
        return new Rectangle(newX, newY, width, height);
    }

    /*
     * Returns the origin of the coordinate system of a given control in absolute
     * coordinates, i.e. relative to the display.
     */
    private static Point getAbsoluteOrigin(Control control) {
        Control currentControl = control;
        Point absolute = new Point(0, 0);
        while (currentControl != null) {
            Point origin = getOrigin(currentControl);
            absolute.x += applyMirror(currentControl.getParent(), origin.x, currentControl.getSize().x);
            absolute.y += origin.y;
            if (currentControl instanceof Shell) {
                currentControl = null;
            } else {
                currentControl = currentControl.getParent();
            }
        }
        return new Point(absolute.x, absolute.y);
    }

    /*
     * Returns the origin of the coordinate system of a given control, relative to
     * it's parent or, if it does not have a parent, relative to the display.
     */
    private static Point getOrigin(Control control) {
        Point result = control.getLocation();
        // Due the way that the qx client implementation works, the coordinate
        // system of composites starts at the inner edge of their border and thus
        // need to be offset by the border width.
        // Since only composites can contain child widgets, only they need this
        // correction. This implementation seems to be a good fit with SWT.
        if (control instanceof Composite) {
            boolean rtl = control.getOrientation() == SWT.RIGHT_TO_LEFT;
            BoxDimensions borderWidth = control.getBorder();
            result.x += rtl ? borderWidth.right : borderWidth.left;
            result.y += borderWidth.top;
        }
        return result;
    }

    private static int applyMirror(Control control, int x, int width) {
        if (control != null && control.getOrientation() == SWT.RIGHT_TO_LEFT) {
            BoxDimensions border = control.getBorder();
            int innerWidth = control.getSize().x - border.left - border.right;
            return innerWidth - x - width;
        }
        return x;
    }

    ///////////
    // Listener

    /**
     * Adds the listener to the collection of listeners who will
     * be notified when an event of the given type occurs. The event
     * type is one of the event constants defined in class <code>SWT</code>.
     * When the event does occur in the display, the listener is notified by
     * sending it the <code>handleEvent()</code> message.
     *
     * @param eventType the type of event to listen for
     * @param listener the listener which should be notified when the event occurs
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
     * </ul>
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see Listener
     * @see SWT
     * @see #removeListener
     *
     * @since 1.3
     */
    public void addListener(int eventType, Listener listener) {
        checkDevice();
        if (listener == null) {
            error(SWT.ERROR_NULL_ARGUMENT);
        }
        if (eventTable == null) {
            eventTable = new EventTable();
        }
        eventTable.hook(eventType, listener);
    }

    /**
     * Removes the listener from the collection of listeners who will
     * be notified when an event of the given type occurs. The event type
     * is one of the event constants defined in class <code>SWT</code>.
     *
     * @param eventType the type of event to listen for
     * @param listener the listener which should no longer be notified
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
     * </ul>
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see Listener
     * @see SWT
     * @see #addListener
     *
     * @since 1.3
     */
    public void removeListener(int eventType, Listener listener) {
        checkDevice();
        if (listener == null) {
            error(SWT.ERROR_NULL_ARGUMENT);
        }
        if (eventTable != null) {
            eventTable.unhook(eventType, listener);
        }
    }

    void sendEvent(int eventType, Event event) {
        event.display = this;
        event.type = eventType;
        if (event.time == 0) {
            event.time = EventUtil.getLastEventTime();
        }
        filterEvent(event);
        if (eventTable != null) {
            eventTable.sendEvent(event);
        }
    }

    private void notifyListeners(final int eventType, final Event event) {
        ProcessActionRunner.add(new Runnable() {
            @Override
            public void run() {
                sendEvent(eventType, event);
            }
        });
    }

    private boolean isListening(int eventType) {
        return eventTable == null ? false : eventTable.hooks(eventType);
    }

    //////////
    // Dispose

    /**
     * Causes the <code>run()</code> method of the runnable to
     * be invoked by the user-interface thread just before the
     * receiver is disposed.  Specifying a <code>null</code> runnable
     * is ignored.
     *
     * @param runnable code to run at dispose time.
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     */
    public void disposeExec(Runnable runnable) {
        checkDevice();
        if (disposeList == null) {
            disposeList = new Runnable[4];
        }
        for (int i = 0; i < disposeList.length; i++) {
            if (disposeList[i] == null) {
                disposeList[i] = runnable;
                return;
            }
        }
        Runnable[] newDisposeList = new Runnable[disposeList.length + 4];
        System.arraycopy(disposeList, 0, newDisposeList, 0, disposeList.length);
        newDisposeList[disposeList.length] = runnable;
        disposeList = newDisposeList;
    }

    /**
     * Requests that the connection between SWT and the underlying
     * operating system be closed.
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see Device#dispose
     *
     * @since 1.3
     */
    public void close() {
        checkDevice();
        Event event = new Event();
        sendEvent(SWT.Close, event);
        if (event.doit) {
            dispose();
        }
    }

    @Override
    protected void release() {
        sendDisposeEvent();
        disposeShells();
        runDisposeExecs();
        synchronizer.releaseSynchronizer();
        if (scheduler != null) {
            scheduler.dispose();
        }
        filterTable = null;
        eventTable = null;
    }

    @Override
    protected void destroy() {
        deregister();
    }

    private void sendDisposeEvent() {
        sendEvent(SWT.Dispose, new Event());
    }

    private void disposeShells() {
        Shell[] shells = getShells();
        for (int i = 0; i < shells.length; i++) {
            Shell shell = shells[i];
            try {
                shell.dispose();
            } catch (Throwable thr) {
                ServletLog.log("Exception while disposing shell: " + shell, thr);
            }
        }
        // TODO [rh] consider dispatching pending messages (e.g. asyncExec)
        //      while( readAndDispatch() ) {}
    }

    private void runDisposeExecs() {
        checkDevice();
        if (disposeList != null) {
            for (int i = 0; i < disposeList.length; i++) {
                if (disposeList[i] != null) {
                    try {
                        disposeList[i].run();
                    } catch (Throwable thr) {
                        String msg = "Exception while executing dispose-runnable.";
                        ServletLog.log(msg, thr);
                    }
                }
            }
        }
    }

    /////////////////////
    // Adaptable override

    @Override
    @SuppressWarnings("unchecked")
    public <T> T getAdapter(Class<T> adapter) {
        if (adapter == IDisplayAdapter.class) {
            if (displayAdapter == null) {
                displayAdapter = new DisplayAdapter();
            }
            return (T) displayAdapter;
        }
        if (adapter == RemoteAdapter.class) {
            if (remoteAdapter == null) {
                String id = IdGenerator.getInstance(uiSession).createId(this);
                remoteAdapter = new WidgetRemoteAdapter(id);
            }
            return (T) remoteAdapter;
        }
        return null;
    }

    private ApplicationContextImpl getApplicationContext() {
        return (ApplicationContextImpl) uiSession.getApplicationContext();
    }

    ///////////////////
    // Shell management

    /**
     * Returns a (possibly empty) array containing all shells which have
     * not been disposed and have the receiver as their display.
     *
     * @return the receiver's shells
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     */
    public Shell[] getShells() {
        checkDevice();
        Shell[] result = new Shell[shells.size()];
        shells.toArray(result);
        return result;
    }

    /**
     * Returns the currently active <code>Shell</code>, or null
     * if no shell belonging to the currently running application
     * is active.
     *
     * @return the active shell or null
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     */
    public Shell getActiveShell() {
        checkDevice();
        return activeShell;
    }

    final void setActiveShell(Shell activeShell) {
        checkDevice();
        if (this.activeShell != activeShell) {
            Shell lastActiveShell = this.activeShell;
            if (this.activeShell != null) {
                this.activeShell.saveFocus();
            }
            // Move active shell to end of list to maintain correct z-order
            if (activeShell != null) {
                shells.remove(activeShell);
                shells.add(activeShell);
            }
            if (lastActiveShell != null && !lastActiveShell.hasState(Widget.DISPOSE_SENT)) {
                lastActiveShell.notifyListeners(SWT.Deactivate, new Event());
            }
            this.activeShell = activeShell;
            if (activeShell != null) {
                activeShell.notifyListeners(SWT.Activate, new Event());
            }
            if (this.activeShell != null) {
                this.activeShell.restoreFocus();
            }
        }
    }

    final void addShell(Shell shell) {
        shells.add(shell);
    }

    final void removeShell(Shell shell) {
        shells.remove(shell);
        if (shell == activeShell) {
            int counter = 0;
            Shell lastVisibleShell = null;
            while (lastVisibleShell == null && counter < shells.size()) {
                counter++;
                Shell currentShell = shells.get(shells.size() - counter);
                if (currentShell.isVisible()) {
                    lastVisibleShell = currentShell;
                }
            }
            setActiveShell(lastVisibleShell);
        }
    }

    ////////////////////
    // Thread management

    /**
     * Returns the user-interface thread for the receiver. Note that the
     * user-interface thread may change per user-request.
     *
     * @return the receiver's user-interface thread or null if there's no
     *         current user-request executed that belongs to the display.
     *
     * @exception SWTException <ul>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     */
    public Thread getThread() {
        synchronized (deviceLock) {
            if (isDisposed()) {
                error(SWT.ERROR_DEVICE_DISPOSED);
            }
            return thread;
        }
    }

    private void attachThread() {
        thread = Thread.currentThread();
    }

    private void detachThread() {
        thread = null;
    }

    //////////////////////
    // Information methods

    /**
     * Returns the display which the given thread is the
     * user-interface thread for, or null if the given thread
     * is not a user-interface thread for any display.  Specifying
     * <code>null</code> as the thread will return <code>null</code>
     * for the display.
     *
     * @param thread the user-interface thread
     * @return the display for the given thread
     */
    public static Display findDisplay(Thread thread) {
        synchronized (Device.class) {
            for (WeakReference<Display> displayRef : getDisplays()) {
                if (displayRef != null) {
                    Display display = displayRef.get();
                    if (display != null && !display.isDisposed() && display.thread == thread) {
                        return display;
                    }
                }
            }
            return null;
        }
    }

    /**
     * Sets the synchronizer used by the display to be
     * the argument, which can not be null.
     *
     * @param synchronizer the new synchronizer for the display (must not be null)
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the synchronizer is null</li>
     * </ul>
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     *    <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
     * </ul>
     *
     * @since 1.3
     */
    // verbatim copy of SWT code
    public void setSynchronizer(Synchronizer synchronizer) {
        checkDevice();
        if (synchronizer == null) {
            error(SWT.ERROR_NULL_ARGUMENT);
        }
        if (synchronizer == this.synchronizer) {
            return;
        }
        Synchronizer oldSynchronizer;
        synchronized (deviceLock) {
            oldSynchronizer = this.synchronizer;
            this.synchronizer = synchronizer;
        }
        if (oldSynchronizer != null) {
            oldSynchronizer.runAsyncMessages(true);
        }
    }

    /**
     * Gets the synchronizer used by the display.
     *
     * @return the receiver's synchronizer
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @since 1.3
     */
    public Synchronizer getSynchronizer() {
        checkDevice();
        return synchronizer;
    }

    /**
     * Returns the thread that has invoked <code>syncExec</code>
     * or null if no such runnable is currently being invoked by
     * the user-interface thread.
     * <p>
     * Note: If a runnable invoked by asyncExec is currently
     * running, this method will return null.
     * </p>
     *
     * @return the receiver's sync-interface thread
     *
     * @exception SWTException <ul>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @since 1.3
     */
    public Thread getSyncThread() {
        synchronized (deviceLock) {
            if (isDisposed()) {
                error(SWT.ERROR_DEVICE_DISPOSED);
            }
            return synchronizer.syncThread;
        }
    }

    /**
     * Causes the <code>run()</code> method of the runnable to
     * be invoked by the user-interface thread at the next
     * reasonable opportunity. Note that the user-interface thread may change
     * per user-request. The caller of this method continues
     * to run in parallel, and is not notified when the
     * runnable has completed.  Specifying <code>null</code> as the
     * runnable simply wakes the user-interface thread when run.
     * <p>
     * Note that at the time the runnable is invoked, widgets
     * that have the receiver as their display may have been
     * disposed. Therefore, it is necessary to check for this
     * case inside the runnable before accessing the widget.
     * </p>
     *
     * @param runnable code to run on the user-interface thread or <code>null</code>
     *
     * @exception SWTException <ul>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see #syncExec
     */
    public void asyncExec(Runnable runnable) {
        synchronized (deviceLock) {
            if (isDisposed()) {
                error(SWT.ERROR_DEVICE_DISPOSED);
            }
            synchronizer.asyncExec(runnable);
        }
    }

    /**
     * Causes the <code>run()</code> method of the runnable to
     * be invoked by the user-interface thread at the next
     * reasonable opportunity. Note that the user-interface thread may change
     * per user-request. The thread which calls this method
     * is suspended until the runnable completes.  Specifying <code>null</code>
     * as the runnable simply wakes the user-interface thread.
     * <p>
     * Note that at the time the runnable is invoked, widgets
     * that have the receiver as their display may have been
     * disposed. Therefore, it is necessary to check for this
     * case inside the runnable before accessing the widget.
     * </p>
     *
     * @param runnable code to run on the user-interface thread or <code>null</code>
     *
     * @exception SWTException <ul>
     *    <li>ERROR_FAILED_EXEC - if an exception occured when executing the runnable</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see #asyncExec
     */
    public void syncExec(Runnable runnable) {
        Synchronizer synchronizer;
        synchronized (deviceLock) {
            if (isDisposed()) {
                error(SWT.ERROR_DEVICE_DISPOSED);
            }
            synchronizer = this.synchronizer;
        }
        synchronizer.syncExec(runnable);
    }

    /**
     * Causes the <code>run()</code> method of the runnable to
     * be invoked by the user-interface thread after the specified
     * number of milliseconds have elapsed. If milliseconds is less
     * than zero, the runnable is not executed.
     * <p>
     * Note that at the time the runnable is invoked, widgets
     * that have the receiver as their display may have been
     * disposed. Therefore, it is necessary to check for this
     * case inside the runnable before accessing the widget.
     * </p>
     *
     * @param milliseconds the delay before running the runnable
     * @param runnable code to run on the user-interface thread
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the runnable is null</li>
     * </ul>
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see #asyncExec
     * @since 1.2
     */
    public void timerExec(int milliseconds, Runnable runnable) {
        checkDevice();
        if (runnable == null) {
            error(SWT.ERROR_NULL_ARGUMENT);
        }
        if (scheduler == null) {
            scheduler = createTimerExecScheduler();
        }
        if (milliseconds < 0) {
            scheduler.cancel(runnable);
        } else {
            scheduler.schedule(milliseconds, runnable);
        }
    }

    TimerExecScheduler createTimerExecScheduler() {
        return new TimerExecScheduler(this);
    }

    /**
     * Reads an event from the <!-- operating system's --> event queue,
     * dispatches it appropriately, and returns <code>true</code>
     * if there is potentially more work to do, or <code>false</code>
     * if the caller can sleep until another event is placed on
     * the event queue.
     * <p>
     * In addition to checking the system event queue, this method also
     * checks if any inter-thread messages (created by <code>syncExec()</code>
     * or <code>asyncExec()</code>) are waiting to be processed, and if
     * so handles them before returning.
     * </p>
     *
     * @return <code>false</code> if the caller can sleep upon return from this method
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     *    <li>ERROR_FAILED_EXEC - if an exception occurred while running an inter-thread message</li>
     * </ul>
     *
     * @see #sleep
     * @see #wake
     *
     * @since 1.1
     */
    public boolean readAndDispatch() {
        checkDevice();
        return safeReadAndDispatch();
    }

    private boolean safeReadAndDispatch() {
        boolean result = false;
        try {
            runSkin();
            runDeferredLayouts();
            result = runPendingMessages();
        } catch (RuntimeException runtimeException) {
            handleException(runtimeException);
        } catch (Error error) {
            handleException(error);
            throw error;
        }
        return result;
    }

    private boolean runPendingMessages() {
        boolean result = false;
        if (PhaseId.PREPARE_UI_ROOT.equals(CurrentPhase.get())
                || PhaseId.PROCESS_ACTION.equals(CurrentPhase.get())) {
            result = ProcessActionRunner.executeNext();
            if (!result) {
                result = executeNextEvent();
            }
            if (!result) {
                result = synchronizer.runAsyncMessages(false);
            }
            if (!result) {
                result = executeNextRedraw();
            }
        }
        return result;
    }

    private static boolean executeNextEvent() {
        boolean result = false;
        Event[] events = EventList.getInstance().getAll();
        while (!result && events.length > 0) {
            Event event = events[0];
            EventList.getInstance().remove(event);
            if (EventUtil.allowProcessing(event)) {
                event.widget.notifyListeners(event.type, event);
                result = true;
            } else {
                events = EventList.getInstance().getAll();
            }
        }
        return result;
    }

    private void handleException(Throwable throwable) {
        ExceptionHandler exceptionHandler = getExceptionHandler();
        exceptionHandler.handleException(throwable);
    }

    private ExceptionHandler getExceptionHandler() {
        ExceptionHandler result = getApplicationContext().getExceptionHandler();
        if (result == null) {
            result = DEFAULT_EXCEPTION_HANDLER;
        }
        return result;
    }

    /**
     * Causes the user-interface thread to <em>sleep</em> (that is,
     * to be put in a state where it does not consume CPU cycles)
     * until an event is received or it is otherwise awakened.
     *
     * @return <code>true</code> if an event requiring dispatching was placed on the queue.
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see #wake
     *
     * @since 1.1
     */
    public boolean sleep() {
        checkDevice();
        LifeCycle lifeCycle = getApplicationContext().getLifeCycleFactory().getLifeCycle();
        lifeCycle.sleep();
        // return true as we cannot reliably determinate what actually caused
        // lifeCycle#sleep() to return
        return true;
    }

    /**
     * Notifies the client to send a request in order to wake up a sleeping UI thread and to perform
     * pending UI updates. Note that this method may be called from any thread.
     * <p>
     * Note that this method has no effect unless a {@link ServerPushSession} is active.
     * </p>
     *
     * @exception SWTException <ul>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     */
    public void wake() {
        synchronized (deviceLock) {
            if (isDisposed()) {
                error(SWT.ERROR_DEVICE_DISPOSED);
            }
            if (thread != Thread.currentThread()) {
                uiSession.exec(new Runnable() {
                    @Override
                    public void run() {
                        synchronizer.asyncExec(new WakeRunnable());
                    }
                });
            }
        }
    }

    protected void wakeThread() {
        uiSession.exec(new Runnable() {
            @Override
            public void run() {
                ServerPushManager.getInstance().wakeClient();
            }
        });
    }

    Object getDeviceLock() {
        return deviceLock;
    }

    //////////
    // Redraw

    void redrawControl(Control control, boolean redraw) {
        if (redraw) {
            if (redrawControls == null) {
                redrawControls = new LinkedList<>();
            }
            if (!redrawControls.contains(control)) {
                redrawControls.add(control);
            }
        } else {
            if (redrawControls != null) {
                redrawControls.remove(control);
            }
        }
    }

    boolean needsRedraw(Control control) {
        return redrawControls != null && redrawControls.contains(control);
    }

    private boolean executeNextRedraw() {
        boolean result = false;
        if (redrawControls != null) {
            Iterator<Control> iterator = redrawControls.iterator();
            if (iterator.hasNext()) {
                Control control = iterator.next();
                WidgetUtil.getLCA(control).doRedrawFake(control);
                redrawControls.remove(control);
                result = true;
            }
        }
        return result;
    }

    //////////////////////
    // Information methods

    /**
     * Returns the single instance of the system tray or null when there is no
     * system tray available for the platform.
     *
     * @return the system tray or <code>null</code>
     * @exception SWTException <ul>
     *              <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     *              </ul>
     * @since 1.4
     */
    public Tray getSystemTray() {
        checkDevice();
        return null;
    }

    /**
     * Returns the single instance of the application menu bar or null
     * when there is no application menu bar for the platform.
     *
     * @return the application menu bar or <code>null</code>
     *
     * @exception SWTException <ul>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @since 1.4
     */
    public Menu getMenuBar() {
        checkDevice();
        return null;
    }

    /**
     * Returns the single instance of the system taskBar or null
     * when there is no system taskBar available for the platform.
     *
     * @return the system taskBar or <code>null</code>
     *
     * @exception SWTException <ul>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @since 1.4
     */
    public TaskBar getSystemTaskBar() {
        checkDevice();
        return null;
    }

    /**
     * Returns the single instance of the system-provided menu for the application.
     * On platforms where no menu is provided for the application this method returns null.
     *
     * @return the system menu or <code>null</code>
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @since 1.4
     */
    public Menu getSystemMenu() {
        checkDevice();
        return null;
    }

    @Override
    public Color getSystemColor(int id) {
        checkDevice();
        Color result = null;
        CssValue value = null;
        switch (id) {
        case SWT.COLOR_WIDGET_DARK_SHADOW:
            value = ThemeUtil.getCssValue("Display", "rwt-darkshadow-color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_WIDGET_NORMAL_SHADOW:
            value = ThemeUtil.getCssValue("Display", "rwt-shadow-color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_WIDGET_LIGHT_SHADOW:
            value = ThemeUtil.getCssValue("Display", "rwt-lightshadow-color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW:
            value = ThemeUtil.getCssValue("Display", "rwt-highlight-color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_WIDGET_BORDER:
            value = ThemeUtil.getCssValue("Display", "rwt-thinborder-color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_WIDGET_BACKGROUND:
            // TODO [rst] Revise element name
            value = ThemeUtil.getCssValue("NONE", "background-color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_WIDGET_FOREGROUND:
            // TODO [rst] Revise element name
            value = ThemeUtil.getCssValue("NONE", "color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_LIST_FOREGROUND:
            value = ThemeUtil.getCssValue("List", "color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_LIST_BACKGROUND:
            value = ThemeUtil.getCssValue("List", "background-color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_LIST_SELECTION:
            value = ThemeUtil.getCssValue("List-Item", "background-color", SimpleSelector.SELECTED);
            break;
        case SWT.COLOR_LIST_SELECTION_TEXT:
            value = ThemeUtil.getCssValue("List-Item", "color", SimpleSelector.SELECTED);
            break;
        case SWT.COLOR_INFO_FOREGROUND:
            value = ThemeUtil.getCssValue("Widget-ToolTip", "color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_INFO_BACKGROUND:
            value = ThemeUtil.getCssValue("Display", "rwt-infobackground-color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_TITLE_FOREGROUND:
            value = ThemeUtil.getCssValue("Shell-Titlebar", "color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_TITLE_INACTIVE_FOREGROUND:
            value = ThemeUtil.getCssValue("Shell-Titlebar", "color", SimpleSelector.INACTIVE);
            break;
        case SWT.COLOR_TITLE_BACKGROUND:
            value = ThemeUtil.getCssValue("Shell-Titlebar", "background-color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_TITLE_INACTIVE_BACKGROUND:
            value = ThemeUtil.getCssValue("Shell-Titlebar", "background-color", SimpleSelector.INACTIVE);
            break;
        case SWT.COLOR_TITLE_BACKGROUND_GRADIENT:
            value = ThemeUtil.getCssValue("Shell-Titlebar", "background-gradient-color", SimpleSelector.DEFAULT);
            break;
        case SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT:
            value = ThemeUtil.getCssValue("Shell-Titlebar", "background-gradient-color", SimpleSelector.INACTIVE);
            break;
        default:
            result = super.getSystemColor(id);
        }
        if (value != null) {
            result = CssColor.createColor((CssColor) value);
            if (result == null) {
                // TODO [rst] Revise: theming must prevent transparency for system colors
                throw new IllegalArgumentException("Transparent system color");
            }
        }
        return result;
    }

    /**
     * Returns the matching standard platform image for the given
     * constant, which should be one of the icon constants
     * specified in class <code>SWT</code>. This image should
     * not be free'd because it was allocated by the system,
     * not the application.  A value of <code>null</code> will
     * be returned either if the supplied constant is not an
     * SWT icon constant or if the platform does not define an
     * image that corresponds to the constant.
     *
     * @param id the SWT icon constant
     * @return the corresponding image or <code>null</code>
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see SWT#ICON_ERROR
     * @see SWT#ICON_INFORMATION
     * @see SWT#ICON_QUESTION
     * @see SWT#ICON_WARNING
     * @see SWT#ICON_WORKING
     */
    public Image getSystemImage(int id) {
        checkDevice();
        Image result = null;
        switch (id) {
        case SWT.ICON_ERROR:
            result = createSystemImage("rwt-error-image");
            break;
        case SWT.ICON_INFORMATION:
            result = createSystemImage("rwt-information-image");
            break;
        case SWT.ICON_QUESTION:
            result = createSystemImage("rwt-question-image");
            break;
        case SWT.ICON_WARNING:
            result = createSystemImage("rwt-warning-image");
            break;
        case SWT.ICON_WORKING:
            result = createSystemImage("rwt-working-image");
            break;
        }
        return result;
    }

    private static Image createSystemImage(String cssProperty) {
        Image result = null;
        CssValue cssValue = ThemeUtil.getCssValue("Display", cssProperty, SimpleSelector.DEFAULT);
        if (cssValue != null) {
            try {
                result = CssImage.createSwtImage((CssImage) cssValue);
            } catch (IOException ioe) {
                throw new RuntimeException("Could not read system image", ioe);
            }
        }
        return result;
    }

    /**
     * Returns the matching standard platform cursor for the given
     * constant, which should be one of the cursor constants
     * specified in class <code>SWT</code>. This cursor should
     * not be free'd because it was allocated by the system,
     * not the application.  A value of <code>null</code> will
     * be returned if the supplied constant is not an SWT cursor
     * constant.
     *
     * @param id the SWT cursor constant
     * @return the corresponding cursor or <code>null</code>
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see SWT#CURSOR_ARROW
     * @see SWT#CURSOR_WAIT
     * @see SWT#CURSOR_CROSS
     * @see SWT#CURSOR_HELP
     * @see SWT#CURSOR_SIZEALL
     * @see SWT#CURSOR_SIZENS
     * @see SWT#CURSOR_SIZEWE
     * @see SWT#CURSOR_SIZEN
     * @see SWT#CURSOR_SIZES
     * @see SWT#CURSOR_SIZEE
     * @see SWT#CURSOR_SIZEW
     * @see SWT#CURSOR_SIZENE
     * @see SWT#CURSOR_SIZESE
     * @see SWT#CURSOR_SIZESW
     * @see SWT#CURSOR_SIZENW
     * @see SWT#CURSOR_IBEAM
     * @see SWT#CURSOR_HAND
     *
     * @since 1.3
     */
    public Cursor getSystemCursor(int id) {
        checkDevice();
        return getApplicationContext().getResourceFactory().getCursor(id);
    }

    /**
     * Returns the longest duration, in milliseconds, between
     * two mouse button clicks that will be considered a
     * <em>double click</em> <!-- by the underlying operating system -->.
     *
     * @return the double click time
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @since 1.2
     */
    public int getDoubleClickTime() {
        checkDevice();
        return DOUBLE_CLICK_TIME;
    }

    /**
     * Returns the control which the on-screen pointer is currently
     * over top of, or null if it is not currently over one of the
     * controls built by the currently running application.
     *
    * @return the control under the cursor or <code>null</code>
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @since 1.3
     */
    public Control getCursorControl() {
        checkDevice();
        ControlFinder finder = new ControlFinder(this, getCursorLocation());
        return finder.getControl();
    }

    /**
     * Returns the button dismissal alignment, one of <code>LEFT</code> or <code>RIGHT</code>.
     * The button dismissal alignment is the ordering that should be used when positioning the
     * default dismissal button for a dialog.  For example, in a dialog that contains an OK and
     * CANCEL button, on platforms where the button dismissal alignment is <code>LEFT</code>, the
     * button ordering should be OK/CANCEL.  When button dismissal alignment is <code>RIGHT</code>,
     * the button ordering should be CANCEL/OK.
     *
     * @return the button dismissal order
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @since 1.3
     */
    public int getDismissalAlignment() {
        checkDevice();
        return SWT.LEFT;
    }

    /**
     * Returns true when the high contrast mode is enabled.
     * Otherwise, false is returned.
     * <p>
     * Note: This operation is a hint and is not supported on
     * platforms that do not have this concept.
     * </p>
     *
     * @return the high contrast mode
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @since 1.3
     */
    public boolean getHighContrast() {
        checkDevice();
        return false;
    }

    /**
     * Returns the location of the on-screen pointer relative
     * to the top left corner of the screen.
     *
     * @return the cursor location
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @since 1.3
     */
    public Point getCursorLocation() {
        checkDevice();
        return new Point(cursorLocation.x, cursorLocation.y);
    }

    //////////
    // Filters

    /**
     * Adds the listener to the collection of listeners who will be notified when
     * an event of the given type occurs anywhere in a widget. The event type is
     * one of the event constants defined in class <code>SWT</code>. When the
     * event does occur, the listener is notified by sending it the
     * <code>handleEvent()</code> message.
     * <p>
     * Setting the type of an event to <code>SWT.None</code> from within the
     * <code>handleEvent()</code> method can be used to change the event type
     * and stop subsequent Java listeners from running. Because event filters run
     * before other listeners, event filters can both block other listeners and
     * set arbitrary fields within an event. For this reason, event filters are
     * both powerful and dangerous. They should generally be avoided for
     * performance, debugging and code maintenance reasons.
     * </p>
     * <p>
     * <strong>NOTE:</strong> In RAP, only events that have a matching listener registered on the
     * event's source widget are processed on the server. One exception are key events, for which a
     * whitelist can be define using {@link org.eclipse.rap.rwt.RWT#ACTIVE_KEYS RWT#ACTIVE_KEYS}.
     * </p>
     *
     * @param eventType the type of event to listen for
     * @param listener the listener which should be notified when the event occurs
     * @exception IllegalArgumentException
     *                <ul>
     *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
     *                </ul>
     * @exception SWTException
     *                <ul>
     *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
     *                thread that created the receiver</li>
     *                <li>ERROR_DEVICE_DISPOSED - if the receiver has been
     *                disposed</li>
     *                </ul>
     * @see Listener
     * @see SWT
     * @see #removeFilter
     * @see #removeListener
     */
    public void addFilter(int eventType, Listener listener) {
        checkDevice();
        if (listener == null) {
            error(SWT.ERROR_NULL_ARGUMENT);
        }
        if (filterTable == null) {
            filterTable = new EventTable();
        }
        filterTable.hook(eventType, listener);
    }

    /**
     * Removes the listener from the collection of listeners who will be notified
     * when an event of the given type occurs anywhere in a widget. The event type
     * is one of the event constants defined in class <code>SWT</code>.
     *
     * @param eventType the type of event to listen for
     * @param listener the listener which should no longer be notified when the
     *            event occurs
     * @exception IllegalArgumentException
     *                <ul>
     *                <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
     *                </ul>
     * @exception SWTException
     *                <ul>
     *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
     *                thread that created the receiver</li>
     *                </ul>
     * @see Listener
     * @see SWT
     * @see #addFilter
     * @see #addListener
     */
    public void removeFilter(int eventType, Listener listener) {
        checkDevice();
        if (listener == null) {
            error(SWT.ERROR_NULL_ARGUMENT);
        }
        if (filterTable == null) {
            return;
        }
        filterTable.unhook(eventType, listener);
        if (filterTable.size() == 0) {
            filterTable = null;
        }
    }

    boolean filters(int eventType) {
        return filterTable != null ? filterTable.hooks(eventType) : false;
    }

    void filterEvent(Event event) {
        if (filterTable != null) {
            filterTable.sendEvent(event);
        }
    }

    void addLayoutDeferred(Composite comp) {
        if (layoutDeferred == null) {
            layoutDeferred = new Composite[64];
        }
        if (layoutDeferredCount == layoutDeferred.length) {
            Composite[] temp = new Composite[layoutDeferred.length + 64];
            System.arraycopy(layoutDeferred, 0, temp, 0, layoutDeferred.length);
            layoutDeferred = temp;
        }
        layoutDeferred[layoutDeferredCount++] = comp;
    }

    boolean runDeferredLayouts() {
        boolean result = false;
        if (layoutDeferredCount != 0) {
            Composite[] temp = layoutDeferred;
            int count = layoutDeferredCount;
            layoutDeferred = null;
            layoutDeferredCount = 0;
            for (int i = 0; i < count; i++) {
                Composite comp = temp[i];
                if (!comp.isDisposed()) {
                    comp.setLayoutDeferred(false);
                }
            }
            result = true;
        }
        return result;
    }

    ///////////////////
    // Skinning support

    void addSkinnableWidget(Widget widget) {
        if (skinList == null) {
            skinList = new Widget[GROW_SIZE];
        }
        if (skinCount >= skinList.length) {
            Widget[] newSkinWidgets = new Widget[skinList.length + GROW_SIZE];
            System.arraycopy(skinList, 0, newSkinWidgets, 0, skinList.length);
            skinList = newSkinWidgets;
        }
        skinList[skinCount++] = widget;
    }

    boolean runSkin() {
        boolean result = false;
        if (skinCount > 0) {
            Widget[] oldSkinWidgets = skinList;
            int count = skinCount;
            skinList = new Widget[GROW_SIZE];
            skinCount = 0;
            for (int i = 0; i < count; i++) {
                Widget widget = oldSkinWidgets[i];
                if (widget != null && !widget.isDisposed()) {
                    widget.removeState(Widget.SKIN_NEEDED);
                    oldSkinWidgets[i] = null;
                    sendSkinEvent(widget);
                }
            }
            result = true;
        }
        return result;
    }

    private void sendSkinEvent(Widget widget) {
        Event event = new Event();
        event.widget = widget;
        sendEvent(SWT.Skin, event);
    }

    ///////////////
    // Data methods

    /**
     * Returns the application defined, display specific data
     * associated with the receiver, or null if it has not been
     * set. The <em>display specific data</em> is a single,
     * unnamed field that is stored with every display.
     * <p>
     * Applications may put arbitrary objects in this field. If
     * the object stored in the display specific data needs to
     * be notified when the display is disposed of, it is the
     * application's responsibility to provide a
     * <code>disposeExec()</code> handler which does so.
     * </p>
     *
     * @return the display specific data
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
     *    created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see #setData(Object)
     * @see #disposeExec(Runnable)
     *
     * @since 1.2
     */
    public Object getData() {
        checkDevice();
        return data;
    }

    /**
     * Sets the application defined, display specific data
     * associated with the receiver, to the argument.
     * The <em>display specific data</em> is a single,
     * unnamed field that is stored with every display.
     * <p>
     * Applications may put arbitrary objects in this field. If
     * the object stored in the display specific data needs to
     * be notified when the display is disposed of, it is the
     * application's responsibility provide a
     * <code>disposeExec()</code> handler which does so.
     * </p>
     *
     * @param data the new display specific data
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
     *    created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see #getData()
     * @see #disposeExec(Runnable)
     *
     * @since 1.2
     */
    public void setData(Object data) {
        checkDevice();
        this.data = data;
    }

    /**
     * Sets the application defined property of the receiver
     * with the specified name to the given argument.
     * <p>
     * Applications may have associated arbitrary objects with the
     * receiver in this fashion. If the objects stored in the
     * properties need to be notified when the display is disposed
     * of, it is the application's responsibility provide a
     * <code>disposeExec()</code> handler which does so.
     * </p>
     *
     * @param key the name of the property
     * @param value the new value for the property
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the key is null</li>
     * </ul>
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
     *    created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see #getData(String)
     * @see #disposeExec(Runnable)
     *
     * @since 1.2
     */
    // [bm]: This is a verbatim copy of SWT, thus no reformatting was done.
    public void setData(String key, Object value) {
        checkDevice();
        if (key == null) {
            error(SWT.ERROR_NULL_ARGUMENT);
        }

        /* Remove the key/value pair */
        if (value == null) {
            if (keys == null) {
                return;
            }
            int index = 0;
            while (index < keys.length && !keys[index].equals(key)) {
                index++;
            }
            if (index == keys.length) {
                return;
            }
            if (keys.length == 1) {
                keys = null;
                values = null;
            } else {
                String[] newKeys = new String[keys.length - 1];
                Object[] newValues = new Object[values.length - 1];
                System.arraycopy(keys, 0, newKeys, 0, index);
                System.arraycopy(keys, index + 1, newKeys, index, newKeys.length - index);
                System.arraycopy(values, 0, newValues, 0, index);
                System.arraycopy(values, index + 1, newValues, index, newValues.length - index);
                keys = newKeys;
                values = newValues;
            }
            return;
        }

        /* Add the key/value pair */
        if (keys == null) {
            keys = new String[] { key };
            values = new Object[] { value };
            return;
        }
        for (int i = 0; i < keys.length; i++) {
            if (keys[i].equals(key)) {
                values[i] = value;
                return;
            }
        }
        String[] newKeys = new String[keys.length + 1];
        Object[] newValues = new Object[values.length + 1];
        System.arraycopy(keys, 0, newKeys, 0, keys.length);
        System.arraycopy(values, 0, newValues, 0, values.length);
        newKeys[keys.length] = key;
        newValues[values.length] = value;
        keys = newKeys;
        values = newValues;
    }

    /**
     * Returns the application defined property of the receiver
     * with the specified name, or null if it has not been set.
     * <p>
     * Applications may have associated arbitrary objects with the
     * receiver in this fashion. If the objects stored in the
     * properties need to be notified when the display is disposed
     * of, it is the application's responsibility to provide a
     * <code>disposeExec()</code> handler which does so.
     * </p>
     *
     * @param key the name of the property
     * @return the value of the property or null if it has not been set
     *
     * @exception IllegalArgumentException <ul>
     *    <li>ERROR_NULL_ARGUMENT - if the key is null</li>
     * </ul>
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that
     *    created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see #setData(String, Object)
     * @see #disposeExec(Runnable)
     *
     * @since 1.2
     */
    // [bm] This is a verbatim copy of SWT, thus no reformatting was done.
    public Object getData(String key) {
        checkDevice();
        if (key == null) {
            error(SWT.ERROR_NULL_ARGUMENT);
        }
        if (keys == null) {
            return null;
        }
        for (int i = 0; i < keys.length; i++) {
            if (keys[i].equals(key)) {
                return values[i];
            }
        }
        return null;
    }

    ///////////
    // Monitors

    /**
     * Returns an array of monitors attached to the device.
     *
     * @return the array of monitors
     *
     * @since 1.2
     */
    public Monitor[] getMonitors() {
        checkDevice();
        if (monitor == null) {
            monitor = new Monitor(this);
        }
        return new Monitor[] { monitor };
    }

    /**
     * Returns the primary monitor for that device.
     *
     * @return the primary monitor
     *
     * @since 1.2
     */
    public Monitor getPrimaryMonitor() {
        return getMonitors()[0];
    }

    ////////////////////////
    // AppName- and version

    /**
     * Returns the application name.
     *
     * @return the application name
     *
     * @see #setAppName(String)
     *
     * @since 1.3
     */
    public static String getAppName() {
        UISession session = ContextProvider.getUISession();
        return (String) session.getAttribute(APP_NAME);
    }

    /**
     * Returns the application version.
     *
     * @return the application version
     *
     * @see #setAppVersion(String)
     *
     * @since 1.3
     */
    public static String getAppVersion() {
        UISession session = ContextProvider.getUISession();
        return (String) session.getAttribute(APP_VERSION);
    }

    /**
     * Sets the application name to the argument.
     * <p>
     * Specifying <code>null</code> for the name clears it.
     * </p>
     *
     * @param name the new app name or <code>null</code>
     *
     * @since 1.3
     */
    public static void setAppName(String name) {
        UISession session = ContextProvider.getUISession();
        session.setAttribute(APP_NAME, name);
    }

    /**
     * Sets the application version to the argument.
     *
     * @param version the new app version
     *
     * @since 1.3
     */
    public static void setAppVersion(String version) {
        UISession session = ContextProvider.getUISession();
        session.setAttribute(APP_VERSION, version);
    }

    /**
     * Forces all outstanding paint requests for the display
     * to be processed before this method returns.
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @see Control#update()
     *
     * @since 1.3
     */
    public void update() {
        checkDevice();
    }

    /**
     * Causes the system hardware to emit a short sound
     * (if it supports this capability).
     *
     * @exception SWTException <ul>
     *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
     *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
     * </ul>
     *
     * @since 1.3
     */
    public void beep() {
        checkDevice();
        beep = true;
    }

    /**
     * Returns true if a touch-aware input device is attached to the system,
     * enabled, and ready for use.
     *
     * @since 1.4
     */
    public boolean getTouchEnabled() {
        checkDevice();
        return false;
    }

    @SuppressWarnings("unchecked")
    private void register() {
        synchronized (Device.class) {
            boolean registered = false;
            WeakReference<Display>[] displays = getDisplays();
            for (int i = 0; !registered && i < displays.length; i++) {
                if (canDisplayRefBeReplaced(displays[i])) {
                    displays[i] = new WeakReference<>(this);
                    registered = true;
                }
            }
            if (!registered) {
                WeakReference<Display>[] newDisplays = new WeakReference[displays.length + 4];
                System.arraycopy(displays, 0, newDisplays, 0, displays.length);
                newDisplays[displays.length] = new WeakReference<>(this);
                setDisplays(newDisplays);
            }
        }
    }

    private boolean canDisplayRefBeReplaced(WeakReference<Display> displayRef) {
        boolean result = false;
        if (displayRef == null) {
            result = true;
        } else {
            Display display = displayRef.get();
            if (display == null || display.thread == thread) {
                result = true;
            }
        }
        return result;
    }

    private void deregister() {
        synchronized (Device.class) {
            WeakReference<Display>[] displays = getDisplays();
            for (int i = 0; i < displays.length; i++) {
                WeakReference<Display> current = displays[i];
                if (current != null && this == current.get()) {
                    displays[i] = null;
                }
            }
        }
    }

    private static WeakReference<Display>[] getDisplays() {
        return ContextProvider.getApplicationContext().getDisplaysHolder().getDisplays();
    }

    private void setDisplays(WeakReference<Display>[] displays) {
        getApplicationContext().getDisplaysHolder().setDisplays(displays);
    }

    /////////////////////
    // Consistency checks

    @SuppressWarnings("unused")
    static boolean isValidClass(Class<?> clazz) {
        //    String name = clazz.getName();
        //    int index = name.lastIndexOf( '.' );
        //    return name.substring( 0, index + 1 ).equals( PACKAGE_PREFIX );
        return true;
    }

    boolean isValidThread() {
        return thread == Thread.currentThread();
    }

    @Override
    protected void checkDevice() {
        if (!isValidThread()) {
            error(SWT.ERROR_THREAD_INVALID_ACCESS);
        }
        if (isDisposed()) {
            error(SWT.ERROR_DEVICE_DISPOSED);
        }
    }

    //////////////////
    // Helping methods

    /**
     * Does whatever display specific cleanup is required, and then uses the code
     * in <code>SWTError.error</code> to handle the error.
     *
     * @param code the descriptive error code
     * @see SWT#error(int)
     */
    void error(int code) {
        SWT.error(code);
    }

    private Rectangle readInitialBounds() {
        JsonValue value = readPropertyValue(getId(this), BOUNDS);
        return value != null ? readRectangle(value) : new Rectangle(0, 0, 1024, 768);
    }

    private Point readDPI() {
        JsonValue value = readPropertyValue(getId(this), DPI);
        return value != null ? readPoint(value) : new Point(0, 0);
    }

    private int readDepth() {
        JsonValue value = readPropertyValue(getId(this), COLOR_DEPTH);
        return value != null ? value.asInt() : 16;
    }

    /////////////////
    // Inner classes

    private static class WakeRunnable implements Runnable, SerializableCompatibility {

        @Override
        public void run() {
        }

    }

    private static final class ControlFinder {

        private final Display display;
        private final Point location;
        private final Set<Control> foundComponentInParent;
        private Control control;

        ControlFinder(Display display, Point location) {
            this.display = display;
            this.location = new Point(location.x, location.y);
            foundComponentInParent = new HashSet<>();
            find();
        }

        Control getControl() {
            return control;
        }

        private void find() {
            Shell[] shells = display.getShells();
            for (int i = 0; control == null && i < shells.length; i++) {
                WidgetTreeUtil.accept(shells[i], new WidgetTreeVisitor() {
                    @Override
                    public boolean visit(Widget widget) {
                        if (widget instanceof Control) {
                            return visitControl((Control) widget);
                        }
                        return true;
                    }
                });
            }
        }

        private boolean visitControl(Control control) {
            Rectangle bounds = getAbsoluteBounds(control);
            boolean result = false;
            if (control.isVisible() && bounds.contains(location)) {
                /*
                 * only assign control to cursor location if there was no other control
                 * already assigned within the same composite
                 */
                result = foundComponentInParent.add(control.getParent());
                if (result) {
                    this.control = control;
                }
            }
            return result;
        }

        private static Rectangle getAbsoluteBounds(Control control) {
            Rectangle bounds = control.getBounds();
            Point origin = getAbsoluteOrigin(control);
            return new Rectangle(origin.x, origin.y, bounds.width, bounds.height);
        }

    }

    private final class DisplayAdapter implements IDisplayAdapter {

        @Override
        public void setBounds(Rectangle bounds) {
            Display.this.bounds.x = bounds.x;
            Display.this.bounds.y = bounds.y;
            Display.this.bounds.width = bounds.width;
            Display.this.bounds.height = bounds.height;
        }

        @Override
        public void setCursorLocation(int x, int y) {
            cursorLocation.x = x;
            cursorLocation.y = y;
        }

        @Override
        public void setActiveShell(Shell activeShell) {
            Display.this.setActiveShell(activeShell);
        }

        @Override
        public void setFocusControl(Control focusControl, boolean fireEvents) {
            Display.this.setFocusControl(focusControl, fireEvents);
        }

        @Override
        public void invalidateFocus() {
            ContextProvider.getServiceStore().setAttribute(ATTR_INVALIDATE_FOCUS, Boolean.TRUE);
        }

        @Override
        public boolean isFocusInvalidated() {
            Object value = ContextProvider.getServiceStore().getAttribute(ATTR_INVALIDATE_FOCUS);
            return value != null;
        }

        @Override
        public Shell[] getShells() {
            Shell[] result = new Shell[shells.size()];
            shells.toArray(result);
            return result;
        }

        @Override
        public UISession getUISession() {
            return uiSession;
        }

        @Override
        public void attachThread() {
            Display.this.attachThread();
        }

        @Override
        public void detachThread() {
            Display.this.detachThread();
        }

        @Override
        public boolean isValidThread() {
            return Display.this.isValidThread();
        }

        @Override
        public boolean isBeepCalled() {
            return beep;
        }

        @Override
        public void resetBeep() {
            beep = false;
        }

        @Override
        public void notifyListeners(int eventType, Event event) {
            Display.this.notifyListeners(eventType, event);
        }

        @Override
        public boolean isListening(int eventType) {
            return Display.this.isListening(eventType);
        }

    }

}