8166772: Touch keyboard is not shown for text components on a screen touch
Reviewed-by: serb, azvegint
--- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifDesktopIconUI.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifDesktopIconUI.java Wed Oct 11 15:53:25 2017 +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.
@@ -238,11 +240,15 @@
}
@SuppressWarnings("deprecation")
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);
}
@SuppressWarnings("deprecation")
@@ -331,10 +337,14 @@
}
@SuppressWarnings("deprecation")
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);
}
@SuppressWarnings("deprecation")
--- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifInternalFrameTitlePane.java Wed Oct 11 15:53:25 2017 +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
*
@@ -363,11 +366,15 @@
}
@SuppressWarnings("deprecation")
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) {
--- a/src/java.desktop/share/classes/java/awt/Component.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/java/awt/Component.java Wed Oct 11 15:53:25 2017 +0100
@@ -5022,6 +5022,12 @@
tpeer.handleEvent(e);
}
}
+
+ if (SunToolkit.isTouchKeyboardAutoShowEnabled() &&
+ (toolkit instanceof SunToolkit) &&
+ ((e instanceof MouseEvent) || (e instanceof FocusEvent))) {
+ ((SunToolkit)toolkit).showOrHideTouchKeyboard(this, e);
+ }
} // dispatchEventImpl()
/*
--- a/src/java.desktop/share/classes/java/awt/Container.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/java/awt/Container.java Wed Oct 11 15:53:25 2017 +0100
@@ -55,6 +55,7 @@
import sun.awt.AppContext;
import sun.awt.AWTAccessor;
+import sun.awt.AWTAccessor.MouseEventAccessor;
import sun.awt.PeerEvent;
import sun.awt.SunToolkit;
@@ -4783,6 +4784,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();
@@ -4884,6 +4888,9 @@
e.getClickCount(),
e.isPopupTrigger(),
e.getButton());
+ MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
+ meAccessor.setCausedByTouchEvent(retargeted,
+ meAccessor.isCausedByTouchEvent(e));
}
((AWTEvent)e).copyPrivateDataInto(retargeted);
--- a/src/java.desktop/share/classes/java/awt/event/MouseEvent.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/java/awt/event/MouseEvent.java Wed Oct 11 15:53:25 2017 +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;
+ }
+ });
}
/**
--- a/src/java.desktop/share/classes/javax/swing/Autoscroller.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/javax/swing/Autoscroller.java Wed Oct 11 15:53:25 2017 +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)
@@ -97,6 +100,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);
@@ -175,6 +181,9 @@
event.getClickCount(),
event.isPopupTrigger(),
MouseEvent.NOBUTTON);
+ MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
+ meAccessor.setCausedByTouchEvent(e,
+ meAccessor.isCausedByTouchEvent(event));
component.superProcessMouseMotionEvent(e);
}
--- a/src/java.desktop/share/classes/javax/swing/JList.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/javax/swing/JList.java Wed Oct 11 15:53:25 2017 +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.*;
@@ -1552,6 +1554,10 @@
event.getClickCount(),
event.isPopupTrigger(),
MouseEvent.NOBUTTON);
+ MouseEventAccessor meAccessor =
+ AWTAccessor.getMouseEventAccessor();
+ meAccessor.setCausedByTouchEvent(newEvent,
+ meAccessor.isCausedByTouchEvent(event));
String tip = ((JComponent)rComponent).getToolTipText(
newEvent);
--- a/src/java.desktop/share/classes/javax/swing/JTable.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/javax/swing/JTable.java Wed Oct 11 15:53:25 2017 +0100
@@ -56,6 +56,8 @@
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;
@@ -3420,6 +3422,9 @@
event.getClickCount(),
event.isPopupTrigger(),
MouseEvent.NOBUTTON);
+ MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
+ meAccessor.setCausedByTouchEvent(newEvent,
+ meAccessor.isCausedByTouchEvent(event));
tip = ((JComponent)component).getToolTipText(newEvent);
}
--- a/src/java.desktop/share/classes/javax/swing/JTree.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/javax/swing/JTree.java Wed Oct 11 15:53:25 2017 +0100
@@ -39,6 +39,8 @@
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.*;
@@ -1578,6 +1580,10 @@
event.getClickCount(),
event.isPopupTrigger(),
MouseEvent.NOBUTTON);
+ MouseEventAccessor meAccessor =
+ AWTAccessor.getMouseEventAccessor();
+ meAccessor.setCausedByTouchEvent(newEvent,
+ meAccessor.isCausedByTouchEvent(event));
tip = ((JComponent)rComponent).getToolTipText(newEvent);
}
--- a/src/java.desktop/share/classes/javax/swing/MenuSelectionManager.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/javax/swing/MenuSelectionManager.java Wed Oct 11 15:53:25 2017 +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;
/**
@@ -308,6 +310,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);
@@ -320,6 +325,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(),
@@ -329,6 +336,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();
--- a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java Wed Oct 11 15:53:25 2017 +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.
@@ -405,6 +407,9 @@
sourceEvent.getClickCount(),
sourceEvent.isPopupTrigger(),
sourceEvent.getButton());
+ MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
+ meAccessor.setCausedByTouchEvent(newEvent,
+ meAccessor.isCausedByTouchEvent(sourceEvent));
}
return newEvent;
}
--- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicComboPopup.java Wed Oct 11 15:53:25 2017 +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 <code>ComboPopup</code> interface.
@@ -534,13 +536,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);
}
@@ -1251,6 +1258,9 @@
e.getClickCount(),
e.isPopupTrigger(),
MouseEvent.NOBUTTON );
+ MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
+ meAccessor.setCausedByTouchEvent(newEvent,
+ meAccessor.isCausedByTouchEvent(e));
return newEvent;
}
--- a/src/java.desktop/share/classes/javax/swing/table/JTableHeader.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/javax/swing/table/JTableHeader.java Wed Oct 11 15:53:25 2017 +0100
@@ -42,6 +42,9 @@
import java.io.ObjectOutputStream;
import java.io.IOException;
+import sun.awt.AWTAccessor;
+import sun.awt.AWTAccessor.MouseEventAccessor;
+
/**
* This is the object which manages the header of the <code>JTable</code>.
* <p>
@@ -414,6 +417,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);
}
--- a/src/java.desktop/share/classes/sun/awt/AWTAccessor.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/sun/awt/AWTAccessor.java Wed Oct 11 15:53:25 2017 +0100
@@ -38,6 +38,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.image.BufferStrategy;
import java.awt.peer.ComponentPeer;
@@ -412,6 +413,21 @@
boolean canAccessSystemClipboard);
}
+ /**
+ * 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.
*/
@@ -851,6 +867,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;
@@ -965,6 +982,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) {
--- a/src/java.desktop/share/classes/sun/awt/SunToolkit.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/sun/awt/SunToolkit.java Wed Oct 11 15:53:25 2017 +0100
@@ -84,6 +84,9 @@
if (AccessController.doPrivileged(new GetBooleanAction("sun.awt.nativedebug"))) {
DebugSettings.init();
}
+ touchKeyboardAutoShowIsEnabled = Boolean.valueOf(
+ GetPropertyAction.privilegedGetProperty(
+ "awt.touchKeyboardAutoShowIsEnabled", "true"));
};
/**
@@ -1614,6 +1617,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
--- a/src/java.desktop/share/classes/sun/swing/FilePane.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/share/classes/sun/swing/FilePane.java Wed Oct 11 15:53:25 2017 +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.*;
/**
@@ -1858,13 +1860,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;
--- a/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/windows/classes/sun/awt/windows/WToolkit.java Wed Oct 11 15:53:25 2017 +0100
@@ -31,12 +31,16 @@
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.AWTAccessor;
import sun.awt.AppContext;
@@ -1084,6 +1088,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);
--- a/src/java.desktop/windows/native/libawt/windows/awt.h Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/windows/native/libawt/windows/awt.h Wed Oct 11 15:53:25 2017 +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())) || \
--- a/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.cpp Wed Oct 11 15:53:25 2017 +0100
@@ -217,6 +217,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;
@@ -582,6 +586,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.
*/
@@ -1713,6 +1722,9 @@
break;
}
break;
+ case WM_TOUCH:
+ WmTouch(wParam, lParam);
+ break;
case WM_SETCURSOR:
mr = mrDoDefault;
if (LOWORD(lParam) == HTCLIENT) {
@@ -2295,6 +2307,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);
@@ -2337,6 +2381,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);
@@ -2355,7 +2407,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
@@ -2377,13 +2429,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, ::JVM_CurrentTimeMillis(NULL, 0),
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,
@@ -4970,7 +5030,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());
@@ -5020,6 +5080,10 @@
DASSERT(mouseEvent != NULL);
CHECK_NULL(mouseEvent);
+ if (causedByTouchEvent) {
+ env->SetBooleanField(mouseEvent, AwtMouseEvent::causedByTouchEventID,
+ JNI_TRUE);
+ }
if (pMsg != 0) {
AwtAWTEvent::saveMSG(env, pMsg, mouseEvent);
}
--- a/src/java.desktop/windows/native/libawt/windows/awt_Component.h Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Component.h Wed Oct 11 15:53:25 2017 +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
@@ -385,7 +388,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
@@ -528,6 +531,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.
@@ -764,6 +768,11 @@
*/
UINT m_mouseButtonClickAllowed;
+ BOOL m_touchDownOccurred;
+ BOOL m_touchUpOccurred;
+ POINT m_touchDownPoint;
+ POINT m_touchUpPoint;
+
BOOL m_bSubclassed;
BOOL m_bPauseDestroy;
--- a/src/java.desktop/windows/native/libawt/windows/awt_MouseEvent.cpp Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/windows/native/libawt/windows/awt_MouseEvent.cpp Wed Oct 11 15:53:25 2017 +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);
--- a/src/java.desktop/windows/native/libawt/windows/awt_MouseEvent.h Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/windows/native/libawt/windows/awt_MouseEvent.h Wed Oct 11 15:53:25 2017 +0100
@@ -39,6 +39,7 @@
/* java.awt.MouseEvent field ids */
static jfieldID xID;
static jfieldID yID;
+ static jfieldID causedByTouchEventID;
static jfieldID buttonID;
};
--- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.cpp Wed Oct 11 15:53:25 2017 +0100
@@ -29,6 +29,8 @@
#include <signal.h>
#include <windowsx.h>
#include <process.h>
+#include <shellapi.h>
+#include <shlwapi.h>
#include "awt_DrawingSurface.h"
#include "awt_AWTEvent.h"
@@ -305,6 +307,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;
@@ -359,6 +368,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;
@@ -517,6 +669,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;
}
@@ -541,6 +739,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);
}
@@ -2747,6 +2953,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)
{
@@ -2824,3 +3056,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);
+}
--- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h Tue Oct 10 12:15:25 2017 -0700
+++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h Wed Oct 11 15:53:25 2017 +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
*/
@@ -196,6 +238,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; }
@@ -393,6 +446,9 @@
private:
HWND CreateToolkitWnd(LPCTSTR name);
+ void InitTouchKeyboardExeFilePath();
+ HWND GetTouchKeyboardWindow();
+
BOOL m_localPump;
DWORD m_mainThreadId;
HWND m_toolkitHWnd;
@@ -402,6 +458,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