view dwt/widgets/Display.d @ 26:09f5459a5014

Display in work
author Frank Benoit <benoit@tionex.de>
date Tue, 08 Jan 2008 08:07:04 +0100
parents fc2b263b8a3f
children ffa3c27c4328
line wrap: on
line source

/*******************************************************************************
 * Copyright (c) 2000, 2007 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
module dwt.widgets.Display;

import dwt.SWT;
import dwt.graphics.Color;
import dwt.graphics.Cursor;
import dwt.graphics.Device;
import dwt.graphics.DeviceData;
import dwt.graphics.Font;
import dwt.graphics.GCData;
import dwt.graphics.Image;
import dwt.graphics.ImageData;
import dwt.graphics.PaletteData;
import dwt.graphics.Point;
import dwt.graphics.Rectangle;
import dwt.graphics.Resource;
import dwt.internal.Compatibility;
import dwt.internal.Converter;
import dwt.internal.Lock;
import dwt.internal.gtk.c.gdktypes;
import dwt.internal.gtk.c.gtktypes;
import dwt.internal.gtk.OS;
import dwt.widgets.Caret;
import dwt.widgets.Control;
import dwt.widgets.Event;
import dwt.widgets.EventTable;
import dwt.widgets.Listener;
import dwt.widgets.Menu;
import dwt.widgets.Monitor;
import dwt.widgets.Shell;
import dwt.widgets.Synchronizer;
import dwt.widgets.Tray;
import dwt.widgets.Widget;

import tango.io.Stdout;
import tango.stdc.string;
import tango.stdc.stringz;
import dwt.dwthelper.utils;
import dwt.dwthelper.Runnable;

import tango.core.Thread : Thread;

/**
 * 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, Settings</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
 */
public class Display : Device {

	/* Events Dispatching and Callback */
	int gdkEventCount;
	GdkEvent* [] gdkEvents;
	Widget [] gdkEventWidgets;
	int [] dispatchEvents;
	Event [] eventQueue;
	int /*long*/ fds;
	int allocated_nfds;
	bool wake_state;
	int max_priority, timeout;
	void*/*Callback*/ eventCallback, filterCallback;
	int /*long*/ eventProc, filterProc, windowProc2, windowProc3, windowProc4, windowProc5;
	void*/*Callback*/ windowCallback2, windowCallback3, windowCallback4, windowCallback5;
	EventTable eventTable, filterTable;
	static char[] APP_NAME = "SWT";
	static const char[] DISPATCH_EVENT_KEY = "dwt.internal.gtk.dispatchEvent";
	static const char[] ADD_WIDGET_KEY = "dwt.internal.addWidget";
	int /*long*/ [] closures;
	int [] signalIds;
	int /*long*/ shellMapProcClosure;

	/* Widget Table */
	int [] indexTable;
	int freeSlot;
	int /*long*/ lastHandle;
	Widget lastWidget;
	Widget [] widgetTable;
	const static int GROW_SIZE = 1024;
	static const int SWT_OBJECT_INDEX;
	static const int SWT_OBJECT_INDEX1;
	static const int SWT_OBJECT_INDEX2;

	/* Focus */
	int focusEvent;
	Control focusControl;
	Shell activeShell;
	bool activePending;
	bool ignoreActivate, ignoreFocus;

	/* Input method resources */
	Control imControl;
	int /*long*/ preeditWindow, preeditLabel;

	/* Sync/Async Widget Communication */
	Synchronizer synchronizer;
	Thread thread;

	/* Display Shutdown */
	Runnable [] disposeList;

	/* System Tray */
	Tray tray;

	/* Timers */
	int [] timerIds;
	Runnable [] timerList;
	void*/*Callback*/ timerCallback;
	int /*long*/ timerProc;
	void*/*Callback*/ windowTimerCallback;
	int /*long*/ windowTimerProc;

	/* Caret */
	Caret currentCaret;
	void*/*Callback*/ caretCallback;
	int caretId;
	int /*long*/ caretProc;

	/* Mnemonics */
	Control mnemonicControl;

	/* Mouse hover */
	int mouseHoverId;
	int /*long*/ mouseHoverHandle, mouseHoverProc;
	void*/*Callback*/ mouseHoverCallback;

	/* Menu position callback */
	int /*long*/ menuPositionProc;
	void*/*Callback*/ menuPositionCallback;

	/* Tooltip size allocate callback */
	int /*long*/ sizeAllocateProc;
	void*/*Callback*/ sizeAllocateCallback;
	int /*long*/ sizeRequestProc;
	void*/*Callback*/ sizeRequestCallback;

	/* Shell map callback */
	int /*long*/ shellMapProc;
	void*/*Callback*/ shellMapCallback;

	/* Idle proc callback */
	int /*long*/ idleProc;
	int idleHandle;
	void*/*Callback*/ idleCallback;
	static const char[] ADD_IDLE_PROC_KEY;
	static const char[] REMOVE_IDLE_PROC_KEY;
	Object idleLock;
	bool idleNeeded;

	/* GtkTreeView callbacks */
	int[] treeSelection;
	int treeSelectionLength;
	int /*long*/ treeSelectionProc;
	void*/*Callback*/ treeSelectionCallback;
	int /*long*/ cellDataProcFld;
	void*/*Callback*/ cellDataCallback;

	/* Set direction callback */
	int /*long*/ setDirectionProc;
	void*/*Callback*/ setDirectionCallback;

	/* Get all children callback */
	int /*long*/ allChildrenProc;
    GList* allChildren;
	void*/*Callback*/ allChildrenCallback;

	/* Settings callbacks */
	int /*long*/ styleSetProc;
	void*/*Callback*/ styleSetCallback;
	GtkWidget* shellHandle;
	bool settingsChanged, runSettings;

	/* Entry focus behaviour */
	bool entrySelectOnFocus;

	/* Enter/Exit events */
	Control currentControl;

	/* Flush exposes */
	int /*long*/ checkIfEventProc;
	void*/*Callback*/ checkIfEventCallback;
	GdkWindow* flushWindow;
	bool flushAll;
	GdkRectangle* flushRect;
	XExposeEvent* exposeEvent;
	XVisibilityEvent* visibilityEvent;
	//int /*long*/ [] flushData = new int /*long*/ [1];

	/* System Resources */
	Font systemFont;
	Image errorImage, infoImage, questionImage, warningImage;
	Cursor [] cursors;
	Resource [] resources;
	static const int RESOURCE_SIZE = 1 + 4 + SWT.CURSOR_HAND + 1;

	/* Colors */
	GdkColor COLOR_WIDGET_DARK_SHADOW, COLOR_WIDGET_NORMAL_SHADOW, COLOR_WIDGET_LIGHT_SHADOW;
	GdkColor COLOR_WIDGET_HIGHLIGHT_SHADOW, COLOR_WIDGET_BACKGROUND, COLOR_WIDGET_FOREGROUND, COLOR_WIDGET_BORDER;
	GdkColor COLOR_LIST_FOREGROUND, COLOR_LIST_BACKGROUND, COLOR_LIST_SELECTION, COLOR_LIST_SELECTION_TEXT;
	GdkColor COLOR_INFO_BACKGROUND, COLOR_INFO_FOREGROUND;
	GdkColor COLOR_TITLE_FOREGROUND, COLOR_TITLE_BACKGROUND, COLOR_TITLE_BACKGROUND_GRADIENT;
	GdkColor COLOR_TITLE_INACTIVE_FOREGROUND, COLOR_TITLE_INACTIVE_BACKGROUND, COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT;

	/* Popup Menus */
	Menu [] popups;

	/* Click count*/
	int clickCount = 1;

	/* Timestamp of the Last Received Events */
	int lastEventTime, lastUserEventTime;

	/* Fixed Subclass */
	static int /*long*/ fixed_type;
	static int /*long*/ fixed_info_ptr;
	static void*/*Callback*/ fixedClassInitCallback;
    //static void* fixedMapCallback;
	static int /*long*/ fixedClassInitProc;
    //static int    fixedMapProc;

	/* Renderer Subclass */
	static int /*long*/ text_renderer_type, pixbuf_renderer_type, toggle_renderer_type;
	static int /*long*/ text_renderer_info_ptr, pixbuf_renderer_info_ptr, toggle_renderer_info_ptr;
	static void*/*Callback*/ rendererClassInitCallback, rendererRenderCallback, rendererGetSizeCallback;
	static int /*long*/ rendererClassInitProc, rendererRenderProc, rendererGetSizeProc;

	/* Key Mappings */
	static const int [] [] KeyTable = [

		/* Keyboard and Mouse Masks */
		[OS.GDK_Alt_L,		SWT.ALT],
		[OS.GDK_Alt_R,		SWT.ALT],
		[OS.GDK_Meta_L,	SWT.ALT],
		[OS.GDK_Meta_R,	SWT.ALT],
		[OS.GDK_Shift_L,		SWT.SHIFT],
		[OS.GDK_Shift_R,		SWT.SHIFT],
		[OS.GDK_Control_L,	SWT.CONTROL],
		[OS.GDK_Control_R,	SWT.CONTROL],
//		[OS.GDK_????,		SWT.COMMAND],
//		[OS.GDK_????,		SWT.COMMAND],

		/* Non-Numeric Keypad Keys */
		[OS.GDK_Up,						SWT.ARROW_UP],
		[OS.GDK_KP_Up,					SWT.ARROW_UP],
		[OS.GDK_Down,					SWT.ARROW_DOWN],
		[OS.GDK_KP_Down,			SWT.ARROW_DOWN],
		[OS.GDK_Left,						SWT.ARROW_LEFT],
		[OS.GDK_KP_Left,				SWT.ARROW_LEFT],
		[OS.GDK_Right,					SWT.ARROW_RIGHT],
		[OS.GDK_KP_Right,				SWT.ARROW_RIGHT],
		[OS.GDK_Page_Up,				SWT.PAGE_UP],
		[OS.GDK_KP_Page_Up,		SWT.PAGE_UP],
		[OS.GDK_Page_Down,			SWT.PAGE_DOWN],
		[OS.GDK_KP_Page_Down,	SWT.PAGE_DOWN],
		[OS.GDK_Home,					SWT.HOME],
		[OS.GDK_KP_Home,			SWT.HOME],
		[OS.GDK_End,						SWT.END],
		[OS.GDK_KP_End,				SWT.END],
		[OS.GDK_Insert,					SWT.INSERT],
		[OS.GDK_KP_Insert,			SWT.INSERT],

		/* Virtual and Ascii Keys */
		[OS.GDK_BackSpace,		SWT.BS],
		[OS.GDK_Return,				SWT.CR],
		[OS.GDK_Delete,				SWT.DEL],
		[OS.GDK_KP_Delete,		SWT.DEL],
		[OS.GDK_Escape,			SWT.ESC],
		[OS.GDK_Linefeed,			SWT.LF],
		[OS.GDK_Tab,					SWT.TAB],
		[OS.GDK_ISO_Left_Tab, 	SWT.TAB],

		/* Functions Keys */
		[OS.GDK_F1,		SWT.F1],
		[OS.GDK_F2,		SWT.F2],
		[OS.GDK_F3,		SWT.F3],
		[OS.GDK_F4,		SWT.F4],
		[OS.GDK_F5,		SWT.F5],
		[OS.GDK_F6,		SWT.F6],
		[OS.GDK_F7,		SWT.F7],
		[OS.GDK_F8,		SWT.F8],
		[OS.GDK_F9,		SWT.F9],
		[OS.GDK_F10,		SWT.F10],
		[OS.GDK_F11,		SWT.F11],
		[OS.GDK_F12,		SWT.F12],
		[OS.GDK_F13,		SWT.F13],
		[OS.GDK_F14,		SWT.F14],
		[OS.GDK_F15,		SWT.F15],

		/* Numeric Keypad Keys */
		[OS.GDK_KP_Multiply,		SWT.KEYPAD_MULTIPLY],
		[OS.GDK_KP_Add,			SWT.KEYPAD_ADD],
		[OS.GDK_KP_Enter,			SWT.KEYPAD_CR],
		[OS.GDK_KP_Subtract,	SWT.KEYPAD_SUBTRACT],
		[OS.GDK_KP_Decimal,	SWT.KEYPAD_DECIMAL],
		[OS.GDK_KP_Divide,		SWT.KEYPAD_DIVIDE],
		[OS.GDK_KP_0,			SWT.KEYPAD_0],
		[OS.GDK_KP_1,			SWT.KEYPAD_1],
		[OS.GDK_KP_2,			SWT.KEYPAD_2],
		[OS.GDK_KP_3,			SWT.KEYPAD_3],
		[OS.GDK_KP_4,			SWT.KEYPAD_4],
		[OS.GDK_KP_5,			SWT.KEYPAD_5],
		[OS.GDK_KP_6,			SWT.KEYPAD_6],
		[OS.GDK_KP_7,			SWT.KEYPAD_7],
		[OS.GDK_KP_8,			SWT.KEYPAD_8],
		[OS.GDK_KP_9,			SWT.KEYPAD_9],
		[OS.GDK_KP_Equal,	SWT.KEYPAD_EQUAL],

		/* Other keys */
		[OS.GDK_Caps_Lock,		SWT.CAPS_LOCK],
		[OS.GDK_Num_Lock,		SWT.NUM_LOCK],
		[OS.GDK_Scroll_Lock,		SWT.SCROLL_LOCK],
		[OS.GDK_Pause,				SWT.PAUSE],
		[OS.GDK_Break,				SWT.BREAK],
		[OS.GDK_Print,					SWT.PRINT_SCREEN],
		[OS.GDK_Help,					SWT.HELP],

	];

	/* Multiple Displays. */
	static Display Default;
	static Display [] Displays;

	/* Package name */
	static const char[] PACKAGE_PREFIX = "dwt.widgets.";
	/* This code is intentionally commented.
	 * ".class" can not be used on CLDC.
	 */
//	static {
//		char[] name = Display.class.getName ();
//		int index = name.lastIndexOf ('.');
//		PACKAGE_NAME = name.substring (0, index + 1);
//	}

	/*
	* In order to support CLDC, .class cannot be used because
	* it does not compile on some Java compilers when they are
	* targeted for CLDC.  Use Class.forName() instead.
	*/
	static this(){
        Displays = new Display [4];
        initDeviceFinder();
        SWT_OBJECT_INDEX = OS.g_quark_from_string ("SWT_OBJECT_INDEX");
        SWT_OBJECT_INDEX1 = OS.g_quark_from_string ("SWT_OBJECT_INDEX1");
        SWT_OBJECT_INDEX2 = OS.g_quark_from_string ("SWT_OBJECT_INDEX2");
        ADD_IDLE_PROC_KEY = "dwt.internal.gtk2.addIdleProc";
        REMOVE_IDLE_PROC_KEY = "dwt.internal.gtk2.removeIdleProc";
	}

	/* GTK Version */
	static const int MAJOR = 2;
	static const int MINOR = 0;
	static const int MICRO = 6;

	/* Display Data */
	Object data;
	char[] [] keys;
	Object [] values;

	/* Initial Guesses for Shell Trimmings. */
	int borderTrimWidth = 4, borderTrimHeight = 4;
	int resizeTrimWidth = 6, resizeTrimHeight = 6;
	int titleBorderTrimWidth = 5, titleBorderTrimHeight = 28;
	int titleResizeTrimWidth = 6, titleResizeTrimHeight = 29;
	int titleTrimWidth = 0, titleTrimHeight = 23;
	bool ignoreTrim;

	/* Window Manager */
	char[] windowManager;

	/*
	* TEMPORARY CODE.  Install the runnable that
	* gets the current display. This code will
	* be removed in the future.
	*/
	private static void initDeviceFinder(){
		DeviceFinder = new class() Runnable {
			public void run () {
				Device device = getCurrent ();
				if (device is null) {
					device = getDefault ();
				}
				setDevice (device);
			}
		};
	}

/*
* TEMPORARY CODE.
*/
static void setDevice (Device device) {
	CurrentDevice = device;
}

/**
 * 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 this () {
	this (null);
}

/**
 * Constructs a new instance of this class using the parameter.
 *
 * @param data the device data
 */
public this (DeviceData data) {
	super (data);
    synchronizer = new Synchronizer (this);
    idleLock = new Object();
    flushRect = new GdkRectangle ();
    exposeEvent = new XExposeEvent ();
    visibilityEvent = new XVisibilityEvent ();
    cursors = new Cursor [SWT.CURSOR_HAND + 1];
}

/**
 * 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>
 *
 * @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
 *
 * @since 3.0
 */
public void addFilter (int eventType, Listener listener) {
	checkDevice ();
	if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
	if (filterTable is null) filterTable = new EventTable ();
	filterTable.hook (eventType, listener);
}

void addGdkEvent (GdkEvent* event) {
	if (gdkEvents is null) {
		int length = GROW_SIZE;
		gdkEvents.length = length;
		gdkEventWidgets.length = length;
		gdkEventCount = 0;
	}
	if (gdkEventCount is gdkEvents.length) {
		int length = gdkEventCount + GROW_SIZE;
		GdkEvent* [] newEvents = new GdkEvent* [length];
		SimpleType!(GdkEvent*).arraycopy (gdkEvents, 0, newEvents, 0, gdkEventCount);
		gdkEvents = newEvents;
		Widget [] newWidgets = new Widget [length];
		System.arraycopy (gdkEventWidgets, 0, newWidgets, 0, gdkEventCount);
		gdkEventWidgets = newWidgets;
	}
	Widget widget = null;
	GtkWidget* handle = OS.gtk_get_event_widget (event);
	if (handle !is null) {
		do {
			widget = getWidget (handle);
		} while (widget is null && (handle = OS.gtk_widget_get_parent (handle)) !is null);
	}
	gdkEvents [gdkEventCount] = event;
	gdkEventWidgets [gdkEventCount] = widget;
	gdkEventCount++;
}

void addIdleProc() {
	synchronized (idleLock){
		this.idleNeeded = true;
		if (idleHandle is 0) {
			idleHandle = OS.g_idle_add ( &idleProcFunc, cast(void*) this );
		}
	}
}

/**
 * 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 2.0
 */
public void addListener (int eventType, Listener listener) {
	checkDevice ();
	if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable is null) eventTable = new EventTable ();
	eventTable.hook (eventType, listener);
}

//PORTING_LEFT int /*long*/ allChildrenProcMeth (GtkWidget* widget, int /*long*/ recurse) {
//PORTING_LEFT 	allChildren = OS.g_list_append (allChildren, widget);
//PORTING_LEFT 	if (recurse !is null && OS.GTK_IS_CONTAINER (widget)) {
//PORTING_LEFT 		OS.gtk_container_forall (widget, allChildrenProc, recurse);
//PORTING_LEFT 	}
//PORTING_LEFT 	return 0;
//PORTING_LEFT }
//PORTING_LEFT
//PORTING_LEFT void addMouseHoverTimeout (int /*long*/ handle) {
//PORTING_LEFT 	if (mouseHoverId !is 0) OS.gtk_timeout_remove (mouseHoverId);
//PORTING_LEFT 	mouseHoverId = OS.gtk_timeout_add (400, &mouseHoverProcFunc, handle);
//PORTING_LEFT 	mouseHoverHandle = handle;
//PORTING_LEFT }
//PORTING_LEFT
void addPopup (Menu menu) {
	if (popups is null) popups = new Menu [4];
	int length = popups.length;
	for (int i=0; i<length; i++) {
		if (popups [i] is menu) return;
	}
	int index = 0;
	while (index < length) {
		if (popups [index] is null) break;
		index++;
	}
	if (index is length) {
		Menu [] newPopups = new Menu [length + 4];
		System.arraycopy (popups, 0, newPopups, 0, length);
		popups = newPopups;
	}
	popups [index] = menu;
}

void addWidget (int/**/ handle, Widget widget) {
	if (handle is 0) return;
	if (freeSlot is -1) {
		int len = (freeSlot = indexTable.length) + GROW_SIZE;
		int[] newIndexTable = new int[len];
		Widget[] newWidgetTable = new Widget [len];
		System.arraycopy (indexTable, 0, newIndexTable, 0, freeSlot);
		System.arraycopy (widgetTable, 0, newWidgetTable, 0, freeSlot);
		for (int i = freeSlot; i < len - 1; i++) {
			newIndexTable[i] = i + 1;
		}
		newIndexTable[len - 1] = -1;
		indexTable = newIndexTable;
		widgetTable = newWidgetTable;
	}
	int index = freeSlot + 1;
	OS.g_object_set_qdata (cast(GObject*)handle, SWT_OBJECT_INDEX, cast(void*)index);
	int oldSlot = freeSlot;
	freeSlot = indexTable[oldSlot];
	indexTable [oldSlot] = -2;
	widgetTable [oldSlot] = widget;
}

/**
 * Causes the <code>run()</code> method of the runnable to
 * be invoked by the user-interface thread at the next
 * reasonable opportunity. 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) {
	if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
	synchronized (idleLock) {
		if (idleNeeded && idleHandle is 0) {
 			//NOTE: calling unlocked function in OS
			idleHandle = OS.g_idle_add (&idleProcFunc, cast(void*) this);
		}
	}
	synchronizer.asyncExec (runnable);
}

/**
 * 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>
 */
public void beep () {
	if (!isValidThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
	OS.gdk_beep();
	if (!OS.GDK_WINDOWING_X11 ()) {
		OS.gdk_flush ();
	} else {
		GdkDisplay* xDisplay = OS.GDK_DISPLAY ();
		OS.XFlush (xDisplay);
	}
}

int /*long*/ cellDataProc (int /*long*/ tree_column, int /*long*/ cell, int /*long*/ tree_model, int /*long*/ iter, GtkWidget* data) {
	Widget widget = getWidget (data);
	if (widget is null) return 0;
	return widget.cellDataProc (tree_column, cell, tree_model, iter, data);
}

protected void checkDevice () {
	if (thread is null) error (SWT.ERROR_WIDGET_DISPOSED);
	if (thread !is Thread.getThis ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);
	if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
}

static synchronized void checkDisplay (Thread thread, bool multiple) {
	for (int i=0; i<Displays.length; i++) {
		if (Displays [i] !is null) {
			if (!multiple) SWT.error (SWT.ERROR_NOT_IMPLEMENTED, null, " [multiple displays]");
			if (Displays [i].thread is thread) SWT.error (SWT.ERROR_THREAD_INVALID_ACCESS);
		}
	}
}

private static extern(C) int checkIfEventProcFunc (void* display, XEvent* xEvent, void* userData) {
    auto disp = cast(Display)userData;
    return disp.checkIfEventProcMeth( display, xEvent );
}

int checkIfEventProcMeth (void* display, XEvent* xEvent) {
	int type = xEvent.type;
	switch (type) {
		case OS.VisibilityNotify:
		case OS.Expose:
		case OS.GraphicsExpose:
			break;
		default:
			return 0;
	}
	GdkWindow* window = OS.gdk_window_lookup ( xEvent.xany.window );
	if (window is null) return 0;
	if (flushWindow !is null) {
		if (flushAll) {
			auto tempWindow = window;
			do {
				if (tempWindow is flushWindow) break;
			} while ((tempWindow = OS.gdk_window_get_parent (tempWindow)) !is null);
			if (tempWindow !is flushWindow) return 0;
		} else {
			if (window !is flushWindow) return 0;
		}
	}
	*exposeEvent = *cast(XExposeEvent*)xEvent;
	switch (type) {
		case OS.Expose:
		case OS.GraphicsExpose: {
			flushRect.x = exposeEvent.x;
			flushRect.y = exposeEvent.y;
			flushRect.width = exposeEvent.width;
			flushRect.height = exposeEvent.height;
			OS.gdk_window_invalidate_rect (window, flushRect, true);
			exposeEvent.type = -1;
			memmove (xEvent, exposeEvent, XExposeEvent.sizeof);
			break;
		}
		case OS.VisibilityNotify: {
			memmove (visibilityEvent, xEvent, XVisibilityEvent.sizeof);
            GtkWidget* handle;
            OS.gdk_window_get_user_data (window, cast(void**) & handle);
			Widget widget = handle !is null ? getWidget (handle) : null;
			if (auto control = cast(Control)widget ) {
				if (window is control.paintWindow ()) {
					if (visibilityEvent.state is OS.VisibilityFullyObscured) {
						control.state |= Widget.OBSCURED;
					} else {
						control.state &= ~Widget.OBSCURED;
					}
				}
			}
			break;
		}
	}
	return 0;
}

/**
 * Checks that this class can be subclassed.
 * <p>
 * IMPORTANT: See the comment in <code>Widget.checkSubclass()</code>.
 * </p>
 *
 * @exception SWTException <ul>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 *
 * @see Widget#checkSubclass
 */
protected void checkSubclass () {
//PORTING_TODO	if (!isValidClass (getClass ())) error (SWT.ERROR_INVALID_SUBCLASS);
}

/**
 * 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 2.0
 */
public void close () {
	checkDevice ();
	Event event = new Event ();
	sendEvent (SWT.Close, event);
	if (event.doit) dispose ();
}

/**
 * Creates the device in the operating system.  If the device
 * does not have a handle, this method may do nothing depending
 * on the device.
 * <p>
 * This method is called before <code>init</code>.
 * </p>
 *
 * @param data the DeviceData which describes the receiver
 *
 * @see #init
 */
protected void create (DeviceData data) {
	checkSubclass ();
	checkDisplay(thread = Thread.getThis (), false);
	createDisplay (data);
	register ();
	if (Default is null) Default = this;
}

synchronized void createDisplay (DeviceData data) {
	/* Required for g_main_context_wakeup */
	if (!OS.g_thread_supported ()) {
		OS.g_thread_init (null);
	}
	OS.gtk_set_locale();
    int cnt = 0;
	if (!OS.gtk_init_check (&cnt, null)) {
		SWT.error (SWT.ERROR_NO_HANDLES, null, " [gtk_init_check() failed]");
	}
	if (OS.GDK_WINDOWING_X11 ()) xDisplay = cast(dwt.internal.gtk.c.cairotypes.Display*) OS.GDK_DISPLAY ();
	char* ptr = OS.gtk_check_version (MAJOR, MINOR, MICRO);
	if (ptr !is null) {
		char [] buffer = fromUtf8z(ptr);
		Stdout.formatln ("***WARNING: {}", buffer );
		Stdout.formatln ("***WARNING: SWT requires GTK {}.{}.{}", MAJOR, MINOR, MICRO );
		int major = OS.gtk_major_version (), minor = OS.gtk_minor_version (), micro = OS.gtk_micro_version ();
		Stdout.formatln ("***WARNING: Detected: {}.{}.{}", major, minor, micro);
	}
	if (fixed_type is 0) {
		GTypeInfo* fixed_info = new GTypeInfo ();
		fixed_info.class_size = GtkFixedClass.sizeof;
		fixed_info.class_init = & fixedClassInitProcFunc;
		fixed_info.instance_size = GtkFixed.sizeof;
		fixed_type = OS.g_type_register_static (OS.GTK_TYPE_FIXED (), "SwtFixed".ptr, fixed_info, cast(GTypeFlags)0);
	}
	if (text_renderer_type is 0) {
		GTypeInfo* renderer_info = new GTypeInfo ();
		renderer_info.class_size = GtkCellRendererTextClass.sizeof;
		renderer_info.class_init = & rendererClassInitProcFunc;
		renderer_info.instance_size = GtkCellRendererText.sizeof;
		text_renderer_type = OS.g_type_register_static (OS.GTK_TYPE_CELL_RENDERER_TEXT (), "SwtTextRenderer".ptr, renderer_info, cast(GTypeFlags)0);
	}
	if (pixbuf_renderer_type is 0) {
		GTypeInfo* renderer_info = new GTypeInfo ();
		renderer_info.class_size = GtkCellRendererPixbufClass.sizeof;
		renderer_info.class_init = & rendererClassInitProcFunc;
		renderer_info.instance_size = GtkCellRendererPixbuf.sizeof;
		pixbuf_renderer_type = OS.g_type_register_static (OS.GTK_TYPE_CELL_RENDERER_PIXBUF (), "SwtPixbufRenderer".ptr, renderer_info, cast(GTypeFlags)0);
	}
	if (toggle_renderer_type is 0) {
		GTypeInfo* renderer_info = new GTypeInfo ();
		renderer_info.class_size = GtkCellRendererToggleClass.sizeof;
		renderer_info.class_init = & rendererClassInitProcFunc;
		renderer_info.instance_size = GtkCellRendererToggle.sizeof;
		toggle_renderer_type = OS.g_type_register_static (OS.GTK_TYPE_CELL_RENDERER_TOGGLE (), "SwtToggleRenderer".ptr, renderer_info, cast(GTypeFlags)0);
	}

	OS.gtk_widget_set_default_direction (cast(GtkTextDirection)OS.GTK_TEXT_DIR_LTR);
	OS.gdk_rgb_init ();
	char* p = toStringz(APP_NAME);
	OS.g_set_prgname (p);
	OS.gdk_set_program_class (p);
	OS.gtk_rc_parse_string ("style \"swt-flat\" { GtkToolbar::shadow-type = none } widget \"*.swt-toolbar-flat\" style : highest \"swt-flat\"".ptr);

	/* Initialize the hidden shell */
	shellHandle = OS.gtk_window_new (cast(GtkWindowType)OS.GTK_WINDOW_TOPLEVEL);
	if (shellHandle is null) SWT.error (SWT.ERROR_NO_HANDLES);
	OS.gtk_widget_realize (shellHandle);

	/* Initialize the filter and event callback */
	OS.gdk_event_handler_set (&eventProcFunc, cast(void*)this, cast(GDestroyNotify) 0);
	OS.gdk_window_add_filter  (null, &filterProcFunc, cast(void*)this );
}

Image createImage (char[] name) {
	auto style = OS.gtk_widget_get_default_style ();
	char[] buffer = name;
	auto pixbuf = OS.gtk_icon_set_render_icon (
		OS.gtk_icon_factory_lookup_default (buffer.ptr), style,
		cast(GtkTextDirection)OS.GTK_TEXT_DIR_NONE,
        cast(GtkStateType)OS.GTK_STATE_NORMAL,
        cast(GtkIconSize)OS.GTK_ICON_SIZE_DIALOG, null, null );
	if (pixbuf is null) return null;
	int width = OS.gdk_pixbuf_get_width (pixbuf);
	int height = OS.gdk_pixbuf_get_height (pixbuf);
	int stride = OS.gdk_pixbuf_get_rowstride (pixbuf);
	bool hasAlpha = cast(bool)OS.gdk_pixbuf_get_has_alpha (pixbuf);
	char* pixels = OS.gdk_pixbuf_get_pixels (pixbuf);
	byte [] data = new byte [stride * height];
	memmove (data.ptr, pixels, data.length);
	OS.g_object_unref (pixbuf);
	ImageData imageData = null;
	if (hasAlpha) {
		PaletteData palette = new PaletteData (0xFF000000, 0xFF0000, 0xFF00);
		imageData = new ImageData (width, height, 32, palette);
		byte [] alpha = new byte [stride * height];
		for (int y=0; y<height; y++) {
			for (int x=0; x<width; x++) {
				alpha [y*width+x] = data [y*stride+x*4+3];
				data [y*stride+x*4+3] = 0;
			}
		}
		imageData.setAlphas (0, 0, width * height, alpha, 0);
	} else {
		PaletteData palette = new PaletteData (0xFF0000, 0xFF00, 0xFF);
		imageData = new ImageData (width, height, 24, palette);
	}
	imageData.data = data;
	imageData.bytesPerLine = stride;
	return new Image (this, imageData);
}

static GdkPixbuf* createPixbuf(Image image) {
	int w, h;
 	OS.gdk_drawable_get_size (image.pixmap, &w, &h);
	auto colormap = OS.gdk_colormap_get_system ();
	GdkPixbuf* pixbuf;
	bool hasMask = image.mask !is null && OS.gdk_drawable_get_depth (image.mask) is 1;
	if (hasMask) {
		pixbuf = OS.gdk_pixbuf_new (cast(GdkColorspace)OS.GDK_COLORSPACE_RGB, true, 8, w, h );
		if (pixbuf is null) SWT.error (SWT.ERROR_NO_HANDLES);
		OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w, h);
		auto maskPixbuf = OS.gdk_pixbuf_new(cast(GdkColorspace)OS.GDK_COLORSPACE_RGB, false, 8, w, h);
		if (maskPixbuf is null) SWT.error (SWT.ERROR_NO_HANDLES);
		OS.gdk_pixbuf_get_from_drawable(maskPixbuf, image.mask, null, 0, 0, 0, 0, w, h);
		int stride = OS.gdk_pixbuf_get_rowstride(pixbuf);
		auto pixels = OS.gdk_pixbuf_get_pixels(pixbuf);
		byte[] line = new byte[stride];
		int maskStride = OS.gdk_pixbuf_get_rowstride(maskPixbuf);
		auto maskPixels = OS.gdk_pixbuf_get_pixels(maskPixbuf);
		byte[] maskLine = new byte[maskStride];
		for (int y=0; y<h; y++) {
			auto offset = pixels + (y * stride);
			memmove(line.ptr, offset, stride);
			auto maskOffset = maskPixels + (y * maskStride);
			memmove(maskLine.ptr, maskOffset, maskStride);
			for (int x=0; x<w; x++) {
				if (maskLine[x * 3] is 0) {
					line[x * 4 + 3] = 0;
				}
			}
			memmove(offset, line.ptr, stride);
		}
		OS.g_object_unref(maskPixbuf);
	} else {
		ImageData data = image.getImageData ();
		bool hasAlpha = data.getTransparencyType () is SWT.TRANSPARENCY_ALPHA;
		pixbuf = OS.gdk_pixbuf_new (cast(GdkColorspace)OS.GDK_COLORSPACE_RGB, hasAlpha, 8, w, h);
		if (pixbuf is null) SWT.error (SWT.ERROR_NO_HANDLES);
		OS.gdk_pixbuf_get_from_drawable (pixbuf, image.pixmap, colormap, 0, 0, 0, 0, w, h);
		if (hasAlpha) {
			byte [] alpha = data.alphaData;
			int stride = OS.gdk_pixbuf_get_rowstride (pixbuf);
			auto pixels = OS.gdk_pixbuf_get_pixels (pixbuf);
			byte [] line = new byte [stride];
			for (int y = 0; y < h; y++) {
				auto offset = pixels + (y * stride);
				memmove (line.ptr, offset, stride);
				for (int x = 0; x < w; x++) {
					line [x*4+3] = alpha [y*w+x];
				}
				memmove (offset, line.ptr, stride);
			}
		}
	}
	return pixbuf;
}

synchronized void deregister () {
	for (int i=0; i<Displays.length; i++) {
		if (this is Displays [i]) Displays [i] = null;
	}
}

/**
 * Destroys the device in the operating system and releases
 * the device's handle.  If the device does not have a handle,
 * this method may do nothing depending on the device.
 * <p>
 * This method is called after <code>release</code>.
 * </p>
 * @see Device#dispose
 * @see #release
 */
protected void destroy () {
	if (this is Default) Default = null;
	deregister ();
	destroyDisplay ();
}

void destroyDisplay () {
}

/**
 * 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 synchronized Display findDisplay (Thread thread) {
	for (int i=0; i<Displays.length; i++) {
		Display display = Displays [i];
		if (display !is null && display.thread is thread) {
			return display;
		}
	}
	return null;
}

/**
 * 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 is null) disposeList = new Runnable [4];
	for (int i=0; i<disposeList.length; i++) {
		if (disposeList [i] is null) {
			disposeList [i] = runnable;
			return;
		}
	}
	Runnable [] newDisposeList = new Runnable [disposeList.length + 4];
	SimpleType!(Runnable).arraycopy (disposeList, 0, newDisposeList, 0, disposeList.length);
	newDisposeList [disposeList.length] = runnable;
	disposeList = newDisposeList;
}

/**
 * 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 SWTError#error
 */
void error (int code) {
	SWT.error (code);
}

private static extern(C) void eventProcFunc (GdkEvent* event, void* data) {
    Display disp = cast(Display)data;
    disp.eventProcMeth(event);
}
void eventProcMeth (GdkEvent* event) {
	/*
	* Use gdk_event_get_time() rather than event.time or
	* gtk_get_current_event_time().  If the event does not
	* have a time stamp, then the field will contain garbage.
	* Note that calling gtk_get_current_event_time() from
	* outside of gtk_main_do_event() seems to always
	* return zero.
	*/
	int time = OS.gdk_event_get_time (event);
	if (time !is 0) lastEventTime = time;

	int eventType = OS.GDK_EVENT_TYPE (event);
	switch (eventType) {
		case OS.GDK_BUTTON_PRESS:
		case OS.GDK_KEY_PRESS:
			lastUserEventTime = time;
	}
	bool dispatch = true;
	if (dispatchEvents !is null) {
		dispatch = false;
		for (int i = 0; i < dispatchEvents.length; i++) {
			if (eventType is dispatchEvents [i]) {
				dispatch = true;
				break;
			}
		}
	}
	if (!dispatch) {
		addGdkEvent (OS.gdk_event_copy (event));
		return 0;
	}
	/*
	* Feature in GTK.  GTK implements modality by adding a grab
	* to the GTK top level window.  Normally, all mouse and
	* keyboard events are delivered to child widgets and the
	* shell when the grab is active.  When an override redirect
	* shell is created as a child of a dialog, then events are
	* grabbed by the dialog instead of the override redirect
	* shell.  The fix is to add a temporary grab to the override
	* redirect window when there is not already a grab in a
	* child widget of the override redirect shell (for example,
	* in a scroll bar).
	*/
	Shell shell = null;
	Control control = null;
	auto grabHandle = OS.gtk_grab_get_current ();
	if (grabHandle !is null && OS.GTK_IS_WINDOW (grabHandle) && OS.gtk_window_get_modal (cast(GtkWindow*)grabHandle)) {
		switch (eventType) {
			case OS.GDK_KEY_PRESS:
			case OS.GDK_KEY_RELEASE:
			case OS.GDK_ENTER_NOTIFY:
			case OS.GDK_LEAVE_NOTIFY:
			case OS.GDK_BUTTON_PRESS:
			case OS.GDK_2BUTTON_PRESS:
			case OS.GDK_3BUTTON_PRESS:
			case OS.GDK_BUTTON_RELEASE:
			case OS.GDK_MOTION_NOTIFY:  {
				auto window = OS.GDK_EVENT_WINDOW (cast(GdkEventAny*)event);
				do {
                    GtkWidget* handle;
					OS.gdk_window_get_user_data (window, cast(void**) &handle);
					if (handle !is null) {
						Widget widget = getWidget (handle);
						if (widget !is null && (null !is cast(Control)widget)) {
							control = cast(Control) widget;
							break;
						}
					}
				} while ((window = OS.gdk_window_get_parent (window)) !is null);
			}
		}
		if (control !is null) {
			shell = control.getShell ();
			if ((shell.style & SWT.ON_TOP) !is 0) {
				OS.gtk_grab_add (shell.shellHandle);
			}
		}
	}
	OS.gtk_main_do_event (event);
	if (dispatchEvents is null) putGdkEvents ();
	if (control !is null) {
		if (shell !is null && !shell.isDisposed () && (shell.style & SWT.ON_TOP) !is 0) {
			OS.gtk_grab_remove (shell.shellHandle);
		}
	}
	return 0;
}

/**
 * Given the operating system handle for a widget, returns
 * the instance of the <code>Widget</code> subclass which
 * represents it in the currently running application, if
 * such exists, or null if no matching widget can be found.
 * <p>
 * <b>IMPORTANT:</b> This method should not be called from
 * application code. The arguments are platform-specific.
 * </p>
 *
 * @param handle the handle for the widget
 * @return the SWT widget that the handle represents
 *
 * @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 Widget findWidget (GtkWidget* handle) {
	checkDevice ();
	return getWidget (handle);
}

/**
 * Given the operating system handle for a widget,
 * and widget-specific id, returns the instance of
 * the <code>Widget</code> subclass which represents
 * the handle/id pair in the currently running application,
 * if such exists, or null if no matching widget can be found.
 * <p>
 * <b>IMPORTANT:</b> This method should not be called from
 * application code. The arguments are platform-specific.
 * </p>
 *
 * @param handle the handle for the widget
 * @param id the id for the subwidget (usually an item)
 * @return the SWT widget that the handle/id pair represents
 *
 * @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 3.1
 */
public Widget findWidget (GtkWidget* handle, int id) {
	checkDevice ();
	return null;
}

/**
 * Given a widget and a widget-specific id, returns the
 * instance of the <code>Widget</code> subclass which represents
 * the widget/id pair in the currently running application,
 * if such exists, or null if no matching widget can be found.
 *
 * @param widget the widget
 * @param id the id for the subwidget (usually an item)
 * @return the SWT subwidget (usually an item) that the widget/id pair represents
 *
 * @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 3.3
 */
public Widget findWidget (Widget widget, int id) {
	checkDevice ();
	return null;
}

private static extern(C) void fixedClassInitProcFunc (void* g_class, void* class_data) {
	GtkWidgetClass* klass = cast(GtkWidgetClass*)g_class;
	klass.map = &fixedMapProcFunc;
}

private static extern(C)  void fixedMapProcFunc (GtkWidget * handle) {
	Display display = getCurrent ();
	Widget widget = display.getWidget (handle);
	if (widget !is null) widget.fixedMapProc (handle);
}

private static extern(C) void rendererClassInitProcFunc (void* g_class, void* class_data) {
    GtkCellRendererClass* klass = cast(GtkCellRendererClass*)g_class;
	klass.render = &rendererRenderProcFunc;
	klass.get_size = &rendererGetSizeProcFunc;
}
private static extern(C) void rendererGetSizeProcFunc(GtkCellRenderer *cell, GtkWidget *handle, GdkRectangle *cell_area, int *x_offset, int *y_offset, int *width, int *height) {
	Display display = getCurrent ();
	Widget widget = display.getWidget (handle);
	if (widget !is null) widget.rendererGetSizeProc (cell, handle, cell_area, x_offset, y_offset, width, height);
}
private static extern(C) void rendererRenderProcFunc(GtkCellRenderer * cell, GdkDrawable * window, GtkWidget * handle, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, int flags){
	Display display = getCurrent ();
	Widget widget = display.getWidget (handle);
	if (widget !is null) widget.rendererRenderProc (cell, window, handle, background_area, cell_area, expose_area, flags);
}

void flushExposes (GdkWindow* window, bool all) {
	OS.gdk_flush ();
	OS.gdk_flush ();
	if (OS.GDK_WINDOWING_X11 ()) {
		this.flushWindow = window;
		this.flushAll = all;
		auto xDisplay = OS.GDK_DISPLAY ();
		auto xEvent = cast(XEvent*)OS.g_malloc (XEvent.sizeof);
		OS.XCheckIfEvent (xDisplay, xEvent, &checkIfEventProcFunc, cast(void*)this );
		OS.g_free (xEvent);
		this.flushWindow = null;
	}
}

/**
 * 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;
}

/**
 * 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>
 */
public Rectangle getBounds () {
	checkDevice ();
	return new Rectangle (0, 0, OS.gdk_screen_width (), OS.gdk_screen_height ());
}

/**
 * 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 synchronized Display getCurrent () {
	Thread current = Thread.getThis ();
	for (int i=0; i<Displays.length; i++) {
		Display display = Displays [i];
		if (display !is null && display.thread is current) return display;
	}
	return null;
}

int getCaretBlinkTime () {
//	checkDevice ();
	auto settings = OS.gtk_settings_get_default ();
	if (settings is null) return 500;
	int  buffer;
	OS.g_object_get1 (settings, OS.gtk_cursor_blink.ptr, &buffer );
	if (buffer  is 0) return 0;
	OS.g_object_get1 (settings, OS.gtk_cursor_blink_time.ptr, &buffer);
	if (buffer  is 0) return 500;
	/*
	* By experimentation, GTK application don't use the whole
	* blink cycle time.  Instead, they divide up the time, using
	* an effective blink rate of about 1/2 the total time.
	*/
	return buffer / 2;
}

/**
 * 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
 *
 * @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 getCursorControl () {
	checkDevice();
	int x, y;
	auto window = OS.gdk_window_at_pointer (&x, &y);
	if (window is null) return null;
    GtkWidget* handle;
	OS.gdk_window_get_user_data (window, cast(void**)&handle);
	if (handle is null) return null;
	do {
		Widget widget = getWidget (handle);
		if (widget !is null && (null !is cast(Control)widget)) {
			Control control = cast(Control) widget;
			if (control.isEnabled ()) return control;
		}
	} while ((handle = OS.gtk_widget_get_parent (handle)) !is null);
	return null;
}

bool filterEvent (Event event) {
	if (filterTable !is null) filterTable.sendEvent (event);
	return false;
}

bool filters (int eventType) {
	if (filterTable is null) return false;
	return filterTable.hooks (eventType);
}

private static extern(C) GdkFilterReturn filterProcFunc (GdkXEvent* xEvent, GdkEvent* gdkEvent, void* data) {
    auto disp = cast(Display)data;
    return disp.filterProcMeth(xEvent,gdkEvent);
}

GdkFilterReturn filterProcMeth (GdkXEvent* xEvent, GdkEvent* gdkEvent) {
//     /*
//     * Feature in GTK.  When button 4, 5, 6, or 7 is released, GTK
//     * does not deliver a corresponding GTK event.  Button 6 and 7
//     * are mapped to buttons 4 and 5 in SWT.  The fix is to change
//     * the button number of the event to a negative number so that
//     * it gets dispatched by GTK.  SWT has been modified to look
//     * for negative button numbers.
//     */
//     XButtonEvent* mouseEvent = cast(XButtonEvent*) xEvent;
//     if (mouseEvent.type is OS.ButtonRelease) {
//         switch (mouseEvent.button) {
//             case 6:
//             case 7:
//                 mouseEvent.button = -mouseEvent.button;
//                 break;
//         }
//     }
// 	Widget widget = getWidget (data);
// 	if (widget is null) return 0;
// 	return widget.filterProc (xEvent, gdkEvent, data);
return GdkFilterReturn.init;
}
//
// /**
//  * 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>
//  */
// public Point getCursorLocation () {
// 	checkDevice ();
// 	int [] x = new int [1], y = new int [1];
// 	OS.gdk_window_get_pointer (0, x, y, null);
// 	return new Point (x [0], y [0]);
// }
//
// /**
//  * Returns an array containing the recommended cursor sizes.
//  *
//  * @return the array of cursor sizes
//  *
//  * @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 3.0
//  */
// public Point [] getCursorSizes () {
// 	checkDevice ();
// 	return [new Point (16, 16), new Point (32, 32)];
// }
//
// /**
//  * 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)
//  */
// public Object getData (char[] key) {
// 	checkDevice ();
// 	if (key is null) error (SWT.ERROR_NULL_ARGUMENT);
// 	if (key ==/*eq*/ DISPATCH_EVENT_KEY) {
// 		return dispatchEvents;
// 	}
// 	if (keys is null) return null;
// 	for (int i=0; i<keys.length; i++) {
// 		if (keys [i] ==/*eq*/ key) return values [i];
// 	}
// 	return null;
// }
//
// /**
//  * 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)
//  */
// public Object getData () {
// 	checkDevice ();
// 	return data;
// }
//
// /**
//  * Returns a point whose x coordinate is the horizontal
//  * dots per inch of the display, and whose y coordinate
//  * is the vertical dots per inch of the display.
//  *
//  * @return the horizontal and vertical DPI
//  *
//  * @exception SWTException <ul>
//  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
//  * </ul>
//  */
// public Point getDPI () {
// 	checkDevice ();
// 	int widthMM = OS.gdk_screen_width_mm ();
// 	int width = OS.gdk_screen_width ();
// 	int dpi = Compatibility.round (254 * width, widthMM * 10);
// 	return new Point (dpi, dpi);
// }
//
// int /*long*/ gtk_fixed_get_type () {
// 	return fixed_type;
// }
//
// int /*long*/ gtk_cell_renderer_text_get_type () {
// 	return text_renderer_type;
// }
//
// int /*long*/ gtk_cell_renderer_pixbuf_get_type () {
// 	return pixbuf_renderer_type;
// }
//
// int /*long*/ gtk_cell_renderer_toggle_get_type () {
// 	return toggle_renderer_type;
// }
//
// /**
//  * Returns the default display. One is created (making the
//  * thread that invokes this method its user-interface thread)
//  * if it did not already exist.
//  *
//  * @return the default display
//  */
public static synchronized Display getDefault () {
	if (Default is null) Default = new Display ();
	return Default;
}
//
// /+static bool isValidClass (Class clazz) {
// //PROTING_TODO	char[] name = clazz.getName ();
// //PROTING_TODO	int index = name.lastIndexOf ('.');
// //PROTING_TODO	return name.substring (0, index + 1)==/*eq*/ PACKAGE_PREFIX;
//     return true;
// }+/
//
// /**
//  * 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 2.1
//  */
// public int getDismissalAlignment () {
// 	checkDevice ();
// 	return SWT.RIGHT;
// }
//
// /**
//  * 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>
//  */
// public int getDoubleClickTime () {
// 	checkDevice ();
// 	auto settings = OS.gtk_settings_get_default ();
// 	int [] buffer = new int [1];
// 	OS.g_object_get (settings, OS.gtk_double_click_time, buffer, 0);
// 	return buffer [0];
// }
//
// /**
//  * 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 ();
// 	if (focusControl !is null && !focusControl.isDisposed ()) {
// 		return focusControl;
// 	}
// 	if (activeShell is null) return null;
// 	auto shellHandle = activeShell.shellHandle;
// 	auto handle = OS.gtk_window_get_focus (shellHandle);
// 	if (handle is null) return null;
// 	do {
// 		Widget widget = getWidget (handle);
// 		if (widget !is null && (null !is cast(Control)widget)) {
// 			Control control = cast(Control) widget;
// 			return control.isEnabled () ? control : null;
// 		}
// 	} while ((handle = OS.gtk_widget_get_parent (handle)) !is null);
// 	return null;
// }
//
// /**
//  * 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 3.0
//  */
// public bool getHighContrast () {
// 	checkDevice ();
// 	return false;
// }
//
// public int getDepth () {
// 	checkDevice ();
// 	GdkVisual* visual = new GdkVisual ();
// 	memmove (visual, OS.gdk_visual_get_system());
// 	return visual.depth;
// }
//
// /**
//  * Returns the maximum allowed depth of icons on this display, in bits per pixel.
//  * On some platforms, this may be different than the actual depth of the display.
//  *
//  * @return the maximum icon depth
//  *
//  * @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#getDepth
//  */
// public int getIconDepth () {
// 	checkDevice ();
// 	return getDepth ();
// }
//
// /**
//  * Returns an array containing the recommended icon sizes.
//  *
//  * @return the array of icon sizes
//  *
//  * @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 Decorations#setImages(Image[])
//  *
//  * @since 3.0
//  */
// public Point [] getIconSizes () {
// 	checkDevice ();
// 	return [new Point (16, 16), new Point (32, 32)];
// }
//
// int getLastEventTime () {
// 	return lastEventTime;
// }
//
// int getMessageCount () {
// 	return synchronizer.getMessageCount ();
// }
//
// /**
//  * Returns the work area, an EWMH property to store the size
//  * and position of the screen not covered by dock and panel
//  * windows.  See http://freedesktop.org/Standards/wm-spec.
//  */
// Rectangle getWorkArea() {
// 	byte[] name = Converter.wcsToMbcs (null, "_NET_WORKAREA", true);
// 	auto atom = OS.gdk_atom_intern (name, true);
// 	if (atom is OS.GDK_NONE) return null;
// 	int /*long*/[] actualType = new int /*long*/[1];
// 	int[] actualFormat = new int[1];
// 	int[] actualLength = new int[1];
// 	int /*long*/[] data = new int /*long*/[1];
// 	if (!OS.gdk_property_get (OS.GDK_ROOT_PARENT (), atom, OS.GDK_NONE, 0, 16, 0, actualType, actualFormat, actualLength, data)) {
// 		return null;
// 	}
// 	Rectangle result = null;
// 	if (data [0] !is 0) {
// 		if (actualLength [0] is 16) {
// 			int values [] = new int [4];
// 			memmove (values, data[0], 16);
// 			result = new Rectangle (values [0],values [1],values [2],values [3]);
// 		} else if (actualLength [0] is 32) {
// 			long values [] = new long [4];
// 			memmove (values, data[0], 32);
// 			result = new Rectangle (cast(int)values [0],cast(int)values [1],cast(int)values [2],cast(int)values [3]);
// 		}
// 		OS.g_free (data [0]);
// 	}
// 	return result;
// }
//
// /**
//  * Returns an array of monitors attached to the device.
//  *
//  * @return the array of monitors
//  *
//  * @since 3.0
//  */
// public Monitor [] getMonitors () {
// 	checkDevice ();
// 	Monitor [] monitors = null;
// 	Rectangle workArea = getWorkArea();
// 	auto screen = OS.gdk_screen_get_default ();
// 	if (screen !is null) {
// 		int monitorCount = OS.gdk_screen_get_n_monitors (screen);
// 		if (monitorCount > 0) {
// 			monitors = new Monitor [monitorCount];
// 			GdkRectangle* dest = new GdkRectangle ();
// 			for (int i = 0; i < monitorCount; i++) {
// 				OS.gdk_screen_get_monitor_geometry (screen, i, dest);
// 				Monitor monitor = new Monitor ();
// 				monitor.handle = i;
// 				monitor.x = dest.x;
// 				monitor.y = dest.y;
// 				monitor.width = dest.width;
// 				monitor.height = dest.height;
// 				if (i is 0 && workArea !is null) {
// 					monitor.clientX = workArea.x;
// 					monitor.clientY = workArea.y;
// 					monitor.clientWidth = workArea.width;
// 					monitor.clientHeight = workArea.height;
// 				} else {
// 					monitor.clientX = monitor.x;
// 					monitor.clientY = monitor.y;
// 					monitor.clientWidth = monitor.width;
// 					monitor.clientHeight = monitor.height;
// 				}
// 				monitors [i] = monitor;
// 			}
// 		}
// 	}
// 	if (monitors is null) {
// 		/* No multimonitor support detected, default to one monitor */
// 		Monitor monitor = new Monitor ();
// 		Rectangle bounds = getBounds ();
// 		monitor.x = bounds.x;
// 		monitor.y = bounds.y;
// 		monitor.width = bounds.width;
// 		monitor.height = bounds.height;
// 		if (workArea !is null) {
// 			monitor.clientX = workArea.x;
// 			monitor.clientY = workArea.y;
// 			monitor.clientWidth = workArea.width;
// 			monitor.clientHeight = workArea.height;
// 		} else {
// 			monitor.clientX = monitor.x;
// 			monitor.clientY = monitor.y;
// 			monitor.clientWidth = monitor.width;
// 			monitor.clientHeight = monitor.height;
// 		}
// 		monitors = [ monitor ];
// 	}
// 	return monitors;
// }
//
// /**
//  * Returns the primary monitor for that device.
//  *
//  * @return the primary monitor
//  *
//  * @since 3.0
//  */
// public Monitor getPrimaryMonitor () {
// 	checkDevice ();
// 	Monitor [] monitors = getMonitors ();
// 	return monitors [0];
// }
//
// /**
//  * 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 ();
// 	int index = 0;
// 	Shell [] result = new Shell [16];
// 	for (int i = 0; i < widgetTable.length; i++) {
// 		Widget widget = widgetTable [i];
// 		if (widget !is null && (null !is cast(Shell)widget)) {
// 			int j = 0;
// 			while (j < index) {
// 				if (result [j] is widget) break;
// 				j++;
// 			}
// 			if (j is index) {
// 				if (index is result.length) {
// 					Shell [] newResult = new Shell [index + 16];
// 					System.arraycopy (result, 0, newResult, 0, index);
// 					result = newResult;
// 				}
// 				result [index++] = cast(Shell) widget;
// 			}
// 		}
// 	}
// 	if (index is result.length) return result;
// 	Shell [] newResult = new Shell [index];
// 	System.arraycopy (result, 0, newResult, 0, index);
// 	return newResult;
// }
//
// /**
//  * 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>
//  */
// public Thread getSyncThread () {
// 	if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
// 	return synchronizer.syncThread;
// }
//
// /**
//  * Returns the matching standard color for the given
//  * constant, which should be one of the color constants
//  * specified in class <code>SWT</code>. Any value other
//  * than one of the SWT color constants which is passed
//  * in will result in the color black. This color should
//  * not be free'd because it was allocated by the system,
//  * not the application.
//  *
//  * @param id the color constant
//  * @return the matching color
//  *
//  * @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
//  */
// public Color getSystemColor (int id) {
// 	checkDevice ();
// 	GdkColor gdkColor = null;
// 	switch (id) {
// 		case SWT.COLOR_INFO_FOREGROUND: 					gdkColor = COLOR_INFO_FOREGROUND; break;
// 		case SWT.COLOR_INFO_BACKGROUND: 					gdkColor = COLOR_INFO_BACKGROUND; break;
// 		case SWT.COLOR_TITLE_FOREGROUND:					gdkColor = COLOR_TITLE_FOREGROUND; break;
// 		case SWT.COLOR_TITLE_BACKGROUND:					gdkColor = COLOR_TITLE_BACKGROUND; break;
// 		case SWT.COLOR_TITLE_BACKGROUND_GRADIENT:			gdkColor = COLOR_TITLE_BACKGROUND_GRADIENT; break;
// 		case SWT.COLOR_TITLE_INACTIVE_FOREGROUND:			gdkColor = COLOR_TITLE_INACTIVE_FOREGROUND; break;
// 		case SWT.COLOR_TITLE_INACTIVE_BACKGROUND:			gdkColor = COLOR_TITLE_INACTIVE_BACKGROUND; break;
// 		case SWT.COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT:	gdkColor = COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT; break;
// 		case SWT.COLOR_WIDGET_DARK_SHADOW:					gdkColor = COLOR_WIDGET_DARK_SHADOW; break;
// 		case SWT.COLOR_WIDGET_NORMAL_SHADOW:				gdkColor = COLOR_WIDGET_NORMAL_SHADOW; break;
// 		case SWT.COLOR_WIDGET_LIGHT_SHADOW: 				gdkColor = COLOR_WIDGET_LIGHT_SHADOW; break;
// 		case SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW:				gdkColor = COLOR_WIDGET_HIGHLIGHT_SHADOW; break;
// 		case SWT.COLOR_WIDGET_BACKGROUND: 					gdkColor = COLOR_WIDGET_BACKGROUND; break;
// 		case SWT.COLOR_WIDGET_FOREGROUND: 					gdkColor = COLOR_WIDGET_FOREGROUND; break;
// 		case SWT.COLOR_WIDGET_BORDER: 						gdkColor = COLOR_WIDGET_BORDER; break;
// 		case SWT.COLOR_LIST_FOREGROUND: 					gdkColor = COLOR_LIST_FOREGROUND; break;
// 		case SWT.COLOR_LIST_BACKGROUND: 					gdkColor = COLOR_LIST_BACKGROUND; break;
// 		case SWT.COLOR_LIST_SELECTION: 						gdkColor = COLOR_LIST_SELECTION; break;
// 		case SWT.COLOR_LIST_SELECTION_TEXT: 				gdkColor = COLOR_LIST_SELECTION_TEXT; break;
// 		default:
// 			return super.getSystemColor (id);
// 	}
// 	if (gdkColor is null) return super.getSystemColor (SWT.COLOR_BLACK);
// 	return Color.gtk_new (this, gdkColor);
// }
//
// /**
//  * 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_APPSTARTING
//  * @see SWT#CURSOR_HELP
//  * @see SWT#CURSOR_SIZEALL
//  * @see SWT#CURSOR_SIZENESW
//  * @see SWT#CURSOR_SIZENS
//  * @see SWT#CURSOR_SIZENWSE
//  * @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_UPARROW
//  * @see SWT#CURSOR_IBEAM
//  * @see SWT#CURSOR_NO
//  * @see SWT#CURSOR_HAND
//  *
//  * @since 3.0
//  */
// public Cursor getSystemCursor (int id) {
// 	checkDevice ();
// 	if (!(0 <= id && id < cursors.length)) return null;
// 	if (cursors [id] is null) {
// 		cursors [id] = new Cursor (this, id);
// 	}
// 	return cursors [id];
// }
//
// /**
//  * 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
//  *
//  * @since 3.0
//  */
// public Image getSystemImage (int id) {
// 	checkDevice ();
// 	switch (id) {
// 		case SWT.ICON_ERROR:
// 			if (errorImage is null) {
// 				errorImage = createImage ("gtk-dialog-error");
// 			}
// 			return errorImage;
// 		case SWT.ICON_INFORMATION:
// 		case SWT.ICON_WORKING:
// 			if (infoImage is null) {
// 				infoImage = createImage ("gtk-dialog-info");
// 			}
// 			return infoImage;
// 		case SWT.ICON_QUESTION:
// 			if (questionImage is null) {
// 				questionImage = createImage ("gtk-dialog-question");
// 			}
// 			return questionImage;
// 		case SWT.ICON_WARNING:
// 			if (warningImage is null) {
// 				warningImage = createImage ("gtk-dialog-warning");
// 			}
// 			return warningImage;
// 	}
// 	return null;
// }
//
// void initializeSystemColors () {
// 	GdkColor gdkColor;
//
// 	/* Get Tooltip resources */
// 	auto tooltipShellHandle = OS.gtk_window_new (OS.GTK_WINDOW_POPUP);
// 	if (tooltipShellHandle is null) SWT.error (SWT.ERROR_NO_HANDLES);
// 	byte[] gtk_tooltips = Converter.wcsToMbcs (null, "gtk-tooltips", true);
// 	OS.gtk_widget_set_name (tooltipShellHandle, gtk_tooltips);
// 	OS.gtk_widget_realize (tooltipShellHandle);
// 	auto tooltipStyle = OS.gtk_widget_get_style (tooltipShellHandle);
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_fg (tooltipStyle, OS.GTK_STATE_NORMAL, gdkColor);
// 	COLOR_INFO_FOREGROUND = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_bg (tooltipStyle, OS.GTK_STATE_NORMAL, gdkColor);
// 	COLOR_INFO_BACKGROUND = gdkColor;
// 	OS.gtk_widget_destroy (tooltipShellHandle);
//
// 	/* Get Shell resources */
// 	auto style = OS.gtk_widget_get_style (shellHandle);
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_black (style, gdkColor);
// 	COLOR_WIDGET_DARK_SHADOW = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_dark (style, OS.GTK_STATE_NORMAL, gdkColor);
// 	COLOR_WIDGET_NORMAL_SHADOW = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_bg (style, OS.GTK_STATE_NORMAL, gdkColor);
// 	COLOR_WIDGET_LIGHT_SHADOW = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_light (style, OS.GTK_STATE_NORMAL, gdkColor);
// 	COLOR_WIDGET_HIGHLIGHT_SHADOW = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_fg (style, OS.GTK_STATE_NORMAL, gdkColor);
// 	COLOR_WIDGET_FOREGROUND = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_bg (style, OS.GTK_STATE_NORMAL, gdkColor);
// 	COLOR_WIDGET_BACKGROUND = gdkColor;
// 	//gdkColor = new GdkColor();
// 	//OS.gtk_style_get_text (style, OS.GTK_STATE_NORMAL, gdkColor);
// 	//COLOR_TEXT_FOREGROUND = gdkColor;
// 	//gdkColor = new GdkColor();
// 	//OS.gtk_style_get_base (style, OS.GTK_STATE_NORMAL, gdkColor);
// 	//COLOR_TEXT_BACKGROUND = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_text (style, OS.GTK_STATE_NORMAL, gdkColor);
// 	COLOR_LIST_FOREGROUND = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_base (style, OS.GTK_STATE_NORMAL, gdkColor);
// 	COLOR_LIST_BACKGROUND = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_text (style, OS.GTK_STATE_SELECTED, gdkColor);
// 	COLOR_LIST_SELECTION_TEXT = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_base (style, OS.GTK_STATE_SELECTED, gdkColor);
// 	COLOR_LIST_SELECTION = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_bg (style, OS.GTK_STATE_SELECTED, gdkColor);
// 	COLOR_TITLE_BACKGROUND = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_fg (style, OS.GTK_STATE_SELECTED, gdkColor);
// 	COLOR_TITLE_FOREGROUND = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_light (style, OS.GTK_STATE_SELECTED, gdkColor);
// 	COLOR_TITLE_BACKGROUND_GRADIENT = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_bg (style, OS.GTK_STATE_INSENSITIVE, gdkColor);
// 	COLOR_TITLE_INACTIVE_BACKGROUND = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_fg (style, OS.GTK_STATE_INSENSITIVE, gdkColor);
// 	COLOR_TITLE_INACTIVE_FOREGROUND = gdkColor;
// 	gdkColor = new GdkColor();
// 	OS.gtk_style_get_light (style, OS.GTK_STATE_INSENSITIVE, gdkColor);
// 	COLOR_TITLE_INACTIVE_BACKGROUND_GRADIENT = gdkColor;
// }
//
// /**
//  * Returns a reasonable font for applications to use.
//  * On some platforms, this will match the "default font"
//  * or "system font" if such can be found.  This font
//  * should not be free'd because it was allocated by the
//  * system, not the application.
//  * <p>
//  * Typically, applications which want the default look
//  * should simply not set the font on the widgets they
//  * create. Widgets are always created with the correct
//  * default font for the class of user-interface component
//  * they represent.
//  * </p>
//  *
//  * @return a font
//  *
//  * @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 Font getSystemFont () {
// 	checkDevice ();
// 	if (systemFont !is null) return systemFont;
// 	auto style = OS.gtk_widget_get_style (shellHandle);
// 	auto defaultFont = OS.pango_font_description_copy (OS.gtk_style_get_font_desc (style));
// 	return systemFont = Font.gtk_new (this, defaultFont);
// }
//
// /**
//  * 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 3.0
//  */
// public Tray getSystemTray () {
// 	checkDevice ();
// 	if (tray !is null) return tray;
// 	return tray = new Tray (this, SWT.NONE);
// }
//
// /**
//  * Returns the user-interface thread for the receiver.
//  *
//  * @return the receiver's user-interface thread
//  *
//  * @exception SWTException <ul>
//  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
//  * </ul>
//  */
// public Thread getThread () {
// 	if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
// 	return thread;
// }
//
Widget getWidget (GtkWidget* handle) {
// 	if (handle is null) return null;
// 	if (lastWidget !is null && lastHandle is handle) return lastWidget;
// 	auto index = OS.g_object_get_qdata (handle, SWT_OBJECT_INDEX) - 1;
// 	if (0 <= index && index < widgetTable.length) {
// 		lastHandle = handle;
// 		return lastWidget = widgetTable [cast(int)/*64*/index];
// 	}
	return null;
}

private static extern(C) int idleProcFunc (void* data) {
    Display display = cast(Display)data;
    return display.idleProcMeth();
}
private int idleProcMeth () {
// 	bool result = runAsyncMessages (false);
// 	if (!result) {
// 		synchronized (idleLock) {
// 			idleHandle = 0;
// 		}
// 	}
// 	return result ? 1 : 0;
    return 0;
}
//
// /**
//  * Initializes any internal resources needed by the
//  * device.
//  * <p>
//  * This method is called after <code>create</code>.
//  * </p>
//  *
//  * @see #create
//  */
// protected void init () {
// 	super.init ();
// 	initializeCallbacks ();
// 	initializeSystemColors ();
// 	initializeSystemSettings ();
// 	initializeWidgetTable ();
// 	initializeWindowManager ();
// }
//
// void initializeCallbacks () {
// 	closures = new int /*long*/ [Widget.LAST_SIGNAL];
// 	signalIds = new int [Widget.LAST_SIGNAL];
//
// 	/* Cache signals for GtkWidget */
// 	signalIds [Widget.BUTTON_PRESS_EVENT] = OS.g_signal_lookup (OS.button_press_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.BUTTON_RELEASE_EVENT] = OS.g_signal_lookup (OS.button_release_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.CONFIGURE_EVENT] = OS.g_signal_lookup (OS.configure_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.DELETE_EVENT] = OS.g_signal_lookup (OS.delete_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.ENTER_NOTIFY_EVENT] = OS.g_signal_lookup (OS.enter_notify_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.EVENT] = OS.g_signal_lookup (OS.event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.EVENT_AFTER] = OS.g_signal_lookup (OS.event_after, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.EXPOSE_EVENT] = OS.g_signal_lookup (OS.expose_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.FOCUS] = OS.g_signal_lookup (OS.focus, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.FOCUS_IN_EVENT] = OS.g_signal_lookup (OS.focus_in_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.FOCUS_OUT_EVENT] = OS.g_signal_lookup (OS.focus_out_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.GRAB_FOCUS] = OS.g_signal_lookup (OS.grab_focus, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.HIDE] = OS.g_signal_lookup (OS.hide, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.KEY_PRESS_EVENT] = OS.g_signal_lookup (OS.key_press_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.KEY_RELEASE_EVENT] = OS.g_signal_lookup (OS.key_release_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.LEAVE_NOTIFY_EVENT] = OS.g_signal_lookup (OS.leave_notify_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.MAP] = OS.g_signal_lookup (OS.map, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.MAP_EVENT] = OS.g_signal_lookup (OS.map_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.MNEMONIC_ACTIVATE] = OS.g_signal_lookup (OS.mnemonic_activate, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.MOTION_NOTIFY_EVENT] = OS.g_signal_lookup (OS.motion_notify_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.POPUP_MENU] = OS.g_signal_lookup (OS.popup_menu, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.REALIZE] = OS.g_signal_lookup (OS.realize, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.SCROLL_EVENT] = OS.g_signal_lookup (OS.scroll_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.SHOW] = OS.g_signal_lookup (OS.show, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.SHOW_HELP] = OS.g_signal_lookup (OS.show_help, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.SIZE_ALLOCATE] = OS.g_signal_lookup (OS.size_allocate, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.STYLE_SET] = OS.g_signal_lookup (OS.style_set, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.UNMAP] = OS.g_signal_lookup (OS.unmap, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.UNMAP_EVENT] = OS.g_signal_lookup (OS.unmap_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.UNREALIZE] = OS.g_signal_lookup (OS.realize, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.VISIBILITY_NOTIFY_EVENT] = OS.g_signal_lookup (OS.visibility_notify_event, OS.GTK_TYPE_WIDGET ());
// 	signalIds [Widget.WINDOW_STATE_EVENT] = OS.g_signal_lookup (OS.window_state_event, OS.GTK_TYPE_WIDGET ());
//
// 	windowCallback2 = new void*/*Callback*/ (this, "windowProc", 2);
// 	windowProc2 = windowCallback2.getAddress ();
// 	if (windowProc2 is null) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	closures [Widget.ACTIVATE] = OS.g_cclosure_new (windowProc2, Widget.ACTIVATE, 0);
// 	closures [Widget.ACTIVATE_INVERSE] = OS.g_cclosure_new (windowProc2, Widget.ACTIVATE_INVERSE, 0);
// 	closures [Widget.CHANGED] = OS.g_cclosure_new (windowProc2, Widget.CHANGED, 0);
// 	closures [Widget.CLICKED] = OS.g_cclosure_new (windowProc2, Widget.CLICKED, 0);
// 	closures [Widget.DAY_SELECTED] = OS.g_cclosure_new (windowProc2, Widget.DAY_SELECTED, 0);
// 	closures [Widget.HIDE] = OS.g_cclosure_new (windowProc2, Widget.HIDE, 0);
// 	closures [Widget.GRAB_FOCUS] = OS.g_cclosure_new (windowProc2, Widget.GRAB_FOCUS, 0);
// 	closures [Widget.MAP] = OS.g_cclosure_new (windowProc2, Widget.MAP, 0);
// 	closures [Widget.MONTH_CHANGED] = OS.g_cclosure_new (windowProc2, Widget.MONTH_CHANGED, 0);
// 	closures [Widget.OUTPUT] = OS.g_cclosure_new (windowProc2, Widget.OUTPUT, 0);
// 	closures [Widget.POPUP_MENU] = OS.g_cclosure_new (windowProc2, Widget.POPUP_MENU, 0);
// 	closures [Widget.PREEDIT_CHANGED] = OS.g_cclosure_new (windowProc2, Widget.PREEDIT_CHANGED, 0);
// 	closures [Widget.REALIZE] = OS.g_cclosure_new (windowProc2, Widget.REALIZE, 0);
// 	closures [Widget.SELECT] = OS.g_cclosure_new (windowProc2, Widget.SELECT, 0);
// 	closures [Widget.SHOW] = OS.g_cclosure_new (windowProc2, Widget.SHOW, 0);
// 	closures [Widget.VALUE_CHANGED] = OS.g_cclosure_new (windowProc2, Widget.VALUE_CHANGED, 0);
// 	closures [Widget.UNMAP] = OS.g_cclosure_new (windowProc2, Widget.UNMAP, 0);
// 	closures [Widget.UNREALIZE] = OS.g_cclosure_new (windowProc2, Widget.UNREALIZE, 0);
//
// 	windowCallback3 = new void*/*Callback*/ (this, "windowProc", 3);
// 	windowProc3 = windowCallback3.getAddress ();
// 	if (windowProc3 is null) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	closures [Widget.BUTTON_PRESS_EVENT] = OS.g_cclosure_new (windowProc3, Widget.BUTTON_PRESS_EVENT, 0);
// 	closures [Widget.BUTTON_PRESS_EVENT_INVERSE] = OS.g_cclosure_new (windowProc3, Widget.BUTTON_PRESS_EVENT_INVERSE, 0);
// 	closures [Widget.BUTTON_RELEASE_EVENT] = OS.g_cclosure_new (windowProc3, Widget.BUTTON_RELEASE_EVENT, 0);
// 	closures [Widget.BUTTON_RELEASE_EVENT_INVERSE] = OS.g_cclosure_new (windowProc3, Widget.BUTTON_RELEASE_EVENT_INVERSE, 0);
// 	closures [Widget.COMMIT] = OS.g_cclosure_new (windowProc3, Widget.COMMIT, 0);
// 	closures [Widget.CONFIGURE_EVENT] = OS.g_cclosure_new (windowProc3, Widget.CONFIGURE_EVENT, 0);
// 	closures [Widget.DELETE_EVENT] = OS.g_cclosure_new (windowProc3, Widget.DELETE_EVENT, 0);
// 	closures [Widget.ENTER_NOTIFY_EVENT] = OS.g_cclosure_new (windowProc3, Widget.ENTER_NOTIFY_EVENT, 0);
// 	closures [Widget.EVENT] = OS.g_cclosure_new (windowProc3, Widget.EVENT, 0);
// 	closures [Widget.EVENT_AFTER] = OS.g_cclosure_new (windowProc3, Widget.EVENT_AFTER, 0);
// 	closures [Widget.EXPOSE_EVENT] = OS.g_cclosure_new (windowProc3, Widget.EXPOSE_EVENT, 0);
// 	closures [Widget.EXPOSE_EVENT_INVERSE] = OS.g_cclosure_new (windowProc3, Widget.EXPOSE_EVENT_INVERSE, 0);
// 	closures [Widget.FOCUS] = OS.g_cclosure_new (windowProc3, Widget.FOCUS, 0);
// 	closures [Widget.FOCUS_IN_EVENT] = OS.g_cclosure_new (windowProc3, Widget.FOCUS_IN_EVENT, 0);
// 	closures [Widget.FOCUS_OUT_EVENT] = OS.g_cclosure_new (windowProc3, Widget.FOCUS_OUT_EVENT, 0);
// 	closures [Widget.KEY_PRESS_EVENT] = OS.g_cclosure_new (windowProc3, Widget.KEY_PRESS_EVENT, 0);
// 	closures [Widget.KEY_RELEASE_EVENT] = OS.g_cclosure_new (windowProc3, Widget.KEY_RELEASE_EVENT, 0);
// 	closures [Widget.INPUT] = OS.g_cclosure_new (windowProc3, Widget.INPUT, 0);
// 	closures [Widget.LEAVE_NOTIFY_EVENT] = OS.g_cclosure_new (windowProc3, Widget.LEAVE_NOTIFY_EVENT, 0);
// 	closures [Widget.MAP_EVENT] = OS.g_cclosure_new (windowProc3, Widget.MAP_EVENT, 0);
// 	closures [Widget.MNEMONIC_ACTIVATE] = OS.g_cclosure_new (windowProc3, Widget.MNEMONIC_ACTIVATE, 0);
// 	closures [Widget.MOTION_NOTIFY_EVENT] = OS.g_cclosure_new (windowProc3, Widget.MOTION_NOTIFY_EVENT, 0);
// 	closures [Widget.MOTION_NOTIFY_EVENT_INVERSE] = OS.g_cclosure_new (windowProc3, Widget.MOTION_NOTIFY_EVENT_INVERSE, 0);
// 	closures [Widget.MOVE_FOCUS] = OS.g_cclosure_new (windowProc3, Widget.MOVE_FOCUS, 0);
// 	closures [Widget.SCROLL_EVENT] = OS.g_cclosure_new (windowProc3, Widget.SCROLL_EVENT, 0);
// 	closures [Widget.SHOW_HELP] = OS.g_cclosure_new (windowProc3, Widget.SHOW_HELP, 0);
// 	closures [Widget.SIZE_ALLOCATE] = OS.g_cclosure_new (windowProc3, Widget.SIZE_ALLOCATE, 0);
// 	closures [Widget.STYLE_SET] = OS.g_cclosure_new (windowProc3, Widget.STYLE_SET, 0);
// 	closures [Widget.TOGGLED] = OS.g_cclosure_new (windowProc3, Widget.TOGGLED, 0);
// 	closures [Widget.UNMAP_EVENT] = OS.g_cclosure_new (windowProc3, Widget.UNMAP_EVENT, 0);
// 	closures [Widget.VISIBILITY_NOTIFY_EVENT] = OS.g_cclosure_new (windowProc3, Widget.VISIBILITY_NOTIFY_EVENT, 0);
// 	closures [Widget.WINDOW_STATE_EVENT] = OS.g_cclosure_new (windowProc3, Widget.WINDOW_STATE_EVENT, 0);
//
// 	windowCallback4 = new void*/*Callback*/ (this, "windowProc", 4);
// 	windowProc4 = windowCallback4.getAddress ();
// 	if (windowProc4 is null) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	closures [Widget.DELETE_RANGE] = OS.g_cclosure_new (windowProc4, Widget.DELETE_RANGE, 0);
// 	closures [Widget.DELETE_TEXT] = OS.g_cclosure_new (windowProc4, Widget.DELETE_TEXT, 0);
// 	closures [Widget.ROW_ACTIVATED] = OS.g_cclosure_new (windowProc4, Widget.ROW_ACTIVATED, 0);
// 	closures [Widget.SCROLL_CHILD] = OS.g_cclosure_new (windowProc4, Widget.SCROLL_CHILD, 0);
// 	closures [Widget.SWITCH_PAGE] = OS.g_cclosure_new (windowProc4, Widget.SWITCH_PAGE, 0);
// 	closures [Widget.TEST_COLLAPSE_ROW] = OS.g_cclosure_new (windowProc4, Widget.TEST_COLLAPSE_ROW, 0);
// 	closures [Widget.TEST_EXPAND_ROW] = OS.g_cclosure_new (windowProc4, Widget.TEST_EXPAND_ROW, 0);
//
// 	windowCallback5 = new void*/*Callback*/ (this, "windowProc", 5);
// 	windowProc5 = windowCallback5.getAddress ();
// 	if (windowProc5 is null) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	closures [Widget.CHANGE_VALUE] = OS.g_cclosure_new (windowProc5, Widget.CHANGE_VALUE, 0);
// 	closures [Widget.EXPAND_COLLAPSE_CURSOR_ROW] = OS.g_cclosure_new (windowProc5, Widget.EXPAND_COLLAPSE_CURSOR_ROW, 0);
// 	closures [Widget.INSERT_TEXT] = OS.g_cclosure_new (windowProc5, Widget.INSERT_TEXT, 0);
// 	closures [Widget.TEXT_BUFFER_INSERT_TEXT] = OS.g_cclosure_new (windowProc5, Widget.TEXT_BUFFER_INSERT_TEXT, 0);
//
// 	for (int i = 0; i < Widget.LAST_SIGNAL; i++) {
// 		if (closures [i] !is null) OS.g_closure_ref (closures [i]);
// 	}
//
// 	timerCallback = new void*/*Callback*/ (this, "timerProc", 1);
// 	timerProc = timerCallback.getAddress ();
// 	if (timerProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	windowTimerCallback = new void*/*Callback*/ (this, "windowTimerProc", 1);
// 	windowTimerProc = windowTimerCallback.getAddress ();
// 	if (windowTimerProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	mouseHoverCallback = new void*/*Callback*/ (this, "mouseHoverProc", 1);
// 	mouseHoverProc = mouseHoverCallback.getAddress ();
// 	if (mouseHoverProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	caretCallback = new void*/*Callback*/(this, "caretProc", 1);
// 	caretProc = caretCallback.getAddress();
// 	if (caretProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	menuPositionCallback = new void*/*Callback*/(this, "menuPositionProc", 5);
// 	menuPositionProc = menuPositionCallback.getAddress();
// 	if (menuPositionProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	sizeAllocateCallback = new void*/*Callback*/(this, "sizeAllocateProc", 3);
// 	sizeAllocateProc = sizeAllocateCallback.getAddress();
// 	if (sizeAllocateProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	sizeRequestCallback = new void*/*Callback*/(this, "sizeRequestProc", 3);
// 	sizeRequestProc = sizeRequestCallback.getAddress();
// 	if (sizeRequestProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	shellMapCallback = new void*/*Callback*/(this, "shellMapProc", 3);
// 	shellMapProc = shellMapCallback.getAddress();
// 	if (shellMapProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	shellMapProcClosure = OS.g_cclosure_new (shellMapProc, 0, 0);
// 	OS.g_closure_ref (shellMapProcClosure);
//
// 	treeSelectionCallback = new void*/*Callback*/(this, "treeSelectionProc", 4);
// 	treeSelectionProc = treeSelectionCallback.getAddress();
// 	if (treeSelectionProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	cellDataCallback = new void*/*Callback*/ (this, "cellDataProc", 5);
// 	cellDataProcFld = cellDataCallback.getAddress ();
// 	if (cellDataProcFld is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	setDirectionCallback = new void*/*Callback*/ (this, "setDirectionProc", 2);
// 	setDirectionProc = setDirectionCallback.getAddress ();
// 	if (setDirectionProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	allChildrenCallback = new void*/*Callback*/ (this, "allChildrenProc", 2);
// 	allChildrenProc = allChildrenCallback.getAddress ();
// 	if (allChildrenProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	checkIfEventCallback = new void*/*Callback*/ (this, "checkIfEventProc", 3);
// 	checkIfEventProc = checkIfEventCallback.getAddress ();
// 	if (checkIfEventProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
//
// 	idleCallback = new void*/*Callback*/ (this, "idleProc", 1);
// 	idleProc = idleCallback.getAddress ();
// 	if (idleProc is null) error (SWT.ERROR_NO_MORE_CALLBACKS);
// }
//
// void initializeSystemSettings () {
// 	styleSetCallback = new void*/*Callback*/ (this, "styleSetProc", 3);
// 	styleSetProc = styleSetCallback.getAddress ();
// 	if (styleSetProc is null) SWT.error (SWT.ERROR_NO_MORE_CALLBACKS);
// 	OS.g_signal_connect (shellHandle, OS.style_set, styleSetProc, 0);
//
// 	/*
// 	* Feature in GTK.  Despite the fact that the
// 	* gtk-entry-select-on-focus property is a global
// 	* setting, it is initialized when the GtkEntry
// 	* is initialized.  This means that it cannot be
// 	* accessed before a GtkEntry is created.  The
// 	* fix is to for the initializaion by creating
// 	* a temporary GtkEntry.
// 	*/
// 	auto entry = OS.gtk_entry_new ();
// 	OS.gtk_widget_destroy (entry);
// 	int [] buffer2 = new int [1];
// 	auto settings = OS.gtk_settings_get_default ();
// 	OS.g_object_get (settings, OS.gtk_entry_select_on_focus, buffer2, 0);
// 	entrySelectOnFocus = buffer2 [0] !is 0;
// }
//
// void initializeWidgetTable () {
// 	indexTable = new int [GROW_SIZE];
// 	widgetTable = new Widget [GROW_SIZE];
// 	for (int i=0; i<GROW_SIZE-1; i++) indexTable [i] = i + 1;
// 	indexTable [GROW_SIZE - 1] = -1;
// }
//
// void initializeWindowManager () {
// 	/* Get the window manager name */
// 	windowManager = "";
// 	if (OS.GTK_VERSION >= OS.VERSION (2, 2, 0)) {
// 		auto screen = OS.gdk_screen_get_default ();
// 		if (screen !is null) {
// 			auto ptr2 = OS.gdk_x11_screen_get_window_manager_name (screen);
// 			if (ptr2 !is null) {
// 				int length = OS.strlen (ptr2);
// 				if (length > 0) {
// 					byte [] buffer2 = new byte [length];
// 					memmove (buffer2, ptr2, length);
// 					windowManager = new char[] (Converter.mbcsToWcs (null, buffer2));
// 				}
// 			}
// 		}
// 	}
// }
//
// /**
//  * Invokes platform specific functionality to dispose a GC handle.
//  * <p>
//  * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
//  * API for <code>Display</code>. It is marked public only so that it
//  * can be shared within the packages provided by SWT. It is not
//  * available on all platforms, and should never be called from
//  * application code.
//  * </p>
//  *
//  * @param hDC the platform specific GC handle
//  * @param data the platform specific GC data
//  */
public void internal_dispose_GC (GdkGC* gdkGC, GCData data) {
// 	OS.g_object_unref (gdkGC);
}
//
// /**
//  * Invokes platform specific functionality to allocate a new GC handle.
//  * <p>
//  * <b>IMPORTANT:</b> This method is <em>not</em> part of the public
//  * API for <code>Display</code>. It is marked public only so that it
//  * can be shared within the packages provided by SWT. It is not
//  * available on all platforms, and should never be called from
//  * application code.
//  * </p>
//  *
//  * @param data the platform specific GC data
//  * @return the platform specific GC handle
//  *
//  * @exception SWTException <ul>
//  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
//  * </ul>
//  * @exception SWTError <ul>
//  *    <li>ERROR_NO_HANDLES if a handle could not be obtained for gc creation</li>
//  * </ul>
//  */
public GdkGC* internal_new_GC (GCData data) {
// 	if (isDisposed()) SWT.error(SWT.ERROR_DEVICE_DISPOSED);
// 	auto root = OS.GDK_ROOT_PARENT ();
// 	auto gdkGC = OS.gdk_gc_new (root);
// 	if (gdkGC is null) SWT.error (SWT.ERROR_NO_HANDLES);
// 	OS.gdk_gc_set_subwindow (gdkGC, OS.GDK_INCLUDE_INFERIORS);
// 	if (data !is null) {
// 		int mask = SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
// 		if ((data.style & mask) is 0) {
// 			data.style |= SWT.LEFT_TO_RIGHT;
// 		}
// 		data.device = this;
// 		data.drawable = root;
// 		data.background = getSystemColor (SWT.COLOR_WHITE).handle;
// 		data.foreground = getSystemColor (SWT.COLOR_BLACK).handle;
// 		data.font = getSystemFont ().handle;
// 	}
//     return gdkGC;
    return null;
}
//
bool isValidThread () {
	return thread is Thread.getThis ();
}
//
// /**
//  * 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>
//  *
//  * @since 2.1.2
//  */
// public Point map (Control from, Control to, Point point) {
// 	checkDevice ();
// 	if (point is null) 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>
//  *
//  * @since 2.1.2
//  */
// public Point map (Control from, Control to, int x, int y) {
// 	checkDevice ();
// 	if (from !is null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
// 	if (to !is null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
// 	Point point = new Point (x, y);
// 	if (from is to) return point;
// 	if (from !is null) {
// 		auto window = from.eventWindow ();
// 		int [] origin_x = new int [1], origin_y = new int [1];
// 		OS.gdk_window_get_origin (window, origin_x, origin_y);
// 		point.x += origin_x [0];
// 		point.y += origin_y [0];
// 	}
// 	if (to !is null) {
// 		auto window = to.eventWindow ();
// 		int [] origin_x = new int [1], origin_y = new int [1];
// 		OS.gdk_window_get_origin (window, origin_x, origin_y);
// 		point.x -= origin_x [0];
// 		point.y -= origin_y [0];
// 	}
// 	return point;
// }
//
// /**
//  * 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>
//  *
//  * @since 2.1.2
//  */
// public Rectangle map (Control from, Control to, Rectangle rectangle) {
// 	checkDevice();
// 	if (rectangle is null) error (SWT.ERROR_NULL_ARGUMENT);
// 	return map (from, to, rectangle.x, rectangle.y, rectangle.width, rectangle.height);
// }
//
// static char mbcsToWcs (char ch) {
// 	int key = ch & 0xFFFF;
// 	if (key <= 0x7F) return ch;
// 	byte [] buffer;
// 	if (key <= 0xFF) {
// 		buffer = new byte [1];
// 		buffer [0] = cast(byte) key;
// 	} else {
// 		buffer = new byte [2];
// 		buffer [0] = cast(byte) ((key >> 8) & 0xFF);
// 		buffer [1] = cast(byte) (key & 0xFF);
// 	}
// 	char [] result = Converter.mbcsToWcs (null, buffer);
// 	if (result.length is 0) return 0;
// 	return result [0];
// }
//
// int /*long*/ menuPositionProcMeth (int /*long*/ menu, int /*long*/ x, int /*long*/ y, int /*long*/ push_in, int /*long*/ user_data) {
// 	Widget widget = getWidget (menu);
// 	if (widget is null) return 0;
// 	return widget.menuPositionProc (menu, x, y, push_in, user_data);
// }
//
// /**
//  * 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>
//  *
//  * @since 2.1.2
//  */
// public Rectangle map (Control from, Control to, int x, int y, int width, int height) {
// 	checkDevice();
// 	if (from !is null && from.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
// 	if (to !is null && to.isDisposed()) error (SWT.ERROR_INVALID_ARGUMENT);
// 	Rectangle rect = new Rectangle (x, y, width, height);
// 	if (from is to) return rect;
// 	if (from !is null) {
// 		auto window = from.eventWindow ();
// 		int [] origin_x = new int [1], origin_y = new int [1];
// 		OS.gdk_window_get_origin (window, origin_x, origin_y);
// 		rect.x += origin_x [0];
// 		rect.y += origin_y [0];
// 	}
// 	if (to !is null) {
// 		auto window = to.eventWindow ();
// 		int [] origin_x = new int [1], origin_y = new int [1];
// 		OS.gdk_window_get_origin (window, origin_x, origin_y);
// 		rect.x -= origin_x [0];
// 		rect.y -= origin_y [0];
// 	}
// 	return rect;
// }
//
// private extern(C) int mouseHoverProcMeth (void* handle) {
// }
//
// int /*long*/ mouseHoverProcMeth (int /*long*/ handle) {
// 	Widget widget = getWidget (handle);
// 	if (widget is null) return 0;
// 	return widget.hoverProc (handle);
// }
//
// /**
//  * Generate a low level system event.
//  *
//  * <code>post</code> is used to generate low level keyboard
//  * and mouse events. The intent is to enable automated UI
//  * testing by simulating the input from the user.  Most
//  * SWT applications should never need to call this method.
//  * <p>
//  * Note that this operation can fail when the operating system
//  * fails to generate the event for any reason.  For example,
//  * this can happen when there is no such key or mouse button
//  * or when the system event queue is full.
//  * </p>
//  * <p>
//  * <b>Event Types:</b>
//  * <p>KeyDown, KeyUp
//  * <p>The following fields in the <code>Event</code> apply:
//  * <ul>
//  * <li>(in) type KeyDown or KeyUp</li>
//  * <p> Either one of:
//  * <li>(in) character a character that corresponds to a keyboard key</li>
//  * <li>(in) keyCode the key code of the key that was typed,
//  *          as defined by the key code constants in class <code>SWT</code></li>
//  * </ul>
//  * <p>MouseDown, MouseUp</p>
//  * <p>The following fields in the <code>Event</code> apply:
//  * <ul>
//  * <li>(in) type MouseDown or MouseUp
//  * <li>(in) button the button that is pressed or released
//  * </ul>
//  * <p>MouseMove</p>
//  * <p>The following fields in the <code>Event</code> apply:
//  * <ul>
//  * <li>(in) type MouseMove
//  * <li>(in) x the x coordinate to move the mouse pointer to in screen coordinates
//  * <li>(in) y the y coordinate to move the mouse pointer to in screen coordinates
//  * </ul>
//  * </dl>
//  *
//  * @param event the event to be generated
//  *
//  * @return true if the event was generated or false otherwise
//  *
//  * @exception IllegalArgumentException <ul>
//  *    <li>ERROR_NULL_ARGUMENT - if the event is null</li>
//  * </ul>
//  * @exception SWTException <ul>
//  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
//  * </ul>
//  *
//  * @since 3.0
//  *
//  */
// public bool post (Event event) {
// 	if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
// 	if (event is null) error (SWT.ERROR_NULL_ARGUMENT);
// 	if (!OS.GDK_WINDOWING_X11()) return false;
// 	auto xDisplay = OS.GDK_DISPLAY ();
// 	int type = event.type;
// 	switch (type) {
// 		case SWT.KeyDown:
// 		case SWT.KeyUp: {
// 			int keyCode = 0;
// 			auto keysym = untranslateKey (event.keyCode);
// 			if (keysym !is 0) keyCode = OS.XKeysymToKeycode (xDisplay, keysym);
// 			if (keyCode is 0) {
// 				char key = event.character;
// 				switch (key) {
// 					case SWT.BS: keysym = OS.GDK_BackSpace; break;
// 					case SWT.CR: keysym = OS.GDK_Return; break;
// 					case SWT.DEL: keysym = OS.GDK_Delete; break;
// 					case SWT.ESC: keysym = OS.GDK_Escape; break;
// 					case SWT.TAB: keysym = OS.GDK_Tab; break;
// 					case SWT.LF: keysym = OS.GDK_Linefeed; break;
// 					default:
// 						keysym = wcsToMbcs (key);
// 				}
// 				keyCode = OS.XKeysymToKeycode (xDisplay, keysym);
// 				if (keyCode is 0) return false;
// 			}
// 			OS.XTestFakeKeyEvent (xDisplay, keyCode, type is SWT.KeyDown, 0);
// 			return true;
// 		}
// 		case SWT.MouseDown:
// 		case SWT.MouseMove:
// 		case SWT.MouseUp: {
// 			if (type is SWT.MouseMove) {
// 				OS.XTestFakeMotionEvent (xDisplay, -1, event.x, event.y, 0);
// 			} else {
// 				int button = event.button;
// 				switch (button) {
// 					case 1:
// 					case 2:
// 					case 3:	break;
// 					case 4: button = 6;	break;
// 					case 5: button = 7;	break;
// 					default: return false;
// 				}
// 				OS.XTestFakeButtonEvent (xDisplay, button, type is SWT.MouseDown, 0);
// 			}
// 			return true;
// 		}
// 		/*
// 		* This code is intentionally commented. After posting a
// 		* mouse wheel event the system may respond unpredictably
// 		* to subsequent mouse actions.
// 		*/
// //		case SWT.MouseWheel: {
// //			if (event.count is 0) return false;
// //			int button = event.count < 0 ? 5 : 4;
// //			OS.XTestFakeButtonEvent (xDisplay, button, type is SWT.MouseWheel, 0);
// //		}
// 	}
// 	return false;
// }
//
// void postEvent (Event event) {
// 	/*
// 	* Place the event at the end of the event queue.
// 	* This code is always called in the Display's
// 	* thread so it must be re-enterant but does not
// 	* need to be synchronized.
// 	*/
// 	if (eventQueue is null) eventQueue = new Event [4];
// 	int index = 0;
// 	int length = eventQueue.length;
// 	while (index < length) {
// 		if (eventQueue [index] is null) break;
// 		index++;
// 	}
// 	if (index is length) {
// 		Event [] newQueue = new Event [length + 4];
// 		System.arraycopy (eventQueue, 0, newQueue, 0, length);
// 		eventQueue = newQueue;
// 	}
// 	eventQueue [index] = event;
// }
//
void putGdkEvents () {
// 	if (gdkEventCount !is 0) {
// 		for (int i = 0; i < gdkEventCount; i++) {
// 			auto event = gdkEvents [i];
// 			Widget widget = gdkEventWidgets [i];
// 			if (widget is null || !widget.isDisposed ()) {
// 				OS.gdk_event_put (event);
// 			}
// 			OS.gdk_event_free (event);
// 			gdkEvents [i] = 0;
// 			gdkEventWidgets [i] = null;
// 		}
// 		gdkEventCount = 0;
// 	}
}

// /**
//  * 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
//  */
// public bool readAndDispatch () {
// 	checkDevice ();
// 	bool events = false;
// 	events |= runSettings ();
// 	events |= runPopups ();
// 	events |= OS.g_main_context_iteration (0, false);
// 	if (events) {
// 		runDeferredEvents ();
// 		return true;
// 	}
// 	return runAsyncMessages (false);
// }
//
synchronized void register () {
	for (int i=0; i<Displays.length; i++) {
		if (Displays [i] is null) {
			Displays [i] = this;
			return;
		}
	}
	Display [] newDisplays = new Display [Displays.length + 4];
	System.arraycopy (Displays, 0, newDisplays, 0, Displays.length);
	newDisplays [Displays.length] = this;
	Displays = newDisplays;
}

// /**
//  * Releases any internal resources back to the operating
//  * system and clears all fields except the device handle.
//  * <p>
//  * Disposes all shells which are currently open on the display.
//  * After this method has been invoked, all related related shells
//  * will answer <code>true</code> when sent the message
//  * <code>isDisposed()</code>.
//  * </p><p>
//  * When a device is destroyed, resources that were acquired
//  * on behalf of the programmer need to be returned to the
//  * operating system.  For example, if the device allocated a
//  * font to be used as the system font, this font would be
//  * freed in <code>release</code>.  Also,to assist the garbage
//  * collector and minimize the amount of memory that is not
//  * reclaimed when the programmer keeps a reference to a
//  * disposed device, all fields except the handle are zero'd.
//  * The handle is needed by <code>destroy</code>.
//  * </p>
//  * This method is called before <code>destroy</code>.
//  *
//  * @see Device#dispose
//  * @see #destroy
//  */
// protected void release () {
// 	sendEvent (SWT.Dispose, new Event ());
// 	Shell [] shells = getShells ();
// 	for (int i=0; i<shells.length; i++) {
// 		Shell shell = shells [i];
// 		if (!shell.isDisposed ())  shell.dispose ();
// 	}
// 	if (tray !is null) tray.dispose ();
// 	tray = null;
// 	while (readAndDispatch ()) {}
// 	if (disposeList !is null) {
// 		for (int i=0; i<disposeList.length; i++) {
// 			if (disposeList [i] !is null) disposeList [i].run ();
// 		}
// 	}
// 	disposeList = null;
// 	synchronizer.releaseSynchronizer ();
// 	synchronizer = null;
// 	releaseDisplay ();
// 	super.release ();
// }
//
// void releaseDisplay () {
// 	windowCallback2.dispose ();  windowCallback2 = null;
// 	windowCallback3.dispose ();  windowCallback3 = null;
// 	windowCallback4.dispose ();  windowCallback4 = null;
// 	windowCallback5.dispose ();  windowCallback5 = null;
// 	windowProc2 = windowProc3 = windowProc4 = windowProc5 = 0;
//
// 	/* Dispose xfilter callback */
// 	filterCallback.dispose(); filterCallback = null;
// 	filterProc = 0;
//
// 	/* Dispose checkIfEvent callback */
// 	checkIfEventCallback.dispose(); checkIfEventCallback = null;
// 	checkIfEventProc = 0;
//
// 	/* Dispose preedit window */
// 	if (preeditWindow !is null) OS.gtk_widget_destroy (preeditWindow);
// 	imControl = null;
//
// 	/* Dispose the menu callback */
// 	menuPositionCallback.dispose (); menuPositionCallback = null;
// 	menuPositionProc = 0;
//
// 	/* Dispose the tooltip map callback */
// 	sizeAllocateCallback.dispose (); sizeAllocateCallback = null;
// 	sizeAllocateProc = 0;
// 	sizeRequestCallback.dispose (); sizeRequestCallback = null;
// 	sizeRequestProc = 0;
//
// 	/* Dispose the shell map callback */
// 	shellMapCallback.dispose (); shellMapCallback = null;
// 	shellMapProc = 0;
//
// 	/* Dispose the run async messages callback */
// 	idleCallback.dispose (); idleCallback = null;
// 	idleProc = 0;
// 	if (idleHandle !is null) OS.g_source_remove (idleHandle);
// 	idleHandle = 0;
//
// 	/* Dispose GtkTreeView callbacks */
// 	treeSelectionCallback.dispose (); treeSelectionCallback = null;
// 	treeSelectionProc = 0;
// 	cellDataCallback.dispose (); cellDataCallback = null;
// 	cellDataProcFld = 0;
//
// 	/* Dispose the set direction callback */
// 	setDirectionCallback.dispose (); setDirectionCallback = null;
// 	setDirectionProc = 0;
//
// 	/* Dispose the set direction callback */
// 	allChildrenCallback.dispose (); allChildrenCallback = null;
// 	allChildrenProc = 0;
//
// 	/* Dispose the caret callback */
// 	if (caretId !is null) OS.gtk_timeout_remove (caretId);
// 	caretId = 0;
// 	caretProc = 0;
// 	caretCallback.dispose ();
// 	caretCallback = null;
//
// 	/* Release closures */
// 	for (int i = 0; i < Widget.LAST_SIGNAL; i++) {
// 		if (closures [i] !is null) OS.g_closure_unref (closures [i]);
// 	}
// 	if (shellMapProcClosure !is null) OS.g_closure_unref (shellMapProcClosure);
//
// 	/* Dispose the timer callback */
// 	if (timerIds !is null) {
// 		for (int i=0; i<timerIds.length; i++) {
// 			if (timerIds [i] !is null) OS.gtk_timeout_remove (timerIds [i]);
// 		}
// 	}
// 	timerIds = null;
// 	timerList = null;
// 	timerProc = 0;
// 	timerCallback.dispose ();
// 	timerCallback = null;
// 	windowTimerProc = 0;
// 	windowTimerCallback.dispose ();
// 	windowTimerCallback = null;
//
// 	/* Dispose mouse hover callback */
// 	if (mouseHoverId !is null) OS.gtk_timeout_remove (mouseHoverId);
// 	mouseHoverId = 0;
// 	mouseHoverHandle = mouseHoverProc = 0;
// 	mouseHoverCallback.dispose ();
// 	mouseHoverCallback = null;
//
// 	/* Dispose the default font */
// 	if (systemFont !is null) systemFont.dispose ();
// 	systemFont = null;
//
// 	/* Dispose the System Images */
// 	if (errorImage !is null) errorImage.dispose();
// 	if (infoImage !is null) infoImage.dispose();
// 	if (questionImage !is null) questionImage.dispose();
// 	if (warningImage !is null) warningImage.dispose();
// 	errorImage = infoImage = questionImage = warningImage = null;
//
// 	/* Release the System Cursors */
// 	for (int i = 0; i < cursors.length; i++) {
// 		if (cursors [i] !is null) cursors [i].dispose ();
// 	}
// 	cursors = null;
//
// 	/* Release Acquired Resources */
// 	if (resources !is null) {
// 		for (int i=0; i<resources.length; i++) {
// 			if (resources [i] !is null) resources [i].dispose ();
// 		}
// 		resources = null;
// 	}
//
// 	/* Release the System Colors */
// 	COLOR_WIDGET_DARK_SHADOW = COLOR_WIDGET_NORMAL_SHADOW = COLOR_WIDGET_LIGHT_SHADOW =
// 	COLOR_WIDGET_HIGHLIGHT_SHADOW = COLOR_WIDGET_BACKGROUND = COLOR_WIDGET_BORDER =
// 	COLOR_LIST_FOREGROUND = COLOR_LIST_BACKGROUND = COLOR_LIST_SELECTION = COLOR_LIST_SELECTION_TEXT =
// 	COLOR_INFO_BACKGROUND = COLOR_INFO_FOREGROUND = null;
//
// 	/* Dispose the event callback */
// 	OS.gdk_event_handler_set (0, 0, 0);
// 	eventCallback.dispose ();  eventCallback = null;
//
// 	/* Dispose the hidden shell */
// 	if (shellHandle !is null) OS.gtk_widget_destroy (shellHandle);
// 	shellHandle = 0;
//
// 	/* Dispose the settings callback */
// 	styleSetCallback.dispose(); styleSetCallback = null;
// 	styleSetProc = 0;
//
// 	/* Release the sleep resources */
// 	max_priority = timeout = null;
// 	if (fds !is null) OS.g_free (fds);
// 	fds = 0;
//
// 	/* Release references */
// 	popups = null;
// 	thread = null;
// 	activeShell = null;
// 	lastWidget = null;
// 	indexTable = null;
// 	widgetTable = null;
// }
//
// /**
//  * 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
//  *
//  * @since 3.0
//  */
// public void removeFilter (int eventType, Listener listener) {
// 	checkDevice ();
// 	if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
// 	if (filterTable is null) return;
// 	filterTable.unhook (eventType, listener);
// 	if (filterTable.size () is 0) filterTable = null;
// }
//
// int /*long*/ removeGdkEvent () {
// 	if (gdkEventCount is 0) return 0;
// 	auto event = gdkEvents [0];
// 	--gdkEventCount;
// 	System.arraycopy (gdkEvents, 1, gdkEvents, 0, gdkEventCount);
// 	System.arraycopy (gdkEventWidgets, 1, gdkEventWidgets, 0, gdkEventCount);
// 	gdkEvents [gdkEventCount] = 0;
// 	gdkEventWidgets [gdkEventCount] = null;
// 	if (gdkEventCount is 0) {
// 		gdkEvents = null;
// 		gdkEventWidgets = null;
// 	}
// 	return event;
// }
//
// void removeIdleProc () {
// 	synchronized(idleLock) {
// 		if (idleHandle !is null) OS.g_source_remove (idleHandle);
// 		idleNeeded = false;
// 		idleHandle = 0;
// 	}
// }
// /**
//  * 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 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 #addListener
//  *
//  * @since 2.0
//  */
// public void removeListener (int eventType, Listener listener) {
// 	checkDevice ();
// 	if (listener is null) error (SWT.ERROR_NULL_ARGUMENT);
// 	if (eventTable is null) return;
// 	eventTable.unhook (eventType, listener);
// }
//
// void removeMouseHoverTimeout (int /*long*/ handle) {
// 	if (handle !is mouseHoverHandle) return;
// 	if (mouseHoverId !is null) OS.gtk_timeout_remove (mouseHoverId);
// 	mouseHoverId = 0;
// 	mouseHoverHandle = 0;
// }
//
// void removePopup (Menu menu) {
// 	if (popups is null) return;
// 	for (int i=0; i<popups.length; i++) {
// 		if (popups [i] is menu) {
// 			popups [i] = null;
// 			return;
// 		}
// 	}
// }
//
// Widget removeWidget (int /*long*/ handle) {
// 	if (handle is null) return null;
// 	lastWidget = null;
// 	Widget widget = null;
// 	int index = cast(int)/*64*/ OS.g_object_get_qdata (handle, SWT_OBJECT_INDEX) - 1;
// 	if (0 <= index && index < widgetTable.length) {
// 		widget = widgetTable [index];
// 		widgetTable [index] = null;
// 		indexTable [index] = freeSlot;
// 		freeSlot = index;
// 		OS.g_object_set_qdata (handle, SWT_OBJECT_INDEX, 0);
// 	}
// 	return widget;
// }
//
// bool runAsyncMessages (bool all) {
// 	return synchronizer.runAsyncMessages (all);
// }
//
// bool runDeferredEvents () {
// 	/*
// 	* Run deferred events.  This code is always
// 	* called in the Display's thread so it must
// 	* be re-enterant but need not be synchronized.
// 	*/
// 	while (eventQueue !is null) {
//
// 		/* Take an event off the queue */
// 		Event event = eventQueue [0];
// 		if (event is null) break;
// 		int length = eventQueue.length;
// 		System.arraycopy (eventQueue, 1, eventQueue, 0, --length);
// 		eventQueue [length] = null;
//
// 		/* Run the event */
// 		Widget widget = event.widget;
// 		if (widget !is null && !widget.isDisposed ()) {
// 			Widget item = event.item;
// 			if (item is null || !item.isDisposed ()) {
// 				widget.sendEvent (event);
// 			}
// 		}
//
// 		/*
// 		* At this point, the event queue could
// 		* be null due to a recursive invokation
// 		* when running the event.
// 		*/
// 	}
//
// 	/* Clear the queue */
// 	eventQueue = null;
// 	return true;
// }
//
// bool runPopups () {
// 	if (popups is null) return false;
// 	bool result = false;
// 	while (popups !is null) {
// 		Menu menu = popups [0];
// 		if (menu is null) break;
// 		int length = popups.length;
// 		System.arraycopy (popups, 1, popups, 0, --length);
// 		popups [length] = null;
// 		runDeferredEvents ();
// 		if (!menu.isDisposed ()) menu._setVisible (true);
// 		result = true;
// 	}
// 	popups = null;
// 	return result;
// }
//
// bool runSettingsMeth () {
// 	if (!runSettings) return false;
// 	runSettings = false;
// 	saveResources ();
// 	initializeSystemColors ();
// 	sendEvent (SWT.Settings, null);
// 	Shell [] shells = getShells ();
// 	for (int i=0; i<shells.length; i++) {
// 		Shell shell = shells [i];
// 		if (!shell.isDisposed ()) {
// 			shell.fixStyle ();
// 			shell.redraw (true);
// 			shell.layout (true, true);
// 		}
// 	}
// 	return true;
// }
//
// /**
//  * On platforms which support it, sets the application name
//  * to be the argument. On Motif, for example, this can be used
//  * to set the name used for resource lookup.  Specifying
//  * <code>null</code> for the name clears it.
//  *
//  * @param name the new app name or <code>null</code>
//  */
// public static void setAppName (char[] name) {
// 	APP_NAME = name;
// }
//
// /**
//  * Sets the location of the on-screen pointer relative to the top left corner
//  * of the screen.  <b>Note: It is typically considered bad practice for a
//  * program to move the on-screen pointer location.</b>
//  *
//  * @param x the new x coordinate for the cursor
//  * @param y the new y coordinate for 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>
//  *
//  * @since 2.1
//  */
// public void setCursorLocation (int x, int y) {
// 	checkDevice ();
// 	if (OS.GDK_WINDOWING_X11 ()) {
// 		auto xDisplay = OS.GDK_DISPLAY ();
// 		auto xWindow = OS.XDefaultRootWindow (xDisplay);
// 		OS.XWarpPointer (xDisplay, OS.None, xWindow, 0, 0, 0, 0, x, y);
// 	}
// }
//
// /**
//  * Sets the location of the on-screen pointer relative to the top left corner
//  * of the screen.  <b>Note: It is typically considered bad practice for a
//  * program to move the on-screen pointer location.</b>
//  *
//  * @param point new position
//  *
//  * @exception SWTException <ul>
//  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
//  *    <li>ERROR_NULL_ARGUMENT - if the point is null
//  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
//  * </ul>
//  *
//  * @since 2.0
//  */
// public void setCursorLocation (Point point) {
// 	checkDevice ();
// 	if (point is null) error (SWT.ERROR_NULL_ARGUMENT);
// 	setCursorLocation (point.x, point.y);
// }
//
// /**
//  * 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)
//  */
// public void setData (char[] key, Object value) {
// 	checkDevice ();
// 	if (key is null) error (SWT.ERROR_NULL_ARGUMENT);
//
// 	if (key==/*eq*/ DISPATCH_EVENT_KEY) {
// 		if (value is null || (null !is cast(ArrayWrapperInt)value)) {
// 			dispatchEvents = value.array;
// 			if (value is null) putGdkEvents ();
// 			return;
// 		}
// 	}
//
// 	if (key==/*eq*/ ADD_WIDGET_KEY) {
//         auto wrap = cast(ArrayWrapperObject) value;
//         if( wrap is null ) SWT.error(SWT.ERROR_INVALID_ARGUMENT, null, " []");
//         Object [] data = wrap.array;
// 		auto handle = (cast(LONG) data [0]).value;
// 		Widget widget = cast(Widget) data [1];
// 		if (widget !is null) {
// 			addWidget (handle, widget);
// 		} else {
// 			removeWidget (handle);
// 		}
// 	}
//
// 	if (key==/*eq*/ ADD_IDLE_PROC_KEY) {
// 		addIdleProc ();
// 		return;
// 	}
// 	if (key==/*eq*/ REMOVE_IDLE_PROC_KEY) {
// 		removeIdleProc ();
// 		return;
// 	}
//
// 	/* Remove the key/value pair */
// 	if (value is null) {
// 		if (keys is null) return;
// 		int index = 0;
// 		while (index < keys.length && !keys [index]==/*eq*/ key) index++;
// 		if (index is keys.length) return;
// 		if (keys.length is 1) {
// 			keys = null;
// 			values = null;
// 		} else {
// 			char[] [] newKeys = new char[] [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 is null) {
// 		keys = [key];
// 		values = [value];
// 		return;
// 	}
// 	for (int i=0; i<keys.length; i++) {
// 		if (keys [i]==/*eq*/ key) {
// 			values [i] = value;
// 			return;
// 		}
// 	}
// 	char[] [] newKeys = new char[] [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;
// }
//
// /**
//  * 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)
//  */
// public void setData (Object data) {
// 	checkDevice ();
// 	this.data = data;
// }
//
// int /*long*/ setDirectionProcMeth (int /*long*/ widget, int /*long*/ direction) {
// 	OS.gtk_widget_set_direction (widget, cast(int)/*64*/ direction);
// 	if (OS.GTK_IS_CONTAINER (widget)) {
// 		OS.gtk_container_forall (widget, setDirectionProc, direction);
// 	}
// 	return 0;
// }
//
// /**
//  * 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>
//  */
// public void setSynchronizer (Synchronizer synchronizer) {
// 	checkDevice ();
// 	if (synchronizer is null) error (SWT.ERROR_NULL_ARGUMENT);
// 	if (this.synchronizer !is null) {
// 		this.synchronizer.runAsyncMessages(true);
// 	}
// 	this.synchronizer = synchronizer;
// }
//
// void showIMWindow (Control control) {
// 	imControl = control;
// 	if (preeditWindow is null) {
// 		preeditWindow = OS.gtk_window_new (OS.GTK_WINDOW_POPUP);
// 		if (preeditWindow is null) error (SWT.ERROR_NO_HANDLES);
// 		preeditLabel = OS.gtk_label_new (null);
// 		if (preeditLabel is null) error (SWT.ERROR_NO_HANDLES);
// 		OS.gtk_container_add (preeditWindow, preeditLabel);
// 		OS.gtk_widget_show (preeditLabel);
// 	}
// 	int /*long*/ [] preeditString = new int /*long*/ [1];
// 	int /*long*/ [] pangoAttrs = new int /*long*/ [1];
// 	auto imHandle = control.imHandle ();
// 	OS.gtk_im_context_get_preedit_string (imHandle, preeditString, pangoAttrs, null);
// 	if (preeditString [0] !is null && OS.strlen (preeditString [0]) > 0) {
// 		Control widget = control.findBackgroundControl ();
// 		if (widget is null) widget = control;
// 		OS.gtk_widget_modify_bg (preeditWindow,  OS.GTK_STATE_NORMAL, widget.getBackgroundColor ());
// 		widget.setForegroundColor (preeditLabel, control.getForegroundColor());
// 		OS.gtk_widget_modify_font (preeditLabel, control.getFontDescription ());
// 		if (pangoAttrs [0] !is null) OS.gtk_label_set_attributes (preeditLabel, pangoAttrs[0]);
// 		OS.gtk_label_set_text (preeditLabel, preeditString [0]);
// 		Point point = control.toDisplay (control.getIMCaretPos ());
// 		OS.gtk_window_move (preeditWindow, point.x, point.y);
// 		GtkRequisition* requisition = new GtkRequisition ();
// 		OS.gtk_widget_size_request (preeditLabel, requisition);
// 		OS.gtk_window_resize (preeditWindow, requisition.width, requisition.height);
// 		OS.gtk_widget_show (preeditWindow);
// 	} else {
// 		OS.gtk_widget_hide (preeditWindow);
// 	}
// 	if (preeditString [0] !is null) OS.g_free (preeditString [0]);
// 	if (pangoAttrs [0] !is null) OS.pango_attr_list_unref (pangoAttrs [0]);
// }
//
// /**
//  * 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
//  */
// public bool sleep () {
// 	checkDevice ();
// 	if (gdkEventCount is 0) {
// 		gdkEvents = null;
// 		gdkEventWidgets = null;
// 	}
// 	if (settingsChanged) {
// 		settingsChanged = false;
// 		runSettings = true;
// 		return false;
// 	}
// 	if (getMessageCount () !is 0) return true;
// 	if (fds is null) {
// 		allocated_nfds = 2;
// 		fds = OS.g_malloc (OS.GPollFD_sizeof () * allocated_nfds);
// 	}
// 	max_priority [0] = timeout [0] = 0;
// 	auto context = OS.g_main_context_default ();
// 	bool result = false;
// 	do {
// 		if (OS.g_main_context_acquire (context)) {
// 			result = OS.g_main_context_prepare (context, max_priority);
// 			int nfds;
// 			while ((nfds = OS.g_main_context_query (context, max_priority [0], timeout, fds, allocated_nfds)) > allocated_nfds) {
// 				OS.g_free (fds);
// 				allocated_nfds = nfds;
// 				fds = OS.g_malloc (OS.GPollFD_sizeof() * allocated_nfds);
// 			}
// 			auto poll = OS.g_main_context_get_poll_func (context);
// 			if (poll !is null) {
// 				if (nfds > 0 || timeout [0] !is 0) {
// 					/*
// 					* Bug in GTK. For some reason, g_main_context_wakeup() may
// 					* fail to wake up the UI thread from the polling function.
// 					* The fix is to sleep for a maximum of 50 milliseconds.
// 					*/
// 					if (timeout [0] < 0) timeout [0] = 50;
//
// 					/* Exit the OS lock to allow other threads to enter GTK */
// 					Lock lock = OS.lock;
// 					int count = lock.lock ();
// 					for (int i = 0; i < count; i++) lock.unlock ();
// 					try {
// 						wake_state = false;
// 						OS.Call (poll, fds, nfds, timeout [0]);
// 					} finally {
// 						for (int i = 0; i < count; i++) lock.lock ();
// 						lock.unlock ();
// 					}
// 				}
// 			}
// 			OS.g_main_context_check (context, max_priority [0], fds, nfds);
// 			OS.g_main_context_release (context);
// 		}
// 	} while (!result && getMessageCount () is null && !wake_state);
// 	wake_state = false;
// 	return true;
// }
//
// /**
//  * 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
//  */
// public void timerExec (int milliseconds, Runnable runnable) {
// 	checkDevice ();
// 	if (runnable is null) error (SWT.ERROR_NULL_ARGUMENT);
// 	if (timerList is null) timerList = new Runnable [4];
// 	if (timerIds is null) timerIds = new int [4];
// 	int index = 0;
// 	while (index < timerList.length) {
// 		if (timerList [index] is runnable) break;
// 		index++;
// 	}
// 	if (index !is timerList.length) {
// 		OS.gtk_timeout_remove (timerIds [index]);
// 		timerList [index] = null;
// 		timerIds [index] = 0;
// 		if (milliseconds < 0) return;
// 	} else {
// 		if (milliseconds < 0) return;
// 		index = 0;
// 		while (index < timerList.length) {
// 			if (timerList [index] is null) break;
// 			index++;
// 		}
// 		if (index is timerList.length) {
// 			Runnable [] newTimerList = new Runnable [timerList.length + 4];
// 			System.arraycopy (timerList, 0, newTimerList, 0, timerList.length);
// 			timerList = newTimerList;
// 			int [] newTimerIds = new int [timerIds.length + 4];
// 			System.arraycopy (timerIds, 0, newTimerIds, 0, timerIds.length);
// 			timerIds = newTimerIds;
// 		}
// 	}
// 	int timerId = OS.gtk_timeout_add (milliseconds, timerProc, index);
// 	if (timerId !is null) {
// 		timerIds [index] = timerId;
// 		timerList [index] = runnable;
// 	}
// }
//
// int /*long*/ timerProcMeth (int /*long*/ i) {
// 	if (timerList is null) return 0;
// 	int index = cast(int)/*64*/i;
// 	if (0 <= index && index < timerList.length) {
// 		Runnable runnable = timerList [index];
// 		timerList [index] = null;
// 		timerIds [index] = 0;
// 		if (runnable !is null) runnable.run ();
// 	}
// 	return 0;
// }
//
// int /*long*/ caretProcMeth (int /*long*/ clientData) {
// 	caretId = 0;
// 	if (currentCaret is null) {
// 		return 0;
// 	}
// 	if (currentCaret.blinkCaret()) {
// 		int blinkRate = currentCaret.blinkRate;
// 		if (blinkRate is 0) return 0;
// 		caretId = OS.gtk_timeout_add (blinkRate, caretProc, 0);
// 	} else {
// 		currentCaret = null;
// 	}
// 	return 0;
// }
//
// int /*long*/ sizeAllocateProcMeth (int /*long*/ handle, int /*long*/ arg0, int /*long*/ user_data) {
// 	Widget widget = getWidget (user_data);
// 	if (widget is null) return 0;
// 	return widget.sizeAllocateProc (handle, arg0, user_data);
// }
//
// int /*long*/ sizeRequestProcMeth (int /*long*/ handle, int /*long*/ arg0, int /*long*/ user_data) {
// 	Widget widget = getWidget (user_data);
// 	if (widget is null) return 0;
// 	return widget.sizeRequestProc (handle, arg0, user_data);
// }
//
// int /*long*/ treeSelectionProcMeth (int /*long*/ model, int /*long*/ path, int /*long*/ iter, int /*long*/ data) {
// 	Widget widget = getWidget (data);
// 	if (widget is null) return 0;
// 	return widget.treeSelectionProc (model, path, iter, treeSelection, treeSelectionLength++);
// }
//
// void saveResources () {
// 	int resourceCount = 0;
// 	if (resources is null) {
// 		resources = new Resource [RESOURCE_SIZE];
// 	} else {
// 		resourceCount = resources.length;
// 		Resource [] newResources = new Resource [resourceCount + RESOURCE_SIZE];
// 		System.arraycopy (resources, 0, newResources, 0, resourceCount);
// 		resources = newResources;
// 	}
// 	if (systemFont !is null) {
// 		resources [resourceCount++] = systemFont;
// 		systemFont = null;
// 	}
// 	if (errorImage !is null) resources [resourceCount++] = errorImage;
// 	if (infoImage !is null) resources [resourceCount++] = infoImage;
// 	if (questionImage !is null) resources [resourceCount++] = questionImage;
// 	if (warningImage !is null) resources [resourceCount++] = warningImage;
// 	errorImage = infoImage = questionImage = warningImage = null;
// 	for (int i=0; i<cursors.length; i++) {
// 		if (cursors [i] !is null) resources [resourceCount++] = cursors [i];
// 		cursors [i] = null;
// 	}
// 	if (resourceCount < RESOURCE_SIZE) {
// 		Resource [] newResources = new Resource [resourceCount];
// 		System.arraycopy (resources, 0, newResources, 0, resourceCount);
// 		resources = newResources;
// 	}
// }
//
void sendEvent (int eventType, Event event) {
// 	if (eventTable is null && filterTable is null) {
// 		return;
// 	}
// 	if (event is null) event = new Event ();
// 	event.display = this;
// 	event.type = eventType;
// 	if (event.time is 0) event.time = getLastEventTime ();
// 	if (!filterEvent (event)) {
// 		if (eventTable !is null) eventTable.sendEvent (event);
// 	}
}
//
// void setCurrentCaret (Caret caret) {
// 	if (caretId !is null) OS.gtk_timeout_remove(caretId);
// 	caretId = 0;
// 	currentCaret = caret;
// 	if (caret is null) return;
// 	int blinkRate = currentCaret.blinkRate;
// 	caretId = OS.gtk_timeout_add (blinkRate, caretProc, 0);
// }
//
// int /*long*/ shellMapProcMeth (int /*long*/ handle, int /*long*/ arg0, int /*long*/ user_data) {
// 	Widget widget = getWidget (handle);
// 	if (widget is null) return 0;
// 	return widget.shellMapProc (handle, arg0, user_data);
// }
//
// int /*long*/ styleSetProcMeth (int /*long*/ gobject, int /*long*/ arg1, int /*long*/ user_data) {
// 	settingsChanged = true;
// 	return 0;
// }
//
// /**
//  * Causes the <code>run()</code> method of the runnable to
//  * be invoked by the user-interface thread at the next
//  * reasonable opportunity. 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 occurred when executing the runnable</li>
//  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
//  * </ul>
//  *
//  * @see #asyncExec
//  */
// public void syncExec (Runnable runnable) {
// 	if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
// 	synchronized (idleLock) {
// 		if (idleNeeded && idleHandle is null) {
// 			//NOTE: calling unlocked function in OS
// 			idleHandle = OS._g_idle_add (idleProc, 0);
// 		}
// 	}
// 	synchronizer.syncExec (runnable);
// }
//
// static int translateKey (int key) {
// 	for (int i=0; i<KeyTable.length; i++) {
// 		if (KeyTable [i] [0] is key) return KeyTable [i] [1];
// 	}
// 	return 0;
// }
//
// static int untranslateKey (int key) {
// 	for (int i=0; i<KeyTable.length; i++) {
// 		if (KeyTable [i] [1] is key) return KeyTable [i] [0];
// 	}
// 	return 0;
// }
//
// /**
//  * 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()
//  */
// public void update () {
// 	checkDevice ();
// 	flushExposes (0, true);
// 	OS.gdk_window_process_all_updates ();
// }
//
// /**
//  * If the receiver's user-interface thread was <code>sleep</code>ing,
//  * causes it to be awakened and start running again. Note that this
//  * method may be called from any thread.
//  *
//  * @exception SWTException <ul>
//  *    <li>ERROR_DEVICE_DISPOSED - if the receiver has been disposed</li>
//  * </ul>
//  *
//  * @see #sleep
//  */
// public void wake () {
// 	if (isDisposed ()) error (SWT.ERROR_DEVICE_DISPOSED);
// 	if (thread is Thread.currentThread ()) return;
// 	wakeThread ();
// }
//
// void wakeThread () {
// 	OS.g_main_context_wakeup (0);
// 	wake_state = true;
// }
//
// static char wcsToMbcs (char ch) {
// 	int key = ch & 0xFFFF;
// 	if (key <= 0x7F) return ch;
// 	byte [] buffer = Converter.wcsToMbcs (null,[ch], false);
// 	if (buffer.length is 1) return cast(char) buffer [0];
// 	if (buffer.length is 2) {
// 		return cast(char) (((buffer [0] & 0xFF) << 8) | (buffer [1] & 0xFF));
// 	}
// 	return 0;
// }

// int /*long*/ windowProcMeth (GtkWidget* handle, int /*long*/ user_data) {
// 	Widget widget = getWidget (handle);
// 	if (widget is null) return 0;
// 	return widget.windowProc (handle, user_data);
// }
//
// int /*long*/ windowProcMeth (int /*long*/ handle, int /*long*/ arg0, int /*long*/ user_data) {
// 	Widget widget = getWidget (handle);
// 	if (widget is null) return 0;
// 	return widget.windowProc (handle, arg0, user_data);
// }
//
// int /*long*/ windowProcMeth (int /*long*/ handle, int /*long*/ arg0, int /*long*/ arg1, int /*long*/ user_data) {
// 	Widget widget = getWidget (handle);
// 	if (widget is null) return 0;
// 	return widget.windowProc (handle, arg0, arg1, user_data);
// }
//
// int /*long*/ windowProcMeth (int /*long*/ handle, int /*long*/ arg0, int /*long*/ arg1, int /*long*/ arg2, int /*long*/ user_data) {
// 	Widget widget = getWidget (handle);
// 	if (widget is null) return 0;
// 	return widget.windowProc (handle, arg0, arg1, arg2, user_data);
// }
//
// int /*long*/ windowTimerProcMeth (int /*long*/ handle) {
// 	Widget widget = getWidget (handle);
// 	if (widget is null) return 0;
// 	return widget.timerProc (handle);
// }

}