/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.widgets;


import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.internal.*;
import org.eclipse.swt.internal.cairo.*;
import org.eclipse.swt.internal.gtk.*;
import org.eclipse.swt.internal.gtk3.*;
import org.eclipse.swt.internal.gtk4.*;

/**
 *  Instances of this class implement rubber banding rectangles that are
 *  drawn onto a parent <code>Composite</code> or <code>Display</code>.
 *  These rectangles can be specified to respond to mouse and key events
 *  by either moving or resizing themselves accordingly.  Trackers are
 *  typically used to represent window geometries in a lightweight manner.
 *
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>LEFT, RIGHT, UP, DOWN, RESIZE</dd>
 * <dt><b>Events:</b></dt>
 * <dd>Move, Resize</dd>
 * </dl>
 * <p>
 * Note: Rectangle move behavior is assumed unless RESIZE is specified.
 * </p><p>
 * IMPORTANT: This class is <em>not</em> intended to be subclassed.
 * </p>
 *
 * @see <a href="http://www.eclipse.org/swt/snippets/#tracker">Tracker snippets</a>
 * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
 * @noextend This class is not intended to be subclassed by clients.
 */
public class Tracker extends Widget {
	Composite parent;
	Cursor cursor;
	long lastCursor, window, overlay;
	long surface;
	boolean tracking, cancelled, grabbed, stippled;
	Rectangle [] rectangles = new Rectangle [0], proportions = rectangles;
	Rectangle bounds;
	int cursorOrientation = SWT.NONE;
	int oldX, oldY;
	long provider;

	// Re-use/cache some items for performance reasons as draw-events must be efficient to prevent jitter.
	Rectangle cachedCombinedDisplayResolution = Display.getDefault().getBounds(); // Cached for performance reasons.
	Rectangle cachedUnion = new Rectangle(0, 0, 0, 0);
	Boolean cachedBackgroundIsOpaque; // Note purposely lazy init.

	final static int STEPSIZE_SMALL = 1;
	final static int STEPSIZE_LARGE = 9;

/**
 * Constructs a new instance of this class given its parent
 * and a style value describing its behavior and appearance.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * lists the style constants that are applicable to the class.
 * Style bits are also inherited from superclasses.
 * </p>
 *
 * @param parent a widget which will be the parent of the new instance (cannot be null)
 * @param style the style of widget to construct
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 *
 * @see SWT#LEFT
 * @see SWT#RIGHT
 * @see SWT#UP
 * @see SWT#DOWN
 * @see SWT#RESIZE
 * @see Widget#checkSubclass
 * @see Widget#getStyle
 */
public Tracker (Composite parent, int style) {
	super (parent, checkStyle(style));
	this.parent = parent;
}

/**
 * Constructs a new instance of this class given the display
 * to create it on and a style value describing its behavior
 * and appearance.
 * <p>
 * The style value is either one of the style constants defined in
 * class <code>SWT</code> which is applicable to instances of this
 * class, or must be built by <em>bitwise OR</em>'ing together
 * (that is, using the <code>int</code> "|" operator) two or more
 * of those <code>SWT</code> style constants. The class description
 * lists the style constants that are applicable to the class.
 * Style bits are also inherited from superclasses.
 * </p><p>
 * Note: Currently, null can be passed in for the display argument.
 * This has the effect of creating the tracker on the currently active
 * display if there is one. If there is no current display, the
 * tracker is created on a "default" display. <b>Passing in null as
 * the display argument is not considered to be good coding style,
 * and may not be supported in a future release of SWT.</b>
 * </p>
 *
 * @param display the display to create the tracker on
 * @param style the style of control to construct
 *
 * @exception SWTException <ul>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
 *    <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass</li>
 * </ul>
 *
 * @see SWT#LEFT
 * @see SWT#RIGHT
 * @see SWT#UP
 * @see SWT#DOWN
 * @see SWT#RESIZE
 */
public Tracker (Display display, int style) {
	if (display == null) display = Display.getCurrent ();
	if (display == null) display = Display.getDefault ();
	if (!display.isValidThread ()) {
		error (SWT.ERROR_THREAD_INVALID_ACCESS);
	}
	this.style = checkStyle (style);
	this.display = display;
	reskinWidget ();
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when the control is moved or resized, by sending
 * it one of the messages defined in the <code>ControlListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see ControlListener
 * @see #removeControlListener
 */
public void addControlListener(ControlListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener (SWT.Resize, typedListener);
	addListener (SWT.Move, typedListener);
}

/**
 * Adds the listener to the collection of listeners who will
 * be notified when keys are pressed and released on the system keyboard, by sending
 * it one of the messages defined in the <code>KeyListener</code>
 * interface.
 *
 * @param listener the listener which should be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see KeyListener
 * @see #removeKeyListener
 */
public void addKeyListener(KeyListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	TypedListener typedListener = new TypedListener (listener);
	addListener(SWT.KeyUp,typedListener);
	addListener(SWT.KeyDown,typedListener);
}

Point adjustMoveCursor () {
	if (bounds == null) return null;
	int newX = bounds.x + bounds.width / 2;
	int newY = bounds.y;

	Point point = display.mapInPixels(parent, null, newX, newY);
	display.setCursorLocation(point);

	int[] actualX = new int[1], actualY = new int[1], state = new int[1];
	if (GTK.GTK4) {
		double[] actualXDouble = new double[1], actualYDouble = new double[1];
		display.getPointerPosition(actualXDouble, actualYDouble);

		actualX[0] = (int)actualXDouble[0];
		actualY[0] = (int)actualYDouble[0];
	} else {
		display.getWindowPointerPosition(window, actualX, actualY, state);
	}

	return new Point(actualX[0], actualY[0]);
}

Point adjustResizeCursor () {
	if (bounds == null) return null;
	int newX, newY;

	if ((cursorOrientation & SWT.LEFT) != 0) {
		newX = bounds.x;
	} else if ((cursorOrientation & SWT.RIGHT) != 0) {
		newX = bounds.x + bounds.width;
	} else {
		newX = bounds.x + bounds.width / 2;
	}

	if ((cursorOrientation & SWT.UP) != 0) {
		newY = bounds.y;
	} else if ((cursorOrientation & SWT.DOWN) != 0) {
		newY = bounds.y + bounds.height;
	} else {
		newY = bounds.y + bounds.height / 2;
	}

	Point point = display.mapInPixels (parent, null, newX, newY);
	display.setCursorLocation (point);

	/*
	 * The call to XWarpPointer does not always place the pointer on the
	 * exact location that is specified, so do a query (below) to get the
	 * actual location of the pointer after it has been moved.
	 */
	int [] actualX = new int [1], actualY = new int [1], state = new int [1];
	if (GTK.GTK4) {
		double[] actualXDouble = new double[1], actualYDouble = new double[1];
		display.getPointerPosition(actualXDouble, actualYDouble);

		actualX[0] = (int)actualXDouble[0];
		actualY[0] = (int)actualYDouble[0];
	} else {
		display.getWindowPointerPosition(window, actualX, actualY, state);
	}

	return new Point(actualX[0], actualY[0]);
}


/**
 * Stops displaying the tracker rectangles.  Note that this is not considered
 * to be a cancelation by the user.
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void close () {
	checkWidget();
	tracking = false;
}

static int checkStyle (int style) {
	if ((style & (SWT.LEFT | SWT.RIGHT | SWT.UP | SWT.DOWN)) == 0) {
		style |= SWT.LEFT | SWT.RIGHT | SWT.UP | SWT.DOWN;
	}
	return style;
}

Rectangle computeBounds () {
	if (rectangles.length == 0) return null;
	int xMin = rectangles [0].x;
	int yMin = rectangles [0].y;
	int xMax = rectangles [0].x + rectangles [0].width;
	int yMax = rectangles [0].y + rectangles [0].height;

	for (int i = 1; i < rectangles.length; i++) {
		if (rectangles [i].x < xMin) xMin = rectangles [i].x;
		if (rectangles [i].y < yMin) yMin = rectangles [i].y;
		int rectRight = rectangles [i].x + rectangles [i].width;
		if (rectRight > xMax) xMax = rectRight;
		int rectBottom = rectangles [i].y + rectangles [i].height;
		if (rectBottom > yMax) yMax = rectBottom;
	}

	return new Rectangle (xMin, yMin, xMax - xMin, yMax - yMin);
}

Rectangle [] computeProportions (Rectangle [] rects) {
	Rectangle [] result = new Rectangle [rects.length];
	bounds = computeBounds ();
	if (bounds != null) {
		for (int i = 0; i < rects.length; i++) {
			int x = 0, y = 0, width = 0, height = 0;
			if (bounds.width != 0) {
				x = (rects [i].x - bounds.x) * 100 / bounds.width;
				width = rects [i].width * 100 / bounds.width;
			} else {
				width = 100;
			}
			if (bounds.height != 0) {
				y = (rects [i].y - bounds.y) * 100 / bounds.height;
				height = rects [i].height * 100 / bounds.height;
			} else {
				height = 100;
			}
			result [i] = new Rectangle (x, y, width, height);
		}
	}
	return result;
}

/**
 * Developer note:
 * - Rectangles can have absolute coords [Tracker(Display)] or relative to parent [Tracker(Composite)]
 * - This method is called a lot, optimize your code.
 * - Note, region != rectangle. A region can have a non-squared form, e.g an 'L' shape.
 *
 * @param rects
 */
void drawRectangles (Rectangle [] rects) {
	long gdkResource = 0;
	if (GTK.GTK4) {
		if (parent != null) gdkResource = gtk_widget_get_surface(parent.handle);
	} else {
		gdkResource = GDK.gdk_get_default_root_window();
	}
	if (parent != null) {
		long paintHandle = parent.paintHandle();
		gdkResource = GTK.GTK4 ? gtk_widget_get_surface(paintHandle) : gtk_widget_get_window (paintHandle);
	}
	if (gdkResource == 0) return;

	if (overlay == 0) return;
	GTK.gtk_widget_shape_combine_region (overlay, 0);

	// Bug 498217.
	// As of Gtk 3.9.1, Commit a60ccd3672467efb454b121993febc36f33cbc79, off-screen GDK windows are not processed.
	// Because of this gtk doesn't send move events to SWT. Platform.UI uses an off-screen tracker to draw
	// custom rectangles for it's part-drag-preview. Drawing/updates for these broke because tracker is off screen.
	// Solution: If a tracker is to move off-screen, then instead draw it 1x1 and transparent.
	boolean isOnScreen = true;
	{ // Figure out if the combined rectangles are on or off screen.

		// Produce a single rectangle big enough to contain all rects.
		// Note, this is different from loop below that creates a Region. (See region != rectangle note in javadoc).
		cachedUnion.x = rects[0].x;
		cachedUnion.y = rects[0].y;
		cachedUnion.width = rects[0].width;
		cachedUnion.height = rects[0].height;
		if (rects.length > 1) {
			for (int i = 1; i < rects.length; i++) {
				cachedUnion.add(rects[i]);
			}
		}

		// Ensure we have absolute screen coordinates. (btw, there are no absolute coordinates on Wayland, so Tracker(Display) is probably broken).
		if (parent != null) {  // if Tracker(Display) has absolute coords.  Tracker(Composite) has relative. For relative, we need to find absolute.
			cachedUnion = display.mapInPixels(parent, null, cachedUnion) ;
		}

		if (!cachedCombinedDisplayResolution.intersects(cachedUnion)) {
			isOnScreen = false;
		}
	}

	long region = Cairo.cairo_region_create ();
	cairo_rectangle_int_t rect = new cairo_rectangle_int_t();
	if (isOnScreen) {
		// Combine Rects into a region. (region is not necessarily a rectangle, E.g it can be 'L' shaped etc..).
		for (int i = 0; i < rects.length; i++) {
			// Turn filled rectangles into just the outer lines by drawing one line at a time.
			Rectangle r = parent != null ? display.mapInPixels(parent, null, rects[i]) : rects[i];
			rect.x = r.x;
			rect.y = r.y;
			rect.width = r.width + 1;
			rect.height = 1;
			Cairo.cairo_region_union_rectangle(region, rect); // Top line
			rect.width = 1;
			rect.height = r.height + 1;
			Cairo.cairo_region_union_rectangle(region, rect); // Left line.
			rect.x = r.x + r.width;
			Cairo.cairo_region_union_rectangle(region, rect); // Right line.
			rect.x = r.x;
			rect.y = r.y + r.height;
			rect.width = r.width + 1;
			rect.height = 1;
			Cairo.cairo_region_union_rectangle(region, rect); // Bottom line
		}
		setTrackerBackground(true);
	} else { // Offscreen
		// part of Bug 498217 fix. Tracker must be at least 1x1 for move events to work.
		rect.x = 0;
		rect.y = 0;
		rect.height = 1;
		rect.width = 1;
		Cairo.cairo_region_union_rectangle(region, rect);
		setTrackerBackground(false);
	}

	GTK.gtk_widget_shape_combine_region (overlay, region);
	Cairo.cairo_region_destroy (region);
	if (GTK.GTK4) {
		long overlaySurface = GTK4.gtk_native_get_surface(GTK.gtk_widget_get_native (overlay));
		GDK.gdk_surface_hide (overlaySurface);
		/* TODO: GTK does not provide a gdk_surface_show, probably will require use of the present api */
	} else {
		long overlayWindow = GTK.gtk_widget_get_window (overlay);
		GDK.gdk_window_hide (overlayWindow);
		GDK.gdk_window_show (overlayWindow);
	}
}

/**
 * Returns the bounds that are being drawn, expressed relative to the parent
 * widget.  If the parent is a <code>Display</code> then these are screen
 * coordinates.
 *
 * @return the bounds of the Rectangles being drawn
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public Rectangle [] getRectangles () {
	checkWidget();
	Rectangle [] result = new Rectangle [rectangles.length];
	for (int i = 0; i < rectangles.length; i++) {
		Rectangle current = rectangles [i];
		result [i] = DPIUtil.autoScaleDown (new Rectangle (current.x, current.y, current.width, current.height));
	}
	return result;
}

Rectangle [] getRectanglesInPixels () {
	checkWidget();
	Rectangle [] result = new Rectangle [rectangles.length];
	for (int i = 0; i < rectangles.length; i++) {
		Rectangle current = rectangles [i];
		result [i] = new Rectangle (current.x, current.y, current.width, current.height);
	}
	return result;
}

/**
 * Returns <code>true</code> if the rectangles are drawn with a stippled line, <code>false</code> otherwise.
 *
 * @return the stippled effect of the rectangles
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public boolean getStippled () {
	checkWidget();
	return stippled;
}

boolean grab () {
	long cursor = this.cursor != null ? this.cursor.handle : 0;
	int result = gdk_pointer_grab (GTK.GTK4 ? surface : window, GDK.GDK_OWNERSHIP_NONE, false,
			GDK.GDK_POINTER_MOTION_MASK | GDK.GDK_BUTTON_RELEASE_MASK, 0, cursor, GDK.GDK_CURRENT_TIME);
	return result == GDK.GDK_GRAB_SUCCESS;
}

@Override
long gtk_button_release_event (long widget, long event) {
	Control.mouseDown = false;
	return gtk_mouse (GTK.GTK4 ? GDK.GDK4_BUTTON_RELEASE : GDK.GDK_BUTTON_RELEASE, widget, event);
}

@Override
long gtk_key_press_event (long widget, long eventPtr) {
	long result = super.gtk_key_press_event (widget, eventPtr);
	if (result != 0) return result;

	int [] state = new int [1];
	int [] keyval = new int [1];
	if (GTK.GTK4) {
		state[0] = GDK.gdk_event_get_modifier_state(eventPtr);
		keyval[0] = GDK.gdk_key_event_get_keyval(eventPtr);
	} else {
		GDK.gdk_event_get_state(eventPtr, state);
		GDK.gdk_event_get_keyval(eventPtr, keyval);
	}

	int stepSize = ((state[0] & GDK.GDK_CONTROL_MASK) != 0) ? STEPSIZE_SMALL : STEPSIZE_LARGE;
	int xChange = 0, yChange = 0;
	switch (keyval[0]) {
		case GDK.GDK_Escape:
			cancelled = true;
			// fallthrough
		case GDK.GDK_Return:
			tracking = false;
			break;
		case GDK.GDK_Left:
			xChange = -stepSize;
			break;
		case GDK.GDK_Right:
			xChange = stepSize;
			break;
		case GDK.GDK_Up:
			yChange = -stepSize;
			break;
		case GDK.GDK_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 ();
		Rectangle eventRect = new Rectangle (oldX + xChange, oldY + yChange, 0, 0);
		event.setBounds (DPIUtil.autoScaleDown (eventRect));
		if (parent != null && (parent.style & SWT.MIRRORED) != 0) {
			event.x = DPIUtil.autoScaleDown (parent.getClientWidth ()) - event.width - event.x;
		}
		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 return false to indicate
			* that the tracking has failed.
			*/
			if (isDisposed ()) {
				cancelled = true;
				return 1;
			}
			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 (rectangles);
			}
			Point cursorPos = adjustResizeCursor ();
			if (cursorPos != null) {
				oldX = cursorPos.x;
				oldY = cursorPos.y;
			}
		} 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 return false to indicate
			* that the tracking has failed.
			*/
			if (isDisposed ()) {
				cancelled = true;
				return 1;
			}
			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);
				update ();
				drawRectangles (rectangles);
			}
			Point cursorPos = adjustMoveCursor ();
			if (cursorPos != null) {
				oldX = cursorPos.x;
				oldY = cursorPos.y;
			}
		}
	}
	return result;
}

@Override
long gtk_motion_notify_event (long widget, long eventPtr) {
	long cursor = this.cursor != null ? this.cursor.handle : 0;
	if (cursor != lastCursor) {
		ungrab ();
		grabbed = grab ();
		lastCursor = cursor;
	}
	return gtk_mouse (GTK.GTK4 ? GDK.GDK4_MOTION_NOTIFY : GDK.GDK_MOTION_NOTIFY, widget, eventPtr);
}

long gtk_mouse (int eventType, long widget, long eventPtr) {
	int [] newX = new int [1], newY = new int [1];
	if (GTK.GTK4) {
		double[] newXDouble = new double[1], newYDouble = new double[1];
		display.getPointerPosition(newXDouble, newYDouble);

		newX[0] = (int)newXDouble[0];
		newY[0] = (int)newYDouble[0];
	} else {
		display.getWindowPointerPosition(window, newX, newY, null);
	}

	if (oldX != newX [0] || oldY != 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 ();
		if (parent == null) {
			Rectangle eventRect = new Rectangle (newX [0], newY [0], 0, 0);
			event.setBounds (DPIUtil.autoScaleDown (eventRect));
		} else {
			Point screenCoord = display.mapInPixels (parent, null, newX [0], newY [0]);
			Rectangle eventRect = new Rectangle (screenCoord.x, screenCoord.y, 0, 0);
			event.setBounds (DPIUtil.autoScaleDown (eventRect));
		}
		if ((style & SWT.RESIZE) != 0) {
			resizeRectangles (newX [0] - oldX, newY [0] - oldY);
			sendEvent (SWT.Resize, event);
			/*
			* 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;
				return 1;
			}
			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 (rectangles);
			}
			Point cursorPos = adjustResizeCursor ();
			if (cursorPos != null) {
				newX [0] = cursorPos.x;
				newY [0] = cursorPos.y;
			}
		} else {
			moveRectangles (newX [0] - oldX, newY [0] - oldY);
			sendEvent (SWT.Move, event);
			/*
			* 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;
				return 1;
			}
			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 (rectangles);
			}
		}
		oldX = newX [0];
		oldY = newY [0];
	}
	eventType = Control.fixGdkEventTypeValues(eventType);
	tracking = eventType != GDK.GDK_BUTTON_RELEASE;
	return 0;
}

void moveRectangles (int xChange, int yChange) {
	if (bounds == null) return;
	if (xChange < 0 && ((style & SWT.LEFT) == 0)) xChange = 0;
	if (xChange > 0 && ((style & SWT.RIGHT) == 0)) xChange = 0;
	if (yChange < 0 && ((style & SWT.UP) == 0)) yChange = 0;
	if (yChange > 0 && ((style & SWT.DOWN) == 0)) yChange = 0;
	if (xChange == 0 && yChange == 0) return;
	if (parent != null && (parent.style & SWT.MIRRORED) != 0) xChange *= -1;
	bounds.x += xChange; bounds.y += yChange;
	for (int i = 0; i < rectangles.length; i++) {
		rectangles [i].x += xChange;
		rectangles [i].y += yChange;
	}
}

/**
 * Displays the Tracker rectangles for manipulation by the user.  Returns when
 * the user has either finished manipulating the rectangles or has cancelled the
 * Tracker.
 *
 * @return <code>true</code> if the user did not cancel the Tracker, <code>false</code> otherwise
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public boolean open () {
	checkWidget();
	if (!GTK.GTK4) window = GDK.gdk_get_default_root_window();
	if (parent != null) {
		window = gtk_widget_get_window (parent.paintHandle());
	}
	if (window == 0) return false;
	cancelled = false;
	tracking = true;
	int [] oldX = new int [1], oldY = new int [1], state = new int [1];
	if (GTK.GTK4) {
		double [] oldXDouble = new double [1], oldYDouble = new double [1];
		display.getPointerPosition(oldXDouble, oldYDouble);

		oldX[0] = (int) oldXDouble[0];
		oldY[0] = (int) oldYDouble[0];
	} else {
		display.getWindowPointerPosition (window, oldX, oldY, state);
	}

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

	int mask = GDK.GDK_BUTTON1_MASK | GDK.GDK_BUTTON2_MASK | GDK.GDK_BUTTON3_MASK;
	boolean mouseDown = (state [0] & mask) != 0;
	if (!mouseDown) {
		Point cursorPos = null;
		if ((style & SWT.RESIZE) != 0) {
			cursorPos = adjustResizeCursor ();
		} else {
			cursorPos = adjustMoveCursor ();
		}
		if (cursorPos != null) {
			oldX [0] = cursorPos.x;
			oldY [0] = cursorPos.y;
		}
	}
	this.oldX = oldX [0];
	this.oldY = oldY [0];

	grabbed = grab ();
	lastCursor = this.cursor != null ? this.cursor.handle : 0;

	cachedCombinedDisplayResolution = Display.getDefault().getBounds(); // In case resolution was changed during run time.
	overlay = GTK3.gtk_window_new (GTK.GTK_WINDOW_POPUP);
	GTK3.gtk_window_set_skip_taskbar_hint (overlay, true);
	GTK.gtk_window_set_title (overlay, new byte [1]);
	if (parent != null) GTK.gtk_window_set_transient_for(overlay, parent.topHandle());
	GTK.gtk_widget_realize (overlay);
	if (!GTK.GTK4) {
		long overlayWindow = GTK.gtk_widget_get_window (overlay);
		GDK.gdk_window_set_override_redirect (overlayWindow, true);
	}
	setTrackerBackground(true);
	Rectangle bounds = display.getBoundsInPixels();
	GTK3.gtk_window_move (overlay, bounds.x, bounds.y);
	GTK3.gtk_window_resize (overlay, bounds.width, bounds.height);
	GTK.gtk_widget_show (overlay);

	/* Tracker behaves like a Dialog with its own OS event loop. */
	Display display = this.display;
	Tracker oldTracker = display.tracker;
	display.tracker = this;
	try {
		while (tracking) {
			if (parent != null && parent.isDisposed ()) break;
			display.runSkin ();
			display.runDeferredLayouts ();
			display.sendPreExternalEventDispatchEvent ();
			if (GTK.GTK4) {
				OS.g_main_context_iteration (0, true);
			} else {
				GTK3.gtk_main_iteration_do (true);
			}
			display.sendPostExternalEventDispatchEvent ();
			display.runAsyncMessages (false);
		}
	} finally {
		display.tracker = oldTracker;
	}
	ungrab ();
	if (overlay != 0) {
		GTK.gtk_widget_destroy (overlay);
		overlay = 0;
	}
	window = 0;
	return !cancelled;
}

private void setTrackerBackground(boolean opaque) {
	if (cachedBackgroundIsOpaque == null || cachedBackgroundIsOpaque.booleanValue() != opaque) {
		cachedBackgroundIsOpaque = Boolean.valueOf(opaque);
	} else if (opaque == cachedBackgroundIsOpaque.booleanValue()) {
		return;
	}
	String css;
	if (opaque) {
		GTK.gtk_widget_set_opacity (overlay, 1.0);
		css = "window {background-color: rgb(0,0,0);}";
	} else {
		GTK.gtk_widget_set_opacity (overlay, 0.0);
		css = "window {  "
				+ "border-top-color: transparent;"
				+ "border-left-color: transparent;"
				+ "border-right-color: transparent;"
				+ "border-bottom-color: transparent;}";
	}
	long context = GTK.gtk_widget_get_style_context (overlay);
	if (provider == 0) {
		provider = GTK.gtk_css_provider_new ();
		GTK.gtk_style_context_add_provider (context, provider, GTK.GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
		OS.g_object_unref (provider);
	}
	if (GTK.GTK4) {
		GTK.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs (css, true), -1);
	} else {
		GTK.gtk_css_provider_load_from_data (provider, Converter.wcsToMbcs (css, true), -1, null);
	}
	GTK.gtk_style_context_invalidate (context);
	long region = Cairo.cairo_region_create ();

	if (GTK.GTK4) {
		//TODO: GTK4
		//GDK.gdk_surface_set_opaque_region(context, region);
		//GDK.gdk_surface_set_input_region(context, region);
	} else {
		GTK.gtk_widget_shape_combine_region (overlay, region);
		GTK.gtk_widget_input_shape_combine_region (overlay, region);
	}

	Cairo.cairo_region_destroy (region);
}

boolean processEvent (long eventPtr) {
	int eventType = GDK.gdk_event_get_event_type(eventPtr);
	eventType = Control.fixGdkEventTypeValues(eventType);
	long widget = GTK3.gtk_get_event_widget (eventPtr);
	switch (eventType) {
		case GDK.GDK_MOTION_NOTIFY: gtk_motion_notify_event (widget, eventPtr); break;
		case GDK.GDK_BUTTON_RELEASE: gtk_button_release_event (widget, eventPtr); break;
		case GDK.GDK_KEY_PRESS: gtk_key_press_event (widget, eventPtr); break;
		case GDK.GDK_KEY_RELEASE: gtk_key_release_event (widget, eventPtr); break;
		case GDK.GDK_BUTTON_PRESS:
		case GDK.GDK_2BUTTON_PRESS:
		case GDK.GDK_3BUTTON_PRESS:
		case GDK.GDK_ENTER_NOTIFY:
		case GDK.GDK_LEAVE_NOTIFY:
			/* Do not dispatch these */
			break;
		case GDK.GDK_EXPOSE:
			update ();
			GTK3.gtk_main_do_event (eventPtr);
			break;
		default:
			return true;
	}
	return false;
}

@Override
void releaseWidget () {
	super.releaseWidget ();
	parent = null;
	rectangles = proportions = null;
	bounds = null;
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when the control is moved or resized.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see ControlListener
 * @see #addControlListener
 */
public void removeControlListener (ControlListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.Resize, listener);
	eventTable.unhook (SWT.Move, listener);
}

/**
 * Removes the listener from the collection of listeners who will
 * be notified when keys are pressed and released on the system keyboard.
 *
 * @param listener the listener which should no longer be notified
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the listener is null</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 *
 * @see KeyListener
 * @see #addKeyListener
 */
public void removeKeyListener(KeyListener listener) {
	checkWidget();
	if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);
	if (eventTable == null) return;
	eventTable.unhook (SWT.KeyUp, listener);
	eventTable.unhook (SWT.KeyDown, listener);
}

void resizeRectangles (int xChange, int yChange) {
	if (bounds == null) return;
	if (parent != null && (parent.style & SWT.MIRRORED) != 0) xChange *= -1;
	/*
	* If the cursor orientation has not been set in the orientation of
	* this change then try to set it here.
	*/
	if (xChange < 0 && ((style & SWT.LEFT) != 0) && ((cursorOrientation & SWT.RIGHT) == 0)) {
		cursorOrientation |= SWT.LEFT;
	}
	if (xChange > 0 && ((style & SWT.RIGHT) != 0) && ((cursorOrientation & SWT.LEFT) == 0)) {
		cursorOrientation |= SWT.RIGHT;
	}
	if (yChange < 0 && ((style & SWT.UP) != 0) && ((cursorOrientation & SWT.DOWN) == 0)) {
		cursorOrientation |= SWT.UP;
	}
	if (yChange > 0 && ((style & SWT.DOWN) != 0) && ((cursorOrientation & SWT.UP) == 0)) {
		cursorOrientation |= SWT.DOWN;
	}

	/*
	 * If the bounds will flip about the x or y axis then apply the adjustment
	 * up to the axis (ie.- where bounds width/height becomes 0), change the
	 * cursor's orientation accordingly, and flip each Rectangle's origin (only
	 * necessary for > 1 Rectangles)
	 */
	if ((cursorOrientation & SWT.LEFT) != 0) {
		if (xChange > bounds.width) {
			if ((style & SWT.RIGHT) == 0) return;
			cursorOrientation |= SWT.RIGHT;
			cursorOrientation &= ~SWT.LEFT;
			bounds.x += bounds.width;
			xChange -= bounds.width;
			bounds.width = 0;
			if (proportions.length > 1) {
				for (int i = 0; i < proportions.length; i++) {
					Rectangle proportion = proportions [i];
					proportion.x = 100 - proportion.x - proportion.width;
				}
			}
		}
	} else if ((cursorOrientation & SWT.RIGHT) != 0) {
		if (bounds.width < -xChange) {
			if ((style & SWT.LEFT) == 0) return;
			cursorOrientation |= SWT.LEFT;
			cursorOrientation &= ~SWT.RIGHT;
			xChange += bounds.width;
			bounds.width = 0;
			if (proportions.length > 1) {
				for (int i = 0; i < proportions.length; i++) {
					Rectangle proportion = proportions [i];
					proportion.x = 100 - proportion.x - proportion.width;
				}
			}
		}
	}
	if ((cursorOrientation & SWT.UP) != 0) {
		if (yChange > bounds.height) {
			if ((style & SWT.DOWN) == 0) return;
			cursorOrientation |= SWT.DOWN;
			cursorOrientation &= ~SWT.UP;
			bounds.y += bounds.height;
			yChange -= bounds.height;
			bounds.height = 0;
			if (proportions.length > 1) {
				for (int i = 0; i < proportions.length; i++) {
					Rectangle proportion = proportions [i];
					proportion.y = 100 - proportion.y - proportion.height;
				}
			}
		}
	} else if ((cursorOrientation & SWT.DOWN) != 0) {
		if (bounds.height < -yChange) {
			if ((style & SWT.UP) == 0) return;
			cursorOrientation |= SWT.UP;
			cursorOrientation &= ~SWT.DOWN;
			yChange += bounds.height;
			bounds.height = 0;
			if (proportions.length > 1) {
				for (int i = 0; i < proportions.length; i++) {
					Rectangle proportion = proportions [i];
					proportion.y = 100 - proportion.y - proportion.height;
				}
			}
		}
	}

	// apply the bounds adjustment
	if ((cursorOrientation & SWT.LEFT) != 0) {
		bounds.x += xChange;
		bounds.width -= xChange;
	} else if ((cursorOrientation & SWT.RIGHT) != 0) {
		bounds.width += xChange;
	}
	if ((cursorOrientation & SWT.UP) != 0) {
		bounds.y += yChange;
		bounds.height -= yChange;
	} else if ((cursorOrientation & SWT.DOWN) != 0) {
		bounds.height += yChange;
	}

	Rectangle [] newRects = new Rectangle [rectangles.length];
	for (int i = 0; i < rectangles.length; i++) {
		Rectangle proportion = proportions[i];
		newRects[i] = new Rectangle (
			proportion.x * bounds.width / 100 + bounds.x,
			proportion.y * bounds.height / 100 + bounds.y,
			proportion.width * bounds.width / 100,
			proportion.height * bounds.height / 100);
	}
	rectangles = newRects;
}

/**
 * Sets the <code>Cursor</code> of the Tracker.  If this cursor is <code>null</code>
 * then the cursor reverts to the default.
 *
 * @param newCursor the new <code>Cursor</code> to display
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setCursor (Cursor newCursor) {
	checkWidget ();
	cursor = newCursor;
}

/**
 * Specifies the rectangles that should be drawn, expressed relative to the parent
 * widget.  If the parent is a Display then these are screen coordinates.
 *
 * @param rectangles the bounds of the rectangles to be drawn
 *
 * @exception IllegalArgumentException <ul>
 *    <li>ERROR_NULL_ARGUMENT - if the set of rectangles is null or contains a null rectangle</li>
 * </ul>
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setRectangles (Rectangle [] rectangles) {
	checkWidget();
	if (rectangles == null) error (SWT.ERROR_NULL_ARGUMENT);
	int length = rectangles.length;
	for (int i = 0; i < length; i++) {
		rectangles [i] = DPIUtil.autoScaleUp (rectangles [i]);
	}
	setRectanglesInPixels (rectangles);
}

void setRectanglesInPixels (Rectangle [] rectangles) {
	checkWidget();
	if (rectangles == null) error (SWT.ERROR_NULL_ARGUMENT);
	int length = rectangles.length;
	this.rectangles = new Rectangle [length];
	for (int i = 0; i < length; i++) {
		Rectangle current = rectangles [i];
		if (current == null) error (SWT.ERROR_NULL_ARGUMENT);
		this.rectangles [i] = new Rectangle (current.x, current.y, current.width, current.height);
	}
	proportions = computeProportions (rectangles);
}

/**
 * Changes the appearance of the line used to draw the rectangles.
 *
 * @param stippled <code>true</code> if rectangle should appear stippled
 *
 * @exception SWTException <ul>
 *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
 *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
 * </ul>
 */
public void setStippled (boolean stippled) {
	checkWidget();
	this.stippled = stippled;
}

void ungrab () {
	if (grabbed) gdk_pointer_ungrab (window, GDK.GDK_CURRENT_TIME);
}

void update () {
	if (parent != null) {
		if (parent.isDisposed ()) return;
		parent.getShell ().update ();
	} else {
		display.update ();
	}
}

}
