mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 07:14:30 +02:00
8166772: Touch keyboard is not shown for text components on a screen touch
Reviewed-by: serb, azvegint
This commit is contained in:
parent
a9cb8eb350
commit
dd41b7691f
24 changed files with 726 additions and 13 deletions
|
@ -36,6 +36,8 @@ import java.beans.*;
|
|||
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 @@ public class MotifDesktopIconUI extends BasicDesktopIconUI
|
|||
}
|
||||
@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 @@ public class MotifDesktopIconUI extends BasicDesktopIconUI
|
|||
}
|
||||
@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")
|
||||
|
|
|
@ -37,6 +37,9 @@ import java.beans.PropertyChangeEvent;
|
|||
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 @@ public class MotifInternalFrameTitlePane
|
|||
}
|
||||
@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) {
|
||||
|
|
|
@ -5022,6 +5022,12 @@ public abstract class Component implements ImageObserver, MenuContainer,
|
|||
tpeer.handleEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (SunToolkit.isTouchKeyboardAutoShowEnabled() &&
|
||||
(toolkit instanceof SunToolkit) &&
|
||||
((e instanceof MouseEvent) || (e instanceof FocusEvent))) {
|
||||
((SunToolkit)toolkit).showOrHideTouchKeyboard(this, e);
|
||||
}
|
||||
} // dispatchEventImpl()
|
||||
|
||||
/*
|
||||
|
|
|
@ -55,6 +55,7 @@ import sun.util.logging.PlatformLogger;
|
|||
|
||||
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 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
|
|||
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 @@ class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
|
|||
e.getClickCount(),
|
||||
e.isPopupTrigger(),
|
||||
e.getButton());
|
||||
MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
|
||||
meAccessor.setCausedByTouchEvent(retargeted,
|
||||
meAccessor.isCausedByTouchEvent(e));
|
||||
}
|
||||
|
||||
((AWTEvent)e).copyPrivateDataInto(retargeted);
|
||||
|
|
|
@ -33,6 +33,8 @@ import java.io.IOException;
|
|||
import java.io.ObjectInputStream;
|
||||
import java.awt.IllegalComponentStateException;
|
||||
import java.awt.MouseInfo;
|
||||
|
||||
import sun.awt.AWTAccessor;
|
||||
import sun.awt.SunToolkit;
|
||||
|
||||
/**
|
||||
|
@ -331,6 +333,11 @@ public class MouseEvent extends InputEvent {
|
|||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -399,6 +406,17 @@ public class MouseEvent extends InputEvent {
|
|||
//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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,6 +28,9 @@ package javax.swing;
|
|||
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 @@ class Autoscroller implements ActionListener {
|
|||
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 @@ class Autoscroller implements ActionListener {
|
|||
event.getClickCount(),
|
||||
event.isPopupTrigger(),
|
||||
MouseEvent.NOBUTTON);
|
||||
MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
|
||||
meAccessor.setCausedByTouchEvent(e,
|
||||
meAccessor.isCausedByTouchEvent(event));
|
||||
component.superProcessMouseMotionEvent(e);
|
||||
}
|
||||
|
||||
|
|
|
@ -48,6 +48,8 @@ import java.io.ObjectOutputStream;
|
|||
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 @@ public class JList<E> extends JComponent implements Scrollable, Accessible
|
|||
event.getClickCount(),
|
||||
event.isPopupTrigger(),
|
||||
MouseEvent.NOBUTTON);
|
||||
MouseEventAccessor meAccessor =
|
||||
AWTAccessor.getMouseEventAccessor();
|
||||
meAccessor.setCausedByTouchEvent(newEvent,
|
||||
meAccessor.isCausedByTouchEvent(event));
|
||||
|
||||
String tip = ((JComponent)rComponent).getToolTipText(
|
||||
newEvent);
|
||||
|
|
|
@ -56,6 +56,8 @@ import java.util.List;
|
|||
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 @@ public class JTable extends JComponent implements TableModelListener, Scrollable
|
|||
event.getClickCount(),
|
||||
event.isPopupTrigger(),
|
||||
MouseEvent.NOBUTTON);
|
||||
MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
|
||||
meAccessor.setCausedByTouchEvent(newEvent,
|
||||
meAccessor.isCausedByTouchEvent(event));
|
||||
|
||||
tip = ((JComponent)component).getToolTipText(newEvent);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ 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.*;
|
||||
|
@ -1578,6 +1580,10 @@ public class JTree extends JComponent implements Scrollable, Accessible
|
|||
event.getClickCount(),
|
||||
event.isPopupTrigger(),
|
||||
MouseEvent.NOBUTTON);
|
||||
MouseEventAccessor meAccessor =
|
||||
AWTAccessor.getMouseEventAccessor();
|
||||
meAccessor.setCausedByTouchEvent(newEvent,
|
||||
meAccessor.isCausedByTouchEvent(event));
|
||||
|
||||
tip = ((JComponent)rComponent).getToolTipText(newEvent);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ import java.awt.event.*;
|
|||
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 @@ public class MenuSelectionManager {
|
|||
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 @@ public class MenuSelectionManager {
|
|||
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 @@ public class MenuSelectionManager {
|
|||
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();
|
||||
|
|
|
@ -44,6 +44,8 @@ import java.security.AccessController;
|
|||
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 @@ public class SwingUtilities implements SwingConstants
|
|||
sourceEvent.getClickCount(),
|
||||
sourceEvent.isPopupTrigger(),
|
||||
sourceEvent.getButton());
|
||||
MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
|
||||
meAccessor.setCausedByTouchEvent(newEvent,
|
||||
meAccessor.isCausedByTouchEvent(sourceEvent));
|
||||
}
|
||||
return newEvent;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,8 @@ import java.beans.PropertyChangeListener;
|
|||
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 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup {
|
|||
// 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 @@ public class BasicComboPopup extends JPopupMenu implements ComboPopup {
|
|||
e.getClickCount(),
|
||||
e.isPopupTrigger(),
|
||||
MouseEvent.NOBUTTON );
|
||||
MouseEventAccessor meAccessor = AWTAccessor.getMouseEventAccessor();
|
||||
meAccessor.setCausedByTouchEvent(newEvent,
|
||||
meAccessor.isCausedByTouchEvent(e));
|
||||
return newEvent;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,9 @@ import java.beans.Transient;
|
|||
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 @@ public class JTableHeader extends JComponent implements TableColumnModelListener
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.awt.event.AWTEventListener;
|
|||
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 @@ public final class AWTAccessor {
|
|||
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 @@ public final class AWTAccessor {
|
|||
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;
|
||||
|
@ -964,6 +981,23 @@ public final class AWTAccessor {
|
|||
return inputEventAccessor;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
|
|
@ -84,6 +84,9 @@ public abstract class SunToolkit extends Toolkit
|
|||
if (AccessController.doPrivileged(new GetBooleanAction("sun.awt.nativedebug"))) {
|
||||
DebugSettings.init();
|
||||
}
|
||||
touchKeyboardAutoShowIsEnabled = Boolean.valueOf(
|
||||
GetPropertyAction.privilegedGetProperty(
|
||||
"awt.touchKeyboardAutoShowIsEnabled", "true"));
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1614,6 +1617,13 @@ public abstract class SunToolkit extends Toolkit
|
|||
*/
|
||||
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
|
||||
|
|
|
@ -44,6 +44,8 @@ import javax.swing.plaf.basic.*;
|
|||
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 @@ public class FilePane extends JPanel implements PropertyChangeListener {
|
|||
// 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;
|
||||
|
|
|
@ -31,12 +31,16 @@ import java.awt.im.InputMethodHighlight;
|
|||
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 @@ public final class WToolkit extends SunToolkit implements Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 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);
|
||||
|
||||
|
|
|
@ -163,6 +163,9 @@ typedef AwtObject* PDATA;
|
|||
#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())) || \
|
||||
|
|
|
@ -217,6 +217,10 @@ BOOL windowMoveLockHeld = FALSE;
|
|||
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 @@ AwtComponent::CreateHWnd(JNIEnv *env, LPCWSTR title,
|
|||
/* 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 @@ LRESULT AwtComponent::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case WM_TOUCH:
|
||||
WmTouch(wParam, lParam);
|
||||
break;
|
||||
case WM_SETCURSOR:
|
||||
mr = mrDoDefault;
|
||||
if (LOWORD(lParam) == HTCLIENT) {
|
||||
|
@ -2295,6 +2307,38 @@ MsgRouting AwtComponent::WmWindowPosChanged(LPARAM windowPos) {
|
|||
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 @@ MsgRouting AwtComponent::WmMouseDown(UINT flags, int x, int y, int button)
|
|||
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 @@ MsgRouting AwtComponent::WmMouseDown(UINT flags, int x, int y, int button)
|
|||
|
||||
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::WmMouseDown(UINT flags, int x, int y, int button)
|
|||
|
||||
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::ReleaseDragCapture(UINT flags)
|
|||
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 @@ void AwtComponent::SendMouseEvent(jint id, jlong when, jint x, jint y,
|
|||
|
||||
DASSERT(mouseEvent != NULL);
|
||||
CHECK_NULL(mouseEvent);
|
||||
if (causedByTouchEvent) {
|
||||
env->SetBooleanField(mouseEvent, AwtMouseEvent::causedByTouchEventID,
|
||||
JNI_TRUE);
|
||||
}
|
||||
if (pMsg != 0) {
|
||||
AwtAWTEvent::saveMSG(env, pMsg, mouseEvent);
|
||||
}
|
||||
|
|
|
@ -67,7 +67,10 @@ const UINT MAX_ACP_STR_LEN = 7; // ANSI CP identifiers are no longer than this
|
|||
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 @@ public:
|
|||
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 @@ public:
|
|||
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 @@ private:
|
|||
*/
|
||||
UINT m_mouseButtonClickAllowed;
|
||||
|
||||
BOOL m_touchDownOccurred;
|
||||
BOOL m_touchUpOccurred;
|
||||
POINT m_touchDownPoint;
|
||||
POINT m_touchUpPoint;
|
||||
|
||||
BOOL m_bSubclassed;
|
||||
BOOL m_bPauseDestroy;
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
jfieldID AwtMouseEvent::xID;
|
||||
jfieldID AwtMouseEvent::yID;
|
||||
jfieldID AwtMouseEvent::causedByTouchEventID;
|
||||
jfieldID AwtMouseEvent::buttonID;
|
||||
|
||||
/************************************************************************
|
||||
|
@ -52,6 +53,11 @@ Java_java_awt_event_MouseEvent_initIDs(JNIEnv *env, jclass cls) {
|
|||
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);
|
||||
|
|
|
@ -39,6 +39,7 @@ public:
|
|||
/* java.awt.MouseEvent field ids */
|
||||
static jfieldID xID;
|
||||
static jfieldID yID;
|
||||
static jfieldID causedByTouchEventID;
|
||||
static jfieldID buttonID;
|
||||
|
||||
};
|
||||
|
|
|
@ -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 @@ AwtToolkit::AwtToolkit() {
|
|||
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 @@ HWND AwtToolkit::CreateToolkitWnd(LPCTSTR name)
|
|||
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 @@ BOOL AwtToolkit::Initialize(BOOL localPump) {
|
|||
|
||||
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 @@ BOOL AwtToolkit::Dispose() {
|
|||
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 @@ Java_sun_awt_windows_WToolkit_getWindowsVersion(JNIEnv *env, jclass cls)
|
|||
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 @@ JNIEXPORT jint JNICALL Java_sun_awt_windows_WToolkit_getNumberOfButtonsImpl
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -158,6 +158,48 @@ class CriticalSection {
|
|||
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 @@ public:
|
|||
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 @@ public:
|
|||
private:
|
||||
HWND CreateToolkitWnd(LPCTSTR name);
|
||||
|
||||
void InitTouchKeyboardExeFilePath();
|
||||
HWND GetTouchKeyboardWindow();
|
||||
|
||||
BOOL m_localPump;
|
||||
DWORD m_mainThreadId;
|
||||
HWND m_toolkitHWnd;
|
||||
|
@ -402,6 +458,18 @@ private:
|
|||
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
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue