/// <summary>
	/// <para>Constructs a new <see cref="T:Xsharp.InputOnlyWidget"/>
	/// instance underneath a specified parent widget.</para>
	/// </summary>
	///
	/// <param name="parent">
	/// <para>The parent of the new widget.</para>
	/// </param>
	///
	/// <param name="x">
	/// <para>The X co-ordinate of the top-left corner of
	/// the new widget.</para>
	/// </param>
	///
	/// <param name="y">
	/// <para>The Y co-ordinate of the top-left corner of
	/// the new widget.</para>
	/// </param>
	///
	/// <param name="width">
	/// <para>The width of the new widget.</para>
	/// </param>
	///
	/// <param name="height">
	/// <para>The height of the new widget.</para>
	/// </param>
	///
	/// <exception cref="T:System.ArgumentNullException">
	/// <para>Raised if <paramref name="parent"/> is <see langword="null"/>.
	/// </para>
	/// </exception>
	///
	/// <exception cref="T:Xsharp.XException">
	/// <para>Raised if <paramref name="x"/>, <paramref name="y"/>,
	/// <paramref name="width"/>, or <paramref name="height"/> are
	/// out of range.</para>
	/// </exception>
	///
	/// <exception cref="T.Xsharp.XInvalidOperationException">
	/// <para>Raised if <paramref name="parent"/> is disposed or the
	/// root window.</para>
	/// </exception>
	public InputOnlyWidget(Widget parent, int x, int y, int width, int height)
			: base(GetDisplay(parent, false), GetScreen(parent),
				   DrawableKind.InputOnlyWidget, parent)
			{
				bool ok = false;
				try
				{
					// Validate the position and size.
					if(x < -32768 || x > 32767 ||
					   y < -32768 || y > 32767)
					{
						throw new XException(S._("X_InvalidPosition"));
					}
					if(width < 1 || width > 32767 ||
					   height < 1 || height > 32767 ||
					   !ValidateSize(width, height))
					{
						throw new XException(S._("X_InvalidSize"));
					}

					// Set the initial position and size of the widget.
					this.x = x;
					this.y = y;
					this.width = width;
					this.height = height;
					this.focusable = true;

					// Lock down the display and create the window handle.
					try
					{
						IntPtr display = dpy.Lock();
						XWindow pwindow = parent.GetWidgetHandle();
						XWindow window = Xlib.XCreateWindow
								(display, pwindow,
								 x, y, (uint)width, (uint)height, (uint)0,
								 0 /* depth */, 2 /* InputOnly */,
								 screen.DefaultVisual,
								 (uint)0, IntPtr.Zero);
						SetWidgetHandle(window);
						if(parent.AutoMapChildren)
						{
							Xlib.XMapWindow(display, window);
							mapped = true;
						}
					}
					finally
					{
						dpy.Unlock();
					}

					// Push the widget down to the default layer.
					layer = 0x7FFFFFFF;
					Layer = 0;
					ok = true;

					// Select for mouse events.
					SelectInput(EventMask.ButtonPressMask |
								EventMask.ButtonReleaseMask |
								EventMask.EnterWindowMask |
								EventMask.LeaveWindowMask |
								EventMask.PointerMotionMask);
				}
				finally
				{
					if(!ok)
					{
						// Creation failed, so detach ourselves from
						// the parent's widget tree.
						Detach(false);
					}
				}
			}
	// Internal constructor that is used by the "InputOutputWidget" subclass.
	internal InputOnlyWidget(Widget parent, int x, int y,
							 int width, int height, Color background,
							 bool rootAllowed, bool overrideRedirect)
			: base(GetDisplay(parent, rootAllowed), GetScreen(parent),
				   DrawableKind.Widget, parent)
			{
				bool ok = false;
				try
				{
					// Validate the position and size.
					if(x < -32768 || x > 32767 ||
					   y < -32768 || y > 32767)
					{
						throw new XException(S._("X_InvalidPosition"));
					}
					if(width < 1 || width > 32767 ||
					   height < 1 || height > 32767 ||
					   !ValidateSize(width, height))
					{
						throw new XException(S._("X_InvalidSize"));
					}

					// Set the initial position and size of the widget.
					this.x = x;
					this.y = y;
					this.width = width;
					this.height = height;
					this.focusable = true;

					// Lock down the display and create the window handle.
					try
					{
						IntPtr display = dpy.Lock();
						XWindow pwindow = parent.GetWidgetHandle();
						XSetWindowAttributes attrs = new XSetWindowAttributes();
						attrs.override_redirect = overrideRedirect;
						XWindow window = Xlib.XCreateWindow
								(display, pwindow,
								 x, y, (uint)width, (uint)height, (uint)0,
								 screen.DefaultDepth, 1 /* InputOutput */,
								 screen.DefaultVisual,
								 (uint)(CreateWindowMask.CWOverrideRedirect),
								 ref attrs);
						SetWidgetHandle(window);
						if(background.Index == StandardColor.Inherit)
						{
							Xlib.XSetWindowBackgroundPixmap
								(display, window, XPixmap.ParentRelative);
						}
						else
						{
							Xlib.XSetWindowBackground(display, window,
													  ToPixel(background));
						}
						if(parent.AutoMapChildren)
						{
							Xlib.XMapWindow(display, window);
							mapped = true;
						}
					}
					finally
					{
						dpy.Unlock();
					}

					// Push the widget down to the default layer.
					layer = 0x7FFFFFFF;
					Layer = 0;
					ok = true;

					// Select for mouse events.
					SelectInput(EventMask.ButtonPressMask |
								EventMask.ButtonReleaseMask |
								EventMask.EnterWindowMask |
								EventMask.LeaveWindowMask |
								EventMask.PointerMotionMask);
				}
				finally
				{
					if(!ok)
					{
						// Creation failed, so detach ourselves from
						// the parent's widget tree.
						Detach(false);
					}
				}
			}
	// Reposition this widget above one of its siblings.
	private void RepositionAbove(Widget child)
			{
				// Detach ourselves from the widget tree.
				if(nextAbove != null)
				{
					nextAbove.nextBelow = nextBelow;
				}
				else
				{
					parent.topChild = nextBelow;
				}
				if(nextBelow != null)
				{
					nextBelow.nextAbove = nextAbove;
				}

				// Re-insert at the new position.
				nextAbove = child.nextAbove;
				nextBelow = child;
				if(nextAbove != null)
				{
					nextAbove.nextBelow = this;
				}
				else
				{
					parent.topChild = this;
				}
				child.nextAbove = this;

				try
				{
					IntPtr display = dpy.Lock();
					XWindowChanges changes = new XWindowChanges();
					changes.stack_mode = 0;		/* Above */
					if(child is TopLevelWindow)
					{
						Xlib.XConfigureWindow
								(display, GetWidgetHandle(),
							     (uint)(ConfigureWindowMask.CWStackMode),
								 ref changes);
					}
					else
					{
						changes.sibling = child.GetWidgetHandle();
						Xlib.XConfigureWindow
								(display, GetWidgetHandle(),
							     (uint)(ConfigureWindowMask.CWSibling |
								 	    ConfigureWindowMask.CWStackMode),
								 ref changes);
					}
				}
				finally
				{
					dpy.Unlock();
				}
			}
	// Set this cursor on a widget.
	internal void SetCursor(Widget widget)
			{
				Display dpy = widget.dpy;
				try
				{
					IntPtr display = dpy.Lock();
					XWindow window = widget.GetWidgetHandle();
					if(source != null)
					{
						if(cursor == XCursor.Zero)
						{
							XColor foreground = new XColor();
							foreground.red = (ushort)0;
							foreground.green = (ushort)0;
							foreground.blue = (ushort)0;
							foreground.flags =
								(XColor.DoRed | XColor.DoGreen | XColor.DoBlue);
							XColor background = new XColor();
							background.red = (ushort)0xFFFF;
							background.green = (ushort)0xFFFF;
							background.blue = (ushort)0xFFFF;
							background.flags =
								(XColor.DoRed | XColor.DoGreen | XColor.DoBlue);
							if(reverse)
							{
								cursor = Xlib.XCreatePixmapCursor
									(display,
									 source.GetPixmapHandle(),
									 mask.GetPixmapHandle(),
									 ref background, ref foreground,
									 (uint)hotspotX, (uint)hotspotY);
							}
							else
							{
								cursor = Xlib.XCreatePixmapCursor
									(display,
									 source.GetPixmapHandle(),
									 mask.GetPixmapHandle(),
									 ref foreground, ref background,
									 (uint)hotspotX, (uint)hotspotY);
							}
						}
						Xlib.XDefineCursor(display, window, cursor);
					}
					else if(type == CursorType.XC_inherit_parent)
					{
						Xlib.XUndefineCursor(display, window);
					}
					else
					{
						Xlib.XDefineCursor
							(display, window, dpy.GetCursor(type));
					}
				}
				finally
				{
					dpy.Unlock();
				}
			}
	/// <summary>
	/// <para>Reparent this widget underneath a new parent.</para>
	/// </summary>
	///
	/// <param name="newParent">
	/// <para>The new parent widget.  This should be the placeholder widget
	/// for the screen if you wish to give this widget "no parent".</para>
	/// </param>
	///
	/// <param name="x">
	/// <para>The X co-ordinate of the new top-left widget corner.</para>
	/// </param>
	///
	/// <param name="y">
	/// <para>The Y co-ordinate of the new top-left widget corner.</para>
	/// </param>
	///
	/// <exception cref="T:System.ArgumentNullException">
	/// <para>Raised if <paramref name="newParent"/> is
	/// <see langword="null"/>.</para>
	/// </exception>
	///
	/// <exception cref="T:Xsharp.XException">
	/// <para>Raised if <paramref name="x"/> or <paramref name="y"/>
	/// is out of range.</para>
	/// </exception>
	///
	/// <exception cref="T:Xsharp.XInvalidOperationException">
	/// <para>Raised if <paramref name="newParent"/> is a descendent
	/// of this widget, which would create a circularity.</para>
	/// </exception>
	///
	/// <exception cref="T:Xsharp.XInvalidOperationException">
	/// <para>Raised if <paramref name="newParent"/> is on a different
	/// screen from this widget.</para>
	/// </exception>
	///
	/// <exception cref="T:Xsharp.XInvalidOperationException">
	/// <para>Raised if <paramref name="newParent"/> is an input only
	/// widget, but this widget is input-output.</para>
	/// </exception>
	///
	/// <exception cref="T:Xsharp.XInvalidOperationException">
	/// <para>Raised if an attempt is made to reparent the root window
	/// or a top-level window.</para>
	/// </exception>
	public virtual void Reparent(Widget newParent, int x, int y)
			{
				// Validate the parameters.
				if(newParent == null)
				{
					throw new ArgumentNullException("newParent");
				}
				if(x < -32768 || x > 32767 ||
				   y < -32768 || y > 32767)
				{
					throw new XException(S._("X_InvalidPosition"));
				}
				Widget temp = newParent;
				while(temp != null && temp != this)
				{
					temp = temp.parent;
				}
				if(temp != null)
				{
					throw new XInvalidOperationException 
						(S._("X_InvalidReparent"));
				}
				if(screen != newParent.screen)
				{
					throw new XInvalidOperationException 
						(S._("X_InvalidReparent"));
				}
				if(!(newParent is InputOutputWidget) &&
				   this is InputOutputWidget)
				{
					throw new XInvalidOperationException 
						(S._("X_InvalidReparent"));
				}

				// If the new parent is the same as the old, then simply
				// move and raise the widget, but do nothing else.
				if(newParent == parent)
				{
					Move(x, y);
					Raise();
					return;
				}

				// Detach the widget from its current parent.
				if(nextBelow != null)
				{
					nextBelow.nextAbove = nextAbove;
				}
				if(nextAbove != null)
				{
					nextAbove.nextBelow = nextBelow;
				}
				else if(parent != null)
				{
					parent.topChild = nextBelow;
				}

				// Attach the widget to its new parent as the top-most child.
				nextBelow = newParent.topChild;
				nextAbove = null;
				if(newParent.topChild != null)
				{
					newParent.topChild.nextAbove = this;
				}
				newParent.topChild = this;
				parent = newParent;

				// Temporarily put the widget in the top-most layer.
				int saveLayer = layer;
				layer = 0x7FFFFFFF;

				// Perform the actual reparent operation.  This will
				// put the window at the top of the stacking order.
				try
				{
					IntPtr display = dpy.Lock();
					XWindow widget = GetWidgetHandle();
					XWindow pwidget = newParent.GetWidgetHandle();
					Xlib.XReparentWindow(display, widget, pwidget, x, y);
					this.x = x;
					this.y = y;
				}
				finally
				{
					dpy.Unlock();
				}

				// Push the widget down to its original layer position.
				Layer = saveLayer;
			}