drawRectangles (rectangles);
drawRectangles (rectangles, stippled);
public boolean open () {	checkWidget ();	if (rectangles == null) return false;	int xDisplay = display.xDisplay;	int xWindow = OS.XDefaultRootWindow (xDisplay);	if (parent != null) {		xWindow = OS.XtWindow (parent.handle);		if (xWindow == 0) return false;	}	boolean cancelled = false;	tracking = true;	drawRectangles (rectangles);	int [] oldX = new int [1], oldY = new int [1];	int [] unused = new int [1], mask = new int [1];	OS.XQueryPointer (xDisplay, xWindow, unused, unused, oldX, oldY, unused, unused, mask);		/*	* If exactly one of UP/DOWN is specified as a style then set the cursor	* orientation accordingly (the same is done for LEFT/RIGHT styles below).	*/	int vStyle = style & (SWT.UP | SWT.DOWN);	if (vStyle == SWT.UP || vStyle == SWT.DOWN) {		cursorOrientation |= vStyle;	}	int hStyle = style & (SWT.LEFT | SWT.RIGHT);	if (hStyle == SWT.LEFT || hStyle == SWT.RIGHT) {		cursorOrientation |= hStyle;	}		Point cursorPos;	int mouseMasks = OS.Button1Mask | OS.Button2Mask | OS.Button3Mask;	boolean mouseDown = (mask [0] & mouseMasks) != 0;	if (!mouseDown) {		if ((style & SWT.RESIZE) != 0) {			cursorPos = adjustResizeCursor (xDisplay, xWindow);		} else {			cursorPos = adjustMoveCursor (xDisplay, xWindow);		}		oldX [0] = cursorPos.x;  oldY [0] = cursorPos.y;	}	int xEvent = OS.XtMalloc (XEvent.sizeof);	XEvent anyEvent = new XEvent();	int [] newX = new int [1], newY = new int [1];	int xtContext = OS.XtDisplayToApplicationContext (xDisplay);		int ptrGrabResult = OS.XGrabPointer (		xDisplay,		xWindow,		0,		OS.ButtonPressMask | OS.ButtonReleaseMask | OS.PointerMotionMask,		OS.GrabModeAsync,		OS.GrabModeAsync,		OS.None,		OS.None,		OS.CurrentTime);	int kbdGrabResult = OS.XGrabKeyboard (		xDisplay,		xWindow,		0,		OS.GrabModeAsync,		OS.GrabModeAsync,		OS.CurrentTime);					/*	 * Tracker behaves like a Dialog with its own OS event loop.	 */	while (tracking) {		if (parent != null && parent.isDisposed ()) break;		OS.XtAppNextEvent (xtContext, xEvent);		OS.memmove (anyEvent, xEvent, XEvent.sizeof);		switch (anyEvent.type) {			case OS.MotionNotify:				if (cursor != 0) {					OS.XChangeActivePointerGrab (						xDisplay,						OS.ButtonPressMask | OS.ButtonReleaseMask | OS.PointerMotionMask,						cursor,						OS.CurrentTime);				}				// fall through			case OS.ButtonRelease:				OS.XQueryPointer (xDisplay, xWindow, unused, unused, newX, newY, unused, unused, unused);				if (oldX [0] != newX [0] || oldY [0] != newY [0]) {					Rectangle [] oldRectangles = rectangles;					Rectangle [] rectsToErase = new Rectangle [rectangles.length];					for (int i = 0; i < rectangles.length; i++) {						Rectangle current = rectangles [i];						rectsToErase [i] = new Rectangle (current.x, current.y, current.width, current.height);					}					Event event = new Event ();					event.x = newX [0];					event.y = newY [0];					if ((style & SWT.RESIZE) != 0) {						resizeRectangles (newX [0] - oldX [0], newY [0] - oldY [0]);						sendEvent (SWT.Resize, event);						/*						 * It is possible (but unlikely) that application code						 * could have disposed the widget in the resize event.						 * If this happens then return false to indicate that						 * the move failed.						 */						if (isDisposed ()) {							cancelled = true;							break;						}						boolean draw = false;						/*						 * It is possible that application code could have						 * changed the rectangles in the resize event.  If this						 * happens then only redraw the tracker if the rectangle						 * values have changed.						 */						if (rectangles != oldRectangles) {							int length = rectangles.length;							if (length != rectsToErase.length) {								draw = true;							} else {								for (int i = 0; i < length; i++) {									if (!rectangles [i].equals (rectsToErase [i])) {										draw = true;										break;									}								}							}						} else {							draw = true;						}						if (draw) {							drawRectangles (rectsToErase);							drawRectangles (rectangles);						}						cursorPos = adjustResizeCursor (xDisplay, xWindow);						newX [0] = cursorPos.x;  newY [0] = cursorPos.y;					} else {						moveRectangles (newX [0] - oldX [0], newY [0] - oldY [0]);						sendEvent (SWT.Move, event);						/*						 * It is possible (but unlikely) that application code						 * could have disposed the widget in the move event.						 * If this happens then return false to indicate that						 * the move failed.						 */						if (isDisposed ()) {							cancelled = true;							break;						}						boolean draw = false;						/*						 * It is possible that application code could have						 * changed the rectangles in the move event.  If this						 * happens then only redraw the tracker if the rectangle						 * values have changed.						 */						if (rectangles != oldRectangles) {							int length = rectangles.length;							if (length != rectsToErase.length) {								draw = true;							} else {								for (int i = 0; i < length; i++) {									if (!rectangles [i].equals (rectsToErase [i])) {										draw = true;										break;									}								}							}						} else {							draw = true;						}						if (draw) {							drawRectangles (rectsToErase);							drawRectangles (rectangles);						}					}					oldX [0] = newX [0];  oldY [0] = newY [0];				}				tracking = anyEvent.type != OS.ButtonRelease;				break;			case OS.KeyPress:				XKeyEvent keyEvent = new XKeyEvent ();				OS.memmove (keyEvent, xEvent, XKeyEvent.sizeof);				if (keyEvent.keycode != 0) {					int [] keysym = new int [1];					OS.XLookupString (keyEvent, null, 0, keysym, null);					keysym [0] &= 0xFFFF;					int xChange = 0, yChange = 0;					int stepSize = ((keyEvent.state & OS.ControlMask) != 0) ? STEPSIZE_SMALL : STEPSIZE_LARGE;					switch (keysym [0]) {						case OS.XK_KP_Enter:						case OS.XK_Return:							tracking = false;							/*							 * Eat the subsequent KeyRelease event							 */							OS.XtAppNextEvent (xtContext, xEvent);							break;						case OS.XK_Escape:							tracking = false;							cancelled = true;							/*							 * Eat the subsequent KeyRelease event							 */							OS.XtAppNextEvent (xtContext, xEvent);							break;						case OS.XK_Left:							xChange = -stepSize;							break;						case OS.XK_Right:							xChange = stepSize;							break;						case OS.XK_Up:							yChange = -stepSize;							break;						case OS.XK_Down:							yChange = stepSize;							break;					}					if (xChange != 0 || yChange != 0) {						Rectangle [] oldRectangles = rectangles;						Rectangle [] rectsToErase = new Rectangle [rectangles.length];						for (int i = 0; i < rectangles.length; i++) {							Rectangle current = rectangles [i];							rectsToErase [i] = new Rectangle (current.x, current.y, current.width, current.height);						}						Event event = new Event ();						event.x = oldX [0] + xChange;						event.y = oldY [0] + yChange;						if ((style & SWT.RESIZE) != 0) {							resizeRectangles (xChange, yChange);							sendEvent (SWT.Resize, event);							/*							 * It is possible (but unlikely) that application code							 * could have disposed the widget in the resize event.							 * If this happens then return false to indicate that							 * the move failed.							 */							if (isDisposed ()) {								cancelled = true;								break;							}							boolean draw = false;							/*							 * It is possible that application code could have							 * changed the rectangles in the resize event.  If this							 * happens then only redraw the tracker if the rectangle							 * values have changed.							 */							if (rectangles != oldRectangles) {								int length = rectangles.length;								if (length != rectsToErase.length) {									draw = true;								} else {									for (int i = 0; i < length; i++) {										if (!rectangles [i].equals (rectsToErase [i])) {											draw = true;											break;										}									}								}							} else {								draw = true;							}							if (draw) {								drawRectangles (rectsToErase);								drawRectangles (rectangles);							}							cursorPos = adjustResizeCursor (xDisplay, xWindow);						} else {							moveRectangles (xChange, yChange);							sendEvent (SWT.Move, event);							/*							 * It is possible (but unlikely) that application code							 * could have disposed the widget in the move event.							 * If this happens then return false to indicate that							 * the move failed.							 */							if (isDisposed ()) {								cancelled = true;								break;							}							boolean draw = false;							/*							 * It is possible that application code could have							 * changed the rectangles in the move event.  If this							 * happens then only redraw the tracker if the rectangle							 * values have changed.							 */							if (rectangles != oldRectangles) {								int length = rectangles.length;								if (length != rectsToErase.length) {									draw = true;								} else {									for (int i = 0; i < length; i++) {										if (!rectangles [i].equals (rectsToErase [i])) {											draw = true;											break;										}									}								}							} else {								draw = true;							}							if (draw) {								drawRectangles (rectsToErase);								drawRectangles (rectangles);							}							cursorPos = adjustMoveCursor (xDisplay, xWindow);						}						oldX [0] = cursorPos.x;  oldY [0] = cursorPos.y;					}				}				break;			case OS.EnterNotify:			case OS.LeaveNotify:				/*				 * Do not dispatch these				 */				break;			default:				OS.XtDispatchEvent (xEvent);		}	}	OS.XtFree (xEvent);	if (!isDisposed()) drawRectangles (rectangles);	if (ptrGrabResult == OS.GrabSuccess) OS.XUngrabPointer (xDisplay, OS.CurrentTime);	if (kbdGrabResult == OS.GrabSuccess) OS.XUngrabKeyboard (xDisplay, OS.CurrentTime);	return !cancelled;}