diff options
author | Scott Kovatch <skovatch> | 2011-01-17 22:46:48 +0000 |
---|---|---|
committer | Scott Kovatch <skovatch> | 2011-01-17 22:46:48 +0000 |
commit | 92ca57cf28cccc9ff516d24846fb2cf295e0276b (patch) | |
tree | 1bec47a08bccedba135ebeae2b85ab0c243de5a9 /bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java | |
parent | f2baed61eb63d2f361e0bcedf8f5898e1419dca7 (diff) | |
download | eclipse.platform.swt-92ca57cf28cccc9ff516d24846fb2cf295e0276b.tar.gz eclipse.platform.swt-92ca57cf28cccc9ff516d24846fb2cf295e0276b.tar.xz eclipse.platform.swt-92ca57cf28cccc9ff516d24846fb2cf295e0276b.zip |
279884 - Add support for touch events. Also some gesture code cleanup.
Diffstat (limited to 'bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java')
-rwxr-xr-x | bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java | 236 |
1 files changed, 233 insertions, 3 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java index a550d916b1..9793137f15 100755 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java @@ -11,6 +11,7 @@ package org.eclipse.swt.widgets; +import org.eclipse.swt.internal.*; import org.eclipse.swt.internal.gdip.*; import org.eclipse.swt.internal.win32.*; import org.eclipse.swt.graphics.*; @@ -451,6 +452,34 @@ public void addPaintListener (PaintListener listener) { /** * Adds the listener to the collection of listeners who will + * be notified when touch events occur, by sending it + * one of the messages defined in the <code>TouchListener</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> + * + * @since 3.7 + * + * @see TouchListener + * @see #removeTouchListener + */ +public void addTouchListener (TouchListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + TypedListener typedListener = new TypedListener (listener); + addListener (SWT.Touch,typedListener); +} + +/** + * Adds the listener to the collection of listeners who will * be notified when traversal events occur, by sending it * one of the messages defined in the <code>TraverseListener</code> * interface. @@ -1842,6 +1871,27 @@ boolean isTabItem () { } /** + * Returns <code>true</code> if this control is receiving OS-level touch events, + * otherwise <code>false</code> + * <p> + * Note that this method will return false if the current platform does not support touch-based input. + * If this method does return true, gesture events will not be sent to the control. + * + * @return <code>true</code> if the widget is currently receiving touch events; <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> + * + * @since 3.7 + */ +public boolean isTouchEnabled() { + checkWidget(); + return OS.IsTouchWindow(handle, null); +} + +/** * Returns <code>true</code> if the receiver is visible and all * ancestors up to and including the receiver's nearest ancestor * shell are visible. Otherwise, <code>false</code> is returned. @@ -2679,6 +2729,32 @@ public void removePaintListener(PaintListener listener) { /** * Removes the listener from the collection of listeners who will + * be notified when touch events occur. + * + * @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> + * + * @since 3.7 + * + * @see TouchListener + * @see #addTouchListener +*/ +public void removeTouchListener(TouchListener listener) { + checkWidget(); + if (listener == null) error (SWT.ERROR_NULL_ARGUMENT); + if (eventTable == null) return; + eventTable.unhook (SWT.Touch, listener); +} + +/** + * Removes the listener from the collection of listeners who will * be notified when traversal events occur. * * @param listener the listener which should no longer be notified @@ -2749,6 +2825,84 @@ boolean sendFocusEvent (int type) { return true; } +boolean sendGestureEvent (GESTUREINFO gi) { + /** + * Feature in Windows 7. GID_BEGIN and GID_END events bubble up through the window + * hierarchy for legacy support. Ignore events not targeted for this control. + */ + if (gi.hwndTarget != handle) return true; + Event event = new Event (); + int type = 0; + Point globalPt = new Point(gi.x, gi.y); + Point point = toControl(globalPt); + event.x = point.x; + event.y = point.y; + switch (gi.dwID) { + case OS.GID_ZOOM: + type = SWT.Gesture; + event.detail = SWT.GESTURE_MAGNIFY; + int fingerDistance = OS.LODWORD (gi.ullArguments); + if ((gi.dwFlags & OS.GF_BEGIN) != 0) { + event.detail = SWT.GESTURE_BEGIN; + display.magStartDistance = display.lastDistance = fingerDistance; + } else if ((gi.dwFlags & OS.GF_END) != 0) { + event.detail = SWT.GESTURE_END; + } + + /* + * The gi.ullArguments is the distance between the fingers. + * Scale factor is relative to that original value. + */ + if (fingerDistance == display.lastDistance && event.detail == SWT.GESTURE_MAGNIFY) return true; + if (fingerDistance != 0) event.magnification = fingerDistance / display.magStartDistance; + display.lastDistance = fingerDistance; + break; + case OS.GID_PAN: + type = SWT.Gesture; + event.detail = SWT.GESTURE_PAN; + if ((gi.dwFlags & OS.GF_BEGIN) != 0) { + event.detail = SWT.GESTURE_BEGIN; + display.lastX = point.x; + display.lastY = point.y; + } else if ((gi.dwFlags & OS.GF_END) != 0) { + event.detail = SWT.GESTURE_END; + } + if (display.lastX == point.x && display.lastY == point.y && event.detail == SWT.GESTURE_PAN) return true; + event.xDirection = point.x - display.lastX; + event.yDirection = point.y - display.lastY; + display.lastX = point.x; + display.lastY = point.y; + break; + case OS.GID_ROTATE: + type = SWT.Gesture; + event.detail = SWT.GESTURE_ROTATE; + double rotationInRadians = OS.GID_ROTATE_ANGLE_FROM_ARGUMENT (OS.LODWORD (gi.ullArguments)); + if ((gi.dwFlags & OS.GF_BEGIN) != 0) { + event.detail = SWT.GESTURE_BEGIN; + display.rotationAngle = rotationInRadians; + } else if ((gi.dwFlags & OS.GF_END) != 0) { + event.detail = SWT.GESTURE_END; + } + + /* + * Feature in Win32. Rotation events are sent even when the fingers are at rest. + * If the current rotation is the same as the last one received don't send the event. + */ + if (display.rotationAngle == rotationInRadians && event.detail == SWT.GESTURE_ROTATE) return true; + event.rotation = rotationInRadians * 180.0 / Compatibility.PI; + display.rotationAngle = rotationInRadians; + break; + default: + // Unknown gesture -- ignore. + break; + } + + if (type == 0) return true; + setInputState (event, type); + sendEvent (type, event); + return true;// event.doit; +} + void sendMove () { sendEvent (SWT.Move); } @@ -2757,6 +2911,35 @@ void sendResize () { sendEvent (SWT.Resize); } +boolean sendTouchEvent (int /*long*/ hWnd, TOUCHINPUT touchInput[]) { + Event event = new Event (); + Point cursorLoc = display.getCursorLocation(); + cursorLoc = toControl(cursorLoc); + event.x = cursorLoc.x; + event.y = cursorLoc.y; + + Touch[] touches = new Touch[touchInput.length]; + + for (int i = 0; i < touchInput.length; i++) { + TOUCHINPUT touch = touchInput[i]; + int identity = touch.dwID; + int /*long*/ source = touch.hSource; + TouchSource inputSource = display.findTouchSource(source, getMonitor()); + int state = 0; + boolean primary = false; + if ((touch.dwFlags & OS.TOUCHEVENTF_DOWN) != 0) state = SWT.TOUCHSTATE_DOWN; + if ((touch.dwFlags & OS.TOUCHEVENTF_UP) != 0) state = SWT.TOUCHSTATE_UP; + if ((touch.dwFlags & OS.TOUCHEVENTF_MOVE) != 0) state = SWT.TOUCHSTATE_MOVE; + if ((touch.dwFlags & OS.TOUCHEVENTF_PRIMARY) != 0) primary = true; + touches[i] = new Touch(identity, inputSource, state, primary, (int)OS.TOUCH_COORD_TO_PIXEL(touch.x), (int)OS.TOUCH_COORD_TO_PIXEL(touch.y)); + } + + event.touches = touches; + setInputState (event, SWT.Touch); + postEvent (SWT.Touch, event); + return event.doit; +} + void setBackground () { Control control = findBackgroundControl (); if (control == null) control = this; @@ -3481,6 +3664,27 @@ void setToolTipText (Shell shell, String string) { } /** + * Sets whether the receiver should accept touch events. By default, a Control does not accept touch + * events. No error or exception is thrown if the underlying hardware does not support touch input. + * + * @param enabled the new touch-enabled state + * + * @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> + * + * @since 3.7 + */ +public void setTouchEventsEnabled(boolean enabled) { + checkWidget(); + if (enabled) { + OS.RegisterTouchWindow(handle, 0); + } else { + OS.UnregisterTouchWindow(handle); + } +} + +/** * Marks the receiver as visible if the argument is <code>true</code>, * and marks it invisible otherwise. * <p> @@ -4383,6 +4587,7 @@ int /*long*/ windowProc (int /*long*/ hwnd, int msg, int /*long*/ wParam, int /* case OS.WM_SYSKEYUP: result = WM_SYSKEYUP (wParam, lParam); break; case OS.WM_TABLET_FLICK: result = WM_TABLET_FLICK (wParam, lParam); break; case OS.WM_TIMER: result = WM_TIMER (wParam, lParam); break; + case OS.WM_TOUCH: result = WM_TOUCH (wParam, lParam); break; case OS.WM_UNDO: result = WM_UNDO (wParam, lParam); break; case OS.WM_UPDATEUISTATE: result = WM_UPDATEUISTATE (wParam, lParam); break; case OS.WM_VSCROLL: result = WM_VSCROLL (wParam, lParam); break; @@ -4503,9 +4708,10 @@ LRESULT WM_GESTURE (int /*long*/ wParam, int /*long*/ lParam) { GESTUREINFO gi = new GESTUREINFO (); gi.cbSize = GESTUREINFO.sizeof; if (OS.GetGestureInfo (lParam, gi)) { - boolean result = sendGestureEvent (gi); - OS.CloseGestureInfoHandle (lParam); - if (result) return LRESULT.ZERO; + if (!sendGestureEvent (gi)) { + OS.CloseGestureInfoHandle (lParam); + return LRESULT.ZERO; + } } } return null; @@ -5159,6 +5365,30 @@ LRESULT WM_TABLET_FLICK (int /*long*/ wParam, int /*long*/ lParam) { return event.doit ? null : LRESULT.ONE; } +LRESULT WM_TOUCH (int /*long*/ wParam, int /*long*/ lParam) { + LRESULT result = null; + + if (hooks(SWT.Touch) || filters(SWT.Touch)) { + int cInputs = OS.LOWORD(wParam); + int /*long*/ hHeap = OS.GetProcessHeap (); + int /*long*/ pInputs = OS.HeapAlloc (hHeap, OS.HEAP_ZERO_MEMORY, cInputs * TOUCHINPUT.sizeof); + + if (pInputs != 0){ + if (OS.GetTouchInputInfo(lParam, cInputs, pInputs, OS.TOUCHINPUT_sizeof())) { + TOUCHINPUT ti[] = new TOUCHINPUT[cInputs]; + for (int i = 0; i < cInputs; i++){ + ti[i] = new TOUCHINPUT(); + OS.MoveMemory(ti[i], pInputs + i * OS.TOUCHINPUT_sizeof(), OS.TOUCHINPUT_sizeof()); + } + if (!sendTouchEvent(handle, ti)) + OS.HeapFree(hHeap, 0, pInputs); + result = LRESULT.ZERO; + } + } + } + return result; +} + LRESULT WM_TIMER (int /*long*/ wParam, int /*long*/ lParam) { return null; } |