--- old/src/share/classes/com/sun/java/swing/plaf/motif/MotifDesktopIconUI.java 2017-10-13 16:26:07.000000000 +0100 +++ new/src/share/classes/com/sun/java/swing/plaf/motif/MotifDesktopIconUI.java 2017-10-13 16:26:06.000000000 +0100 @@ -36,6 +36,8 @@ import java.util.EventListener; import java.io.Serializable; +import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; /** * Motif rendition of the component. @@ -237,11 +239,15 @@ } void forwardEventToParent(MouseEvent e) { - getParent().dispatchEvent(new MouseEvent( + MouseEvent newEvent = new MouseEvent( getParent(), e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), - e.isPopupTrigger(), MouseEvent.NOBUTTON)); + e.isPopupTrigger(), MouseEvent.NOBUTTON); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(newEvent, + meAccessor.isCausedByTouchEvent(e)); + getParent().dispatchEvent(newEvent); } public boolean isFocusTraversable() { @@ -328,10 +334,14 @@ } void forwardEventToParent(MouseEvent e) { - getParent().dispatchEvent(new MouseEvent( + MouseEvent newEvent = new MouseEvent( getParent(), e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), - e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON )); + e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON ); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(newEvent, + meAccessor.isCausedByTouchEvent(e)); + getParent().dispatchEvent(newEvent); } public boolean isFocusTraversable() { --- old/src/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java 2017-10-13 16:26:08.000000000 +0100 +++ new/src/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java 2017-10-13 16:26:07.000000000 +0100 @@ -37,6 +37,9 @@ import java.beans.VetoableChangeListener; import java.beans.PropertyVetoException; +import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; + /** * Class that manages a Motif title bar * @@ -356,11 +359,15 @@ } void forwardEventToParent(MouseEvent e) { - getParent().dispatchEvent(new MouseEvent( + MouseEvent newEvent = new MouseEvent( getParent(), e.getID(), e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), - e.isPopupTrigger(), MouseEvent.NOBUTTON)); + e.isPopupTrigger(), MouseEvent.NOBUTTON); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(newEvent, + meAccessor.isCausedByTouchEvent(e)); + getParent().dispatchEvent(newEvent); } public void paintComponent(Graphics g) { --- old/src/share/classes/java/awt/Component.java 2017-10-13 16:26:08.000000000 +0100 +++ new/src/share/classes/java/awt/Component.java 2017-10-13 16:26:08.000000000 +0100 @@ -4965,6 +4965,12 @@ tpeer.handleEvent(e); } } + + if (SunToolkit.isTouchKeyboardAutoShowEnabled() && + (toolkit instanceof SunToolkit) && + ((e instanceof MouseEvent) || (e instanceof FocusEvent))) { + ((SunToolkit)toolkit).showOrHideTouchKeyboard(this, e); + } } // dispatchEventImpl() /* --- old/src/share/classes/java/awt/Container.java 2017-10-13 16:26:10.000000000 +0100 +++ new/src/share/classes/java/awt/Container.java 2017-10-13 16:26:10.000000000 +0100 @@ -55,6 +55,7 @@ import sun.awt.AppContext; import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; import sun.awt.CausedFocusEvent; import sun.awt.PeerEvent; import sun.awt.SunToolkit; @@ -4769,6 +4770,9 @@ srcEvent.getClickCount(), srcEvent.isPopupTrigger(), srcEvent.getButton()); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(me, + meAccessor.isCausedByTouchEvent(srcEvent)); ((AWTEvent)srcEvent).copyPrivateDataInto(me); // translate coordinates to this native container final Point ptSrcOrigin = srcComponent.getLocationOnScreen(); @@ -4869,6 +4873,9 @@ e.getClickCount(), e.isPopupTrigger(), e.getButton()); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(retargeted, + meAccessor.isCausedByTouchEvent(e)); } ((AWTEvent)e).copyPrivateDataInto(retargeted); --- old/src/share/classes/java/awt/event/MouseEvent.java 2017-10-13 16:26:11.000000000 +0100 +++ new/src/share/classes/java/awt/event/MouseEvent.java 2017-10-13 16:26:11.000000000 +0100 @@ -33,6 +33,8 @@ import java.io.ObjectInputStream; import java.awt.IllegalComponentStateException; import java.awt.MouseInfo; + +import sun.awt.AWTAccessor; import sun.awt.SunToolkit; /** @@ -332,6 +334,11 @@ int clickCount; /** + * Indicates whether the event is a result of a touch event. + */ + private boolean causedByTouchEvent; + + /** * Indicates which, if any, of the mouse buttons has changed state. * * The valid values are ranged from 0 to the value returned by the @@ -399,6 +406,17 @@ //whatever besides SunToolkit) could also operate. cachedNumberOfButtons = 3; } + AWTAccessor.setMouseEventAccessor( + new AWTAccessor.MouseEventAccessor() { + public boolean isCausedByTouchEvent(MouseEvent ev) { + return ev.causedByTouchEvent; + } + + public void setCausedByTouchEvent(MouseEvent ev, + boolean causedByTouchEvent) { + ev.causedByTouchEvent = causedByTouchEvent; + } + }); } /** --- old/src/share/classes/javax/swing/Autoscroller.java 2017-10-13 16:26:12.000000000 +0100 +++ new/src/share/classes/javax/swing/Autoscroller.java 2017-10-13 16:26:12.000000000 +0100 @@ -28,6 +28,9 @@ import java.awt.*; import java.awt.event.*; +import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; + /** * Autoscroller is responsible for generating synthetic mouse dragged * events. It is the responsibility of the Component (or its MouseListeners) @@ -96,6 +99,9 @@ e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(event, + meAccessor.isCausedByTouchEvent(e)); if (timer == null) { timer = new Timer(100, this); @@ -173,6 +179,9 @@ event.getClickCount(), event.isPopupTrigger(), MouseEvent.NOBUTTON); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(e, + meAccessor.isCausedByTouchEvent(event)); component.superProcessMouseMotionEvent(e); } --- old/src/share/classes/javax/swing/JList.java 2017-10-13 16:26:13.000000000 +0100 +++ new/src/share/classes/javax/swing/JList.java 2017-10-13 16:26:13.000000000 +0100 @@ -48,6 +48,8 @@ import java.io.IOException; import java.io.Serializable; +import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; import sun.swing.SwingUtilities2; import sun.swing.SwingUtilities2.Section; import static sun.swing.SwingUtilities2.Section.*; @@ -1553,6 +1555,10 @@ event.getClickCount(), event.isPopupTrigger(), MouseEvent.NOBUTTON); + MouseEventAccessor meAccessor = + AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(newEvent, + meAccessor.isCausedByTouchEvent(event)); String tip = ((JComponent)rComponent).getToolTipText( newEvent); --- old/src/share/classes/javax/swing/JTable.java 2017-10-13 16:26:14.000000000 +0100 +++ new/src/share/classes/javax/swing/JTable.java 2017-10-13 16:26:14.000000000 +0100 @@ -51,6 +51,9 @@ import javax.print.attribute.*; import javax.print.PrintService; + +import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; import sun.reflect.misc.ReflectUtil; import sun.swing.SwingUtilities2; @@ -3404,6 +3407,9 @@ event.getClickCount(), event.isPopupTrigger(), MouseEvent.NOBUTTON); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(newEvent, + meAccessor.isCausedByTouchEvent(event)); tip = ((JComponent)component).getToolTipText(newEvent); } --- old/src/share/classes/javax/swing/JTree.java 2017-10-13 16:26:15.000000000 +0100 +++ new/src/share/classes/javax/swing/JTree.java 2017-10-13 16:26:15.000000000 +0100 @@ -35,6 +35,9 @@ import javax.swing.tree.*; import javax.swing.text.Position; import javax.accessibility.*; + +import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; import sun.swing.SwingUtilities2; import sun.swing.SwingUtilities2.Section; import static sun.swing.SwingUtilities2.Section.*; @@ -1562,6 +1565,10 @@ event.getClickCount(), event.isPopupTrigger(), MouseEvent.NOBUTTON); + MouseEventAccessor meAccessor = + AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(newEvent, + meAccessor.isCausedByTouchEvent(event)); tip = ((JComponent)rComponent).getToolTipText(newEvent); } --- old/src/share/classes/javax/swing/MenuSelectionManager.java 2017-10-13 16:26:17.000000000 +0100 +++ new/src/share/classes/javax/swing/MenuSelectionManager.java 2017-10-13 16:26:16.000000000 +0100 @@ -30,6 +30,8 @@ import javax.swing.event.*; import sun.awt.AppContext; +import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; import sun.swing.SwingUtilities2; /** @@ -305,6 +307,9 @@ event.getClickCount(), event.isPopupTrigger(), MouseEvent.NOBUTTON); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(exitEvent, + meAccessor.isCausedByTouchEvent(event)); currentSelection[currentSelection.length-1]. processMouseEvent(exitEvent, path, this); @@ -317,6 +322,8 @@ event.getClickCount(), event.isPopupTrigger(), MouseEvent.NOBUTTON); + meAccessor.setCausedByTouchEvent(enterEvent, + meAccessor.isCausedByTouchEvent(event)); subElements[j].processMouseEvent(enterEvent, path, this); } MouseEvent mouseEvent = new MouseEvent(mc, event.getID(),event. getWhen(), @@ -326,6 +333,9 @@ event.getClickCount(), event.isPopupTrigger(), MouseEvent.NOBUTTON); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(mouseEvent, + meAccessor.isCausedByTouchEvent(event)); subElements[j].processMouseEvent(mouseEvent, path, this); success = true; event.consume(); --- old/src/share/classes/javax/swing/SwingUtilities.java 2017-10-13 16:26:18.000000000 +0100 +++ new/src/share/classes/javax/swing/SwingUtilities.java 2017-10-13 16:26:17.000000000 +0100 @@ -44,6 +44,8 @@ import sun.security.action.GetPropertyAction; import sun.awt.AppContext; +import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; /** * A collection of utility methods for Swing. @@ -355,6 +357,9 @@ sourceEvent.getClickCount(), sourceEvent.isPopupTrigger(), sourceEvent.getButton()); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(newEvent, + meAccessor.isCausedByTouchEvent(sourceEvent)); } return newEvent; } --- old/src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java 2017-10-13 16:26:19.000000000 +0100 +++ new/src/share/classes/javax/swing/plaf/basic/BasicComboPopup.java 2017-10-13 16:26:18.000000000 +0100 @@ -36,6 +36,8 @@ import java.beans.PropertyChangeEvent; import java.io.Serializable; +import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; /** * This is a basic implementation of the ComboPopup interface. @@ -499,13 +501,18 @@ // Fix for 4234053. Filter out the Control Key from the list. // ie., don't allow CTRL key deselection. Toolkit toolkit = Toolkit.getDefaultToolkit(); - e = new MouseEvent((Component)e.getSource(), e.getID(), e.getWhen(), + MouseEvent newEvent = new MouseEvent( + (Component)e.getSource(), e.getID(), e.getWhen(), e.getModifiers() ^ toolkit.getMenuShortcutKeyMask(), e.getX(), e.getY(), e.getXOnScreen(), e.getYOnScreen(), e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(newEvent, + meAccessor.isCausedByTouchEvent(e)); + e = newEvent; } super.processMouseEvent(e); } @@ -1195,6 +1202,9 @@ e.getClickCount(), e.isPopupTrigger(), MouseEvent.NOBUTTON ); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(newEvent, + meAccessor.isCausedByTouchEvent(e)); return newEvent; } --- old/src/share/classes/javax/swing/table/JTableHeader.java 2017-10-13 16:26:20.000000000 +0100 +++ new/src/share/classes/javax/swing/table/JTableHeader.java 2017-10-13 16:26:19.000000000 +0100 @@ -43,6 +43,8 @@ import java.io.ObjectInputStream; import java.io.IOException; +import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; /** * This is the object which manages the header of the JTable. @@ -420,6 +422,9 @@ p.x, p.y, event.getXOnScreen(), event.getYOnScreen(), event.getClickCount(), event.isPopupTrigger(), MouseEvent.NOBUTTON); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(newEvent, + meAccessor.isCausedByTouchEvent(event)); tip = ((JComponent)component).getToolTipText(newEvent); } --- old/src/share/classes/sun/awt/AWTAccessor.java 2017-10-13 16:26:21.000000000 +0100 +++ new/src/share/classes/sun/awt/AWTAccessor.java 2017-10-13 16:26:21.000000000 +0100 @@ -34,6 +34,7 @@ import java.awt.event.InputEvent; import java.awt.event.InvocationEvent; import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; import java.awt.geom.Point2D; import java.awt.peer.ComponentPeer; import java.awt.peer.MenuComponentPeer; @@ -385,6 +386,21 @@ int[] getButtonDownMasks(); } + /** + * An accessor for the MouseEvent class. + */ + public interface MouseEventAccessor { + /** + * Indicates whether the event is a result of a touch event. + */ + boolean isCausedByTouchEvent(MouseEvent ev); + + /** + * Sets whether the event is a result of a touch event. + */ + void setCausedByTouchEvent(MouseEvent ev, boolean causedByTouchEvent); + } + /* * An accessor for the java.awt.Frame class. */ @@ -770,6 +786,7 @@ private static WindowAccessor windowAccessor; private static AWTEventAccessor awtEventAccessor; private static InputEventAccessor inputEventAccessor; + private static MouseEventAccessor mouseEventAccessor; private static FrameAccessor frameAccessor; private static KeyboardFocusManagerAccessor kfmAccessor; private static MenuComponentAccessor menuComponentAccessor; @@ -881,6 +898,23 @@ } /* + * Set an accessor object for the java.awt.event.MouseEvent class. + */ + public static void setMouseEventAccessor(MouseEventAccessor mea) { + mouseEventAccessor = mea; + } + + /* + * Retrieve the accessor object for the java.awt.event.MouseEvent class. + */ + public static MouseEventAccessor getMouseEventAccessor() { + if (mouseEventAccessor == null) { + unsafe.ensureClassInitialized(MouseEvent.class); + } + return mouseEventAccessor; + } + + /* * Set an accessor object for the java.awt.Frame class. */ public static void setFrameAccessor(FrameAccessor fa) { --- old/src/share/classes/sun/awt/SunToolkit.java 2017-10-13 16:26:22.000000000 +0100 +++ new/src/share/classes/sun/awt/SunToolkit.java 2017-10-13 16:26:21.000000000 +0100 @@ -70,6 +70,9 @@ if (AccessController.doPrivileged(new GetBooleanAction("sun.awt.nativedebug"))) { DebugSettings.init(); } + touchKeyboardAutoShowIsEnabled = Boolean.valueOf( + AccessController.doPrivileged(new GetPropertyAction( + "awt.touchKeyboardAutoShowIsEnabled", "true"))); }; /** @@ -1707,6 +1710,13 @@ */ public abstract void ungrab(Window w); + public void showOrHideTouchKeyboard(Component comp, AWTEvent e) {} + + private static boolean touchKeyboardAutoShowIsEnabled; + + public static boolean isTouchKeyboardAutoShowEnabled() { + return touchKeyboardAutoShowIsEnabled; + } /** * Locates the splash screen library in a platform dependent way and closes --- old/src/share/classes/sun/swing/FilePane.java 2017-10-13 16:26:23.000000000 +0100 +++ new/src/share/classes/sun/swing/FilePane.java 2017-10-13 16:26:23.000000000 +0100 @@ -44,6 +44,8 @@ import javax.swing.table.*; import javax.swing.text.*; +import sun.awt.AWTAccessor; +import sun.awt.AWTAccessor.MouseEventAccessor; import sun.awt.shell.*; /** @@ -1835,13 +1837,17 @@ // Make a new event with the list as source, placing the // click in the corresponding list cell. Rectangle r = list.getCellBounds(index, index); - evt = new MouseEvent(list, evt.getID(), + MouseEvent newEvent = new MouseEvent(list, evt.getID(), evt.getWhen(), evt.getModifiers(), r.x + 1, r.y + r.height/2, evt.getXOnScreen(), evt.getYOnScreen(), evt.getClickCount(), evt.isPopupTrigger(), evt.getButton()); + MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor(); + meAccessor.setCausedByTouchEvent(newEvent, + meAccessor.isCausedByTouchEvent(evt)); + evt = newEvent; } } else { return; --- old/src/windows/classes/sun/awt/windows/WToolkit.java 2017-10-13 16:26:24.000000000 +0100 +++ new/src/windows/classes/sun/awt/windows/WToolkit.java 2017-10-13 16:26:24.000000000 +0100 @@ -30,13 +30,19 @@ import java.awt.im.spi.InputMethodDescriptor; import java.awt.image.*; import java.awt.peer.*; +import java.awt.event.FocusEvent; import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; import java.awt.datatransfer.Clipboard; +import java.awt.TextComponent; import java.awt.TrayIcon; import java.beans.PropertyChangeListener; import java.security.AccessController; import java.security.PrivilegedAction; +import javax.swing.text.JTextComponent; + import sun.awt.AppContext; +import sun.awt.AWTAccessor; import sun.awt.AWTAutoShutdown; import sun.awt.LightweightFrame; import sun.awt.SunToolkit; @@ -1101,6 +1107,61 @@ } } + /////////////////////////////////////////////////////////////////////////// + // The following code is used for support of automatic showing of the touch + // keyboard for text components and is accessed only from EDT. + /////////////////////////////////////////////////////////////////////////// + private volatile Component compOnTouchDownEvent; + private volatile Component compOnMousePressedEvent; + + @Override + public void showOrHideTouchKeyboard(Component comp, AWTEvent e) { + if ((comp == null) || (e == null) || + (!(comp instanceof TextComponent) && + !(comp instanceof JTextComponent))) { + return; + } + + if ((e instanceof MouseEvent) && comp.isEnabled() && + (((comp instanceof TextComponent) && + ((TextComponent)comp).isEditable()) || + ((comp instanceof JTextComponent) && + ((JTextComponent)comp).isEditable()))) { + MouseEvent me = (MouseEvent)e; + if (me.getID() == MouseEvent.MOUSE_PRESSED) { + if (AWTAccessor.getMouseEventAccessor() + .isCausedByTouchEvent(me)) { + compOnTouchDownEvent = comp; + } else { + compOnMousePressedEvent = comp; + } + } else if (me.getID() == MouseEvent.MOUSE_RELEASED) { + if (AWTAccessor.getMouseEventAccessor() + .isCausedByTouchEvent(me)) { + if (compOnTouchDownEvent == comp) { + showTouchKeyboard(true); + } + compOnTouchDownEvent = null; + } else { + if (compOnMousePressedEvent == comp) { + showTouchKeyboard(false); + } + compOnMousePressedEvent = null; + } + } + } else if (e instanceof FocusEvent) { + if (e.getID() == FocusEvent.FOCUS_LOST) { + hideTouchKeyboard(); + } + } + } + + private native void showTouchKeyboard(boolean causedByTouchEvent); + private native void hideTouchKeyboard(); + /////////////////////////////////////////////////////////////////////////// + // End of the touch keyboard related code. + /////////////////////////////////////////////////////////////////////////// + @Override public native boolean syncNativeQueue(final long timeout); @Override --- old/src/windows/native/sun/windows/awt.h 2017-10-13 16:26:25.000000000 +0100 +++ new/src/windows/native/sun/windows/awt.h 2017-10-13 16:26:25.000000000 +0100 @@ -163,6 +163,9 @@ #define IS_WIN2000 (LOBYTE(LOWORD(::GetVersion())) >= 5) #define IS_WINXP ((IS_WIN2000 && HIBYTE(LOWORD(::GetVersion())) >= 1) || LOBYTE(LOWORD(::GetVersion())) > 5) #define IS_WINVISTA (LOBYTE(LOWORD(::GetVersion())) >= 6) +#define IS_WIN8 ( \ + (IS_WINVISTA && (HIBYTE(LOWORD(::GetVersion())) >= 2)) || \ + (LOBYTE(LOWORD(::GetVersion())) > 6)) #define IS_WINVER_ATLEAST(maj, min) \ ((maj) < LOBYTE(LOWORD(::GetVersion())) || \ --- old/src/windows/native/sun/windows/awt_Component.cpp 2017-10-13 16:26:26.000000000 +0100 +++ new/src/windows/native/sun/windows/awt_Component.cpp 2017-10-13 16:26:26.000000000 +0100 @@ -216,6 +216,10 @@ AwtComponent::AwtComponent() { m_mouseButtonClickAllowed = 0; + m_touchDownOccurred = FALSE; + m_touchUpOccurred = FALSE; + m_touchDownPoint.x = m_touchDownPoint.y = 0; + m_touchUpPoint.x = m_touchUpPoint.y = 0; m_callbacksEnabled = FALSE; m_hwnd = NULL; @@ -580,6 +584,11 @@ /* Subclass the window now so that we can snoop on its messages */ SubclassHWND(); + AwtToolkit& tk = AwtToolkit::GetInstance(); + if (tk.IsWin8OrLater() && tk.IsTouchKeyboardAutoShowEnabled()) { + tk.TIRegisterTouchWindow(GetHWnd(), TWF_WANTPALM); + } + /* * Fix for 4046446. */ @@ -1700,6 +1709,9 @@ break; } break; + case WM_TOUCH: + WmTouch(wParam, lParam); + break; case WM_SETCURSOR: mr = mrDoDefault; if (LOWORD(lParam) == HTCLIENT) { @@ -2291,6 +2303,38 @@ return mrDoDefault; } +void AwtComponent::WmTouch(WPARAM wParam, LPARAM lParam) { + AwtToolkit& tk = AwtToolkit::GetInstance(); + if (!tk.IsWin8OrLater() || !tk.IsTouchKeyboardAutoShowEnabled()) { + return; + } + + UINT inputsCount = LOWORD(wParam); + TOUCHINPUT* pInputs = new TOUCHINPUT[inputsCount]; + if (pInputs != NULL) { + if (tk.TIGetTouchInputInfo((HTOUCHINPUT)lParam, inputsCount, pInputs, + sizeof(TOUCHINPUT)) != 0) { + for (UINT i = 0; i < inputsCount; i++) { + TOUCHINPUT ti = pInputs[i]; + if (ti.dwFlags & TOUCHEVENTF_PRIMARY) { + if (ti.dwFlags & TOUCHEVENTF_DOWN) { + m_touchDownPoint.x = ti.x / 100; + m_touchDownPoint.y = ti.y / 100; + ::ScreenToClient(GetHWnd(), &m_touchDownPoint); + m_touchDownOccurred = TRUE; + } else if (ti.dwFlags & TOUCHEVENTF_UP) { + m_touchUpPoint.x = ti.x / 100; + m_touchUpPoint.y = ti.y / 100; + ::ScreenToClient(GetHWnd(), &m_touchUpPoint); + m_touchUpOccurred = TRUE; + } + } + } + } + delete[] pInputs; + } +} + /* Double-click variables. */ static jlong multiClickTime = ::GetDoubleClickTime(); static int multiClickMaxX = ::GetSystemMetrics(SM_CXDOUBLECLK); @@ -2333,6 +2377,14 @@ m_mouseButtonClickAllowed |= GetButtonMK(button); lastTime = now; + BOOL causedByTouchEvent = FALSE; + if (m_touchDownOccurred && + (abs(m_touchDownPoint.x - x) <= TOUCH_MOUSE_COORDS_DELTA) && + (abs(m_touchDownPoint.y - y) <= TOUCH_MOUSE_COORDS_DELTA)) { + causedByTouchEvent = TRUE; + m_touchDownOccurred = FALSE; + } + MSG msg; InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); @@ -2351,7 +2403,7 @@ SendMouseEvent(java_awt_event_MouseEvent_MOUSE_PRESSED, now, x, y, GetJavaModifiers(), clickCount, JNI_FALSE, - GetButton(button), &msg); + GetButton(button), &msg, causedByTouchEvent); /* * NOTE: this call is intentionally placed after all other code, * since AwtComponent::WmMouseDown() assumes that the cached id of the @@ -2373,13 +2425,21 @@ MsgRouting AwtComponent::WmMouseUp(UINT flags, int x, int y, int button) { + BOOL causedByTouchEvent = FALSE; + if (m_touchUpOccurred && + (abs(m_touchUpPoint.x - x) <= TOUCH_MOUSE_COORDS_DELTA) && + (abs(m_touchUpPoint.y - y) <= TOUCH_MOUSE_COORDS_DELTA)) { + causedByTouchEvent = TRUE; + m_touchUpOccurred = FALSE; + } + MSG msg; InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, TimeHelper::getMessageTimeUTC(), x, y, GetJavaModifiers(), clickCount, (GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ? - TRUE : FALSE), GetButton(button), &msg); + TRUE : FALSE), GetButton(button), &msg, causedByTouchEvent); /* * If no movement, then report a click following the button release. * When WM_MOUSEUP comes to a window without previous WM_MOUSEDOWN, @@ -4894,7 +4954,7 @@ void AwtComponent::SendMouseEvent(jint id, jlong when, jint x, jint y, jint modifiers, jint clickCount, jboolean popupTrigger, jint button, - MSG *pMsg) + MSG *pMsg, BOOL causedByTouchEvent) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); CriticalSection::Lock l(GetLock()); @@ -4943,6 +5003,10 @@ DASSERT(mouseEvent != NULL); CHECK_NULL(mouseEvent); + if (causedByTouchEvent) { + env->SetBooleanField(mouseEvent, AwtMouseEvent::causedByTouchEventID, + JNI_TRUE); + } if (pMsg != 0) { AwtAWTEvent::saveMSG(env, pMsg, mouseEvent); } --- old/src/windows/native/sun/windows/awt_Component.h 2017-10-13 16:26:27.000000000 +0100 +++ new/src/windows/native/sun/windows/awt_Component.h 2017-10-13 16:26:27.000000000 +0100 @@ -67,7 +67,10 @@ const int ALL_MK_BUTTONS = MK_LBUTTON|MK_MBUTTON|MK_RBUTTON; const int X_BUTTONS = MK_XBUTTON1|MK_XBUTTON2; - +// The allowable difference between coordinates of the WM_TOUCH event and the +// corresponding WM_LBUTTONDOWN/WM_LBUTTONUP event letting to associate these +// events, when their coordinates are slightly different. +const int TOUCH_MOUSE_COORDS_DELTA = 10; // Whether to check for embedded frame and adjust location #define CHECK_EMBEDDED 0 @@ -384,7 +387,7 @@ void SendMouseEvent(jint id, jlong when, jint x, jint y, jint modifiers, jint clickCount, jboolean popupTrigger, jint button = 0, - MSG *msg = NULL); + MSG *msg = NULL, BOOL causedByTouchEvent = FALSE); /* * Allocate and initialize a new java.awt.event.MouseWheelEvent, and @@ -526,6 +529,7 @@ virtual MsgRouting WmNcMouseUp(WPARAM hitTest, int x, int y, int button); virtual MsgRouting WmWindowPosChanging(LPARAM windowPos); virtual MsgRouting WmWindowPosChanged(LPARAM windowPos); + virtual void WmTouch(WPARAM wParam, LPARAM lParam); // NB: 64-bit: vkey is wParam of the message, but other API's take // vkey parameters of type UINT, so we do the cast before dispatching. @@ -756,6 +760,11 @@ */ UINT m_mouseButtonClickAllowed; + BOOL m_touchDownOccurred; + BOOL m_touchUpOccurred; + POINT m_touchDownPoint; + POINT m_touchUpPoint; + BOOL m_bSubclassed; BOOL m_bPauseDestroy; --- old/src/windows/native/sun/windows/awt_MouseEvent.cpp 2017-10-13 16:26:28.000000000 +0100 +++ new/src/windows/native/sun/windows/awt_MouseEvent.cpp 2017-10-13 16:26:28.000000000 +0100 @@ -32,6 +32,7 @@ jfieldID AwtMouseEvent::xID; jfieldID AwtMouseEvent::yID; +jfieldID AwtMouseEvent::causedByTouchEventID; jfieldID AwtMouseEvent::buttonID; /************************************************************************ @@ -52,6 +53,11 @@ DASSERT(AwtMouseEvent::yID != NULL); CHECK_NULL(AwtMouseEvent::yID); + AwtMouseEvent::causedByTouchEventID = env->GetFieldID( + cls, "causedByTouchEvent", "Z"); + DASSERT(AwtMouseEvent::causedByTouchEventID != NULL); + CHECK_NULL(AwtMouseEvent::causedByTouchEventID); + AwtMouseEvent::buttonID = env->GetFieldID(cls, "button", "I"); DASSERT(AwtMouseEvent::buttonID != NULL); CHECK_NULL(AwtMouseEvent::buttonID); --- old/src/windows/native/sun/windows/awt_MouseEvent.h 2017-10-13 16:26:29.000000000 +0100 +++ new/src/windows/native/sun/windows/awt_MouseEvent.h 2017-10-13 16:26:29.000000000 +0100 @@ -39,6 +39,7 @@ /* java.awt.MouseEvent field ids */ static jfieldID xID; static jfieldID yID; + static jfieldID causedByTouchEventID; static jfieldID buttonID; }; --- old/src/windows/native/sun/windows/awt_Toolkit.cpp 2017-10-13 16:26:30.000000000 +0100 +++ new/src/windows/native/sun/windows/awt_Toolkit.cpp 2017-10-13 16:26:30.000000000 +0100 @@ -29,6 +29,8 @@ #include #include #include +#include +#include #include "awt_DrawingSurface.h" #include "awt_AWTEvent.h" @@ -292,6 +294,13 @@ m_isDynamicLayoutSet = FALSE; m_areExtraMouseButtonsEnabled = TRUE; + m_isWin8OrLater = FALSE; + m_touchKbrdAutoShowIsEnabled = FALSE; + m_touchKbrdExeFilePath = NULL; + m_pRegisterTouchWindow = NULL; + m_pGetTouchInputInfo = NULL; + m_pCloseTouchInputHandle = NULL; + m_verifyComponents = FALSE; m_breakOnError = FALSE; @@ -345,6 +354,149 @@ return hwnd; } +void AwtToolkit::InitTouchKeyboardExeFilePath() { + enum RegistryView { WOW64_32BIT, WOW64_64BIT }; + const TCHAR tabTipCoKeyName[] = _T("SOFTWARE\\Classes\\CLSID\\") + _T("{054AAE20-4BEA-4347-8A35-64A533254A9D}\\LocalServer32"); + HKEY hTabTipCoKey = NULL; + RegistryView regViewWithTabTipCoKey = WOW64_32BIT; + + if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, tabTipCoKeyName, 0, + KEY_READ | KEY_WOW64_32KEY, &hTabTipCoKey) != ERROR_SUCCESS) { + if (::RegOpenKeyEx(HKEY_LOCAL_MACHINE, tabTipCoKeyName, 0, + KEY_READ | KEY_WOW64_64KEY, &hTabTipCoKey) != ERROR_SUCCESS) { + return; + } else { + regViewWithTabTipCoKey = WOW64_64BIT; + } + } + + DWORD keyValType = 0; + DWORD bytesCopied = 0; + if ((::RegQueryValueEx(hTabTipCoKey, NULL, NULL, &keyValType, NULL, + &bytesCopied) != ERROR_SUCCESS) || + ((keyValType != REG_EXPAND_SZ) && (keyValType != REG_SZ))) { + if (hTabTipCoKey != NULL) { + ::RegCloseKey(hTabTipCoKey); + } + return; + } + + // Increase the buffer size for 1 additional null-terminating character. + bytesCopied += sizeof(TCHAR); + TCHAR* tabTipFilePath = new TCHAR[bytesCopied / sizeof(TCHAR)]; + ::memset(tabTipFilePath, 0, bytesCopied); + + DWORD oldBytesCopied = bytesCopied; + if (::RegQueryValueEx(hTabTipCoKey, NULL, NULL, NULL, + (LPBYTE)tabTipFilePath, &bytesCopied) == ERROR_SUCCESS) { + const TCHAR searchedStr[] = _T("%CommonProgramFiles%"); + const size_t searchedStrLen = ::_tcslen(searchedStr); + int searchedStrStartIndex = -1; + + TCHAR* commonFilesDirPath = NULL; + DWORD commonFilesDirPathLen = 0; + + // Check, if '%CommonProgramFiles%' string is present in the defined + // path of the touch keyboard executable. + TCHAR* const searchedStrStart = ::_tcsstr(tabTipFilePath, searchedStr); + if (searchedStrStart != NULL) { + searchedStrStartIndex = searchedStrStart - tabTipFilePath; + + // Get value of 'CommonProgramFiles' environment variable, if the + // file path of the touch keyboard executable was found in 32-bit + // registry view, otherwise get value of 'CommonProgramW6432'. + const TCHAR envVar32BitName[] = _T("CommonProgramFiles"); + const TCHAR envVar64BitName[] = _T("CommonProgramW6432"); + const TCHAR* envVarName = (regViewWithTabTipCoKey == WOW64_32BIT ? + envVar32BitName : envVar64BitName); + + DWORD charsStored = ::GetEnvironmentVariable(envVarName, NULL, 0); + if (charsStored > 0) { + commonFilesDirPath = new TCHAR[charsStored]; + ::memset(commonFilesDirPath, 0, charsStored * sizeof(TCHAR)); + + DWORD oldCharsStored = charsStored; + if (((charsStored = ::GetEnvironmentVariable(envVarName, + commonFilesDirPath, charsStored)) > 0) && + (charsStored <= oldCharsStored)) { + commonFilesDirPathLen = charsStored; + } else { + delete[] commonFilesDirPath; + commonFilesDirPath = NULL; + } + } + } + + // Calculate 'm_touchKbrdExeFilePath' length in characters including + // the null-terminating character. + DWORD exeFilePathLen = oldBytesCopied / sizeof(TCHAR); + if (commonFilesDirPathLen > 0) { + exeFilePathLen = exeFilePathLen - searchedStrLen + + commonFilesDirPathLen; + } + + if (m_touchKbrdExeFilePath != NULL) { + delete[] m_touchKbrdExeFilePath; + m_touchKbrdExeFilePath = NULL; + } + m_touchKbrdExeFilePath = new TCHAR[exeFilePathLen]; + ::memset(m_touchKbrdExeFilePath, 0, exeFilePathLen * sizeof(TCHAR)); + + if (commonFilesDirPathLen > 0) { + ::_tcsncpy_s(m_touchKbrdExeFilePath, exeFilePathLen, tabTipFilePath, + searchedStrStartIndex); + DWORD charsCopied = searchedStrStartIndex; + + ::_tcsncpy_s(m_touchKbrdExeFilePath + charsCopied, + exeFilePathLen - charsCopied, commonFilesDirPath, + commonFilesDirPathLen); + charsCopied += commonFilesDirPathLen; + + ::_tcsncpy_s(m_touchKbrdExeFilePath + charsCopied, + exeFilePathLen - charsCopied, searchedStrStart + searchedStrLen, + bytesCopied / sizeof(TCHAR) - + (searchedStrStartIndex + searchedStrLen)); + } else { + ::_tcsncpy_s(m_touchKbrdExeFilePath, exeFilePathLen, tabTipFilePath, + bytesCopied / sizeof(TCHAR)); + } + + // Remove leading and trailing quotation marks. + ::StrTrim(m_touchKbrdExeFilePath, _T("\"")); + + // Verify that a file with the path 'm_touchKbrdExeFilePath' exists. + DWORD fileAttrs = ::GetFileAttributes(m_touchKbrdExeFilePath); + DWORD err = ::GetLastError(); + if ((fileAttrs == INVALID_FILE_ATTRIBUTES) || + (fileAttrs & FILE_ATTRIBUTE_DIRECTORY)) { + delete[] m_touchKbrdExeFilePath; + m_touchKbrdExeFilePath = NULL; + } + + if (commonFilesDirPath != NULL) { + delete[] commonFilesDirPath; + } + } + + if (tabTipFilePath != NULL) { + delete[] tabTipFilePath; + } + if (hTabTipCoKey != NULL) { + ::RegCloseKey(hTabTipCoKey); + } +} + +HWND AwtToolkit::GetTouchKeyboardWindow() { + const TCHAR wndClassName[] = _T("IPTip_Main_Window"); + HWND hwnd = ::FindWindow(wndClassName, NULL); + if ((hwnd != NULL) && ::IsWindow(hwnd) && ::IsWindowEnabled(hwnd) && + ::IsWindowVisible(hwnd)) { + return hwnd; + } + return NULL; +} + struct ToolkitThreadProc_Data { bool result; @@ -503,6 +655,52 @@ awt_dnd_initialize(); + /* + * Initialization of the touch keyboard related variables. + */ + tk.m_isWin8OrLater = IS_WIN8; + + TRY; + + JNIEnv* env = AwtToolkit::GetEnv(); + jclass sunToolkitCls = env->FindClass("sun/awt/SunToolkit"); + DASSERT(sunToolkitCls != 0); + CHECK_NULL_RETURN(sunToolkitCls, FALSE); + + jmethodID isTouchKeyboardAutoShowEnabledMID = env->GetStaticMethodID( + sunToolkitCls, "isTouchKeyboardAutoShowEnabled", "()Z"); + DASSERT(isTouchKeyboardAutoShowEnabledMID != 0); + CHECK_NULL_RETURN(isTouchKeyboardAutoShowEnabledMID, FALSE); + + tk.m_touchKbrdAutoShowIsEnabled = env->CallStaticBooleanMethod( + sunToolkitCls, isTouchKeyboardAutoShowEnabledMID); + + CATCH_BAD_ALLOC_RET(FALSE); + + if (tk.m_isWin8OrLater && tk.m_touchKbrdAutoShowIsEnabled) { + tk.InitTouchKeyboardExeFilePath(); + HMODULE hUser32Dll = ::LoadLibrary(_T("user32.dll")); + if (hUser32Dll != NULL) { + tk.m_pRegisterTouchWindow = (RegisterTouchWindowFunc) + ::GetProcAddress(hUser32Dll, "RegisterTouchWindow"); + tk.m_pGetTouchInputInfo = (GetTouchInputInfoFunc) + ::GetProcAddress(hUser32Dll, "GetTouchInputInfo"); + tk.m_pCloseTouchInputHandle = (CloseTouchInputHandleFunc) + ::GetProcAddress(hUser32Dll, "CloseTouchInputHandle"); + } + + if ((tk.m_pRegisterTouchWindow == NULL) || + (tk.m_pGetTouchInputInfo == NULL) || + (tk.m_pCloseTouchInputHandle == NULL)) { + tk.m_pRegisterTouchWindow = NULL; + tk.m_pGetTouchInputInfo = NULL; + tk.m_pCloseTouchInputHandle = NULL; + } + } + /* + * End of the touch keyboard related initialization code. + */ + return TRUE; } @@ -527,6 +725,14 @@ awt_dnd_uninitialize(); awt_clipboard_uninitialize((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2)); + if (tk.m_touchKbrdExeFilePath != NULL) { + delete[] tk.m_touchKbrdExeFilePath; + tk.m_touchKbrdExeFilePath = NULL; + } + tk.m_pRegisterTouchWindow = NULL; + tk.m_pGetTouchInputInfo = NULL; + tk.m_pCloseTouchInputHandle = NULL; + if (tk.m_inputMethodHWnd != NULL) { ::SendMessage(tk.m_inputMethodHWnd, WM_IME_CONTROL, IMC_OPENSTATUSWINDOW, 0); } @@ -2658,6 +2864,32 @@ CATCH_BAD_ALLOC_RET(NULL); } +JNIEXPORT void JNICALL +Java_sun_awt_windows_WToolkit_showTouchKeyboard(JNIEnv *env, jobject self, + jboolean causedByTouchEvent) +{ + AwtToolkit& tk = AwtToolkit::GetInstance(); + if (!tk.IsWin8OrLater() || !tk.IsTouchKeyboardAutoShowEnabled()) { + return; + } + + if (causedByTouchEvent || + (tk.IsTouchKeyboardAutoShowSystemEnabled() && + !tk.IsAnyKeyboardAttached())) { + tk.ShowTouchKeyboard(); + } +} + +JNIEXPORT void JNICALL +Java_sun_awt_windows_WToolkit_hideTouchKeyboard(JNIEnv *env, jobject self) +{ + AwtToolkit& tk = AwtToolkit::GetInstance(); + if (!tk.IsWin8OrLater() || !tk.IsTouchKeyboardAutoShowEnabled()) { + return; + } + tk.HideTouchKeyboard(); +} + JNIEXPORT jboolean JNICALL Java_sun_awt_windows_WToolkit_syncNativeQueue(JNIEnv *env, jobject self, jlong timeout) { @@ -2730,3 +2962,119 @@ UINT AwtToolkit::GetNumberOfButtons() { return MOUSE_BUTTONS_WINDOWS_SUPPORTED; } + +bool AwtToolkit::IsWin8OrLater() { + return m_isWin8OrLater; +} + +bool AwtToolkit::IsTouchKeyboardAutoShowEnabled() { + return m_touchKbrdAutoShowIsEnabled; +} + +bool AwtToolkit::IsAnyKeyboardAttached() { + UINT numDevs = 0; + UINT numDevsRet = 0; + const UINT devListTypeSize = sizeof(RAWINPUTDEVICELIST); + if ((::GetRawInputDeviceList(NULL, &numDevs, devListTypeSize) != 0) || + (numDevs == 0)) { + return false; + } + + RAWINPUTDEVICELIST* pDevList = new RAWINPUTDEVICELIST[numDevs]; + while (((numDevsRet = ::GetRawInputDeviceList(pDevList, &numDevs, + devListTypeSize)) == (UINT)-1) && + (::GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { + if (pDevList != NULL) { + delete[] pDevList; + } + pDevList = new RAWINPUTDEVICELIST[numDevs]; + } + + bool keyboardIsAttached = false; + if (numDevsRet != (UINT)-1) { + for (UINT i = 0; i < numDevsRet; i++) { + if (pDevList[i].dwType == RIM_TYPEKEYBOARD) { + keyboardIsAttached = true; + break; + } + } + } + + if (pDevList != NULL) { + delete[] pDevList; + } + return keyboardIsAttached; +} + +bool AwtToolkit::IsTouchKeyboardAutoShowSystemEnabled() { + const TCHAR tabTipKeyName[] = _T("SOFTWARE\\Microsoft\\TabletTip\\1.7"); + HKEY hTabTipKey = NULL; + if (::RegOpenKeyEx(HKEY_CURRENT_USER, tabTipKeyName, 0, KEY_READ, + &hTabTipKey) != ERROR_SUCCESS) { + return false; + } + + const TCHAR enableAutoInvokeValName[] = _T("EnableDesktopModeAutoInvoke"); + DWORD keyValType = 0; + bool autoShowIsEnabled = false; + if (::RegQueryValueEx(hTabTipKey, enableAutoInvokeValName, NULL, + &keyValType, NULL, NULL) == ERROR_SUCCESS) { + if (keyValType == REG_DWORD) { + DWORD enableAutoInvokeVal = 0; + DWORD bytesCopied = sizeof(DWORD); + if (::RegQueryValueEx(hTabTipKey, enableAutoInvokeValName, NULL, + NULL, (LPBYTE)(DWORD*)&enableAutoInvokeVal, + &bytesCopied) == ERROR_SUCCESS) { + autoShowIsEnabled = (enableAutoInvokeVal == 0 ? false : true); + } + } + } + + if (hTabTipKey != NULL) { + ::RegCloseKey(hTabTipKey); + } + return autoShowIsEnabled; +} + +void AwtToolkit::ShowTouchKeyboard() { + if (m_isWin8OrLater && m_touchKbrdAutoShowIsEnabled && + (m_touchKbrdExeFilePath != NULL)) { + HINSTANCE retVal = ::ShellExecute(NULL, _T("open"), + m_touchKbrdExeFilePath, NULL, NULL, SW_SHOW); + if ((int)retVal <= 32) { + DTRACE_PRINTLN1("AwtToolkit::ShowTouchKeyboard: Failed" + ", retVal='%d'", (int)retVal); + } + } +} + +void AwtToolkit::HideTouchKeyboard() { + if (m_isWin8OrLater && m_touchKbrdAutoShowIsEnabled) { + HWND hwnd = GetTouchKeyboardWindow(); + if (hwnd != NULL) { + ::PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, 0); + } + } +} + +BOOL AwtToolkit::TIRegisterTouchWindow(HWND hWnd, ULONG ulFlags) { + if (m_pRegisterTouchWindow == NULL) { + return FALSE; + } + return m_pRegisterTouchWindow(hWnd, ulFlags); +} + +BOOL AwtToolkit::TIGetTouchInputInfo(HTOUCHINPUT hTouchInput, + UINT cInputs, PTOUCHINPUT pInputs, int cbSize) { + if (m_pGetTouchInputInfo == NULL) { + return FALSE; + } + return m_pGetTouchInputInfo(hTouchInput, cInputs, pInputs, cbSize); +} + +BOOL AwtToolkit::TICloseTouchInputHandle(HTOUCHINPUT hTouchInput) { + if (m_pCloseTouchInputHandle == NULL) { + return FALSE; + } + return m_pCloseTouchInputHandle(hTouchInput); +} --- old/src/windows/native/sun/windows/awt_Toolkit.h 2017-10-13 16:26:31.000000000 +0100 +++ new/src/windows/native/sun/windows/awt_Toolkit.h 2017-10-13 16:26:31.000000000 +0100 @@ -158,6 +158,48 @@ GetCurrentThreadId(), &(cs), THIS_FILE, __LINE__); \ } +// Redefine WinAPI values related to touch input, if OS < Windows 7. +#if (!defined(WINVER) || ((WINVER) < 0x0601)) + /* + * RegisterTouchWindow flag values + */ + #define TWF_FINETOUCH (0x00000001) + #define TWF_WANTPALM (0x00000002) + + #define WM_TOUCH 0x0240 + + /* + * Touch input handle + */ + typedef HANDLE HTOUCHINPUT; + + typedef struct tagTOUCHINPUT { + LONG x; + LONG y; + HANDLE hSource; + DWORD dwID; + DWORD dwFlags; + DWORD dwMask; + DWORD dwTime; + ULONG_PTR dwExtraInfo; + DWORD cxContact; + DWORD cyContact; + } TOUCHINPUT, *PTOUCHINPUT; + typedef TOUCHINPUT const * PCTOUCHINPUT; + + /* + * Touch input flag values (TOUCHINPUT.dwFlags) + */ + #define TOUCHEVENTF_MOVE 0x0001 + #define TOUCHEVENTF_DOWN 0x0002 + #define TOUCHEVENTF_UP 0x0004 + #define TOUCHEVENTF_INRANGE 0x0008 + #define TOUCHEVENTF_PRIMARY 0x0010 + #define TOUCHEVENTF_NOCOALESCE 0x0020 + #define TOUCHEVENTF_PEN 0x0040 + #define TOUCHEVENTF_PALM 0x0080 +#endif + /************************************************************************ * AwtToolkit class */ @@ -193,6 +235,17 @@ void setExtraMouseButtonsEnabled(BOOL enable); static UINT GetNumberOfButtons(); + bool IsWin8OrLater(); + bool IsTouchKeyboardAutoShowEnabled(); + bool IsAnyKeyboardAttached(); + bool IsTouchKeyboardAutoShowSystemEnabled(); + void ShowTouchKeyboard(); + void HideTouchKeyboard(); + BOOL TIRegisterTouchWindow(HWND hWnd, ULONG ulFlags); + BOOL TIGetTouchInputInfo(HTOUCHINPUT hTouchInput, + UINT cInputs, PTOUCHINPUT pInputs, int cbSize); + BOOL TICloseTouchInputHandle(HTOUCHINPUT hTouchInput); + INLINE BOOL localPump() { return m_localPump; } INLINE BOOL VerifyComponents() { return FALSE; } // TODO: Use new DebugHelper class to set this flag INLINE HWND GetHWnd() { return m_toolkitHWnd; } @@ -389,6 +442,9 @@ private: HWND CreateToolkitWnd(LPCTSTR name); + void InitTouchKeyboardExeFilePath(); + HWND GetTouchKeyboardWindow(); + BOOL m_localPump; DWORD m_mainThreadId; HWND m_toolkitHWnd; @@ -398,6 +454,18 @@ BOOL m_isDisposed; // set to TRUE at end of Dispose BOOL m_areExtraMouseButtonsEnabled; + typedef BOOL (WINAPI *RegisterTouchWindowFunc)(HWND hWnd, ULONG ulFlags); + typedef BOOL (WINAPI *GetTouchInputInfoFunc)(HTOUCHINPUT hTouchInput, + UINT cInputs, PTOUCHINPUT pInputs, int cbSize); + typedef BOOL (WINAPI *CloseTouchInputHandleFunc)(HTOUCHINPUT hTouchInput); + + BOOL m_isWin8OrLater; + BOOL m_touchKbrdAutoShowIsEnabled; + TCHAR* m_touchKbrdExeFilePath; + RegisterTouchWindowFunc m_pRegisterTouchWindow; + GetTouchInputInfoFunc m_pGetTouchInputInfo; + CloseTouchInputHandleFunc m_pCloseTouchInputHandle; + BOOL m_vmSignalled; // set to TRUE if QUERYENDSESSION has successfully // raised SIGTERM