int XKeyPress(int w, int client_data, int call_data, int continue_to_dispatch) { int result = super.XKeyPress(w, client_data, call_data, continue_to_dispatch); if (result != 0) return result; XKeyEvent keyEvent = new XKeyEvent(); OS.memmove(keyEvent, call_data, 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(OS.XtDisplayToApplicationContext(keyEvent.display), call_data); break; case OS.XK_Escape: tracking = false; cancelled = true; /* Eat the subsequent KeyRelease event */ OS.XtAppNextEvent(OS.XtDisplayToApplicationContext(keyEvent.display), call_data); 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; 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 = oldX + xChange; event.y = oldY + yChange; Point cursorPos; 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; 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); } cursorPos = adjustResizeCursor(); } 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; 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); } cursorPos = adjustMoveCursor(); } if (cursorPos != null) { oldX = cursorPos.x; oldY = cursorPos.y; } } } return result; }
/** * 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; }