diff options
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt')
3 files changed, 466 insertions, 405 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Control.java index 1a08b9f572..0eb1e7b6b2 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Control.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Control.java @@ -11,7 +11,6 @@ package org.eclipse.swt.widgets; -import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.motif.*; import org.eclipse.swt.*; import org.eclipse.swt.graphics.*; @@ -1705,106 +1704,6 @@ void sendHelpEvent (int callData) { control = control.parent; } } -boolean sendIMKeyEvent (int type, XKeyEvent xEvent) { - return sendIMKeyEvent (type, xEvent, 0); -} -boolean sendIMKeyEvent (int type, XKeyEvent xEvent, int textHandle) { - /* - * Bug in Motif. On Linux only, XmImMbLookupString () does not return - * XBufferOverflow as the status if the buffer is too small. The fix - * is to pass a large buffer. - */ - byte [] buffer = new byte [512]; - int [] status = new int [1], unused = new int [1]; - int focusHandle = OS.XtWindowToWidget (xEvent.display, xEvent.window); - int length = OS.XmImMbLookupString (focusHandle, xEvent, buffer, buffer.length, unused, status); - if (status [0] == OS.XBufferOverflow) { - buffer = new byte [length]; - length = OS.XmImMbLookupString (focusHandle, xEvent, buffer, length, unused, status); - } - if (length == 0) return true; - - /* Convert from MBCS to UNICODE and send the event */ - /* Use the character encoding for the default locale */ - char [] chars = Converter.mbcsToWcs (null, buffer); - int index = 0, count = 0; - while (index < chars.length) { - if (chars [index] == 0) { - chars [count] = 0; - break; - } - Event event = new Event (); - event.time = xEvent.time; - event.character = chars [index]; - setInputState (event, xEvent.state); - sendEvent (type, event); - // widget could be disposed at this point - - /* - * It is possible (but unlikely), that application - * code could have disposed the widget in the key - * events. If this happens, end the processing of - * the key by returning false. - */ - if (isDisposed ()) return false; - if (event.doit) chars [count++] = chars [index]; - index++; - } - if (count == 0) return false; - if (textHandle != 0) { - /* - * Bug in Motif. On Solaris and Linux, XmImMbLookupString() clears - * the characters from the IME. This causes the characters to be - * stolen from the text widget. The fix is to detect that the IME - * has been cleared and use XmTextInsert() to insert the stolen - * characters. This problem does not happen on AIX. - */ - byte [] testBuffer = new byte [5]; - int testLength = OS.XmImMbLookupString (textHandle, xEvent, testBuffer, testBuffer.length, unused, unused); - if (testLength == 0 || index != count) { - int [] start = new int [1], end = new int [1]; - OS.XmTextGetSelectionPosition (textHandle, start, end); - if (start [0] == end [0]) { - start [0] = end [0] = OS.XmTextGetInsertionPosition (textHandle); - } - boolean warnings = display.getWarnings (); - display.setWarnings (false); - if (index != count) { - buffer = Converter.wcsToMbcs (getCodePage (), chars, true); - } - OS.XmTextReplace (textHandle, start [0], end [0], buffer); - int position = start [0] + count; - OS.XmTextSetInsertionPosition (textHandle, position); - display.setWarnings (warnings); - return false; - } - } - return true; -} -boolean sendKeyEvent (int type, XKeyEvent xEvent) { - Event event = new Event (); - event.time = xEvent.time; - if (!setKeyState (event, xEvent)) return true; - Control control = this; - if ((state & CANVAS) != 0) { - if ((style & SWT.NO_FOCUS) != 0) { - control = display.getFocusControl (); - } - } - if (control != null) { - control.sendEvent (type, event); - // widget could be disposed at this point - - /* - * It is possible (but unlikely), that application - * code could have disposed the widget in the key - * events. If this happens, end the processing of - * the key by returning false. - */ - if (isDisposed ()) return false; - } - return event.doit; -} void sendMouseEvent (int type) { int xDisplay = OS.XtDisplay (handle), xWindow = OS.XtWindow (handle); int [] windowX = new int [1], windowY = new int [1], mask = new int [1], unused = new int [1]; @@ -3121,21 +3020,6 @@ int xFocusOut (XFocusChangeEvent xEvent) { } return 0; } -int XKeyPress (int w, int client_data, int call_data, int continue_to_dispatch) { - XKeyEvent xEvent = new XKeyEvent (); - OS.memmove (xEvent, call_data, XKeyEvent.sizeof); - boolean doit = true; - if (xEvent.keycode != 0) { - doit = sendKeyEvent (SWT.KeyDown, xEvent); - } else { - doit = sendIMKeyEvent (SWT.KeyDown, xEvent); - } - if (!doit) { - OS.memmove (continue_to_dispatch, new int [1], 4); - return 1; - } - return 0; -} int XKeyRelease (int w, int client_data, int call_data, int continue_to_dispatch) { XKeyEvent xEvent = new XKeyEvent (); OS.memmove (xEvent, call_data, XKeyEvent.sizeof); @@ -3147,11 +3031,7 @@ int XKeyRelease (int w, int client_data, int call_data, int continue_to_dispatch showMenu (xEvent.x_root, xEvent.y_root); } } - if (!sendKeyEvent (SWT.KeyUp, xEvent)) { - OS.memmove (continue_to_dispatch, new int [1], 4); - return 1; - } - return 0; + return super.XKeyRelease (w, client_data, call_data, continue_to_dispatch); } int XLeaveWindow (int w, int client_data, int call_data, int continue_to_dispatch) { display.removeMouseHoverTimeOut (); diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Tracker.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Tracker.java index 09e24b1b98..fe26955ae6 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Tracker.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Tracker.java @@ -37,11 +37,12 @@ import org.eclipse.swt.events.*; */ public class Tracker extends Widget { Composite parent; - boolean tracking, stippled; + boolean tracking, cancelled, stippled; Rectangle [] rectangles, proportions; Rectangle bounds; int cursorOrientation = SWT.NONE; - int cursor; + int cursor, window, oldX, oldY; + final static int STEPSIZE_SMALL = 1; final static int STEPSIZE_LARGE = 9; @@ -152,8 +153,34 @@ public void addControlListener (ControlListener 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 (int xDisplay, int xWindow) { +Point adjustMoveCursor () { final int unused[] = new int[1]; int actualX[] = new int[1]; int actualY[] = new int[1]; @@ -161,16 +188,17 @@ Point adjustMoveCursor (int xDisplay, int xWindow) { int newX = bounds.x + bounds.width / 2; int newY = bounds.y; - OS.XWarpPointer (xDisplay, OS.None, xWindow, 0, 0, 0, 0, newX, newY); + 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, xWindow, unused, unused, actualX, actualY, unused, unused, unused); + OS.XQueryPointer (xDisplay, window, unused, unused, actualX, actualY, unused, unused, unused); return new Point (actualX[0], actualY[0]); } -Point adjustResizeCursor (int xDisplay, int xWindow) { +Point adjustResizeCursor () { int newX, newY; if ((cursorOrientation & SWT.LEFT) != 0) { @@ -192,13 +220,14 @@ Point adjustResizeCursor (int xDisplay, int xWindow) { final int unused[] = new int[1]; int actualX[] = new int[1]; int actualY[] = new int[1]; - OS.XWarpPointer (xDisplay, 0, xWindow, 0, 0, 0, 0, newX, newY); + 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, xWindow, unused, unused, actualX, actualY, unused, unused, unused); + OS.XQueryPointer (xDisplay, window, unused, unused, actualX, actualY, unused, unused, unused); return new Point (actualX[0], actualY[0]); } static int checkStyle (int style) { @@ -365,17 +394,17 @@ public boolean open () { checkWidget (); if (rectangles == null) return false; int xDisplay = display.xDisplay; - int xWindow = OS.XDefaultRootWindow (xDisplay); + window = OS.XDefaultRootWindow (xDisplay); if (parent != null) { - xWindow = OS.XtWindow (parent.handle); - if (xWindow == 0) return false; + window = OS.XtWindow (parent.handle); + if (window == 0) return false; } - boolean cancelled = false; + cancelled = false; tracking = true; drawRectangles (rectangles, stippled); 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); + 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 @@ -395,288 +424,37 @@ public boolean open () { boolean mouseDown = (mask [0] & mouseMasks) != 0; if (!mouseDown) { if ((style & SWT.RESIZE) != 0) { - cursorPos = adjustResizeCursor (xDisplay, xWindow); + cursorPos = adjustResizeCursor (); } else { - cursorPos = adjustMoveCursor (xDisplay, xWindow); + cursorPos = adjustMoveCursor (); } oldX [0] = cursorPos.x; oldY [0] = cursorPos.y; } + this.oldX = oldX [0]; + this.oldY = oldY [0]; - 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, + 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, - xWindow, - 0, - OS.GrabModeAsync, - OS.GrabModeAsync, - OS.CurrentTime); + 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. - */ + /* 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, XEvent.sizeof); + OS.memmove (anyEvent, xEvent, XAnyEvent.sizeof); + int widget = OS.XtWindowToWidget (anyEvent.display, anyEvent.window); 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; - 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 [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, oldStippled); - drawRectangles (rectangles, stippled); - } - 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, oldStippled); - drawRectangles (rectangles, stippled); - } - } - 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; - 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 [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, oldStippled); - drawRectangles (rectangles, stippled); - } - 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, oldStippled); - drawRectangles (rectangles, stippled); - } - cursorPos = adjustMoveCursor (xDisplay, xWindow); - } - oldX [0] = cursorPos.x; oldY [0] = cursorPos.y; - } - } - break; + 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.KeyRelease: case OS.EnterNotify: case OS.LeaveNotify: /* Do not dispatch these */ @@ -685,10 +463,12 @@ public boolean open () { OS.XtDispatchEvent (xEvent); } } - OS.XtFree (xEvent); + if (xEvent != 0) OS.XtFree (xEvent); + if (dispatch != 0) OS.XtFree (dispatch); if (!isDisposed()) 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; } /** @@ -715,6 +495,30 @@ public void removeControlListener (ControlListener listener) { 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 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 the cursor orientation has not been set in the orientation of @@ -879,4 +683,260 @@ public void setStippled (boolean stippled) { checkWidget (); this.stippled = stippled; } + +int XButtonRelease (int w, int client_data, int call_data, int continue_to_dispatch) { + return xMouse (OS.ButtonRelease, w, client_data, call_data, continue_to_dispatch); +} + +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); + 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); + drawRectangles (rectangles, stippled); + } + cursorPos = adjustMoveCursor (); + } + oldX = cursorPos.x; + oldY = cursorPos.y; + } + } + return result; +} + +int XPointerMotion (int w, int client_data, int call_data, int continue_to_dispatch) { + if (cursor != 0) { + int xDisplay = display.xDisplay; + OS.XChangeActivePointerGrab (xDisplay, + OS.ButtonPressMask | OS.ButtonReleaseMask | OS.PointerMotionMask, + cursor, OS.CurrentTime); + } + return xMouse (OS.MotionNotify, w, client_data, call_data, continue_to_dispatch); +} + +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); + drawRectangles (rectangles, stippled); + } + Point cursorPos = adjustResizeCursor (); + 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); + drawRectangles (rectangles, stippled); + } + } + oldX = newX [0]; + oldY = newY [0]; + } + tracking = type != OS.ButtonRelease; + return 0; } + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Widget.java b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Widget.java index 0fae8e6fea..5d0134ccbf 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Widget.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/motif/org/eclipse/swt/widgets/Widget.java @@ -353,6 +353,9 @@ char fixMnemonic (char [] buffer) { int focusProc (int w, int client_data, int call_data, int continue_to_dispatch) { return 0; } +String getCodePage () { + return null; +} /** * Returns the application defined widget data associated * with the receiver, or null if it has not been set. The @@ -754,6 +757,106 @@ void sendEvent (int eventType, Event event, boolean send) { display.postEvent (event); } } +boolean sendIMKeyEvent (int type, XKeyEvent xEvent) { + return sendIMKeyEvent (type, xEvent, 0); +} +boolean sendIMKeyEvent (int type, XKeyEvent xEvent, int textHandle) { + /* + * Bug in Motif. On Linux only, XmImMbLookupString () does not return + * XBufferOverflow as the status if the buffer is too small. The fix + * is to pass a large buffer. + */ + byte [] buffer = new byte [512]; + int [] status = new int [1], unused = new int [1]; + int focusHandle = OS.XtWindowToWidget (xEvent.display, xEvent.window); + int length = OS.XmImMbLookupString (focusHandle, xEvent, buffer, buffer.length, unused, status); + if (status [0] == OS.XBufferOverflow) { + buffer = new byte [length]; + length = OS.XmImMbLookupString (focusHandle, xEvent, buffer, length, unused, status); + } + if (length == 0) return true; + + /* Convert from MBCS to UNICODE and send the event */ + /* Use the character encoding for the default locale */ + char [] chars = Converter.mbcsToWcs (null, buffer); + int index = 0, count = 0; + while (index < chars.length) { + if (chars [index] == 0) { + chars [count] = 0; + break; + } + Event event = new Event (); + event.time = xEvent.time; + event.character = chars [index]; + setInputState (event, xEvent.state); + sendEvent (type, event); + // widget could be disposed at this point + + /* + * It is possible (but unlikely), that application + * code could have disposed the widget in the key + * events. If this happens, end the processing of + * the key by returning false. + */ + if (isDisposed ()) return false; + if (event.doit) chars [count++] = chars [index]; + index++; + } + if (count == 0) return false; + if (textHandle != 0) { + /* + * Bug in Motif. On Solaris and Linux, XmImMbLookupString() clears + * the characters from the IME. This causes the characters to be + * stolen from the text widget. The fix is to detect that the IME + * has been cleared and use XmTextInsert() to insert the stolen + * characters. This problem does not happen on AIX. + */ + byte [] testBuffer = new byte [5]; + int testLength = OS.XmImMbLookupString (textHandle, xEvent, testBuffer, testBuffer.length, unused, unused); + if (testLength == 0 || index != count) { + int [] start = new int [1], end = new int [1]; + OS.XmTextGetSelectionPosition (textHandle, start, end); + if (start [0] == end [0]) { + start [0] = end [0] = OS.XmTextGetInsertionPosition (textHandle); + } + boolean warnings = display.getWarnings (); + display.setWarnings (false); + if (index != count) { + buffer = Converter.wcsToMbcs (getCodePage (), chars, true); + } + OS.XmTextReplace (textHandle, start [0], end [0], buffer); + int position = start [0] + count; + OS.XmTextSetInsertionPosition (textHandle, position); + display.setWarnings (warnings); + return false; + } + } + return true; +} +boolean sendKeyEvent (int type, XKeyEvent xEvent) { + Event event = new Event (); + event.time = xEvent.time; + if (!setKeyState (event, xEvent)) return true; + Widget control = this; + if ((state & CANVAS) != 0) { + if ((style & SWT.NO_FOCUS) != 0) { + control = display.getFocusControl (); + } + } + if (control != null) { + control.sendEvent (type, event); + // widget could be disposed at this point + + /* + * It is possible (but unlikely), that application + * code could have disposed the widget in the key + * events. If this happens, end the processing of + * the key by returning false. + */ + if (isDisposed ()) return false; + } + return event.doit; +} /** * Sets the application defined widget data associated * with the receiver to be the argument. The <em>widget @@ -961,9 +1064,27 @@ int XFocusChange (int w, int client_data, int call_data, int continue_to_dispatc return 0; } int XKeyPress (int w, int client_data, int call_data, int continue_to_dispatch) { + XKeyEvent xEvent = new XKeyEvent (); + OS.memmove (xEvent, call_data, XKeyEvent.sizeof); + boolean doit = true; + if (xEvent.keycode != 0) { + doit = sendKeyEvent (SWT.KeyDown, xEvent); + } else { + doit = sendIMKeyEvent (SWT.KeyDown, xEvent); + } + if (!doit) { + OS.memmove (continue_to_dispatch, new int [1], 4); + return 1; + } return 0; } int XKeyRelease (int w, int client_data, int call_data, int continue_to_dispatch) { + XKeyEvent xEvent = new XKeyEvent (); + OS.memmove (xEvent, call_data, XKeyEvent.sizeof); + if (!sendKeyEvent (SWT.KeyUp, xEvent)) { + OS.memmove (continue_to_dispatch, new int [1], 4); + return 1; + } return 0; } int XLeaveWindow (int w, int client_data, int call_data, int continue_to_dispatch) { |