提交 14bbfff1 编写于 作者: D dav

6799099: All automatic regression tests that create Robot fail on X11

Reviewed-by: art, ant
上级 edb22b63
......@@ -155,7 +155,7 @@ SUNWprivate_1.1 {
Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl;
Java_sun_awt_X11_XRobotPeer_mouseWheelImpl;
Java_sun_awt_X11_XRobotPeer_setup;
Java_sun_awt_X11_XRobotPeer_getNumberOfButtonsImpl;
Java_sun_awt_X11_XToolkit_getNumberOfButtonsImpl;
Java_java_awt_Component_initIDs;
Java_java_awt_Container_initIDs;
Java_java_awt_Button_initIDs;
......
......@@ -96,11 +96,15 @@ public class Robot {
init(GraphicsEnvironment.getLocalGraphicsEnvironment()
.getDefaultScreenDevice());
int tmpMask = 0;
if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){
for (int i = 0; i < peer.getNumberOfButtons(); i++){
if (Toolkit.getDefaultToolkit() instanceof SunToolkit) {
final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
for (int i = 0; i < buttonsNumber; i++){
tmpMask |= InputEvent.getMaskForButton(i+1);
}
}
}
tmpMask |= InputEvent.BUTTON1_MASK|
InputEvent.BUTTON2_MASK|
InputEvent.BUTTON3_MASK|
......
......@@ -157,6 +157,8 @@ public abstract class InputEvent extends ComponentEvent {
/**
* An array of extended modifiers for additional buttons.
* @see getButtonDownMasks
* There are twenty buttons fit into 4byte space.
* one more bit is reserved for FIRST_HIGH_BIT.
* @since 7.0
*/
private static final int [] BUTTON_DOWN_MASK = new int [] { BUTTON1_DOWN_MASK,
......@@ -169,7 +171,16 @@ public abstract class InputEvent extends ComponentEvent {
1<<18,
1<<19,
1<<20,
1<<21 };
1<<21,
1<<22,
1<<23,
1<<24,
1<<25,
1<<26,
1<<27,
1<<28,
1<<29,
1<<30};
/**
* A method to access an array of extended modifiers for additional buttons.
......@@ -240,7 +251,7 @@ public abstract class InputEvent extends ComponentEvent {
// in fact, it is undesirable to add modifier bits
// to the same field as this may break applications
// see bug# 5066958
static final int FIRST_HIGH_BIT = 1 << 22;
static final int FIRST_HIGH_BIT = 1 << 31;
static final int JDK_1_3_MODIFIERS = SHIFT_DOWN_MASK - 1;
static final int HIGH_MODIFIERS = ~( FIRST_HIGH_BIT - 1 );
......
......@@ -33,6 +33,7 @@ import java.io.IOException;
import java.io.ObjectInputStream;
import java.awt.IllegalComponentStateException;
import java.awt.MouseInfo;
import sun.awt.SunToolkit;
/**
* An event which indicates that a mouse action occurred in a component.
......@@ -379,12 +380,25 @@ public class MouseEvent extends InputEvent {
*/
private static final long serialVersionUID = -991214153494842848L;
/**
* A number of buttons available on the mouse at the {@code Toolkit} machinery startup.
*/
private static int cachedNumberOfButtons;
static {
/* ensure that the necessary native libraries are loaded */
NativeLibLoader.loadLibraries();
if (!GraphicsEnvironment.isHeadless()) {
initIDs();
}
final Toolkit tk = Toolkit.getDefaultToolkit();
if (tk instanceof SunToolkit) {
cachedNumberOfButtons = ((SunToolkit)tk).getNumberOfButtons();
} else {
//It's expected that some toolkits (Headless,
//whatever besides SunToolkit) could also operate.
cachedNumberOfButtons = 3;
}
}
/**
......@@ -411,15 +425,6 @@ public class MouseEvent extends InputEvent {
return new Point(xAbs, yAbs);
}
/**
* A number of buttons available on the mouse at the {@code Toolkit} machinery startup.
*/
private static int cachedNumberOfButtons;
static {
cachedNumberOfButtons = MouseInfo.getNumberOfButtons();
}
/**
* Returns the absolute horizontal x position of the event.
* In a virtual device multi-screen environment in which the
......@@ -735,7 +740,6 @@ public class MouseEvent extends InputEvent {
if (button < NOBUTTON){
throw new IllegalArgumentException("Invalid button value :" + button);
}
//TODO: initialize MouseInfo.cachedNumber on toolkit creation.
if (button > BUTTON3) {
if (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){
throw new IllegalArgumentException("Extra mouse events are disabled " + button);
......
......@@ -121,11 +121,4 @@ public interface RobotPeer
* Disposes the robot peer when it is not needed anymore.
*/
void dispose();
/**
* Returns the number of buttons that the robot simulates.
*
* @return the number of buttons that the robot simulates
*/
int getNumberOfButtons();
}
......@@ -89,6 +89,25 @@ public abstract class SunToolkit extends Toolkit
*/
private static final String POST_EVENT_QUEUE_KEY = "PostEventQueue";
/**
* Number of buttons.
* By default it's taken from the system. If system value does not
* fit into int type range, use our own MAX_BUTTONS_SUPPORT value.
*/
protected static int numberOfButtons = 0;
/* XFree standard mention 24 buttons as maximum:
* http://www.xfree86.org/current/mouse.4.html
* We workaround systems supporting more than 24 buttons.
* Otherwise, we have to use long type values as masks
* which leads to API change.
* InputEvent.BUTTON_DOWN_MASK may contain only 21 masks due to
* the 4-bytes limit for the int type. (CR 6799099)
* One more bit is reserved for FIRST_HIGH_BIT.
*/
public final static int MAX_BUTTONS_SUPPORTED = 20;
public SunToolkit() {
/* If awt.threadgroup is set to class name the instance of
* this class is created (should be subclass of ThreadGroup)
......@@ -2079,6 +2098,12 @@ public abstract class SunToolkit extends Toolkit
return false;
}
/**
* Descendants of the SunToolkit should override and put their own logic here.
*/
public int getNumberOfButtons(){
return 3;
}
} // class SunToolkit
......
......@@ -989,8 +989,17 @@ public class XBaseWindow {
*/
public void handleButtonPressRelease(XEvent xev) {
XButtonEvent xbe = xev.get_xbutton();
/*
* Ignore the buttons above 20 due to the bit limit for
* InputEvent.BUTTON_DOWN_MASK.
* One more bit is reserved for FIRST_HIGH_BIT.
*/
if (xbe.get_button() > SunToolkit.MAX_BUTTONS_SUPPORTED) {
return;
}
int buttonState = 0;
for (int i = 0; i<XToolkit.getNumMouseButtons(); i++){
final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
for (int i = 0; i<buttonsNumber; i++){
// A bug in WM implementation: extra buttons doesn't have state!=0 as they should on Release message.
if ((i != 4) && (i != 5)){
buttonState |= (xbe.get_state() & XConstants.buttonsMask[i]);
......@@ -1026,7 +1035,9 @@ public class XBaseWindow {
* Checks ButtonRelease released all Mouse buttons
*/
static boolean isFullRelease(int buttonState, int button) {
if (button < 0 || button > XToolkit.getNumMouseButtons()) {
final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
if (button < 0 || button > buttonsNumber) {
return buttonState == 0;
} else {
return buttonState == XConstants.buttonsMask[button - 1];
......
......@@ -42,6 +42,7 @@ import sun.awt.ComponentAccessor;
import sun.awt.dnd.SunDragSourceContextPeer;
import sun.awt.dnd.SunDropTargetContextPeer;
import sun.awt.SunToolkit;
/**
* The XDragSourceContextPeer class is the class responsible for handling
......@@ -665,6 +666,15 @@ public final class XDragSourceContextPeer
return true;
case XConstants.ButtonRelease: {
XButtonEvent xbutton = ev.get_xbutton();
/*
* Ignore the buttons above 20 due to the bit limit for
* InputEvent.BUTTON_DOWN_MASK.
* One more bit is reserved for FIRST_HIGH_BIT.
*/
if (xbutton.get_button() > SunToolkit.MAX_BUTTONS_SUPPORTED) {
return true;
}
/*
* On some X servers it could happen that ButtonRelease coordinates
* differ from the latest MotionNotify coordinates, so we need to
......
......@@ -81,16 +81,11 @@ class XRobotPeer implements RobotPeer {
return pixelArray;
}
public int getNumberOfButtons(){
return getNumberOfButtonsImpl();
}
private static native synchronized void setup();
private static native synchronized void mouseMoveImpl(X11GraphicsConfig xgc, int x, int y);
private static native synchronized void mousePressImpl(int buttons);
private static native synchronized void mouseReleaseImpl(int buttons);
private static native synchronized int getNumberOfButtonsImpl();
private static native synchronized void mouseWheelImpl(int wheelAmt);
private static native synchronized void keyPressImpl(int keycode);
......
......@@ -84,21 +84,6 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
//Set to true by default.
private static boolean areExtraMouseButtonsEnabled = true;
/**
* Number of buttons.
* By default it's taken from the system. If system value does not
* fit into int type range, use our own MAX_BUTTONS_SUPPORT value.
*/
private static int numberOfButtons = 0;
/* XFree standard mention 24 buttons as maximum:
* http://www.xfree86.org/current/mouse.4.html
* We workaround systems supporting more than 24 buttons.
* Otherwise, we have to use long type values as masks
* which leads to API change.
*/
private static int MAX_BUTTONS_SUPPORT = 24;
/**
* True when the x settings have been loaded.
*/
......@@ -1458,19 +1443,26 @@ public final class XToolkit extends UNIXToolkit implements Runnable {
desktopProperties.put("awt.multiClickInterval",
Integer.valueOf(getMultiClickTime()));
desktopProperties.put("awt.mouse.numButtons",
Integer.valueOf(getNumMouseButtons()));
Integer.valueOf(getNumberOfButtons()));
}
}
public static int getNumMouseButtons() {
/**
* This method runs through the XPointer and XExtendedPointer array.
* XExtendedPointer has priority because on some systems XPointer
* (which is assigned to the virtual pointer) reports the maximum
* capabilities of the mouse pointer (i.e. 32 physical buttons).
*/
private native synchronized int getNumberOfButtonsImpl();
@Override
public int getNumberOfButtons(){
awtLock();
try {
if (numberOfButtons == 0) {
numberOfButtons = Math.min(
XlibWrapper.XGetPointerMapping(XToolkit.getDisplay(), 0, 0),
MAX_BUTTONS_SUPPORT);
numberOfButtons = getNumberOfButtonsImpl();
}
return numberOfButtons;
return (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons;
} finally {
awtUnlock();
}
......
......@@ -677,6 +677,14 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
int button=0;
boolean wheel_mouse = false;
int lbutton = xbe.get_button();
/*
* Ignore the buttons above 20 due to the bit limit for
* InputEvent.BUTTON_DOWN_MASK.
* One more bit is reserved for FIRST_HIGH_BIT.
*/
if (lbutton > SunToolkit.MAX_BUTTONS_SUPPORTED) {
return;
}
int type = xev.get_type();
when = xbe.get_time();
long jWhen = XToolkit.nowMillisUTC_offset(when);
......@@ -795,8 +803,9 @@ public class XWindow extends XBaseWindow implements X11ComponentPeer {
//this doesn't work for extra buttons because Xsystem is sending state==0 for every extra button event.
// we can't correct it in MouseEvent class as we done it with modifiers, because exact type (DRAG|MOVE)
// should be passed from XWindow.
//TODO: eliminate it with some other value obtained w/o AWTLock.
for (int i = 0; i < XToolkit.getNumMouseButtons(); i++){
final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
for (int i = 0; i < buttonsNumber; i++){
// TODO : here is the bug in WM: extra buttons doesn't have state!=0 as they should.
if ((i != 4) && (i != 5)) {
mouseKeyState = mouseKeyState | (xme.get_state() & XConstants.buttonsMask[i]);
......
......@@ -1894,7 +1894,9 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
}
if (isGrabbed()) {
boolean dragging = false;
for (int i = 0; i<XToolkit.getNumMouseButtons(); i++){
final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
for (int i = 0; i < buttonsNumber; i++){
// here is the bug in WM: extra buttons doesn't have state!=0 as they should.
if ((i != 4) && (i != 5)){
dragging = dragging || ((xme.get_state() & XConstants.buttonsMask[i]) != 0);
......@@ -1940,6 +1942,15 @@ class XWindowPeer extends XPanelPeer implements WindowPeer,
public void handleButtonPressRelease(XEvent xev) {
XButtonEvent xbe = xev.get_xbutton();
/*
* Ignore the buttons above 20 due to the bit limit for
* InputEvent.BUTTON_DOWN_MASK.
* One more bit is reserved for FIRST_HIGH_BIT.
*/
if (xbe.get_button() > SunToolkit.MAX_BUTTONS_SUPPORTED) {
return;
}
if (grabLog.isLoggable(Level.FINE)) {
grabLog.log(Level.FINE, "{0}, when grabbed {1}, contains {2} ({3}, {4}, {5}x{6})",
new Object[] {xbe, isGrabbed(), containsGlobal(xbe.get_x_root(), xbe.get_y_root()), getAbsoluteX(), getAbsoluteY(), getWidth(), getHeight()});
......
/*
* Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1995-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -624,7 +624,6 @@ public class MToolkit extends UNIXToolkit implements Runnable {
}
private native int getMulticlickTime();
private native int getNumMouseButtons();
protected void initializeDesktopProperties() {
desktopProperties.put("DnD.Autoscroll.initialDelay", Integer.valueOf(50));
......@@ -643,7 +642,7 @@ public class MToolkit extends UNIXToolkit implements Runnable {
desktopProperties.put("awt.multiClickInterval",
Integer.valueOf(getMulticlickTime()));
desktopProperties.put("awt.mouse.numButtons",
Integer.valueOf(getNumMouseButtons()));
Integer.valueOf(getNumberOfButtons()));
}
}
......
......@@ -3166,21 +3166,6 @@ JNIEXPORT jint JNICALL Java_sun_awt_motif_MToolkit_getMulticlickTime
return awt_multiclick_time;
}
/*
* Class: sun_awt_motif_MToolkit
* Method: getNumMouseButtons
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_sun_awt_motif_MToolkit_getNumMouseButtons
(JNIEnv *env, jobject this)
{
jint res = 0;
AWT_LOCK();
res = XGetPointerMapping(awt_display, NULL, 0);
AWT_UNLOCK();
return res;
}
/*
* Class: sun_awt_motif_MToolkit
* Method: loadXSettings
......
......@@ -51,9 +51,8 @@
extern struct X11GraphicsConfigIDs x11GraphicsConfigIDs;
// 2 would be more correct, however that's how Robot originally worked
// and tests start to fail if this value is changed
static int32_t num_buttons = 3;
extern int32_t getNumButtons();
static jint * masks;
static int32_t isXTestAvailable() {
......@@ -90,46 +89,6 @@ static int32_t isXTestAvailable() {
return isXTestAvailable;
}
static void getNumButtons() {
int32_t major_opcode, first_event, first_error;
int32_t xinputAvailable;
int32_t numDevices, devIdx, clsIdx;
XDeviceInfo* devices;
XDeviceInfo* aDevice;
XButtonInfo* bInfo;
/* 4700242:
* If XTest is asked to press a non-existant mouse button
* (i.e. press Button3 on a system configured with a 2-button mouse),
* then a crash may happen. To avoid this, we use the XInput
* extension to query for the number of buttons on the XPointer, and check
* before calling XTestFakeButtonEvent().
*/
xinputAvailable = XQueryExtension(awt_display, INAME, &major_opcode, &first_event, &first_error);
DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XINPUT) returns major_opcode = %d, first_event = %d, first_error = %d",
major_opcode, first_event, first_error);
if (xinputAvailable) {
devices = XListInputDevices(awt_display, &numDevices);
for (devIdx = 0; devIdx < numDevices; devIdx++) {
aDevice = &(devices[devIdx]);
if (aDevice->use == IsXPointer) {
for (clsIdx = 0; clsIdx < aDevice->num_classes; clsIdx++) {
if (aDevice->inputclassinfo[clsIdx].class == ButtonClass) {
bInfo = (XButtonInfo*)(&(aDevice->inputclassinfo[clsIdx]));
num_buttons = bInfo->num_buttons;
DTRACE_PRINTLN1("RobotPeer: XPointer has %d buttons", num_buttons);
break;
}
}
break;
}
}
XFreeDeviceList(devices);
}
else {
DTRACE_PRINTLN1("RobotPeer: XINPUT extension is unavailable, assuming %d mouse buttons", num_buttons);
}
}
static XImage *getWindowImage(Display * display, Window window,
int32_t x, int32_t y,
......@@ -241,17 +200,10 @@ Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls) {
return;
}
getNumButtons();
finally:
AWT_UNLOCK();
}
JNIEXPORT jint JNICALL
Java_sun_awt_X11_XRobotPeer_getNumberOfButtonsImpl(JNIEnv *env,
jclass cls) {
// At the moment this routine being called we already should have an initialized num_buttons variable.
return num_buttons;
}
JNIEXPORT void JNICALL
Java_sun_awt_X11_XRobotPeer_getRGBPixelsImpl( JNIEnv *env,
......@@ -386,6 +338,8 @@ void mouseAction(JNIEnv *env,
{
AWT_LOCK();
int32_t num_buttons = getNumButtons(); //from XToolkit.c
DTRACE_PRINTLN1("RobotPeer: mouseAction(%i)", buttonMask);
DTRACE_PRINTLN1("RobotPeer: mouseAction, press = %d", isMousePress);
......
......@@ -45,10 +45,14 @@
#include "sun_awt_X11_XToolkit.h"
#include "java_awt_SystemColor.h"
#include "java_awt_TrayIcon.h"
#include <X11/extensions/XTest.h>
uint32_t awt_NumLockMask = 0;
Boolean awt_ModLockIsShiftLock = False;
static int32_t num_buttons = 0;
int32_t getNumButtons();
extern JavaVM *jvm;
// Tracing level
......@@ -908,3 +912,78 @@ Java_java_awt_Cursor_finalizeImpl(JNIEnv *env, jclass clazz, jlong pData)
AWT_UNLOCK();
}
}
/*
* Class: sun_awt_X11_XToolkit
* Method: getNumberOfButtonsImpl
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_sun_awt_X11_XToolkit_getNumberOfButtonsImpl
(JNIEnv * env, jobject cls){
if (num_buttons == 0) {
num_buttons = getNumButtons();
}
return num_buttons;
}
int32_t getNumButtons() {
int32_t major_opcode, first_event, first_error;
int32_t xinputAvailable;
int32_t numDevices, devIdx, clsIdx;
XDeviceInfo* devices;
XDeviceInfo* aDevice;
XButtonInfo* bInfo;
int32_t local_num_buttons = 0;
/* 4700242:
* If XTest is asked to press a non-existant mouse button
* (i.e. press Button3 on a system configured with a 2-button mouse),
* then a crash may happen. To avoid this, we use the XInput
* extension to query for the number of buttons on the XPointer, and check
* before calling XTestFakeButtonEvent().
*/
xinputAvailable = XQueryExtension(awt_display, INAME, &major_opcode, &first_event, &first_error);
DTRACE_PRINTLN3("RobotPeer: XQueryExtension(XINPUT) returns major_opcode = %d, first_event = %d, first_error = %d",
major_opcode, first_event, first_error);
if (xinputAvailable) {
devices = XListInputDevices(awt_display, &numDevices);
for (devIdx = 0; devIdx < numDevices; devIdx++) {
aDevice = &(devices[devIdx]);
if (aDevice->use == IsXExtensionPointer) {
for (clsIdx = 0; clsIdx < aDevice->num_classes; clsIdx++) {
if (aDevice->inputclassinfo[clsIdx].class == ButtonClass) {
bInfo = (XButtonInfo*)(&(aDevice->inputclassinfo[clsIdx]));
local_num_buttons = bInfo->num_buttons;
DTRACE_PRINTLN1("RobotPeer: XPointer has %d buttons", num_buttons);
break;
}
}
break;
}
if (local_num_buttons <= 0 ) {
if (aDevice->use == IsXPointer) {
for (clsIdx = 0; clsIdx < aDevice->num_classes; clsIdx++) {
if (aDevice->inputclassinfo[clsIdx].class == ButtonClass) {
bInfo = (XButtonInfo*)(&(aDevice->inputclassinfo[clsIdx]));
local_num_buttons = bInfo->num_buttons;
DTRACE_PRINTLN1("RobotPeer: XPointer has %d buttons", num_buttons);
break;
}
}
break;
}
}
}
XFreeDeviceList(devices);
}
else {
DTRACE_PRINTLN1("RobotPeer: XINPUT extension is unavailable, assuming %d mouse buttons", num_buttons);
}
if (local_num_buttons == 0 ) {
local_num_buttons = 3;
}
return local_num_buttons;
}
......@@ -60,8 +60,6 @@ class WRobotPeer extends WObjectPeer implements RobotPeer
}
public native int getRGBPixelImpl(int x, int y);
public native int getNumberOfButtons();
public int [] getRGBPixels(Rectangle bounds) {
int pixelArray[] = new int[bounds.width*bounds.height];
getRGBPixels(bounds.x, bounds.y, bounds.width, bounds.height, pixelArray);
......
......@@ -982,6 +982,16 @@ public class WToolkit extends SunToolkit implements Runnable {
return areExtraMouseButtonsEnabled;
}
private native synchronized int getNumberOfButtonsImpl();
@Override
public int getNumberOfButtons(){
if (numberOfButtons == 0) {
numberOfButtons = getNumberOfButtonsImpl();
}
return (numberOfButtons > MAX_BUTTONS_SUPPORTED)? MAX_BUTTONS_SUPPORTED : numberOfButtons;
}
@Override
public boolean isWindowOpacitySupported() {
// supported in Win2K and later
......
......@@ -437,9 +437,3 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WRobotPeer_keyRelease(
CATCH_BAD_ALLOC;
}
JNIEXPORT jint JNICALL Java_sun_awt_windows_WRobotPeer_getNumberOfButtons(
JNIEnv *, jobject self)
{
return GetSystemMetrics(SM_CMOUSEBUTTONS);
}
......@@ -2259,3 +2259,8 @@ extern "C" JNIEXPORT void JNICALL Java_sun_awt_windows_WToolkit_setExtraMouseBut
void AwtToolkit::setExtraMouseButtonsEnabled(BOOL enable) {
m_areExtraMouseButtonsEnabled = enable;
}
JNIEXPORT jint JNICALL Java_sun_awt_windows_WToolkit_getNumberOfButtonsImpl
(JNIEnv *, jobject self) {
return GetSystemMetrics(SM_CMOUSEBUTTONS);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册