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; } final int unused[] = new int[1]; int actualX[] = new int[1]; int actualY[] = new int[1]; int xDisplay = display.xDisplay; OS.XWarpPointer(xDisplay, 0, window, 0, 0, 0, 0, newX, newY); /* * 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. */ OS.XQueryPointer(xDisplay, window, unused, unused, actualX, actualY, unused, unused, unused); return new Point(actualX[0], actualY[0]); }
boolean hasCursor() { int[] unused = new int[1], buffer = new int[1]; int xDisplay = OS.XtDisplay(handle); int xWindow, xParent = OS.XDefaultRootWindow(xDisplay); do { if (OS.XQueryPointer( xDisplay, xParent, unused, buffer, unused, unused, unused, unused, unused) == 0) return false; if ((xWindow = buffer[0]) != 0) xParent = xWindow; } while (xWindow != 0); return handle == OS.XtWindowToWidget(xDisplay, xParent); }
Point adjustMoveCursor() { if (bounds == null) return null; final int unused[] = new int[1]; int actualX[] = new int[1]; int actualY[] = new int[1]; int newX = bounds.x + bounds.width / 2; int newY = bounds.y; int xDisplay = display.xDisplay; OS.XWarpPointer(xDisplay, OS.None, window, 0, 0, 0, 0, newX, newY); /* * 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. */ OS.XQueryPointer(xDisplay, window, unused, unused, actualX, actualY, unused, unused, unused); return new Point(actualX[0], actualY[0]); }
int xMouse(int type, int w, int client_data, int call_data, int continue_to_dispatch) { int xDisplay = display.xDisplay; int[] newX = new int[1], newY = new int[1], unused = new int[1]; OS.XQueryPointer(xDisplay, window, unused, unused, newX, newY, unused, unused, unused); if (oldX != newX[0] || oldY != newY[0]) { Rectangle[] oldRectangles = rectangles; boolean oldStippled = stippled; 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, 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 then return false to indicate that * the move 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(rectsToErase, oldStippled); update(); drawRectangles(rectangles, stippled); } 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 then return false to indicate that * the move 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, oldStippled); update(); drawRectangles(rectangles, stippled); } } oldX = newX[0]; oldY = newY[0]; } tracking = type != OS.ButtonRelease; return 0; }
/** * 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>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver * </ul> */ public boolean open() { checkWidget(); int xDisplay = display.xDisplay; window = OS.XDefaultRootWindow(xDisplay); if (parent != null) { window = OS.XtWindow(parent.handle); if (window == 0) return false; } cancelled = false; tracking = true; update(); drawRectangles(rectangles, stippled); int[] oldX = new int[1], oldY = new int[1]; int[] unused = new int[1], mask = new int[1]; OS.XQueryPointer(xDisplay, window, 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; } int mouseMasks = OS.Button1Mask | OS.Button2Mask | OS.Button3Mask; boolean mouseDown = (mask[0] & mouseMasks) != 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]; int ptrGrabResult = OS.XGrabPointer( xDisplay, window, 0, OS.ButtonPressMask | OS.ButtonReleaseMask | OS.PointerMotionMask, OS.GrabModeAsync, OS.GrabModeAsync, OS.None, OS.None, OS.CurrentTime); int kbdGrabResult = OS.XGrabKeyboard(xDisplay, window, 0, OS.GrabModeAsync, OS.GrabModeAsync, OS.CurrentTime); /* Tracker behaves like a Dialog with its own OS event loop. */ XAnyEvent anyEvent = new XAnyEvent(); int xEvent = OS.XtMalloc(XEvent.sizeof); int dispatch = OS.XtMalloc(4); int xtContext = OS.XtDisplayToApplicationContext(xDisplay); while (tracking) { if (parent != null && parent.isDisposed()) break; OS.XtAppNextEvent(xtContext, xEvent); OS.memmove(anyEvent, xEvent, XAnyEvent.sizeof); int widget = OS.XtWindowToWidget(anyEvent.display, anyEvent.window); switch (anyEvent.type) { case OS.MotionNotify: XPointerMotion(widget, 0, xEvent, dispatch); break; case OS.ButtonRelease: XButtonRelease(widget, 0, xEvent, dispatch); break; case OS.KeyPress: XKeyPress(widget, 0, xEvent, dispatch); break; case OS.KeyRelease: XKeyRelease(widget, 0, xEvent, dispatch); break; case OS.ButtonPress: case OS.EnterNotify: case OS.LeaveNotify: /* Do not dispatch these */ break; case OS.Expose: update(); drawRectangles(rectangles, stippled); OS.XtDispatchEvent(xEvent); drawRectangles(rectangles, stippled); break; default: OS.XtDispatchEvent(xEvent); } } if (xEvent != 0) OS.XtFree(xEvent); if (dispatch != 0) OS.XtFree(dispatch); if (!isDisposed()) { update(); drawRectangles(rectangles, stippled); } if (ptrGrabResult == OS.GrabSuccess) OS.XUngrabPointer(xDisplay, OS.CurrentTime); if (kbdGrabResult == OS.GrabSuccess) OS.XUngrabKeyboard(xDisplay, OS.CurrentTime); window = 0; return !cancelled; }