drawRectangles (rectsToErase); drawRectangles (rectangles);
drawRectangles (rectsToErase, oldStippled); drawRectangles (rectangles, stippled);
public boolean open () {	checkWidget ();	if (rectangles == null) return false;	boolean cancelled = false;	tracking = true;	Event event = new Event ();	MSG msg = new MSG ();	boolean isMirrored = parent != null && (parent.style & SWT.MIRRORED) != 0;	/*	* 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;	}	/*	* If this tracker is being created without a mouse drag then	* we need to create a transparent window that fills the screen	* in order to get all mouse/keyboard events that occur	* outside of our visible windows (ie.- over the desktop).	*/	int hwndTransparent = 0;	Callback newProc = null;	boolean mouseDown = OS.GetKeyState(OS.VK_LBUTTON) < 0;	if (!mouseDown) {		int width = OS.GetSystemMetrics (OS.SM_CXSCREEN);		int height = OS.GetSystemMetrics (OS.SM_CYSCREEN);		hwndTransparent = OS.CreateWindowEx (			OS.WS_EX_TRANSPARENT,			display.windowClass,			null,			OS.WS_POPUP | OS.WS_VISIBLE,			0, 0,			width, height,			0,			0,			OS.GetModuleHandle (null),			null);		final int oldProc = OS.GetWindowLong (hwndTransparent, OS.GWL_WNDPROC);		Object windowProc = new Object () {			public int windowProc (int hwnd, int msg, int wParam, int lParam) {				switch (msg) {					/*					* We typically do not want to answer that the transparent window is					* transparent to hits since doing so negates the effect of having it					* to grab events.  However, clients of the tracker should not be aware					* of this transparent window.  Therefore if there is a hit query					* performed as a result of client code then answer that the transparent					* window is transparent to hits so that its existence will not impact					* the client.					*/					case OS.WM_NCHITTEST:						if (inEvent) return OS.HTTRANSPARENT;						break;					case OS.WM_SETCURSOR:						if (clientCursor != 0) {							OS.SetCursor (clientCursor);							return 1;						}						if (resizeCursor != 0) {							OS.SetCursor (resizeCursor);							return 1;						}				}				return OS.CallWindowProc (oldProc, hwnd, msg, wParam, lParam);			}		};		newProc = new Callback (windowProc, "windowProc", 4); //$NON-NLS-1$		OS.SetWindowLong (hwndTransparent, OS.GWL_WNDPROC, newProc.getAddress ());	}	drawRectangles (rectangles);	Point cursorPos;	if (mouseDown) {		POINT pt = new POINT ();		OS.GetCursorPos (pt);		cursorPos = new Point (pt.x, pt.y);	} else {		if ((style & SWT.RESIZE) != 0) {			cursorPos = adjustResizeCursor ();		} else {			cursorPos = adjustMoveCursor ();		}	}		int oldX = cursorPos.x, oldY = cursorPos.y;	/*	* Tracker behaves like a Dialog with its own OS event loop.	*/	while (tracking && !cancelled) {		if (parent != null && parent.isDisposed ()) break;		OS.GetMessage (msg, 0, 0, 0);		int message = msg.message;		switch (message) {			case OS.WM_LBUTTONUP:			case OS.WM_MOUSEMOVE:				int newPos = OS.GetMessagePos ();				int newX = (short) (newPos & 0xFFFF);				int newY = (short) (newPos >> 16);					if (newX != oldX || newY != oldY) {					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.x = newX;					event.y = newY;					if ((style & SWT.RESIZE) != 0) {						if (isMirrored) {						   resizeRectangles (oldX - newX, newY - oldY);						} else {						   resizeRectangles (newX - oldX, newY - oldY);						}						inEvent = true;						sendEvent (SWT.Resize, event);						inEvent = false;						/*						* It is possible (but unlikely), that application						* code could have disposed the widget in the resize						* event.  If this happens, return false to indicate						* that the tracking has 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 ();						newX = cursorPos.x;  newY = cursorPos.y;					} else {						if (isMirrored) {							moveRectangles (oldX - newX, newY - oldY); 						} else { 							moveRectangles (newX - oldX, newY - oldY);						}						inEvent = true;						sendEvent (SWT.Move, event);						inEvent = false;						/*						* It is possible (but unlikely), that application						* code could have disposed the widget in the move						* event.  If this happens, return false to indicate						* that the tracking has 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 = newX;  oldY = newY;				}				tracking = msg.message != OS.WM_LBUTTONUP;				break;			case OS.WM_SYSKEYDOWN:				cancelled = true;							tracking = false;				break;			case OS.WM_KEYDOWN:				int stepSize = OS.GetKeyState (OS.VK_CONTROL) < 0 ? STEPSIZE_SMALL : STEPSIZE_LARGE;				int xChange = 0, yChange = 0;				switch (msg.wParam) {					case OS.VK_ESCAPE:						cancelled = true;						tracking = false;						break;					case OS.VK_RETURN:						tracking = false;						break;					case OS.VK_LEFT:						xChange = isMirrored ? stepSize : -stepSize;						break;					case OS.VK_RIGHT:						xChange = isMirrored ? -stepSize : stepSize;						break;					case OS.VK_UP:						yChange = -stepSize;						break;					case OS.VK_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.x = oldX + xChange;					event.y = oldY + yChange;					if ((style & SWT.RESIZE) != 0) {						resizeRectangles (xChange, yChange);						inEvent = true;						sendEvent (SWT.Resize, event);						inEvent = false;						/*						* It is possible (but unlikely) that application						* code could have disposed the widget in the resize						* event.  If this happens return false to indicate						* that the tracking has 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 ();					} else {						moveRectangles (xChange, yChange);						inEvent = true;						sendEvent (SWT.Move, event);						inEvent = false;						/*						* It is possible (but unlikely) that application						* code could have disposed the widget in the move						* event.  If this happens return false to indicate						* that the tracking has 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 ();					}					oldX = cursorPos.x;  oldY = cursorPos.y;				}				break;		}		if (OS.WM_KEYFIRST <= message && message <= OS.WM_KEYLAST) continue;		if (OS.WM_MOUSEFIRST <= message && message <= OS.WM_MOUSELAST) continue;		OS.DispatchMessage (msg);	}	if (mouseDown) OS.ReleaseCapture ();	if (!isDisposed()) drawRectangles (rectangles);	/*	* Cleanup: If a transparent window was created in order to capture events then	* destroy it and its callback object now.	*/	if (hwndTransparent != 0) {		OS.DestroyWindow (hwndTransparent);	}	if (newProc != null) {		newProc.dispose ();	}	/*	* Cleanup: If this tracker was resizing then the last cursor that it created	* needs to be destroyed.	*/	if (resizeCursor != 0) {		OS.DestroyCursor (resizeCursor);	}	tracking = false;	return !cancelled;}