OpenJDK / bsd-port / jdk9 / jdk
changeset 870:3b9a288d7ddb
6315717: Support for mouse with multiple scroll wheels and 4 or more buttons
Summary: implementation of the more mouse buttons support
Reviewed-by: art, dcherepanov
line wrap: on
line diff
--- a/make/sun/xawt/mapfile-vers Thu Sep 11 10:38:00 2008 +0400 +++ b/make/sun/xawt/mapfile-vers Tue Sep 16 12:17:02 2008 +0400 @@ -151,6 +151,7 @@ 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_java_awt_Component_initIDs; Java_java_awt_Container_initIDs; Java_java_awt_Button_initIDs;
--- a/src/share/classes/java/awt/Robot.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/share/classes/java/awt/Robot.java Tue Sep 16 12:17:02 2008 +0400 @@ -70,10 +70,7 @@ private RobotPeer peer; private boolean isAutoWaitForIdle = false; private int autoDelay = 0; - private static final int LEGAL_BUTTON_MASK = - InputEvent.BUTTON1_MASK| - InputEvent.BUTTON2_MASK| - InputEvent.BUTTON3_MASK; + private static int LEGAL_BUTTON_MASK; // location of robot's GC, used in mouseMove(), getPixelColor() and captureScreenImage() private Point gdLoc; @@ -98,6 +95,19 @@ } init(GraphicsEnvironment.getLocalGraphicsEnvironment() .getDefaultScreenDevice()); + int tmpMask = 0; + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + for (int i = 0; i < peer.getNumberOfButtons(); i++){ + tmpMask |= InputEvent.getMaskForButton(i+1); + } + } + tmpMask |= InputEvent.BUTTON1_MASK| + InputEvent.BUTTON2_MASK| + InputEvent.BUTTON3_MASK| + InputEvent.BUTTON1_DOWN_MASK| + InputEvent.BUTTON2_DOWN_MASK| + InputEvent.BUTTON3_DOWN_MASK; + LEGAL_BUTTON_MASK = tmpMask; } /** @@ -187,18 +197,55 @@ /** * Presses one or more mouse buttons. The mouse buttons should - * be released using the <code>mouseRelease</code> method. + * be released using the {@link #mouseRelease(int)} method. * - * @param buttons the Button mask; a combination of one or more - * of these flags: + * @param buttons the Button mask; a combination of one or more + * mouse button masks. + * <p> + * It is allowed to use only a combination of valid values as a {@code buttons} parameter. + * A valid combination consists of {@code InputEvent.BUTTON1_DOWN_MASK}, + * {@code InputEvent.BUTTON2_DOWN_MASK}, {@code InputEvent.BUTTON3_DOWN_MASK} + * and values returned by the + * {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)} method. + * + * The valid combination also depends on a + * {@link Toolkit#areExtraMouseButtonsEnabled() Toolkit.areExtraMouseButtonsEnabled()} value as follows: * <ul> - * <li><code>InputEvent.BUTTON1_MASK</code> - * <li><code>InputEvent.BUTTON2_MASK</code> - * <li><code>InputEvent.BUTTON3_MASK</code> + * <li> If support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * then it is allowed to use only the following standard button masks: + * {@code InputEvent.BUTTON1_DOWN_MASK}, {@code InputEvent.BUTTON2_DOWN_MASK}, + * {@code InputEvent.BUTTON3_DOWN_MASK}. + * <li> If support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java + * then it is allowed to use the standard button masks + * and masks for existing extended mouse buttons, if the mouse has more then three buttons. + * In that way, it is allowed to use the button masks corresponding to the buttons + * in the range from 1 to {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}. + * <br> + * It is recommended to use the {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)} + * method to obtain the mask for any mouse button by its number. * </ul> - * @throws IllegalArgumentException if the button mask is not a - * valid combination + * <p> + * The following standard button masks are also accepted: + * <ul> + * <li>{@code InputEvent.BUTTON1_MASK} + * <li>{@code InputEvent.BUTTON2_MASK} + * <li>{@code InputEvent.BUTTON3_MASK} + * </ul> + * However, it is recommended to use {@code InputEvent.BUTTON1_DOWN_MASK}, + * {@code InputEvent.BUTTON2_DOWN_MASK}, {@code InputEvent.BUTTON3_DOWN_MASK} instead. + * Either extended {@code _DOWN_MASK} or old {@code _MASK} values + * should be used, but both those models should not be mixed. + * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button + * and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button + * that does not exist on the mouse and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java * @see #mouseRelease(int) + * @see InputEvent#getMaskForButton(int) + * @see Toolkit#areExtraMouseButtonsEnabled() + * @see java.awt.MouseInfo#getNumberOfButtons() + * @see java.awt.event.MouseEvent */ public synchronized void mousePress(int buttons) { checkButtonsArgument(buttons); @@ -209,16 +256,53 @@ /** * Releases one or more mouse buttons. * - * @param buttons the Button mask; a combination of one or more - * of these flags: + * @param buttons the Button mask; a combination of one or more + * mouse button masks. + * <p> + * It is allowed to use only a combination of valid values as a {@code buttons} parameter. + * A valid combination consists of {@code InputEvent.BUTTON1_DOWN_MASK}, + * {@code InputEvent.BUTTON2_DOWN_MASK}, {@code InputEvent.BUTTON3_DOWN_MASK} + * and values returned by the + * {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)} method. + * + * The valid combination also depends on a + * {@link Toolkit#areExtraMouseButtonsEnabled() Toolkit.areExtraMouseButtonsEnabled()} value as follows: * <ul> - * <li><code>InputEvent.BUTTON1_MASK</code> - * <li><code>InputEvent.BUTTON2_MASK</code> - * <li><code>InputEvent.BUTTON3_MASK</code> + * <li> If the support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * then it is allowed to use only the following standard button masks: + * {@code InputEvent.BUTTON1_DOWN_MASK}, {@code InputEvent.BUTTON2_DOWN_MASK}, + * {@code InputEvent.BUTTON3_DOWN_MASK}. + * <li> If the support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java + * then it is allowed to use the standard button masks + * and masks for existing extended mouse buttons, if the mouse has more then three buttons. + * In that way, it is allowed to use the button masks corresponding to the buttons + * in the range from 1 to {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}. + * <br> + * It is recommended to use the {@link InputEvent#getMaskForButton(int) InputEvent.getMaskForButton(button)} + * method to obtain the mask for any mouse button by its number. * </ul> + * <p> + * The following standard button masks are also accepted: + * <ul> + * <li>{@code InputEvent.BUTTON1_MASK} + * <li>{@code InputEvent.BUTTON2_MASK} + * <li>{@code InputEvent.BUTTON3_MASK} + * </ul> + * However, it is recommended to use {@code InputEvent.BUTTON1_DOWN_MASK}, + * {@code InputEvent.BUTTON2_DOWN_MASK}, {@code InputEvent.BUTTON3_DOWN_MASK} instead. + * Either extended {@code _DOWN_MASK} or old {@code _MASK} values + * should be used, but both those models should not be mixed. + * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button + * and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * @throws IllegalArgumentException if the {@code buttons} mask contains the mask for extra mouse button + * that does not exist on the mouse and support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java * @see #mousePress(int) - * @throws IllegalArgumentException if the button mask is not a valid - * combination + * @see InputEvent#getMaskForButton(int) + * @see Toolkit#areExtraMouseButtonsEnabled() + * @see java.awt.MouseInfo#getNumberOfButtons() + * @see java.awt.event.MouseEvent */ public synchronized void mouseRelease(int buttons) { checkButtonsArgument(buttons);
--- a/src/share/classes/java/awt/Toolkit.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/share/classes/java/awt/Toolkit.java Tue Sep 16 12:17:02 2008 +0400 @@ -1,5 +1,5 @@ /* - * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1995-2008 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 @@ -2550,4 +2550,37 @@ } } } + + /** + * Reports whether events from extra mouse buttons are allowed to be processed and posted into + * {@code EventQueue}. + * <br> + * To change the returned value it is necessary to set the {@code sun.awt.enableExtraMouseButtons} + * property before the {@code Toolkit} class initialization. This setting could be done on the application + * startup by the following command: + * <pre> + * java -Dsun.awt.enableExtraMouseButtons=false Application + * </pre> + * Alternatively, the property could be set in the application by using the following code: + * <pre> + * System.setProperty("sun.awt.enableExtraMouseButtons", "true"); + * </pre> + * before the {@code Toolkit} class initialization. + * If not set by the time of the {@code Toolkit} class initialization, this property will be + * initialized with {@code true}. + * Changing this value after the {@code Toolkit} class initialization will have no effect. + * <p> + * The current value could be queried by using the + * {@code System.getProperty("sun.awt.enableExtraMouseButtons")} method. + * @exception HeadlessException if GraphicsEnvironment.isHeadless() returns true + * @return {@code true} if events from extra mouse buttons are allowed to be processed and posted; + * {@code false} otherwise + * @see System#getProperty(String propertyName) + * @see System#setProperty(String propertyName, String value) + * @see java.awt.EventQueue + * @since 1.7 + */ + public boolean areExtraMouseButtonsEnabled() throws HeadlessException { + return Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled(); + } }
--- a/src/share/classes/java/awt/doc-files/DesktopProperties.html Thu Sep 11 10:38:00 2008 +0400 +++ b/src/share/classes/java/awt/doc-files/DesktopProperties.html Tue Sep 16 12:17:02 2008 +0400 @@ -1,5 +1,5 @@ <!-- - Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved. + Copyright 2005-2008 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 @@ -64,6 +64,11 @@ <td valign="TOP"><a href="../../util/Map.html">java.util.Map<a/></td> <td valign="TOP">Font smoothing (text antialiasing) settings.<a/></td> </tr> +<tr> +<td valign="TOP"><A href=#"sun.awt.enableExtraMouseButtons">sun.awt.enableExtraMouseButtons</A</td> +<td valign="TOP"><a href="../../lang/Boolean.html">java.lang.Boolean<a/></td> +<td valign="TOP">Controls if mouse events from extra buttons are to be generated or not<a/></td> +</tr> </table> <p> <h2>Desktop Font Rendering Hints</h2> @@ -219,5 +224,50 @@ determine that there is a non-null return for any screen device using the per-device property name. </ul> +<h2>Mouse Functionality</h2> +<b>Desktop Property: <A name="sun.awt.enableExtraMouseButtons">"sun.awt.enableExtraMouseButtons"</A></b> +<p> +This property determines if events from extra mouse buttons (if they are exist and are +enabled by the underlying operating system) are allowed to be processed and posted into +{@code EventQueue}. +<br> +The value could be changed by passing "sun.awt.enableExtraMouseButtons" +property value into java before application starts. This could be done with the following command: +<pre> +java -Dsun.awt.enableExtraMouseButtons=false Application +</pre> +Once set on application startup, it is impossible to change this value after. +<br> +Current value could also be queried using getDesktopProperty("sun.awt.enableExtraMouseButtons") +method. +<br> +If the property is set to {@code true} then +<ul> +<li> it is still legal to create {@code MouseEvent} objects with +standard buttons and, if the mouse has more +then three buttons, it is also legal to use buttons from the range started +from 0 up to {@link java.awt.MouseInfo#getNumberOfButtons() getNumberOfButtons()}. + +<li> it is legal to use standard button masks when using {@code Robot.mousePress()} +and {@code Robot.mouseRelease()} methods and, if the mouse has more then three buttons, +it is also legal to use masks for existing extended mouse buttons. +That way, if there are more then three buttons on the mouse then it is allowed to +use button masks corresponding to the buttons +in the range from 1 up to {@link java.awt.MouseInfo#getNumberOfButtons() getNumberOfButtons()} +</ul> +<br> +If the property is set to {@code false} then +<ul> +<li> it is legal to create {@code MouseEvent} objects with standard buttons +only: {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2} and +{@code BUTTON3} +<li> it is legal to use standard button masks only: +{@code InputEvent.BUTTON1_DOWN_MASK}, {@code InputEvent.BUTTON2_DOWN_MASK}, +{@code InputEvent.BUTTON3_DOWN_MASK} +</ul> + +This property should be used when there is no need in listening mouse events fired as a result of +activity with extra mouse button. +By default this property is set to {@code true}. </body> </html>
--- a/src/share/classes/java/awt/event/InputEvent.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/share/classes/java/awt/event/InputEvent.java Tue Sep 16 12:17:02 2008 +0400 @@ -31,6 +31,7 @@ import java.awt.Toolkit; import java.util.logging.Logger; import java.util.logging.Level; +import java.util.Arrays; /** * The root event class for all component-level input events. @@ -153,13 +154,93 @@ */ public static final int ALT_GRAPH_DOWN_MASK = 1 << 13; + /** + * An array of extended modifiers for additional buttons. + * @see getButtonDownMasks + * @since 7.0 + */ + private static final int [] BUTTON_DOWN_MASK = new int [] { BUTTON1_DOWN_MASK, + BUTTON2_DOWN_MASK, + BUTTON3_DOWN_MASK, + 1<<14, //4th phisical button (this is not a wheel!) + 1<<15, //(this is not a wheel!) + 1<<16, + 1<<17, + 1<<18, + 1<<19, + 1<<20, + 1<<21 }; + + /** + * A method to access an array of extended modifiers for additional buttons. + * @since 7.0 + */ + private static int [] getButtonDownMasks(){ + return Arrays.copyOf(BUTTON_DOWN_MASK, BUTTON_DOWN_MASK.length); + } + + + /** + * A method to obtain a mask for any existing mouse button. + * The returned mask may be used for different purposes. Following are some of them: + * <ul> + * <li> {@link java.awt.Robot#mousePress(int) mousePress(buttons)} and + * {@link java.awt.Robot#mouseRelease(int) mouseRelease(buttons)} + * <li> as a {@code modifiers} parameter when creating a new {@link MouseEvent} instance + * <li> to check {@link MouseEvent#getModifiersEx() modifiersEx} of existing {@code MouseEvent} + * </ul> + * @param button is a number to represent a button starting from 1. + * For example, + * <pre> + * int button = InputEvent.getMaskForButton(1); + * </pre> + * will have the same meaning as + * <pre> + * int button = InputEvent.getMaskForButton(MouseEvent.BUTTON1); + * </pre> + * because {@link MouseEvent#BUTTON1 MouseEvent.BUTTON1} equals to 1. + * If a mouse has three enabled buttons(see {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}) + * then the values from the left column passed into the method will return + * corresponding values from the right column: + * <PRE> + * <b>button </b> <b>returned mask</b> + * {@link MouseEvent#BUTTON1 BUTTON1} {@link MouseEvent#BUTTON1_DOWN_MASK BUTTON1_DOWN_MASK} + * {@link MouseEvent#BUTTON2 BUTTON2} {@link MouseEvent#BUTTON2_DOWN_MASK BUTTON2_DOWN_MASK} + * {@link MouseEvent#BUTTON3 BUTTON3} {@link MouseEvent#BUTTON3_DOWN_MASK BUTTON3_DOWN_MASK} + * </PRE> + * If a mouse has more than three enabled buttons then more values + * are admissible (4, 5, etc.). There is no assigned constants for these extended buttons. + * The button masks for the extra buttons returned by this method have no assigned names like the + * first three button masks. + * <p> + * This method has the following implementation restriction. + * It returns masks for a limited number of buttons only. The maximum number is + * implementation dependent and may vary. + * This limit is defined by the relevant number + * of buttons that may hypothetically exist on the mouse but it is greater than the + * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()}. + * <p> + * @throws IllegalArgumentException if {@code button} is less than zero or greater than the number + * of button masks reserved for buttons + * @since 7.0 + * @see java.awt.MouseInfo#getNumberOfButtons() + * @see Toolkit#areExtraMouseButtonsEnabled() + * @see MouseEvent#getModifiers() + * @see MouseEvent#getModifiersEx() + */ + public static int getMaskForButton(int button) { + if (button <= 0 || button > BUTTON_DOWN_MASK.length) { + throw new IllegalArgumentException("button doesn\'t exist " + button); + } + return BUTTON_DOWN_MASK[button - 1]; + } + // the constant below MUST be updated if any extra modifier // bits are to be added! // 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 << 14; + static final int FIRST_HIGH_BIT = 1 << 22; static final int JDK_1_3_MODIFIERS = SHIFT_DOWN_MASK - 1; static final int HIGH_MODIFIERS = ~( FIRST_HIGH_BIT - 1 ); @@ -382,7 +463,7 @@ * cause the returning an empty string. * * @param modifiers a modifier mask describing the extended - * modifier keys and mouse buttons for the event + * modifier keys and mouse buttons for the event * @return a text description of the combination of extended * modifier keys and mouse buttons that were held down * during the event. @@ -410,17 +491,14 @@ buf.append(Toolkit.getProperty("AWT.altGraph", "Alt Graph")); buf.append("+"); } - if ((modifiers & InputEvent.BUTTON1_DOWN_MASK) != 0) { - buf.append(Toolkit.getProperty("AWT.button1", "Button1")); - buf.append("+"); - } - if ((modifiers & InputEvent.BUTTON2_DOWN_MASK) != 0) { - buf.append(Toolkit.getProperty("AWT.button2", "Button2")); - buf.append("+"); - } - if ((modifiers & InputEvent.BUTTON3_DOWN_MASK) != 0) { - buf.append(Toolkit.getProperty("AWT.button3", "Button3")); - buf.append("+"); + + int buttonNumber = 1; + for (int mask : InputEvent.BUTTON_DOWN_MASK){ + if ((modifiers & mask) != 0) { + buf.append(Toolkit.getProperty("AWT.button"+buttonNumber, "Button"+buttonNumber)); + buf.append("+"); + } + buttonNumber++; } if (buf.length() > 0) { buf.setLength(buf.length()-1); // remove trailing '+'
--- a/src/share/classes/java/awt/event/MouseEvent.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/share/classes/java/awt/event/MouseEvent.java Tue Sep 16 12:17:02 2008 +0400 @@ -32,6 +32,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.awt.IllegalComponentStateException; +import java.awt.MouseInfo; /** * An event which indicates that a mouse action occurred in a component. @@ -135,7 +136,15 @@ * for <code>BUTTON2_MASK</code> arrives first, * followed by the pair for <code>BUTTON1_MASK</code>. * <p> - * + * Some extra mouse buttons are added to extend the standard set of buttons + * represented by the following constants:{@code BUTTON1}, {@code BUTTON2}, and {@code BUTTON3}. + * Extra buttons have no assigned {@code BUTTONx} + * constants as well as their button masks have no assigned {@code BUTTONx_DOWN_MASK} + * constants. Nevertheless, ordinal numbers starting from 4 may be + * used as button numbers (button ids). Values obtained by the + * {@link InputEvent#getMaskForButton(int) getMaskForButton(button)} method may be used + * as button masks. + * <p> * <code>MOUSE_DRAGGED</code> events are delivered to the <code>Component</code> * in which the mouse button was pressed until the mouse button is released * (regardless of whether the mouse position is within the bounds of the @@ -324,13 +333,31 @@ /** * Indicates which, if any, of the mouse buttons has changed state. * - * The only legal values are the following constants: - * <code>NOBUTTON</code>, - * <code>BUTTON1</code>, - * <code>BUTTON2</code> or - * <code>BUTTON3</code>. + * The valid values are ranged from 0 to the value returned by the + * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} method. + * This range already includes constants {@code NOBUTTON}, {@code BUTTON1}, + * {@code BUTTON2}, and {@code BUTTON3} + * if these buttons are present. So it is allowed to use these constants too. + * For example, for a mouse with two buttons this field may contain the following values: + * <ul> + * <li> 0 ({@code NOBUTTON}) + * <li> 1 ({@code BUTTON1}) + * <li> 2 ({@code BUTTON2}) + * </ul> + * If a mouse has 5 buttons, this field may contain the following values: + * <ul> + * <li> 0 ({@code NOBUTTON}) + * <li> 1 ({@code BUTTON1}) + * <li> 2 ({@code BUTTON2}) + * <li> 3 ({@code BUTTON3}) + * <li> 4 + * <li> 5 + * </ul> + * If support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled()} disabled by Java + * then the field may not contain the value larger than {@code BUTTON3}. * @serial - * @see #getButton(). + * @see #getButton() + * @see java.awt.Toolkit#areExtraMouseButtonsEnabled() */ int button; @@ -385,6 +412,15 @@ } /** + * 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 * desktop area could span multiple physical screen devices, @@ -421,7 +457,8 @@ /** * Constructs a <code>MouseEvent</code> object with the * specified source component, - * type, modifiers, coordinates, and click count. + * type, time, modifiers, coordinates, click count, popupTrigger flag, + * and button number. * <p> * Creating an invalid event (such * as by using more than one of the old _MASKs, or modifier/button @@ -464,7 +501,33 @@ * @param popupTrigger A boolean that equals {@code true} if this event * is a trigger for a popup menu * @param button An integer that indicates, which of the mouse buttons has - * changed its state + * changed its state. + * The following rules are applied to this parameter: + * <ul> + * <li>If support for the extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * then it is allowed to create {@code MouseEvent} objects only with the standard buttons: + * {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2}, and + * {@code BUTTON3}. + * <li> If support for the extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java + * then it is allowed to create {@code MouseEvent} objects with + * the standard buttons. + * In case the support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java, then + * in addition to the standard buttons, {@code MouseEvent} objects can be created + * using buttons from the range starting from 4 to + * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} + * if the mouse has more than three buttons. + * </ul> + * @throws IllegalArgumentException if {@code button} is less then zero + * @throws IllegalArgumentException if <code>source</code> is null + * @throws IllegalArgumentException if {@code button} is greater then BUTTON3 and the support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * @throws IllegalArgumentException if {@code button} is greater then the + * {@link java.awt.MouseInfo#getNumberOfButtons() current number of buttons} and the support + * for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} + * by Java * @throws IllegalArgumentException if an invalid <code>button</code> * value is passed in * @throws IllegalArgumentException if <code>source</code> is null @@ -498,7 +561,7 @@ /** * Constructs a <code>MouseEvent</code> object with the * specified source component, - * type, modifiers, coordinates, and click count. + * type, modifiers, coordinates, click count, and popupTrigger flag. * An invocation of the form * <tt>MouseEvent(source, id, when, modifiers, x, y, clickCount, popupTrigger)</tt> * behaves in exactly the same way as the invocation @@ -551,10 +614,26 @@ } + /* if the button is an extra button and it is released or clicked then in Xsystem its state + is not modified. Exclude this button number from ExtModifiers mask.*/ + transient private boolean shouldExcludeButtonFromExtModifiers = false; + + /** + * {@inheritDoc} + */ + public int getModifiersEx() { + int tmpModifiers = modifiers; + if (shouldExcludeButtonFromExtModifiers) { + tmpModifiers &= ~(InputEvent.getMaskForButton(getButton())); + } + return tmpModifiers & ~JDK_1_3_MODIFIERS; + } + /** * Constructs a <code>MouseEvent</code> object with the * specified source component, - * type, modifiers, coordinates, absolute coordinates, and click count. + * type, time, modifiers, coordinates, absolute coordinates, click count, popupTrigger flag, + * and button number. * <p> * Creating an invalid event (such * as by using more than one of the old _MASKs, or modifier/button @@ -595,7 +674,33 @@ * @param popupTrigger A boolean that equals {@code true} if this event * is a trigger for a popup menu * @param button An integer that indicates, which of the mouse buttons has - * changed its state + * changed its state. + * The following rules are applied to this parameter: + * <ul> + * <li>If support for the extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * then it is allowed to create {@code MouseEvent} objects only with the standard buttons: + * {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2}, and + * {@code BUTTON3}. + * <li> If support for the extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java + * then it is allowed to create {@code MouseEvent} objects with + * the standard buttons. + * In case the support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java, then + * in addition to the standard buttons, {@code MouseEvent} objects can be created + * using buttons from the range starting from 4 to + * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} + * if the mouse has more than three buttons. + * </ul> + * @throws IllegalArgumentException if {@code button} is less then zero + * @throws IllegalArgumentException if <code>source</code> is null + * @throws IllegalArgumentException if {@code button} is greater then BUTTON3 and the support for extended mouse buttons is + * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * @throws IllegalArgumentException if {@code button} is greater then the + * {@link java.awt.MouseInfo#getNumberOfButtons() current number of buttons} and the support + * for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} + * by Java * @throws IllegalArgumentException if an invalid <code>button</code> * value is passed in * @throws IllegalArgumentException if <code>source</code> is null @@ -610,6 +715,10 @@ * @see #getClickCount() * @see #isPopupTrigger() * @see #getButton() + * @see #button + * @see Toolkit#areExtraMouseButtonsEnabled() + * @see java.awt.MouseInfo#getNumberOfButtons() + * @see InputEvent#getMaskForButton(int) * @since 1.6 */ public MouseEvent(Component source, int id, long when, int modifiers, @@ -623,14 +732,41 @@ this.yAbs = yAbs; this.clickCount = clickCount; this.popupTrigger = popupTrigger; - if (button < NOBUTTON || button >BUTTON3) { - throw new IllegalArgumentException("Invalid button value"); + 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); + } else { + if (button > cachedNumberOfButtons) { + throw new IllegalArgumentException("Nonexistent button " + button); + } + } + // XToolkit: extra buttons are not reporting about their state correctly. + // Being pressed they report the state=0 both on the press and on the release. + // For 1-3 buttons the state value equals zero on press and non-zero on release. + // Other modifiers like Shift, ALT etc seem report well with extra buttons. + // The problem reveals as follows: one button is pressed and then another button is pressed and released. + // So, the getModifiersEx() would not be zero due to a first button and we will skip this modifier. + // This may have to be moved into the peer code instead if possible. + + if (getModifiersEx() != 0) { //There is at least one more button in a pressed state. + if (id == MouseEvent.MOUSE_RELEASED || id == MouseEvent.MOUSE_CLICKED){ + System.out.println("MEvent. CASE!"); + shouldExcludeButtonFromExtModifiers = true; + } + } + } + this.button = button; + if ((getModifiers() != 0) && (getModifiersEx() == 0)) { setNewModifiers(); } else if ((getModifiers() == 0) && - (getModifiersEx() != 0 || button != NOBUTTON)) + (getModifiersEx() != 0 || button != NOBUTTON) && + (button <= BUTTON3)) { setOldModifiers(); } @@ -701,13 +837,55 @@ /** * Returns which, if any, of the mouse buttons has changed state. + * The returned value is ranged + * from 0 to the {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} + * value. + * The returned value includes at least the following constants: + * <ul> + * <li> {@code NOBUTTON} + * <li> {@code BUTTON1} + * <li> {@code BUTTON2} + * <li> {@code BUTTON3} + * </ul> + * It is allowed to use those constants to compare with the returned button number in the application. + * For example, + * <pre> + * if (anEvent.getButton() == MouseEvent.BUTTON1) { + * </pre> + * In particular, for a mouse with one, two, or three buttons this method may return the following values: + * <ul> + * <li> 0 ({@code NOBUTTON}) + * <li> 1 ({@code BUTTON1}) + * <li> 2 ({@code BUTTON2}) + * <li> 3 ({@code BUTTON3}) + * </ul> + * Button numbers greater then {@code BUTTON3} have no constant identifier. So if a mouse with five buttons is + * installed, this method may return the following values: + * <ul> + * <li> 0 ({@code NOBUTTON}) + * <li> 1 ({@code BUTTON1}) + * <li> 2 ({@code BUTTON2}) + * <li> 3 ({@code BUTTON3}) + * <li> 4 + * <li> 5 + * </ul> + * <p> + * Note: If support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java + * then the AWT event subsystem does not produce mouse events for the extended mouse + * buttons. So it is not expected that this method returns anything except {@code NOBUTTON}, {@code BUTTON1}, + * {@code BUTTON2}, {@code BUTTON3}. * - * @return one of the following constants: - * <code>NOBUTTON</code>, - * <code>BUTTON1</code>, - * <code>BUTTON2</code> or - * <code>BUTTON3</code>. + * @return one of the values from 0 to {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} + * if support for the extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java. + * That range includes {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2}, {@code BUTTON3}; + * <br> + * {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2} or {@code BUTTON3} + * if support for the extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java * @since 1.4 + * @see Toolkit#areExtraMouseButtonsEnabled() + * @see java.awt.MouseInfo#getNumberOfButtons() + * @see #MouseEvent(Component, int, long, int, int, int, int, int, int, boolean, int) + * @see InputEvent#getMaskForButton(int) */ public int getButton() { return button; @@ -746,7 +924,7 @@ * and will cause the returning an unspecified string. * Zero parameter means that no modifiers were passed and will * cause the returning an empty string. - * + * <p> * @param modifiers A modifier mask describing the modifier keys and * mouse buttons that were down during the event * @return string string text description of the combination of modifier @@ -788,6 +966,24 @@ buf.append(Toolkit.getProperty("AWT.button3", "Button3")); buf.append("+"); } + + int mask; + + // TODO: add a toolkit field that holds a number of button on the mouse. + // As the method getMouseModifiersText() is static and obtain + // an integer as a parameter then we may not restrict this with the number + // of buttons installed on the mouse. + // It's a temporary solution. We need to somehow hold the number of buttons somewhere else. + for (int i = 1; i <= cachedNumberOfButtons; i++){ + mask = InputEvent.getMaskForButton(i); + if ((modifiers & mask) != 0 && + buf.indexOf(Toolkit.getProperty("AWT.button"+i, "Button"+i)) == -1) //1,2,3 buttons may already be there; so don't duplicate it. + { + buf.append(Toolkit.getProperty("AWT.button"+i, "Button"+i)); + buf.append("+"); + } + } + if (buf.length() > 0) { buf.setLength(buf.length()-1); // remove trailing '+' } @@ -836,14 +1032,18 @@ str.append(",(").append(x).append(",").append(y).append(")"); str.append(",absolute(").append(xAbs).append(",").append(yAbs).append(")"); - str.append(",button=").append(getButton()); + if (id != MOUSE_DRAGGED && id != MOUSE_MOVED){ + str.append(",button=").append(getButton()); + } if (getModifiers() != 0) { str.append(",modifiers=").append(getMouseModifiersText(modifiers)); } if (getModifiersEx() != 0) { - str.append(",extModifiers=").append(getModifiersExText(modifiers)); + //Using plain "modifiers" here does show an excluded extended buttons in the string event representation. + //getModifiersEx() solves the problem. + str.append(",extModifiers=").append(getModifiersExText(getModifiersEx())); } str.append(",clickCount=").append(clickCount);
--- a/src/share/classes/java/awt/peer/RobotPeer.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/share/classes/java/awt/peer/RobotPeer.java Tue Sep 16 12:17:02 2008 +0400 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 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 @@ -52,4 +52,5 @@ public int [] getRGBPixels(Rectangle bounds); public void dispose(); + public int getNumberOfButtons(); }
--- a/src/share/classes/sun/awt/HeadlessToolkit.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/share/classes/sun/awt/HeadlessToolkit.java Tue Sep 16 12:17:02 2008 +0400 @@ -1,5 +1,5 @@ /* - * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2000-2008 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 @@ -468,4 +468,8 @@ throws HeadlessException{ throw new HeadlessException(); } + + public boolean areExtraMouseButtonsEnabled() throws HeadlessException{ + throw new HeadlessException(); + } }
--- a/src/solaris/classes/sun/awt/X11/XBaseWindow.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/solaris/classes/sun/awt/X11/XBaseWindow.java Tue Sep 16 12:17:02 2008 +0400 @@ -979,8 +979,13 @@ */ public void handleButtonPressRelease(XEvent xev) { XButtonEvent xbe = xev.get_xbutton(); - final int buttonState = xbe.get_state() & (XConstants.Button1Mask | XConstants.Button2Mask - | XConstants.Button3Mask | XConstants.Button4Mask | XConstants.Button5Mask); + int buttonState = 0; + for (int i = 0; i<XToolkit.getNumMouseButtons(); 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]); + } + } switch (xev.get_type()) { case XConstants.ButtonPress: if (buttonState == 0) { @@ -1011,19 +1016,11 @@ * Checks ButtonRelease released all Mouse buttons */ static boolean isFullRelease(int buttonState, int button) { - switch (button) { - case XConstants.Button1: - return buttonState == XConstants.Button1Mask; - case XConstants.Button2: - return buttonState == XConstants.Button2Mask; - case XConstants.Button3: - return buttonState == XConstants.Button3Mask; - case XConstants.Button4: - return buttonState == XConstants.Button4Mask; - case XConstants.Button5: - return buttonState == XConstants.Button5Mask; + if (button < 0 || button > XToolkit.getNumMouseButtons()) { + return buttonState == 0; + } else { + return buttonState == XConstants.buttonsMask[button - 1]; } - return buttonState == 0; } static boolean isGrabbedEvent(XEvent ev, XBaseWindow target) {
--- a/src/solaris/classes/sun/awt/X11/XConstants.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/solaris/classes/sun/awt/X11/XConstants.java Tue Sep 16 12:17:02 2008 +0400 @@ -197,12 +197,30 @@ /* button masks. Used in same manner as Key masks above. Not to be confused with button names below. */ - - public static final int Button1Mask = (1<<8) ; - public static final int Button2Mask = (1<<9) ; - public static final int Button3Mask = (1<<10) ; - public static final int Button4Mask = (1<<11) ; - public static final int Button5Mask = (1<<12) ; + public static final int [] buttonsMask = new int []{ 1<<8, + 1<<9, + 1<<10, + 1<<11, + 1<<12, + 1<<13, + 1<<14, + 1<<15, + 1<<16, + 1<<17, + 1<<18, + 1<<19, + 1<<20, + 1<<21, + 1<<22, + 1<<23, + 1<<24, + 1<<25, + 1<<26, + 1<<27, + 1<<28, + 1<<29, + 1<<30, + 1<<31 }; public static final int AnyModifier = (1<<15) ; /* used in GrabButton, GrabKey */ @@ -211,11 +229,7 @@ and ButtonRelease events. Not to be confused with button masks above. Note that 0 is already defined above as "AnyButton". */ - public static final int Button1 = 1 ; - public static final int Button2 = 2 ; - public static final int Button3 = 3 ; - public static final int Button4 = 4 ; - public static final int Button5 = 5 ; + public static final int buttons [] = new int [] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}; /* Notify modes */
--- a/src/solaris/classes/sun/awt/X11/XDragSourceContextPeer.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/solaris/classes/sun/awt/X11/XDragSourceContextPeer.java Tue Sep 16 12:17:02 2008 +0400 @@ -694,8 +694,8 @@ } finally { xmotion.dispose(); } - if (xbutton.get_button() == XConstants.Button1 - || xbutton.get_button() == XConstants.Button2) { + if (xbutton.get_button() == XConstants.buttons[0] + || xbutton.get_button() == XConstants.buttons[1]) { // drag is initiated with Button1 or Button2 pressed and // ended on release of either of these buttons (as the same // behavior was with our old Motif DnD-based implementation)
--- a/src/solaris/classes/sun/awt/X11/XRobotPeer.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/solaris/classes/sun/awt/X11/XRobotPeer.java Tue Sep 16 12:17:02 2008 +0400 @@ -1,5 +1,5 @@ /* - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 2003-2008 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 @@ -81,11 +81,16 @@ 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);
--- a/src/solaris/classes/sun/awt/X11/XToolkit.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/solaris/classes/sun/awt/X11/XToolkit.java Tue Sep 16 12:17:02 2008 +0400 @@ -74,6 +74,10 @@ // Dynamic Layout Resize client code setting protected static boolean dynamicLayoutSetting = false; + //Is it allowed to generate events assigned to extra mouse buttons. + //Set to true by default. + private static boolean areExtraMouseButtonsEnabled = true; + /** * True when the x settings have been loaded. */ @@ -273,6 +277,9 @@ arrowCursor = XlibWrapper.XCreateFontCursor(XToolkit.getDisplay(), XCursorFontConstants.XC_arrow); + areExtraMouseButtonsEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons", "true")); + //set system property if not yet assigned + System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled); } finally { awtUnlock(); } @@ -1383,7 +1390,7 @@ } } - private int getNumMouseButtons() { + public static int getNumMouseButtons() { awtLock(); try { return XlibWrapper.XGetPointerMapping(XToolkit.getDisplay(), 0, 0); @@ -2166,4 +2173,8 @@ } public static native void setNoisyXErrorHandler(); + + public boolean areExtraMouseButtonsEnabled() throws HeadlessException { + return areExtraMouseButtonsEnabled; + } }
--- a/src/solaris/classes/sun/awt/X11/XWindow.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/solaris/classes/sun/awt/X11/XWindow.java Tue Sep 16 12:17:02 2008 +0400 @@ -553,6 +553,10 @@ } static int getModifiers(int state, int button, int keyCode) { + return getModifiers(state, button, keyCode, 0, false); + } + + static int getModifiers(int state, int button, int keyCode, int type, boolean wheel_mouse) { int modifiers = 0; if (((state & XConstants.ShiftMask) != 0) ^ (keyCode == KeyEvent.VK_SHIFT)) { @@ -570,14 +574,23 @@ if (((state & XToolkit.modeSwitchMask) != 0) ^ (keyCode == KeyEvent.VK_ALT_GRAPH)) { modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK; } - if (((state & XConstants.Button1Mask) != 0) ^ (button == MouseEvent.BUTTON1)) { - modifiers |= InputEvent.BUTTON1_DOWN_MASK; - } - if (((state & XConstants.Button2Mask) != 0) ^ (button == MouseEvent.BUTTON2)) { - modifiers |= InputEvent.BUTTON2_DOWN_MASK; - } - if (((state & XConstants.Button3Mask) != 0) ^ (button == MouseEvent.BUTTON3)) { - modifiers |= InputEvent.BUTTON3_DOWN_MASK; + //InputEvent.BUTTON_DOWN_MASK array is starting from BUTTON1_DOWN_MASK on index == 0. + // button currently reflects a real button number and starts from 1. (except NOBUTTON which is zero ) + + /* this is an attempt to refactor button IDs in : MouseEvent, InputEvent, XlibWrapper and XWindow.*/ + + //reflects a button number similar to MouseEvent.BUTTON1, 2, 3 etc. + for (int i = 0; i < XConstants.buttonsMask.length; i ++){ + //modifier should be added if : + // 1) current button is now still in PRESSED state (means that user just pressed mouse but not released yet) or + // 2) if Xsystem reports that "state" represents that button was just released. This only happens on RELEASE with 1,2,3 buttons. + // ONLY one of these conditions should be TRUE to add that modifier. + if (((state & XConstants.buttonsMask[i]) != 0) != (button == XConstants.buttons[i])){ + //exclude wheel buttons from adding their numbers as modifiers + if (!wheel_mouse) { + modifiers |= InputEvent.getMaskForButton(i+1); + } + } } return modifiers; } @@ -603,17 +616,6 @@ return res; } - private static int getButtonMask(long mouseButton) { - if (mouseButton == XConstants.Button1) { - return XConstants.Button1Mask; - } else if (mouseButton == XConstants.Button2) { - return XConstants.Button2Mask; - } else if (mouseButton == XConstants.Button3) { - return XConstants.Button3Mask; - } - return 0; - } - /** * Returns true if this event is disabled and shouldn't be passed to Java. * Default implementation returns false for all events. @@ -648,7 +650,7 @@ boolean popupTrigger = false; int button=0; boolean wheel_mouse = false; - long lbutton = xbe.get_button(); + int lbutton = xbe.get_button(); int type = xev.get_type(); when = xbe.get_time(); long jWhen = XToolkit.nowMillisUTC_offset(when); @@ -663,7 +665,7 @@ if (type == XConstants.ButtonPress) { //Allow this mouse button to generate CLICK event on next ButtonRelease - mouseButtonClickAllowed |= getButtonMask(lbutton); + mouseButtonClickAllowed |= XConstants.buttonsMask[lbutton]; XWindow lastWindow = (lastWindowRef != null) ? ((XWindow)lastWindowRef.get()):(null); /* multiclick checking @@ -693,21 +695,22 @@ } } - if (lbutton == XConstants.Button1) - button = MouseEvent.BUTTON1; - else if (lbutton == XConstants.Button2 ) - button = MouseEvent.BUTTON2; - else if (lbutton == XConstants.Button3) - button = MouseEvent.BUTTON3; - else if (lbutton == XConstants.Button4) { - button = 4; - wheel_mouse = true; - } else if (lbutton == XConstants.Button5) { - button = 5; + button = XConstants.buttons[lbutton - 1]; + // 4 and 5 buttons are usually considered assigned to a first wheel + if (lbutton == XConstants.buttons[3] || + lbutton == XConstants.buttons[4]) { wheel_mouse = true; } - modifiers = getModifiers(xbe.get_state(),button,0); + // mapping extra buttons to numbers starting from 4. + if ((button > XConstants.buttons[4]) && (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled())){ + return; + } + + if (button > XConstants.buttons[4]){ + button -= 2; + } + modifiers = getModifiers(xbe.get_state(),button,0, type, wheel_mouse); if (!wheel_mouse) { MouseEvent me = new MouseEvent((Component)getEventSource(), @@ -720,7 +723,7 @@ postEventToEventQueue(me); if ((type == XConstants.ButtonRelease) && - ((mouseButtonClickAllowed & getButtonMask(lbutton)) != 0) ) // No up-button in the drag-state + ((mouseButtonClickAllowed & XConstants.buttonsMask[lbutton]) != 0) ) // No up-button in the drag-state { postEventToEventQueue(me = new MouseEvent((Component)getEventSource(), MouseEvent.MOUSE_CLICKED, @@ -750,7 +753,7 @@ /* Update the state variable AFTER the CLICKED event post. */ if (type == XConstants.ButtonRelease) { /* Exclude this mouse button from allowed list.*/ - mouseButtonClickAllowed &= ~getButtonMask(lbutton); + mouseButtonClickAllowed &= ~XConstants.buttonsMask[lbutton]; } } @@ -761,7 +764,19 @@ return; } - int mouseKeyState = (xme.get_state() & (XConstants.Button1Mask | XConstants.Button2Mask | XConstants.Button3Mask)); + int mouseKeyState = 0; //(xme.get_state() & (XConstants.buttonsMask[0] | XConstants.buttonsMask[1] | XConstants.buttonsMask[2])); + + //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++){ + // 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]); + } + } + boolean isDragging = (mouseKeyState != 0); int mouseEventType = 0;
--- a/src/solaris/classes/sun/awt/X11/XWindowPeer.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/solaris/classes/sun/awt/X11/XWindowPeer.java Tue Sep 16 12:17:02 2008 +0400 @@ -1936,7 +1936,13 @@ new Object[] {xme, isGrabbed(), containsGlobal(xme.get_x_root(), xme.get_y_root())}); } if (isGrabbed()) { - boolean dragging = (xme.get_state() & (XConstants.Button1Mask | XConstants.Button2Mask | XConstants.Button3Mask)) != 0; + boolean dragging = false; + for (int i = 0; i<XToolkit.getNumMouseButtons(); 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); + } + } // When window is grabbed, all events are dispatched to // it. Retarget them to the corresponding windows (notice // that XBaseWindow.dispatchEvent does the opposite @@ -1990,12 +1996,12 @@ try { grabLog.log(Level.FINER, " - Grab event target {0} (press target {1})", new Object[] {target, pressTarget}); if (xbe.get_type() == XConstants.ButtonPress - && xbe.get_button() == XConstants.Button1) + && xbe.get_button() == XConstants.buttons[0]) { // need to keep it to retarget mouse release pressTarget = target; } else if (xbe.get_type() == XConstants.ButtonRelease - && xbe.get_button() == XConstants.Button1 + && xbe.get_button() == XConstants.buttons[0] && pressTarget != target) { // during grab we do receive mouse release on different component (not on the source
--- a/src/solaris/native/sun/awt/awt_Robot.c Thu Sep 11 10:38:00 2008 +0400 +++ b/src/solaris/native/sun/awt/awt_Robot.c Tue Sep 16 12:17:02 2008 +0400 @@ -1,5 +1,5 @@ /* - * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1999-2008 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 @@ -54,6 +54,7 @@ // 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; +static jint * masks; static int32_t isXTestAvailable() { int32_t major_opcode, first_event, first_error; @@ -208,6 +209,26 @@ Java_sun_awt_X11_XRobotPeer_setup (JNIEnv * env, jclass cls) { int32_t xtestAvailable; +// this should be called from XRobotPeer constructor + jclass inputEventClazz = (*env)->FindClass(env, "java/awt/event/InputEvent"); + jmethodID getButtonDownMasksID = (*env)->GetStaticMethodID(env, inputEventClazz, "getButtonDownMasks", "()[I"); + jintArray obj = (jintArray)(*env)->CallStaticObjectMethod(env, inputEventClazz, getButtonDownMasksID); + jsize len = (*env)->GetArrayLength(env, obj); + jint * tmp = (*env)->GetIntArrayElements(env, obj, JNI_FALSE); + + masks = (jint *)malloc(sizeof(jint)*len); + if (masks == (jint *) NULL) { + JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL); + goto finally; + } + + int i; + for (i = 0; i < len; i++) { + masks[i] = tmp[i]; + } + (*env)->ReleaseIntArrayElements(env, obj, tmp, 0); + (*env)->DeleteLocalRef(env, obj); + DTRACE_PRINTLN("RobotPeer: setup()"); AWT_LOCK(); @@ -221,8 +242,15 @@ } getNumButtons(); + finally: + AWT_UNLOCK(); +} - AWT_UNLOCK(); +JNIEXPORT void 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 @@ -352,6 +380,8 @@ Java_sun_awt_X11_XRobotPeer_mousePressImpl (JNIEnv *env, jclass cls, jint buttonMask) { + mouseAction(env, cls, buttonMask, True); +/* AWT_LOCK(); DTRACE_PRINTLN1("RobotPeer: mousePressImpl(%i)", buttonMask); @@ -370,12 +400,15 @@ XSync(awt_display, False); AWT_UNLOCK(); +*/ } JNIEXPORT void JNICALL Java_sun_awt_X11_XRobotPeer_mouseReleaseImpl (JNIEnv *env, jclass cls, jint buttonMask) { + mouseAction(env, cls, buttonMask, False); +/* AWT_LOCK(); DTRACE_PRINTLN1("RobotPeer: mouseReleaseImpl(%i)", buttonMask); @@ -394,8 +427,57 @@ XSync(awt_display, False); AWT_UNLOCK(); +*/ } +/* + * Function joining the code of mousePressImpl and mouseReleaseImpl + */ +void mouseAction(JNIEnv *env, + jclass cls, + jint buttonMask, + Bool isMousePress) +{ + AWT_LOCK(); + + DTRACE_PRINTLN1("RobotPeer: mouseAction(%i)", buttonMask); + DTRACE_PRINTLN1("RobotPeer: mouseAction, press = %d", isMousePress); + + if (buttonMask & java_awt_event_InputEvent_BUTTON1_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK ) + { + XTestFakeButtonEvent(awt_display, 1, isMousePress, CurrentTime); + } + if ((buttonMask & java_awt_event_InputEvent_BUTTON2_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) && + (num_buttons >= 2)) { + XTestFakeButtonEvent(awt_display, 2, isMousePress, CurrentTime); + } + if ((buttonMask & java_awt_event_InputEvent_BUTTON3_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) && + (num_buttons >= 3)) { + XTestFakeButtonEvent(awt_display, 3, isMousePress, CurrentTime); + } + + if (num_buttons > 3){ + int32_t i; + int32_t button = 0; + for (i = 3; i<num_buttons; i++){ + if ((buttonMask & masks[i])) { + // arrays starts from zero index => +1 + // users wants to affect 4 or 5 button but they are assigned + // to the wheel so => we have to shift it to the right by 2. + button = i + 3; + XTestFakeButtonEvent(awt_display, button, isMousePress, CurrentTime); + } + } + } + + XSync(awt_display, False); + AWT_UNLOCK(); +} + + JNIEXPORT void JNICALL Java_sun_awt_X11_XRobotPeer_mouseWheelImpl (JNIEnv *env, jclass cls,
--- a/src/windows/classes/sun/awt/windows/WRobotPeer.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/windows/classes/sun/awt/windows/WRobotPeer.java Tue Sep 16 12:17:02 2008 +0400 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2008 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 @@ -60,6 +60,8 @@ } 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);
--- a/src/windows/classes/sun/awt/windows/WToolkit.java Thu Sep 11 10:38:00 2008 +0400 +++ b/src/windows/classes/sun/awt/windows/WToolkit.java Tue Sep 16 12:17:02 2008 +0400 @@ -80,6 +80,10 @@ // Dynamic Layout Resize client code setting protected boolean dynamicLayoutSetting = false; + //Is it allowed to generate events assigned to extra mouse buttons. + //Set to true by default. + private static boolean areExtraMouseButtonsEnabled = true; + /** * Initialize JNI field and method IDs */ @@ -249,6 +253,11 @@ // Enabled "live resizing" by default. It remains controlled // by the native system though. setDynamicLayout(true); + + areExtraMouseButtonsEnabled = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons", "true")); + //set system property if not yet assigned + System.setProperty("sun.awt.enableExtraMouseButtons", ""+areExtraMouseButtonsEnabled); + setExtraMouseButtonsEnabledNative(areExtraMouseButtonsEnabled); } public void run() { @@ -961,4 +970,9 @@ return new WDesktopPeer(); } + public static native void setExtraMouseButtonsEnabledNative(boolean enable); + + public boolean areExtraMouseButtonsEnabled() throws HeadlessException { + return areExtraMouseButtonsEnabled; + } }
--- a/src/windows/native/sun/windows/awt_Component.cpp Thu Sep 11 10:38:00 2008 +0400 +++ b/src/windows/native/sun/windows/awt_Component.cpp Tue Sep 16 12:17:02 2008 +0400 @@ -187,6 +187,8 @@ UINT AwtComponent::m_CodePage = AwtComponent::LangToCodePage(m_idLang); +jint *AwtComponent::masks; + static BOOL bLeftShiftIsDown = false; static BOOL bRightShiftIsDown = false; static UINT lastShiftKeyPressed = 0; // init to safe value @@ -1177,6 +1179,9 @@ WIN_MSG(WM_MBUTTONDOWN) WIN_MSG(WM_MBUTTONUP) WIN_MSG(WM_MBUTTONDBLCLK) + WIN_MSG(WM_XBUTTONDBLCLK) + WIN_MSG(WM_XBUTTONDOWN) + WIN_MSG(WM_XBUTTONUP) WIN_MSG(WM_MOUSEWHEEL) WIN_MSG(WM_PARENTNOTIFY) WIN_MSG(WM_ENTERMENULOOP) @@ -1612,6 +1617,9 @@ case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK: case WM_MBUTTONUP: + case WM_XBUTTONDBLCLK: + case WM_XBUTTONDOWN: + case WM_XBUTTONUP: case WM_MOUSEMOVE: case WM_MOUSEWHEEL: case WM_AWT_MOUSEENTER: @@ -1642,6 +1650,31 @@ mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y, MIDDLE_BUTTON); break; + case WM_XBUTTONDOWN: + case WM_XBUTTONDBLCLK: + if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) { + if (HIWORD(wParam) == 1) { + mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y, + X1_BUTTON); + } + if (HIWORD(wParam) == 2) { + mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y, + X2_BUTTON); + } + } + break; + case WM_XBUTTONUP: + if (AwtToolkit::GetInstance().areExtraMouseButtonsEnabled()) { + if (HIWORD(wParam) == 1) { + mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y, + X1_BUTTON); + } + if (HIWORD(wParam) == 2) { + mr = WmMouseUp(static_cast<UINT>(wParam), myPos.x, myPos.y, + X2_BUTTON); + } + } + break; case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK: mr = WmMouseDown(static_cast<UINT>(wParam), myPos.x, myPos.y, @@ -2549,8 +2582,12 @@ lastComp = this; lastX = x; lastY = y; - - if ( (flags & ALL_MK_BUTTONS) != 0 ) { + BOOL extraButtonsEnabled = AwtToolkit::GetInstance().areExtraMouseButtonsEnabled(); + if (((flags & (ALL_MK_BUTTONS)) != 0) || + (extraButtonsEnabled && (flags & (X_BUTTONS)) != 0)) +// if (( extraButtonsEnabled && ( (flags & (ALL_MK_BUTTONS | X_BUTTONS)) != 0 )) || +// ( !extraButtonsEnabled && (((flags & (ALL_MK_BUTTONS)) != 0 )) && ((flags & (X_BUTTONS)) == 0) )) + { // 6404008 : if Dragged event fired we shouldn't fire // Clicked event: m_firstDragSent set to TRUE. // This is a partial backout of 5039416 fix. @@ -2728,7 +2765,7 @@ modifiers |= java_awt_event_InputEvent_ALT_DOWN_MASK; } if (HIBYTE(::GetKeyState(VK_MBUTTON)) != 0) { - modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK; + modifiers |= java_awt_event_InputEvent_BUTTON2_DOWN_MASK; } if (HIBYTE(::GetKeyState(VK_RBUTTON)) != 0) { modifiers |= java_awt_event_InputEvent_BUTTON3_DOWN_MASK; @@ -2736,6 +2773,13 @@ if (HIBYTE(::GetKeyState(VK_LBUTTON)) != 0) { modifiers |= java_awt_event_InputEvent_BUTTON1_DOWN_MASK; } + + if (HIBYTE(::GetKeyState(VK_XBUTTON1)) != 0) { + modifiers |= masks[3]; + } + if (HIBYTE(::GetKeyState(VK_XBUTTON2)) != 0) { + modifiers |= masks[4]; + } return modifiers; } @@ -2750,6 +2794,11 @@ return java_awt_event_MouseEvent_BUTTON2; case RIGHT_BUTTON: return java_awt_event_MouseEvent_BUTTON3; + case X1_BUTTON: //16 : + //just assign 4 and 5 numbers because MouseEvent class doesn't contain const identifier for them now + return 4; + case X2_BUTTON: //32 + return 5; } return java_awt_event_MouseEvent_NOBUTTON; } @@ -2764,6 +2813,10 @@ return MK_MBUTTON; case RIGHT_BUTTON: return MK_RBUTTON; + case X1_BUTTON: + return MK_XBUTTON1; + case X2_BUTTON: + return MK_XBUTTON2; } return 0; } @@ -2781,6 +2834,14 @@ #define VK_NONCONVERT 0x1D #endif +#ifndef VK_XBUTTON1 +#define VK_XBUTTON1 0x05 +#endif + +#ifndef VK_XBUTTON2 +#define VK_XBUTTON2 0x06 +#endif + typedef struct { UINT javaKey; UINT windowsKey; @@ -5068,7 +5129,12 @@ if (modifiers & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) { wLow |= MK_MBUTTON; } - + if (modifiers & X1_BUTTON) { + wLow |= GetButtonMK(X1_BUTTON); + } + if (modifiers & X2_BUTTON) { + wLow |= GetButtonMK(X2_BUTTON); + } wheelAmt = (jint)JNU_CallMethodByName(env, NULL, @@ -6165,6 +6231,18 @@ Java_java_awt_Component_initIDs(JNIEnv *env, jclass cls) { TRY; + jclass inputEventClazz = env->FindClass("java/awt/event/InputEvent"); + jmethodID getButtonDownMasksID = env->GetStaticMethodID(inputEventClazz, "getButtonDownMasks", "()[I"); + jintArray obj = (jintArray)env->CallStaticObjectMethod(inputEventClazz, getButtonDownMasksID); + jint * tmp = env->GetIntArrayElements(obj, JNI_FALSE); + + jsize len = env->GetArrayLength(obj); + AwtComponent::masks = new jint[len]; + for (int i = 0; i < len; i++) { + AwtComponent::masks[i] = tmp[i]; + } + env->ReleaseIntArrayElements(obj, tmp, 0); + env->DeleteLocalRef(obj); /* class ids */ jclass peerCls = env->FindClass("sun/awt/windows/WComponentPeer");
--- a/src/windows/native/sun/windows/awt_Component.h Thu Sep 11 10:38:00 2008 +0400 +++ b/src/windows/native/sun/windows/awt_Component.h Tue Sep 16 12:17:02 2008 +0400 @@ -53,6 +53,22 @@ #define MIDDLE_BUTTON 2 #define RIGHT_BUTTON 4 #define DBL_CLICK 8 +#define X1_BUTTON 16 +#define X2_BUTTON 32 + +#ifndef MK_XBUTTON1 +#define MK_XBUTTON1 0x0020 +#endif + +#ifndef MK_XBUTTON2 +#define MK_XBUTTON2 0x0040 +#endif + +// combination of standard mouse button flags +const int ALL_MK_BUTTONS = MK_LBUTTON|MK_MBUTTON|MK_RBUTTON; +const int X_BUTTONS = MK_XBUTTON1|MK_XBUTTON2; + + // Whether to check for embedded frame and adjust location #define CHECK_EMBEDDED 0 @@ -81,11 +97,6 @@ class AwtComponent : public AwtObject { public: - enum { - // combination of all mouse button flags - ALL_MK_BUTTONS = MK_LBUTTON|MK_MBUTTON|MK_RBUTTON - }; - /* java.awt.Component fields and method IDs */ static jfieldID peerID; static jfieldID xID; @@ -112,6 +123,7 @@ static jmethodID replaceSurfaceDataLaterMID; static const UINT WmAwtIsComponent; + static jint * masks; //InputEvent mask array AwtComponent(); virtual ~AwtComponent();
--- a/src/windows/native/sun/windows/awt_Robot.cpp Thu Sep 11 10:38:00 2008 +0400 +++ b/src/windows/native/sun/windows/awt_Robot.cpp Tue Sep 16 12:17:02 2008 +0400 @@ -31,8 +31,6 @@ #include "java_awt_event_InputEvent.h" #include <winuser.h> -static const int MOUSE_MAX = 65535; - AwtRobot::AwtRobot( jobject peer ) { JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -103,19 +101,38 @@ // left handed mouse setup BOOL bSwap = ::GetSystemMetrics(SM_SWAPBUTTON); - if ( buttonMask & java_awt_event_InputEvent_BUTTON1_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON1_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) + { dwFlags |= !bSwap ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_RIGHTDOWN; } - if ( buttonMask & java_awt_event_InputEvent_BUTTON3_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON3_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) + { dwFlags |= !bSwap ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_LEFTDOWN; } - if ( buttonMask & java_awt_event_InputEvent_BUTTON2_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON2_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) + { dwFlags |= MOUSEEVENTF_MIDDLEDOWN; } - mouse_event(dwFlags, 0, 0, 0, 0 ); + INPUT mouseInput = {0}; + mouseInput.type = INPUT_MOUSE; + mouseInput.mi.time = 0; + mouseInput.mi.dwFlags = dwFlags; + if ( buttonMask & AwtComponent::masks[3] ) { + mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XDOWN; + mouseInput.mi.mouseData = XBUTTON1; + } + + if ( buttonMask & AwtComponent::masks[4] ) { + mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XDOWN; + mouseInput.mi.mouseData = XBUTTON2; + } + ::SendInput(1, &mouseInput, sizeof(mouseInput)); } void AwtRobot::MouseRelease( jint buttonMask ) @@ -126,19 +143,39 @@ // left handed mouse setup BOOL bSwap = ::GetSystemMetrics(SM_SWAPBUTTON); - if ( buttonMask & java_awt_event_InputEvent_BUTTON1_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON1_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) + { dwFlags |= !bSwap ? MOUSEEVENTF_LEFTUP : MOUSEEVENTF_RIGHTUP; } - if ( buttonMask & java_awt_event_InputEvent_BUTTON3_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON3_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON3_DOWN_MASK) + { dwFlags |= !bSwap ? MOUSEEVENTF_RIGHTUP : MOUSEEVENTF_LEFTUP; } - if ( buttonMask & java_awt_event_InputEvent_BUTTON2_MASK ) { + if ( buttonMask & java_awt_event_InputEvent_BUTTON2_MASK || + buttonMask & java_awt_event_InputEvent_BUTTON2_DOWN_MASK) + { dwFlags |= MOUSEEVENTF_MIDDLEUP; } - mouse_event(dwFlags, 0, 0, 0, 0 ); + INPUT mouseInput = {0}; + mouseInput.type = INPUT_MOUSE; + mouseInput.mi.time = 0; + mouseInput.mi.dwFlags = dwFlags; + + if ( buttonMask & AwtComponent::masks[3] ) { + mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XUP; + mouseInput.mi.mouseData = XBUTTON1; + } + + if ( buttonMask & AwtComponent::masks[4] ) { + mouseInput.mi.dwFlags = mouseInput.mi.dwFlags | MOUSEEVENTF_XUP; + mouseInput.mi.mouseData = XBUTTON2; + } + ::SendInput(1, &mouseInput, sizeof(mouseInput)); } void AwtRobot::MouseWheel (jint wheelAmt) { @@ -400,3 +437,9 @@ CATCH_BAD_ALLOC; } + +JNIEXPORT jint JNICALL Java_sun_awt_windows_WRobotPeer_getNumberOfButtons( + JNIEnv *, jobject self) +{ + return GetSystemMetrics(SM_CMOUSEBUTTONS); +}
--- a/src/windows/native/sun/windows/awt_Robot.h Thu Sep 11 10:38:00 2008 +0400 +++ b/src/windows/native/sun/windows/awt_Robot.h Tue Sep 16 12:17:02 2008 +0400 @@ -1,5 +1,5 @@ /* - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved. + * Copyright 1998-2008 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 @@ -42,13 +42,13 @@ void MouseRelease( jint buttonMask ); void MouseWheel(jint wheelAmt); + jint getNumberOfButtons(); jint GetRGBPixel( jint x, jint y); void GetRGBPixels(jint x, jint y, jint width, jint height, jintArray pixelArray); void KeyPress( jint key ); void KeyRelease( jint key ); - static AwtRobot * GetRobot( jobject self ); private:
--- a/src/windows/native/sun/windows/awt_Toolkit.cpp Thu Sep 11 10:38:00 2008 +0400 +++ b/src/windows/native/sun/windows/awt_Toolkit.cpp Tue Sep 16 12:17:02 2008 +0400 @@ -322,6 +322,7 @@ m_vmSignalled = FALSE; m_isDynamicLayoutSet = FALSE; + m_areExtraMouseButtonsEnabled = TRUE; m_verifyComponents = FALSE; m_breakOnError = FALSE; @@ -2092,3 +2093,26 @@ splashClose(); } } + +/* + * accessible from awt_Component + */ +BOOL AwtToolkit::areExtraMouseButtonsEnabled() { + return m_areExtraMouseButtonsEnabled; +} + +/* + * Class: sun_awt_windows_WToolkit + * Method: setExtraMouseButtonsEnabledNative + * Signature: (Z)V + */ +extern "C" JNIEXPORT void JNICALL Java_sun_awt_windows_WToolkit_setExtraMouseButtonsEnabledNative +(JNIEnv *env, jclass self, jboolean enable){ + TRY; + AwtToolkit::GetInstance().setExtraMouseButtonsEnabled(enable); + CATCH_BAD_ALLOC; +} + +void AwtToolkit::setExtraMouseButtonsEnabled(BOOL enable) { + m_areExtraMouseButtonsEnabled = enable; +}
--- a/src/windows/native/sun/windows/awt_Toolkit.h Thu Sep 11 10:38:00 2008 +0400 +++ b/src/windows/native/sun/windows/awt_Toolkit.h Tue Sep 16 12:17:02 2008 +0400 @@ -175,6 +175,8 @@ BOOL IsDynamicLayoutSet(); BOOL IsDynamicLayoutSupported(); BOOL IsDynamicLayoutActive(); + BOOL areExtraMouseButtonsEnabled(); + void setExtraMouseButtonsEnabled(BOOL enable); INLINE BOOL localPump() { return m_localPump; } INLINE BOOL VerifyComponents() { return FALSE; } // TODO: Use new DebugHelper class to set this flag @@ -351,6 +353,7 @@ BOOL m_verbose; BOOL m_isActive; // set to FALSE at beginning of Dispose BOOL m_isDisposed; // set to TRUE at end of Dispose + BOOL m_areExtraMouseButtonsEnabled; BOOL m_vmSignalled; // set to TRUE if QUERYENDSESSION has successfully // raised SIGTERM
--- a/src/windows/native/sun/windows/awt_TrayIcon.cpp Thu Sep 11 10:38:00 2008 +0400 +++ b/src/windows/native/sun/windows/awt_TrayIcon.cpp Tue Sep 16 12:17:02 2008 +0400 @@ -393,7 +393,7 @@ lastX = x; lastY = y; AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y); - if ((flags & AwtComponent::ALL_MK_BUTTONS) != 0) { + if ((flags & ALL_MK_BUTTONS) != 0) { m_mouseButtonClickAllowed = 0; } else { SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::windowsToUTC(::GetTickCount()), x, y,
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,131 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that drag events are coming for every button if the property is set to true + @author Andrei Dmitriev : area=awt.mouse + @run main ExtraButtonDrag + */ + +//events from standard should also come + +import java.awt.*; +import java.awt.event.*; + +public class ExtraButtonDrag extends Frame { + static String tk = Toolkit.getDefaultToolkit().getClass().getName(); + static Robot robot; + static int [] buttonsPressed; + static int [] buttonsReleased; + static int [] buttonsClicked; + volatile static boolean dragged = false; + volatile static boolean moved = false; + + public ExtraButtonDrag(){ + super("ExtraButtonDrag"); + } + + public static void main(String []s){ + Frame frame = new ExtraButtonDrag(); + + MouseAdapter ma = new MouseAdapter() { + public void mouseDragged(MouseEvent e) { + System.out.println("Dragged "+e);// +" : "+ e.getButton() + " : " +e.getButtonState(e.getButton())); + dragged = true; + } + public void mouseMoved(MouseEvent e) { + System.out.println("Moved "+e); + moved = true; + } + public void mousePressed(MouseEvent e) { + System.out.println(">>> "+e); + } + public void mouseReleased(MouseEvent e) { + System.out.println(">>> "+e); + } + + }; + + frame.addMouseMotionListener(ma); + frame.addMouseListener(ma); + + frame.setSize(300, 300); + frame.setVisible(true); + + int [] buttonMask = new int [MouseInfo.getNumberOfButtons()]; //InputEvent.getButtonMasks(); + + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonMask[i] = InputEvent.getMaskForButton(i+1); + // System.out.println("TEST: "+tmp[i]); + } + + try { + robot = new Robot(); + robot.delay(1000); + Point centerFrame = new Point(frame.getLocationOnScreen().x + frame.getWidth()/2, frame.getLocationOnScreen().y + frame.getHeight()/2); + Point outboundsFrame = new Point(frame.getLocationOnScreen().x + frame.getWidth()*3/2, frame.getLocationOnScreen().y + frame.getHeight()/2); + + System.out.println("areExtraMouseButtonsEnabled() == " + Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled() ); + + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + System.out.println("button to drag = " +(i+1) + " : value passed to robot = " +buttonMask[i]); + + try { + dragMouse(buttonMask[i], centerFrame.x, centerFrame.y, outboundsFrame.x, outboundsFrame.y); + } catch (IllegalArgumentException e){ + throw new RuntimeException("Test failed. Exception occured.", e); + } + + robot.delay(500); + //this is a choice-case for X protocol issue: native events from extra buttons doesn't contain + // the correct state so it's unable to decide if there is a drag or move. By default we send MOVED event. + //XToolkit: extra buttons should report MOVED events only + //WToolkit: extra buttons should report DRAGGED events only + if (i > 2){ //extra buttons only + if (tk.equals("sun.awt.X11.XToolkit") || tk.equals("sun.awt.motif.MToolkit")) { + if (!moved || dragged) { + throw new RuntimeException("Test failed."+ tk +" Button = " +(i+1) + " moved = "+moved +" : dragged = " +dragged); + } + } else { //WToolkit + if (moved || !dragged) { + throw new RuntimeException("Test failed."+ tk +" Button = " +(i+1) + " moved = "+moved +" : dragged = " +dragged); + } + } + } else { + if (moved || !dragged){ + throw new RuntimeException("Test failed. Button = " +(i+1) + " not dragged."); + } + } + } + } catch (Exception e){ + throw new RuntimeException("", e); + } + } + + public static void dragMouse(int button, int x0, int y0, int x1, int y1){ + int curX = x0; + int curY = y0; + int dx = x0 < x1 ? 1 : -1; + int dy = y0 < y1 ? 1 : -1; + robot.mouseMove(x0, y0); + + robot.delay(200); + dragged = false; + moved = false; + + robot.mousePress(button); + + while (curX != x1){ + curX += dx; + robot.mouseMove(curX, curY); + robot.delay(5); + } + while (curY != y1 ){ + curY += dy; + robot.mouseMove(curX, curY); + robot.delay(5); + } + robot.mouseRelease(button); + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Mouse/MouseModifiersUnitTest/ModifierPermutation.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,320 @@ +/* + test %I% %E% + @bug 6315717 + @summary presses buttons in all permutations and verifies modifiers + @author Andrei Dmitriev : area=awt.mouse + @run main ModifierPermutation + */ +//package modifierpermutation; + +/* +The test will try to press-release every button present on the mouse in different order. +Here are some abbreviations: + BUTTON1 press = P1 + BUTTON2 press = P2 etc. + BUTTON1 release = R1 + BUTTON2 release = R2 etc. +Only sequences alike below are possible : <P1, P2, R2, R1>. +Sequences like <P1, P2, R1, R2> will not be covered by this test due to its probable complexity. + */ + +import java.awt.*; +import sun.awt.SunToolkit; +import java.awt.event.*; +import java.util.Arrays; + +public class ModifierPermutation { + static boolean failed = false; + final static int BUTTONSNUMBER = MouseInfo.getNumberOfButtons(); + +/* + * Because of some problems with BUTTONx_MASK + * (they are not ordered. Instead, their values are: 16 8 4) + * We have to use array [1..n] and make every permutation on its + * containment. After each permutation, make the same thing with + * array of buttons and array of expected modifiers. + */ + static SunToolkit st = (SunToolkit)(Toolkit.getDefaultToolkit()); + //all button masks + static int [] mouseButtons = new int [BUTTONSNUMBER]; //BUTTONx_MASK + static int [] mouseButtonsDown = new int [BUTTONSNUMBER]; //BUTTONx_DOWN_MASK + + //used to store mouse buttons sequences to press/to release + static int [] affectedButtonsToPressRelease; +// static int [] buttonsToRelease; +// static int [] modifiersToVerifyOnPressRelease; + + static Robot robot; + static CheckingAdapter adapterTest1; + static Frame f; + + static { + for (int i = 0; i < BUTTONSNUMBER; i++){ + mouseButtons[i] = InputEvent.getMaskForButton(i+1); //then change first three elements here to BUTTONx_MASK + mouseButtonsDown[i] = InputEvent.getMaskForButton(i+1); + } + //mouseButtons initially has following values : 16 8 4. +/* mouseButtons[0] = InputEvent.BUTTON1_MASK; + mouseButtons[1] = InputEvent.BUTTON2_MASK; + mouseButtons[2] = InputEvent.BUTTON3_MASK; + */ + } + + public static void main(String s[]){ + init(); + + try { + robot = new Robot(); + } catch (Exception e){ + e.printStackTrace(); + throw new RuntimeException("Test failed.", e); + } + robot.delay(500); + robot.mouseMove(f.getLocationOnScreen().x + f.getWidth()/2, f.getLocationOnScreen().y + f.getHeight()/2); + robot.delay(500); + //Top limit is the factorial of the number of existing buttons + for (int k = 0; k < factorial(mouseButtons.length)-1; k++){ + //now we will press 2 up to maximum buttons and release them in different order and listen for + // PRESSED events and check it's ExModifiers + for (int buttonsToPressNumber = 2; buttonsToPressNumber <= BUTTONSNUMBER; buttonsToPressNumber++ ){ + System.out.println(">>>"); + + //Now get the slice of affected buttons + affectedButtonsToPressRelease = Arrays.copyOf(mouseButtons, buttonsToPressNumber); +// modifiersToVerifyOnPressRelease = Arrays.copyOf(mouseButtons, buttonsToPressNumber); + + //Now press all these buttons in the order as they are in array affectedButtonsToPressRelease + //And release all these buttons in back order. + + dumpArray("Affected Buttons ", affectedButtonsToPressRelease); + pressAllButtons(affectedButtonsToPressRelease); + releaseAllButtonsForwardOrder(affectedButtonsToPressRelease); +// nextPermutation(i, buttonsToRelease); + //TODO: press buttons and release them backward + //All I have to add is : +// pressAllButtons(affectedButtonsToPressRelease); +// releaseAllButtonsBackwardOrder(affectedButtonsToPressRelease); + + System.out.println("<<<"); + } + nextPermutation(k, mouseButtons); +// PermutationGenerator.nextPermutation(k, mouseButtonsDown); + dumpArray("mouseButtons (step="+k+")", mouseButtons); +// dumpArray("mouseButtonsDown (step="+k+")", mouseButtonsDown); + } + } + + private static void init(){ + adapterTest1 = new CheckingAdapter(); + f = new Frame("Robot presses mouse here"); + f.setSize(300, 300); + f.setVisible(true); + f.addMouseListener(adapterTest1); + } + public static int factorial(int t){ + if (t <=1 ) { + return 1; + } else { + return t*factorial(t-1); + } + } + + // use this variable to get current button on EDT in checkModifiers() + static volatile int currentButtonIndexUnderAction; + + public static void pressAllButtons(int []array){ + for (int i = 0; i <array.length; i ++){ + if (failed) { + throw new RuntimeException("PRESSED_EVENT is not filled with correct values. Review messaage above."); + } + System.out.println("Pressing button = " + array[i]); + currentButtonIndexUnderAction = i; + robot.mousePress(array[i]); + System.out.println("currentButtonIndexUnderAction ="+currentButtonIndexUnderAction); + st.realSync(); + // robot.delay(100); + } + } + + public static void releaseAllButtonsForwardOrder(int []array){ + for (int i = 0; i <array.length; i ++){ + System.out.println("Releasing button = " + array[i]); + currentButtonIndexUnderAction = i; + robot.mouseRelease(array[i]); + System.out.println("currentButtonIndexUnderAction ="+currentButtonIndexUnderAction); + st.realSync(); + // robot.delay(100); + } + } + + public static void checkModifiersOnPress(MouseEvent e){ + System.out.println("checkModifiers. currentButtonIndexUnderAction ="+currentButtonIndexUnderAction); + for (int i = 0; i<= currentButtonIndexUnderAction; i++){ + if ((e.getModifiersEx() & affectedButtonsToPressRelease[i]) == 0){ + System.out.println("ERROR["+i+"]: PRESSED_EVENT is not filled with correct values. affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i] +" Event = "+e); + ModifierPermutation.failed = true; + } else { + System.out.println("CORRECT["+i+"]: affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i]+ " Event = "+e); + } + } + } + + /*======================================================================*/ + public static void dumpValues(int button, int modifiers, int modifiersStandard, int modifiersEx, int modifiersExStandard){ + System.out.println("Button = "+button + "Modifiers = "+ modifiers + " standard = "+ modifiersStandard); + System.out.println(" ModifiersEx = "+ modifiersEx + " standardEx = "+ modifiersExStandard); + } + + public static void dumpArray(String id, int [] array){ + System.out.print(id); + for (int i = 0; i < array.length; i++){ + System.out.print(array[i]+" "); + } + System.out.println(); + } + public static void nextPermutation(int step, int []array){ + int i; + int leftEl = 0; + int rightEl = 0; + + i = array.length - 2; + while (i>=0) { + if (array[i] < array[i+1]){ + leftEl = i; + // System.out.println("leftEl = "+leftEl); + break; + } + i--; + } + + i = array.length - 1; + while (i>=0) { + if (array[i] > array[leftEl]) { + rightEl = i; + // System.out.println("rightEl = "+rightEl); + break; + } + i--; + } + swapElements(array, leftEl, rightEl); + if (leftEl + 2 < array.length){ + // System.out.println("sort"); + Arrays.sort(array, leftEl + 1 , array.length); + } + } + + public static void swapElements(int [] array, int leftEl, int rightEl){ + int tmp = array[leftEl]; + array[leftEl] = array[rightEl]; + array[rightEl] = tmp; + } + + public static void checkModifiersOnRelease(MouseEvent e){ + System.out.println("CheckModifiersOnRelease. currentButtonIndexUnderAction ="+currentButtonIndexUnderAction); + for (int i = currentButtonIndexUnderAction+1; i<affectedButtonsToPressRelease.length; i++){ + if ((e.getModifiersEx() & affectedButtonsToPressRelease[i]) == 0){ + System.out.println("ERROR["+i+"]: RELEASED_EVENT is not filled with correct values. affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i] +" Event = "+e); + ModifierPermutation.failed = true; + } else { + System.out.println("CORRECT["+i+"]: affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i]+ " Event = "+e); + } + } + } + + public static void checkModifiersOnClick(MouseEvent e){ + System.out.println("CheckModifiersOnClick. currentButtonIndexUnderAction ="+currentButtonIndexUnderAction); +//Actually the same as in checkModifiersOnRelease() + for (int i = currentButtonIndexUnderAction+1; i<affectedButtonsToPressRelease.length; i++){ + if ((e.getModifiersEx() & affectedButtonsToPressRelease[i]) == 0){ + System.out.println("ERROR["+i+"]: CLICK_EVENT is not filled with correct values. affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i] +" Event = "+e); + ModifierPermutation.failed = true; + } else { + System.out.println("CORRECT["+i+"]: affectedButtonsToPressRelease[i]= "+affectedButtonsToPressRelease[i]+ " Event = "+e); + } + } + } +} +///~ ModifierPermutation clas + +/* A class that invoke appropriate verification + * routine with current modifier. + */ +class CheckingAdapter extends MouseAdapter{ + public CheckingAdapter(){} + + public void mousePressed(MouseEvent e) { + System.out.println("PRESSED "+e); + ModifierPermutation.checkModifiersOnPress(e); + } + public void mouseReleased(MouseEvent e) { + System.out.println("RELEASED "+e); + ModifierPermutation.checkModifiersOnRelease(e); + + } + public void mouseClicked(MouseEvent e) { + System.out.println("CLICKED "+e); + ModifierPermutation.checkModifiersOnClick(e); + } +} + +// A class that could make a standard permutation with no regard to the +// values of array passed in. +// It uses a buttonIndicesToPermutate array with [1..N] values to perform +// these permutations. +//Note that nextPermutation is a static method and you can't keep track +// of more the single permutation sequence. +/* +class PermutationGenerator{ + final static int BUTTONSNUMBER = MouseInfo.getNumberOfButtons(); + static int [] buttonIndicesToPermutate = new int [BUTTONSNUMBER];; + public PermutationGenerator(){ + for (int i = 0; i < BUTTONSNUMBER; i++){ + buttonIndicesToPermutate[i] = i+1; //fill it with [1..N] values + } + } + + public static void nextPermutation(int step, int []array){ + if (array.length != buttonIndicesToPermutate.length) { + throw new IllegalArgumentException("Array should have length equals to mouse buttons number."); + } + int i; + int leftEl = 0; + int rightEl = 0; + + i = array.length - 2; + while (i>=0) { + if (buttonIndicesToPermutate[i] < buttonIndicesToPermutate[i+1]){ + leftEl = i; + // System.out.println("leftEl = "+leftEl); + break; + } + i--; + } + + i = array.length - 1; + while (i>=0) { + if (buttonIndicesToPermutate[i] >buttonIndicesToPermutate[leftEl]) { + rightEl = i; + // System.out.println("rightEl = "+rightEl); + break; + } + i--; + } + swapElements(array, leftEl, rightEl); + swapElements(buttonIndicesToPermutate, leftEl, rightEl); + + if (leftEl + 2 < array.length){ + // System.out.println("sort"); +//need to make our own sorting because arraysort makes this on actual values in array... + Arrays.sort(array, leftEl + 1 , array.length); + Arrays.sort(buttonIndicesToPermutate, leftEl + 1 , buttonIndicesToPermutate.length); +// sortArray(array, leftEl + 1 , array.length); + } + } + public static void swapElements(int [] array, int leftEl, int rightEl){ + int tmp = array[leftEl]; + array[leftEl] = array[rightEl]; + array[rightEl] = tmp; + } +} +*/
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Extra.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,490 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that modifiers are correct for extra buttons + @author Andrei Dmitriev : area=awt.mouse + @run main MouseModifiersUnitTest_Extra + */ + +import java.awt.*; +import java.awt.event.*; +import java.util.Arrays; +import java.util.HashMap; +import java.util.StringTokenizer; +import java.util.Vector; + +// will process extra buttons only +// asking parameters from CMD: manual/automatic, modifier to test + +public class MouseModifiersUnitTest_Extra extends Frame { + static final int NONE = 0; + static final int SHIFT = 1; + static final int CTRL = 2; + static final int ALT = 3; + static CheckingModifierAdapter adapterTest1; + static CheckingModifierAdapter adapterTest2; + static CheckingModifierAdapter adapterTest3; + static CheckingModifierAdapter adapterTest4; + + static boolean debug = true; //dump all errors (debug) or throw first(under jtreg) exception + static boolean autorun = false; //use robot or manual run + static int testModifier = NONE; + + static int [] mouseButtons; + static int [] mouseButtonDownMasks; + + //an arrays representing a modifiersEx of extra mouse buttons while using ALT/CTRL/SHIFT or none of them + static int [] modifiersExStandard; + static int [] modifiersExStandardSHIFT; + static int [] modifiersExStandardCTRL; + static int [] modifiersExStandardALT; + + // final static int [] mouseButtons = new int [] {MouseEvent.BUTTON1_MASK, MouseEvent.BUTTON2_MASK, MouseEvent.BUTTON3_MASK}; + // BUTTON1, 2, 3 press-release. + final static int modifiersStandard = 0; //InputEvent.BUTTON_DOWN_MASK; + + public static void checkPressedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardExModifiers = getStandardExArray(testModifier); + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 4)*3; + dumpValues(button, modifiers, modifiersStandard, modifiersEx, curStandardExModifiers[index]); + if (modifiers != modifiersStandard){ + MessageLogger.reportError("Test failed : Pressed. modifiers != modifiersStandard"); + } + + if (modifiersEx != curStandardExModifiers[index]){ +// System.out.println(">>>>>>>>>>>>>>> Pressed. modifiersEx "+modifiersEx +" : "+!= curStandardExModifiers"); + MessageLogger.reportError("Test failed : Pressed. modifiersEx != curStandardExModifiers"); + } + + //check event.paramString() output + HashMap <String, String> paramStringElements = tokenizeParamString(event.paramString()); + System.out.println(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + checkExtModifiersOnPress(testModifier, paramStringElements, button); + } + + public static void checkExtModifiersOnReleaseClick(int testModifier, HashMap h, int button){ + String ethalon = ""; + switch (testModifier){ + case SHIFT:{ + ethalon = "Shift"; + break; + } + case ALT:{ + ethalon = "Alt"; + break; + } + case CTRL:{ + ethalon = "Ctrl"; + break; + } + } + // + if (h.get("extModifiers") == null){ + h.put("extModifiers", ""); + } + if (!ethalon.equals(h.get("extModifiers"))) { + MessageLogger.reportError("Test failed : Released/Clicked. extModifiers = " +h.get("extModifiers")+" instead of : "+ethalon); + } + } + + public static void checkExtModifiersOnPress(int testModifier, HashMap h, int button){ + String ethalon = ""; + switch (testModifier){ + case SHIFT:{ + ethalon = "Shift+"; + break; + } + case ALT:{ + ethalon = "Alt+"; + break; + } + case CTRL:{ + ethalon = "Ctrl+"; + break; + } + } + ethalon = ethalon + "Button" +button; + + if (!h.get("extModifiers").equals(ethalon)) { + MessageLogger.reportError("Test failed : Pressed. extModifiers = " +h.get("extModifiers")+" instead of : "+ethalon); + } + } + + public static void checkModifiers(int testModifier, HashMap<String, String> h, int button){ + // none of modifiers for extra button should be null + if (h.get("modifiers") != null) { + MessageLogger.reportError("Test failed : modifiers != null"); + } + } + + public static void checkButton(HashMap<String, String> h, int button){ + if (h.get("button") == null) { + MessageLogger.reportError("Test failed : checkButton(). button is absent in paramString()"); + } + if (Integer.parseInt(h.get("button")) != button) { + MessageLogger.reportError("Test failed : checkButton. button in paramString() doesn't equal to button being pressed."); + } + } + public static HashMap<String, String> tokenizeParamString(String param){ + HashMap <String, String> params = new HashMap<String, String>(); + StringTokenizer st = new StringTokenizer(param, ",="); + while (st.hasMoreTokens()){ + String tmp = st.nextToken(); +// System.out.println("PARSER : "+tmp); + if (tmp.equals("button") || + tmp.equals("modifiers") || + tmp.equals("extModifiers")) { + params.put(tmp, st.nextToken()); + } + } + return params; + } + + public static Vector<String> tokenizeModifiers(String modifierList){ + Vector<String> modifiers = new Vector<String>(); + StringTokenizer st = new StringTokenizer(modifierList, "+"); + while (st.hasMoreTokens()){ + String tmp = st.nextToken(); + modifiers.addElement(tmp); + System.out.println("MODIFIER PARSER : "+tmp); + } + return modifiers; + } + + public static void checkReleasedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardExModifiers = getStandardExArray(testModifier); + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 4)*3 + 1; + dumpValues(button, modifiers, modifiersStandard, modifiersEx, curStandardExModifiers[index]); + if (modifiers != modifiersStandard){ + MessageLogger.reportError("Test failed : Released. modifiers != modifiersStandard"); + } + + if (modifiersEx != curStandardExModifiers[index]){ + MessageLogger.reportError("Test failed : Released. modifiersEx != curStandardExModifiers"); + } + + //check event.paramString() output + HashMap <String, String> paramStringElements = tokenizeParamString(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + System.out.println("paramStringElements = "+paramStringElements); + checkExtModifiersOnReleaseClick(testModifier, paramStringElements, button); + } + + public static void checkClickedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardExModifiers = getStandardExArray(testModifier); + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 4)*3 + 2; + dumpValues(button, modifiers, modifiersStandard, modifiersEx, curStandardExModifiers[index]); + if (modifiers != modifiersStandard){ + MessageLogger.reportError("Test failed : Clicked. modifiers != modifiersStandard"); + } + + if (modifiersEx != curStandardExModifiers[index]){ + MessageLogger.reportError("Test failed : Clicked. modifiersEx != curStandardExModifiers"); + } + + //check event.paramString() output + HashMap <String, String> paramStringElements = tokenizeParamString(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + checkExtModifiersOnReleaseClick(testModifier, paramStringElements, button); + } + + private static int[] getStandardExArray(int testModifier) { + int [] curStandardExModifiers; + switch (testModifier){ + case SHIFT: + curStandardExModifiers = modifiersExStandardSHIFT; + break; + case CTRL: + curStandardExModifiers = modifiersExStandardCTRL; + break; + case ALT: + curStandardExModifiers = modifiersExStandardALT; + break; + default: //NONE by default + curStandardExModifiers = modifiersExStandard; + } + return curStandardExModifiers; + } + + static Robot robot; + public void init() { + this.setLayout(new BorderLayout()); + + String[] instructions = + { + "This test should be used with the mouse having more then three buttons.", + "Currently, " + MouseInfo.getNumberOfButtons() +" buttons are available.", + "If there are less then three buttons, press PASS.", + "1. Press each extra mouse button.", + "2. For each mouse event its modifiers and ExModifiers will be printed.", + "3. Verify that they are correct.", + "4. Press Pass or Fail accordingly." + }; +// Sysout.createDialogWithInstructions( instructions ); + +// addMouseListener(adapterTest1); + try { + robot = new Robot(); + } catch (Exception e) { + MessageLogger.reportError("Test failed. "+e); + } + }//End init() + + public void start() { + //Get things going. Request focus, set size, et cetera + setSize(200,200); + setVisible(true); + validate(); + if (autorun) { + testNONE(); + testSHIFT(); + testCTRL(); + testALT(); + } else { + switch (testModifier){ + case SHIFT: + this.addMouseListener(adapterTest2); + break; + case CTRL: + this.addMouseListener(adapterTest3); + break; + case ALT: + this.addMouseListener(adapterTest4); + break; + default: //NONE by default + this.addMouseListener(adapterTest1); + } + } + }// start() + + //000000000000000000000000000000000000000000000000000000000000000 + public void testNONE(){ + this.addMouseListener(adapterTest1); + robot.delay(1000); + robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2); + for (int i = 3; i< mouseButtons.length; i++){ + System.out.println("testNONE() => " +mouseButtons[i] ); + robot.mousePress(mouseButtons[i]); + robot.delay(100); + robot.mouseRelease(mouseButtons[i]); + } + robot.delay(1000); + this.removeMouseListener(adapterTest1); + } + + public void testSHIFT(){ + this.addMouseListener(adapterTest2); + robot.delay(1000); + robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2); + for (int i = 3; i< mouseButtons.length; i++){ + robot.keyPress(KeyEvent.VK_SHIFT); + System.out.println("testSHIFT() => " +mouseButtons[i] ); + robot.mousePress(mouseButtons[i]); + robot.delay(100); + robot.mouseRelease(mouseButtons[i]); + robot.keyRelease(KeyEvent.VK_SHIFT); + } + robot.delay(1000); + this.removeMouseListener(adapterTest2); + } + + public void testCTRL(){ + this.addMouseListener(adapterTest3); + robot.delay(1000); + robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2); + for (int i = 3; i< mouseButtons.length; i++){ + robot.keyPress(KeyEvent.VK_CONTROL); + System.out.println("testCTRL() => " +mouseButtons[i] ); + robot.mousePress(mouseButtons[i]); + robot.delay(100); + robot.mouseRelease(mouseButtons[i]); + robot.keyRelease(KeyEvent.VK_CONTROL); + } + robot.delay(1000); + this.removeMouseListener(adapterTest3); + } + + public void testALT(){ + this.addMouseListener(adapterTest4); + robot.delay(1000); + robot.mouseMove(getLocationOnScreen().x + getWidth()/2, getLocationOnScreen().y + getHeight()/2); + for (int i = 3; i< mouseButtons.length; i++){ + robot.keyPress(KeyEvent.VK_ALT); + System.out.println("testALT() => " +mouseButtons[i] ); + robot.mousePress(mouseButtons[i]); + robot.delay(100); + robot.mouseRelease(mouseButtons[i]); + robot.keyRelease(KeyEvent.VK_ALT); + } + robot.delay(1000); + this.removeMouseListener(adapterTest4); + } + + //************************************************************************************************** + public static void dumpValues(int button, int modifiers, int modifiersStandard, int modifiersEx, int modifiersExStandard){ + System.out.println("Button = "+button + "Modifiers = "+ modifiers + "standard = "+ modifiersStandard); + System.out.println("Button = "+button + "ModifiersEx = "+ modifiersEx + "standardEx = "+ modifiersExStandard); + } + + public static void initParams(String []s){ + if (s.length != 3){ + autorun = true; + debug = false; + testModifier = NONE; + } else { + autorun = Boolean.valueOf(s[0]); + debug = Boolean.valueOf(s[1]); + + if (s[2].equals("NONE")){ + testModifier = NONE; + } + if (s[2].equals("SHIFT")){ + testModifier = SHIFT; + } + if (s[2].equals("CTRL")){ + testModifier = CTRL; + } + if (s[2].equals("ALT")){ + testModifier = ALT; + } + } + MessageLogger.setDebug(debug); + System.out.println("Autorun : " +autorun); + System.out.println("Debug mode : " +debug); + System.out.println("Modifier to verify : " + testModifier); + } + + public static void initAdapters(){ + adapterTest1 = new CheckingModifierAdapter(NONE); + adapterTest2 = new CheckingModifierAdapter(SHIFT); + adapterTest3 = new CheckingModifierAdapter(CTRL); + adapterTest4 = new CheckingModifierAdapter(ALT); + } + + public static void initVars(){ + int [] tmp = new int [MouseInfo.getNumberOfButtons()]; + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + tmp[i] = InputEvent.getMaskForButton(i+1); + // System.out.println("TEST: "+tmp[i]); + } + + mouseButtons = Arrays.copyOf(tmp, tmp.length); + + for (int i = 0; i < mouseButtons.length; i++){ + System.out.println("MouseArray [i] == "+mouseButtons[i]); + } + + mouseButtonDownMasks = Arrays.copyOf(tmp, tmp.length); + + // So we need to get the number of extra buttons on the mouse: "MouseInfo.getNumberOfButtons() - 3" + // and multyply on 3 because each button will generate three events : PRESS, RELEASE and CLICK. + tmp = new int [(MouseInfo.getNumberOfButtons()-3)*3]; + Arrays.fill(tmp, 0); + + for (int i = 0, j = 3; i < tmp.length; i = i + 3, j++){ + tmp[i] = mouseButtonDownMasks[j]; + } + modifiersExStandard = Arrays.copyOf(tmp, tmp.length); + + Arrays.fill(tmp, InputEvent.SHIFT_DOWN_MASK); + for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){ + tmp[i] = tmp[j] | mouseButtonDownMasks[j]; + } + modifiersExStandardSHIFT = Arrays.copyOf(tmp, tmp.length); + + Arrays.fill(tmp, InputEvent.CTRL_DOWN_MASK); + for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){ + tmp[i] = tmp[j] | mouseButtonDownMasks[j]; + } + modifiersExStandardCTRL = Arrays.copyOf(tmp, tmp.length); + + Arrays.fill(tmp, InputEvent.ALT_DOWN_MASK); + for (int i = 0, j = 3; i < MouseInfo.getNumberOfButtons(); i = i + 3, j++){ + tmp[i] = tmp[j] | mouseButtonDownMasks[j]; + } + modifiersExStandardALT = Arrays.copyOf(tmp, tmp.length); + } + + public static void main(String []s){ + if (MouseInfo.getNumberOfButtons() < 4){ + System.out.println("There are less then 4 buttons on the mouse. The test may not be accomplished. Skipping."); + return; + } + initVars(); + MouseModifiersUnitTest_Extra frame = new MouseModifiersUnitTest_Extra(); + frame.initParams(s); + frame.init(); + initAdapters(); + frame.start(); + } + +}// class + +/* A class that invoke appropriate verification + * routine with current modifier. + */ +class CheckingModifierAdapter extends MouseAdapter{ + int modifier; + public CheckingModifierAdapter(int modifier){ + this.modifier = modifier; + } + + public void mousePressed(MouseEvent e) { + System.out.println("PRESSED "+e); + if (e.getButton() <= MouseEvent.BUTTON3) { + System.out.println("Standard button affected. Skip."); + } else { + MouseModifiersUnitTest_Extra.checkPressedModifiersTest(modifier, e); + } + } + public void mouseReleased(MouseEvent e) { + System.out.println("RELEASED "+e); + if (e.getButton() <= MouseEvent.BUTTON3) { + System.out.println("Standard button affected. Skip."); + } else { + MouseModifiersUnitTest_Extra.checkReleasedModifiersTest(modifier, e); + } + } + public void mouseClicked(MouseEvent e) { + System.out.println("CLICKED "+e); + if (e.getButton() <= MouseEvent.BUTTON3) { + System.out.println("Standard button affected. Skip."); + } else { + MouseModifiersUnitTest_Extra.checkClickedModifiersTest(modifier, e); + } + } +} +//Utility class that could report a message depending on current purpose of the test run +class MessageLogger{ + private static boolean debug; + + public static void setDebug(boolean d){ + debug = d; + log("Switch to "+ ((debug)?"debug":"trial") +" mode"); + } + + public static void log(String message){ + System.out.println(message); + } + + public static void reportError(String message){ + if (debug){ + System.out.println(message); + } else { + throw new RuntimeException(message); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,598 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that modifiers are correct for standard (1, 2, 3, wheel) mouse buttons + @author Andrei Dmitriev : area=awt.mouse + @run main MouseModifiersUnitTest_Standard + */ + +import java.awt.*; +import java.awt.event.*; +import java.util.HashMap; +import java.util.StringTokenizer; +import java.util.Vector; + +//the test verifies: +// 1) verifies that modifiers are correct for standard (1, 2, 3) mouse buttons +// TODO: 2) verifies that modifiers are correct for wheel +// TODO: 3) +// Case1. the test posts BUTTONx_MASK and verifies that paramString() contains correct modifiers and exModifiers +// Case2. the test posts BUTTONx_DOWN_MASK and verifies that paramString() contains correct modifiers and exModifiers +// Case3. the test posts getMaskForButton(n) and verifies that paramString() contains correct modifiers and exModifiers +// repeat all cases with SHIFT/ALT/CTRL modifiers verify that paramString() contains correct modifiers and exModifiers +// I'm verifying button, modifiers and extModifiers for now. + +public class MouseModifiersUnitTest_Standard { + static final int NONE = 0; + static final int SHIFT = 1; + static final int CTRL = 2; + static final int ALT = 3; + static boolean debug = true; //dump all errors (debug) or throw first(under jtreg) exception + static boolean autorun = false; //use robot or manual run + static int testModifier = NONE; + // static String testModifier = "NONE"; + static CheckingModifierAdapter adapterTest1; + static CheckingModifierAdapter adapterTest2; + static CheckingModifierAdapter adapterTest3; + static CheckingModifierAdapter adapterTest4; + static Frame f; + final static int [] mouseButtons = new int [] {MouseEvent.BUTTON1_MASK, MouseEvent.BUTTON2_MASK, MouseEvent.BUTTON3_MASK}; + // BUTTON1, 2, 3 press-release. + final static int [] modifiersStandardTestNONE = new int[] {MouseEvent.BUTTON1_MASK, MouseEvent.BUTTON1_MASK, MouseEvent.BUTTON1_MASK, + MouseEvent.BUTTON2_MASK, MouseEvent.BUTTON2_MASK, MouseEvent.BUTTON2_MASK, + MouseEvent.BUTTON3_MASK, MouseEvent.BUTTON3_MASK, MouseEvent.BUTTON3_MASK }; + final static int [] modifiersExStandardTestNONE = new int[] {MouseEvent.BUTTON1_DOWN_MASK, 0, 0, + MouseEvent.BUTTON2_DOWN_MASK, 0, 0, + MouseEvent.BUTTON3_DOWN_MASK, 0, 0}; + // BUTTON1, 2, 3 press-release with shift modifier + final static int [] modifiersStandardTestSHIFT = new int[] {MouseEvent.BUTTON1_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON1_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON1_MASK|InputEvent.SHIFT_MASK, + MouseEvent.BUTTON2_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON2_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON2_MASK|InputEvent.SHIFT_MASK, + MouseEvent.BUTTON3_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON3_MASK|InputEvent.SHIFT_MASK, MouseEvent.BUTTON3_MASK|InputEvent.SHIFT_MASK }; + final static int [] modifiersExStandardTestSHIFT = new int[] {MouseEvent.BUTTON1_DOWN_MASK|InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, + MouseEvent.BUTTON2_DOWN_MASK|InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, + MouseEvent.BUTTON3_DOWN_MASK|InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK, InputEvent.SHIFT_DOWN_MASK}; + // BUTTON1, 2, 3 press-release with CTRL modifier + final static int [] modifiersStandardTestCTRL = new int[] {MouseEvent.BUTTON1_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON1_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON1_MASK|InputEvent.CTRL_MASK, + MouseEvent.BUTTON2_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON2_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON2_MASK|InputEvent.CTRL_MASK, + MouseEvent.BUTTON3_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON3_MASK|InputEvent.CTRL_MASK, MouseEvent.BUTTON3_MASK|InputEvent.CTRL_MASK }; + final static int [] modifiersExStandardTestCTRL = new int[] {MouseEvent.BUTTON1_DOWN_MASK|InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, + MouseEvent.BUTTON2_DOWN_MASK|InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, + MouseEvent.BUTTON3_DOWN_MASK|InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK, InputEvent.CTRL_DOWN_MASK}; + + // BUTTON1, 2, 3 press-release with ALT modifier + final static int [] modifiersStandardTestALT = new int[] {MouseEvent.BUTTON1_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON1_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON1_MASK|InputEvent.ALT_MASK, + MouseEvent.BUTTON2_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON2_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON2_MASK|InputEvent.ALT_MASK, + MouseEvent.BUTTON3_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON3_MASK|InputEvent.ALT_MASK, MouseEvent.BUTTON3_MASK|InputEvent.ALT_MASK }; + final static int [] modifiersExStandardTestALT = new int[] {MouseEvent.BUTTON1_DOWN_MASK|InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK, + MouseEvent.BUTTON2_DOWN_MASK|InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK, + MouseEvent.BUTTON3_DOWN_MASK|InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK, InputEvent.ALT_DOWN_MASK}; + + static Robot robot; + + public static void main(String s[]){ + initParams(s); + initAdapters(); + f = new Frame(); + final int [] modifiers = {InputEvent.SHIFT_MASK, InputEvent.CTRL_MASK}; + final String [] modifierNames = {"InputEvent.SHIFT_MASK", "InputEvent.CTRL_MASK"}; + f.setLayout(new FlowLayout()); + f.addMouseWheelListener(new MouseWheelListener() { + public void mouseWheelMoved(MouseWheelEvent e) { + System.out.println("WHEEL "+e); + } + }); + f.setSize(300, 300); + f.setVisible(true); + + try { + robot = new Robot(); + robot.delay(500); + robot.mouseMove(f.getLocationOnScreen().x + f.getWidth()/2, f.getLocationOnScreen().y + f.getHeight()/2); + if (autorun) { + //testing buttons 1, 2, 3 only + testPlainButtons(); + robot.delay(500); + + //testing buttons 1, 2, 3 with SHIFT, CTRL, ALT keyboard modifiers + testButtonsWithShift(); + robot.delay(500); + + testButtonsWithControl(); + robot.delay(500); + + testButtonsWithAlt(); + robot.delay(500); + } else { + switch (testModifier){ + case SHIFT: + f.addMouseListener(adapterTest2); + break; + case CTRL: + f.addMouseListener(adapterTest3); + break; + case ALT: + f.addMouseListener(adapterTest4); + break; + default: //NONE inclusive + f.addMouseListener(adapterTest1); + } + } + } catch (Exception e){ + throw new RuntimeException("Test failed."); + } + + } + + public static void initAdapters(){ + adapterTest1 = new CheckingModifierAdapter(NONE); + adapterTest2 = new CheckingModifierAdapter(SHIFT); + adapterTest3 = new CheckingModifierAdapter(CTRL); + adapterTest4 = new CheckingModifierAdapter(ALT); + } + + /*======================================================================*/ + public static void checkPressedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardModifiers = getStandardArray(testModifier); + int [] curStandardExModifiers = getStandardExArray(testModifier); + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 1)*3; + // int index = (button - 4)*3; + dumpValues(button, modifiers, curStandardModifiers[index], modifiersEx, curStandardExModifiers[index]); + if (modifiers != curStandardModifiers[index]){ + if (debug){ + System.out.println("Test failed : Pressed. modifiers != modifiersStandard"); + } else { + throw new RuntimeException("Test failed : Pressed. modifiers != modifiersStandard"); + } + } + + if (modifiersEx != curStandardExModifiers[index]){ +// System.out.println(">>>>>>>>>>>>>>> Pressed. modifiersEx "+modifiersEx +" : "+!= curStandardExModifiers"); + if (debug){ + System.out.println("Test failed : Pressed. modifiersEx != curStandardExModifiers"); + } else { + throw new RuntimeException("Test failed : Pressed. modifiersEx != curStandardExModifiers"); + } + } + HashMap <String, String> paramStringElements = tokenizeParamString(event.paramString()); + System.out.println(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + checkExtModifiersOnPress(testModifier, paramStringElements, button); + } + + public static void checkButton(HashMap<String, String> h, int button){ + if (h.get("button") == null) { + throw new RuntimeException("Test failed : Clicked. button is absent in paramString()"); + } + if (Integer.parseInt(h.get("button")) != button) { + throw new RuntimeException("Test failed : Clicked. button in paramString() doesn't equal to button being pressed."); + } + } + + public static void checkExtModifiersOnPress(int testModifier, HashMap h, int button){ + String ethalon = ""; + if (h.get("extModifiers") == null) { + System.out.println("Test failed : Pressed. extModifiers == null"); + throw new RuntimeException("Test failed : Pressed. extModifiers == null"); + } + switch (testModifier){ + case SHIFT:{ + ethalon = "Shift+"; + break; + } + case ALT:{ + ethalon = "Alt+"; + break; + } + case CTRL:{ + ethalon = "Ctrl+"; + break; + } + default: { + ethalon = ""; + } + ethalon = ethalon + "Button" +button; + + if (!h.get("extModifiers").equals(ethalon)) { + System.out.println("Test failed : Pressed. extModifiers = " +h.get("extModifiers")+" instead of : "+ethalon); + throw new RuntimeException("Test failed : Pressed. extModifiers = " +h.get("extModifiers")+" instead of : "+ethalon); + } + } + } + + + + public static void checkModifiers(int testModifier, HashMap<String, String> h, int button){ + // none of modifiers should be null + if (h.get("modifiers") == null) { + System.out.println("Test failed : modifiers == null"); + throw new RuntimeException("Test failed : modifiers == null"); + } + Vector <String> modifierElements = tokenizeModifiers(h.get("modifiers")); + //check that ButtonX is there + String buttonEthalon = "Button" + button; + if (modifierElements.contains(buttonEthalon)){ + modifierElements.remove(buttonEthalon); + } else { + System.out.println("Test failed : modifiers doesn't contain Button "+h.get("modifiers")); + throw new RuntimeException("Test failed : modifiers doesn't contain Button "+h.get("modifiers")); + } + + + //Check all explicitly pressed modifires +// boolean altIncluded = false; //don't duplicate Alt when ALT is pressed and BUTTON2_MASK. + String excplicitModifier = ""; + boolean altIncluded = false; + switch (testModifier){ + case SHIFT:{ + excplicitModifier = "Shift"; + break; + } + case ALT:{ + excplicitModifier = "Alt"; + altIncluded = true; //there should be only on "Alt" for two modifiers. So check it. + break; + } + case CTRL:{ + excplicitModifier = "Ctrl"; + break; + } + } + if (!excplicitModifier.equals("")){ + if (modifierElements.contains(excplicitModifier)){ + modifierElements.remove(excplicitModifier); + } else { + System.out.println("Test failed : modifiers doesn't contain explicit modifier "+excplicitModifier + " in "+ h.get("modifiers")); + throw new RuntimeException("Test failed : modifiers doesn't contain explicit modifier "+excplicitModifier + " in "+ h.get("modifiers")); + } + } + + //Button 2 and 3 reports about Alt+Button2 and Meta+Button3 respectively. + //Check these values too + String extraModifiers = ""; + String extraModifiersButton3 = ""; + switch (button){ + //BUTTON1 with ALT reports about Alt+Button1+Button2. + //We should fix this but I would not change this. + case 1: { + //Alt+Button1+Button2: + // 1) we already handled "Alt" in excplicitModifier + // 2) we already took "Button1" in buttonEthalon + // 3) so "Button2" is only remained. + // This should only happen when ALT+Button1 is pressed + if (altIncluded){ + extraModifiers = "Button2"; + } + break; + } + case 2: { + //Alt+Button2 report about "Alt+Button2". + extraModifiers = "Alt"; + break; + } + case 3: { + //ALT+BUTTON3 reports about "Alt+Meta+Button2+Button3" + // This should only happen when ALT+Button3 is pressed + extraModifiers = "Meta"; + if (altIncluded){ + extraModifiersButton3 = "Button2"; + } + break; + } + }//switch + + if (!extraModifiers.equals("")){ + if (modifierElements.contains(extraModifiers)){ + modifierElements.remove(extraModifiers); + } else { + //we may already removed "Alt" when filtered explicit modifiers. + //Here is no failure in this case. + if (!altIncluded) { + System.out.println("Test failed : modifiers doesn't contain a modifier from BUTTON2 or BUTTON3 "+extraModifiers + " in "+ h.get("modifiers")); + throw new RuntimeException("Test failed : modifiers doesn't contain a modifier from BUTTON2 or BUTTON3 "+extraModifiers + " in "+ h.get("modifiers")); + } + } + } + + if (!extraModifiersButton3.equals("")){ + if (modifierElements.contains(extraModifiersButton3)){ + modifierElements.remove(extraModifiersButton3); + } else { + System.out.println("Test failed : modifiers doesn't contain a modifier from BUTTON2 or BUTTON3 "+extraModifiersButton3 + " in "+ h.get("modifiers")); + throw new RuntimeException("Test failed : modifiers doesn't contain a modifier from BUTTON2 or BUTTON3 "+extraModifiersButton3 + " in "+ h.get("modifiers")); + } + } + + //the length of vector should now be zero + if (!modifierElements.isEmpty()){ + System.out.println("Test failed : there is some more elements in modifiers that shouldn't be there: "+h.get("modifiers")); + throw new RuntimeException("Test failed : there is some more elements in modifiers that shouldn't be there: "+h.get("modifiers")); + } + } + + public static void checkExtModifiersOnReleaseClick(int testModifier, HashMap h, int button){ + String ethalon = ""; + switch (testModifier){ + case SHIFT:{ + ethalon = "Shift+"; + break; + } + case ALT:{ + ethalon = "Alt+"; + break; + } + case CTRL:{ + ethalon = "Ctrl+"; + break; + } + default: { + if (h.get("extModifiers") != null) { + System.out.println("Test failed : Released. extModifiers != null but no modifiers keys are pressed"); + throw new RuntimeException("Test failed : Released. extModifiers != null but no modifiers keys are pressed"); + } else { + //no modifiers + return; + } + } + } + if (h.get("extModifiers").equals(ethalon)) { + System.out.println("Test failed : Released. extModifiers = "+ h.get("extModifiers") +" instead of : "+ethalon); + throw new RuntimeException("Test failed : Released. extModifiers = "+ h.get("extModifiers") +" instead of : "+ethalon); + } + } + + public static void checkReleasedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardModifiers = getStandardArray(testModifier); + int [] curStandardExModifiers = getStandardExArray(testModifier); + // int index = (button - 4)*3 + 1; + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 1)*3 + 1; + dumpValues(button, modifiers, curStandardModifiers[index], modifiersEx, curStandardExModifiers[index]); + if (modifiers != curStandardModifiers[index]){ + if (debug){ + System.out.println("Test failed : Released. modifiers != modifiersStandard"); + } else { + throw new RuntimeException("Test failed : Released. modifiers != modifiersStandard"); + } + } + if (modifiersEx != curStandardExModifiers[index]){ + if (debug){ + System.out.println("Test failed : Released. modifiersEx != curStandardExModifiers"); + } else { + throw new RuntimeException("Test failed : Released. modifiersEx != curStandardExModifiers"); + } + } + HashMap <String, String> paramStringElements = tokenizeParamString(event.paramString()); + System.out.println(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + checkExtModifiersOnReleaseClick(testModifier, paramStringElements, button); + } + + public static void checkClickedModifiersTest(int testModifier, MouseEvent event){ + int [] curStandardModifiers = getStandardArray(testModifier); + int [] curStandardExModifiers = getStandardExArray(testModifier); + // int index = (button - 4)*3 + 2; + int button = event.getButton(); + int modifiers = event.getModifiers(); + int modifiersEx = event.getModifiersEx(); + int index = (button - 1)*3 + 2; + dumpValues(button, modifiers, curStandardModifiers[index], modifiersEx, curStandardExModifiers[index]); + if (modifiers != curStandardModifiers[index]){ + if (debug){ + System.out.println("Test failed : Clicked. modifiers != modifiersStandard"); + } else { + throw new RuntimeException("Test failed : Clicked. modifiers != modifiersStandard"); + } + } + if (modifiersEx != curStandardExModifiers[index]){ + if (debug){ + System.out.println("Test failed : Clicked. modifiersEx != curStandardExModifiers"); + } else { + throw new RuntimeException("Test failed : Clicked. modifiersEx != curStandardExModifiers"); + } + } + HashMap <String, String> paramStringElements = tokenizeParamString(event.paramString()); + checkButton(paramStringElements, button); + checkModifiers(testModifier, paramStringElements, button); + checkExtModifiersOnReleaseClick(testModifier, paramStringElements, button); + } + /*======================================================================*/ + + public static HashMap<String, String> tokenizeParamString(String param){ + HashMap <String, String> params = new HashMap<String, String>(); + StringTokenizer st = new StringTokenizer(param, ",="); + while (st.hasMoreTokens()){ + String tmp = st.nextToken(); +// System.out.println("PARSER : "+tmp); + if (tmp.equals("button") || + tmp.equals("modifiers") || + tmp.equals("extModifiers")) { + params.put(tmp, st.nextToken()); + } + } + return params; + } + + public static Vector<String> tokenizeModifiers(String modifierList){ + Vector<String> modifiers = new Vector<String>(); + StringTokenizer st = new StringTokenizer(modifierList, "+"); + while (st.hasMoreTokens()){ + String tmp = st.nextToken(); + modifiers.addElement(tmp); + System.out.println("MODIFIER PARSER : "+tmp); + } + return modifiers; + } + + + //test BUTTON1, 2 and 3 without any modifiers keys + public static void testPlainButtons(){ + System.out.println("Testing buttons without modifiers."); + f.addMouseListener(adapterTest1); + for (int button : mouseButtons){ + robot.mousePress(button); + robot.delay(100); + robot.mouseRelease(button); + } + robot.delay(1000); + f.removeMouseListener(adapterTest1); + } + + //test BUTTON1, 2 and 3 with SHIFT key + public static void testButtonsWithShift(){ + System.out.println("Testing buttons with SHIFT modifier."); + f.addMouseListener(adapterTest2); + + for (int button : mouseButtons){ + robot.keyPress(KeyEvent.VK_SHIFT); + robot.mousePress(button); + robot.delay(100); + robot.mouseRelease(button); + robot.keyRelease(KeyEvent.VK_SHIFT); + } + robot.delay(1000); + f.removeMouseListener(adapterTest2); + } + + //test BUTTON1, 2 and 3 with CTRL key + public static void testButtonsWithControl(){ + System.out.println("Testing buttons with CONTROL modifier."); + f.addMouseListener(adapterTest3); + for (int button : mouseButtons){ + robot.keyPress(KeyEvent.VK_CONTROL); + robot.mousePress(button); + robot.delay(100); + robot.mouseRelease(button); + robot.keyRelease(KeyEvent.VK_CONTROL); + } + robot.delay(1000); + f.removeMouseListener(adapterTest3); + } + + //test BUTTON1, 2 and 3 with ALT key + public static void testButtonsWithAlt(){ + System.out.println("Testing buttons with ALT modifier."); + f.addMouseListener(adapterTest4); + for (int button : mouseButtons){ + robot.keyPress(KeyEvent.VK_ALT); + robot.mousePress(button); + robot.delay(100); + robot.mouseRelease(button); + robot.keyRelease(KeyEvent.VK_ALT); + } + robot.delay(1000); + f.removeMouseListener(adapterTest4); + } + + public static void initParams(String []s){ + if (s.length != 3){ + autorun = true; + debug = false; + testModifier = NONE; + } else { + autorun = Boolean.valueOf(s[0]); + debug = Boolean.valueOf(s[1]); + + if (s[2].equals("NONE")){ + testModifier = NONE; + } + if (s[2].equals("SHIFT")){ + testModifier = SHIFT; + } + if (s[2].equals("CTRL")){ + testModifier = CTRL; + } + if (s[2].equals("ALT")){ + testModifier = ALT; + } + } + System.out.println("Autorun : " +autorun); + System.out.println("Debug mode : " +debug); + System.out.println("Modifier to verify : " + testModifier); + } + + public static void dumpValues(int button, int modifiers, int modifiersStandard, int modifiersEx, int modifiersExStandard){ + System.out.println("Button = "+button + "Modifiers = "+ modifiers + " standard = "+ modifiersStandard); + System.out.println(" ModifiersEx = "+ modifiersEx + " standardEx = "+ modifiersExStandard); + } + + private static int[] getStandardExArray(int testModifier) { + int [] curStandardExModifiers; + switch (testModifier){ + case SHIFT: + curStandardExModifiers = modifiersExStandardTestSHIFT; + break; + case CTRL: + curStandardExModifiers = modifiersExStandardTestCTRL; + break; + case ALT: + curStandardExModifiers = modifiersExStandardTestALT; + break; + default: //NONE by default + curStandardExModifiers = modifiersExStandardTestNONE; + } + return curStandardExModifiers; + } + + private static int[] getStandardArray(int testModifier) { + int [] curStandardModifiers; + switch (testModifier){ + case SHIFT: + curStandardModifiers = modifiersStandardTestSHIFT; + break; + case CTRL: + curStandardModifiers = modifiersStandardTestCTRL; + break; + case ALT: + curStandardModifiers = modifiersStandardTestALT; + break; + default: //NONE by default + curStandardModifiers = modifiersStandardTestNONE; + } + return curStandardModifiers; + } + +} + + +/* A class that invoke appropriate verification + * routine with current modifier. + */ +class CheckingModifierAdapter extends MouseAdapter{ + int modifier; + public CheckingModifierAdapter(int modifier){ + this.modifier = modifier; + } + + public void mousePressed(MouseEvent e) { + System.out.println("PRESSED "+e); + if (e.getButton() > MouseEvent.BUTTON3) { + System.out.println("Extra button affected. Skip."); + } else { + MouseModifiersUnitTest_Standard.checkPressedModifiersTest(modifier, e); // e.getButton(), e.getModifiers(), e.getModifiersEx(), + } + } + public void mouseReleased(MouseEvent e) { + System.out.println("RELEASED "+e); + if (e.getButton() > MouseEvent.BUTTON3) { + System.out.println("Extra button affected. Skip."); + } else { + MouseModifiersUnitTest_Standard.checkReleasedModifiersTest(modifier, e); // e.getButton(), e.getModifiers(), e.getModifiersEx() + } + } + public void mouseClicked(MouseEvent e) { + System.out.println("CLICKED "+e); + if (e.getButton() > MouseEvent.BUTTON3) { + System.out.println("Extra button affected. Skip."); + } else { + MouseModifiersUnitTest_Standard.checkClickedModifiersTest(modifier, e); //e.getButton(), e.getModifiers(), e.getModifiersEx() + } + } +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,118 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that Robot is accepting extra mouse buttons + @author Andrei Dmitriev : area=awt.mouse + @library ../../regtesthelpers + @build Util + @run main AcceptExtraMouseButtons + */ + +//if we do robot.mousePress(InputEvent.BUTTON1_DOWN_MASK) the test must +// 1) accept it (i.e. don't throw an IllegalArgumentException +// 2) actually post a MouseEvent +// Also, Robot should still accept InputEvent.BUTTONx_MASKs + +import java.awt.*; +import java.awt.event.*; +import sun.awt.SunToolkit; +import test.java.awt.regtesthelpers.Util; + +public class AcceptExtraMouseButtons extends Frame { + static String tk = Toolkit.getDefaultToolkit().getClass().getName(); + static Robot robot; + static int [] standardButtonMasks = {InputEvent.BUTTON1_MASK, + InputEvent.BUTTON2_MASK, + InputEvent.BUTTON3_MASK}; + static int [] buttonsPressed; + static int [] buttonsReleased; + static int [] buttonsClicked; + + static int buttonsNum = MouseInfo.getNumberOfButtons(); + + public static void main(String []s){ + + //MouseInfo.getNumberOfButtons() reports two more buttons on XToolkit + //as they reserved for wheel (both directions). + if (tk.equals("sun.awt.X11.XToolkit") || tk.equals("sun.awt.motif.MToolkit")) { + buttonsNum = buttonsNum - 2; + } + System.out.println("Number Of Buttons = "+ buttonsNum); + if (buttonsNum < 3) { + System.out.println("Linux and Windows systems should emulate three buttons if even there are only 1 or 2 are phsically available. Setting number of buttons to 3."); + buttonsNum = 3; + } + + buttonsPressed = new int [buttonsNum]; + buttonsReleased = new int [buttonsNum]; + buttonsClicked = new int [buttonsNum]; + + AcceptExtraMouseButtons frame = new AcceptExtraMouseButtons(); + + MouseAdapter ma1 = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + buttonsPressed[e.getButton() - 1] += 1; + System.out.println("PRESSED "+e); + } + public void mouseReleased(MouseEvent e) { + buttonsReleased[e.getButton() - 1] += 1; + System.out.println("RELEASED "+e); + } + public void mouseClicked(MouseEvent e) { + buttonsClicked[e.getButton() - 1] += 1; + System.out.println("CLICKED "+e); + } + }; + frame.addMouseListener(ma1); + + frame.setSize(300, 300); + frame.setVisible(true); + + Util.waitForIdle(robot); //a time to show a Frame + + try { + robot = new Robot(); + robot.delay(1000); + robot.mouseMove(frame.getLocationOnScreen().x + frame.getWidth()/2, + frame.getLocationOnScreen().y + frame.getHeight()/2); + + //TestCase 1: verify that all BUTTONx_DOWN_MASKs are accepted by the Robot. + + for (int i = 0; i < buttonsNum; i++){ + int buttonMask = InputEvent.getMaskForButton(i+1); + System.out.println("button to press = " +(i+1) + " : value passed to robot = " +buttonMask); + robot.mousePress(buttonMask); + robot.delay(30); + robot.mouseRelease(buttonMask); + Util.waitForIdle(robot); + } + for (int i = 0; i < buttonsNum; i++){ + if (buttonsPressed[i] != 1 || buttonsReleased[i] != 1 || buttonsClicked[i] !=1 ) { + throw new RuntimeException("TESTCASE 1 FAILED : button " + (i+1) + " wasn't single pressed|released|clicked : "+ buttonsPressed[i] +" : "+ buttonsReleased[i] +" : "+ buttonsClicked[i]); + } + } + + java.util.Arrays.fill(buttonsPressed, 0); + java.util.Arrays.fill(buttonsReleased, 0); + java.util.Arrays.fill(buttonsClicked, 0); + //TestCase 2: verify that all BUTTONx_MASKs are accepted by the Robot. + for (int i = 0; i < standardButtonMasks.length; i++){ + int buttonMask = standardButtonMasks[i]; + System.out.println("button to press = " +(i+1) + " : value passed to robot = " +buttonMask); + robot.mousePress(buttonMask); + robot.delay(30); + robot.mouseRelease(buttonMask); + Util.waitForIdle(robot); + } + for (int i = 0; i < standardButtonMasks.length; i++){ + if (buttonsPressed[i] != 1 || buttonsReleased[i] != 1 || buttonsClicked[i] !=1 ) { + throw new RuntimeException("TESTCASE 2 FAILED : button " + (i+1) + " wasn't single pressed|released|clicked : "+ buttonsPressed[i] +" : "+ buttonsReleased[i] +" : "+ buttonsClicked[i]); + } + } + + } catch (Exception e){ + e.printStackTrace(); + throw new RuntimeException(e); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Robot/ManualInstructions/ManualInstructions.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,305 @@ +/* + test %W% %E% %I%, %G% + @bug 6315717 + @summary manual control over the Robot + @author Andrei Dmitriev : area=awt.robot + @run applet/manual=yesno ManualInstructions.html +*/ + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; +import java.util.Timer; +import java.util.TimerTask; + +public class ManualInstructions extends Applet +{ + final static long SEND_DELAY = 1000; + + public static void main(String s[]){ + ManualInstructions mi = new ManualInstructions(); + mi.init(); + mi.start(); + } + + static Robot robot; + Point mouseLocation; //where mouse should be pressed each time + Panel target = new Panel(); + Button pressOn = new Button("press on ..."); + Button releaseOn = new Button("release on ..."); + Button clickOn = new Button("click on ..."); + Choice buttonNumber = new Choice(); + + public void init() + { + try { + robot = new Robot(); + } catch (AWTException ex) { + ex.printStackTrace(); + throw new RuntimeException(ex); + } + this.setLayout (new BorderLayout ()); + + target.setBackground(Color.green); + target.setName("GreenBox");//for the ease of debug + target.setPreferredSize(new Dimension(100, 100)); + String toolkit = Toolkit.getDefaultToolkit().getClass().getName(); + + // on X systems two buttons are reserved for wheel though they are countable by MouseInfo. + int buttonsNumber = toolkit.equals("sun.awt.windows.WToolkit")?MouseInfo.getNumberOfButtons():MouseInfo.getNumberOfButtons()-2; + + for (int i = 0; i < 8; i++){ + buttonNumber.add("BUTTON"+(i+1)+"_MASK"); + } + + pressOn.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e){ + System.out.println("Now pressing : " + (buttonNumber.getSelectedIndex()+1)); + + Timer timer = new Timer(); + TimerTask robotInteraction = new TimerTask(){ + public void run(){ + robot.mouseMove(updateTargetLocation().x, updateTargetLocation().y); + robot.mousePress(getMask(buttonNumber.getSelectedIndex()+1)); + } + }; + timer.schedule(robotInteraction, SEND_DELAY); + } + }); + + releaseOn.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e){ + System.out.println("Now releasing : " + (buttonNumber.getSelectedIndex()+1)); + Timer timer = new Timer(); + TimerTask robotInteraction = new TimerTask(){ + public void run(){ + robot.mouseMove(updateTargetLocation().x, updateTargetLocation().y); + robot.mouseRelease(getMask(buttonNumber.getSelectedIndex()+1)); + } + }; + timer.schedule(robotInteraction, SEND_DELAY); + } + }); + + clickOn.addActionListener(new ActionListener(){ + public void actionPerformed(ActionEvent e){ + System.out.println("Now clicking : " + (buttonNumber.getSelectedIndex()+1)); + Timer timer = new Timer(); + TimerTask robotInteraction = new TimerTask(){ + public void run(){ + robot.mouseMove(updateTargetLocation().x, updateTargetLocation().y); + robot.mousePress(getMask(buttonNumber.getSelectedIndex()+1)); + robot.mouseRelease(getMask(buttonNumber.getSelectedIndex()+1)); + } + }; + timer.schedule(robotInteraction, SEND_DELAY); + } + + }); + target.addMouseListener(new MouseAdapter(){ + public void mousePressed(MouseEvent e){ + Sysout.println(""+e); + } + public void mouseReleased(MouseEvent e){ + Sysout.println(""+e); + } + public void mouseClicked(MouseEvent e){ + Sysout.println(""+e); + } + }); + + String[] instructions = + { + "Do provide an instruction to the robot by", + "choosing the button number to act and ", + "pressing appropriate java.awt.Button on the left.", + "Inspect an output in the TextArea below.", + "Please don't generate non-natural sequences like Release-Release, etc.", + "If you use keyboard be sure that you released the keyboard shortly.", + "If events are generated well press Pass, otherwise Fail." + }; + Sysout.createDialogWithInstructions( instructions ); + + }//End init() + + private int getMask(int button){ + return InputEvent.getMaskForButton(button); + + /* + //this only works for standard buttons and for old JDK builds + int mask = 0; + switch (button){ + case 1: { + mask = InputEvent.BUTTON1_MASK; + break; + } + case 2: { + mask = InputEvent.BUTTON2_MASK; + break; + } + case 3: { + mask = InputEvent.BUTTON3_MASK; + break; + } + } + return mask; + */ + } + + private Point updateTargetLocation() { + return new Point(target.getLocationOnScreen().x + target.getWidth()/2, target.getLocationOnScreen().y + target.getHeight()/2); + } + + public void start () + { + //Get things going. Request focus, set size, et cetera + setSize (200,200); + setVisible(true); + validate(); + Frame f = new Frame ("Set action for Robot here."); + f.setLayout(new FlowLayout()); + f.add(buttonNumber); + f.add(pressOn); + f.add(releaseOn); + f.add(clickOn); + f.add(target); + f.pack(); + f.setVisible(true); + }// start() +}// class + +/* Place other classes related to the test after this line */ + + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } + +}// Sysout class + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 120; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + }// while + }// for + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } + +}// TestDialog class
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Robot/RobotExtraButton/RobotExtraButton.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,79 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that robot could accept extra buttons + @author Andrei Dmitriev : area=awt.mouse + @library ../../regtesthelpers + @build Util + @run main RobotExtraButton + */ + +import java.awt.*; +import java.awt.event.*; +import test.java.awt.regtesthelpers.Util; + +public class RobotExtraButton extends Frame { + static Robot robot; + public static void main(String []s){ + RobotExtraButton frame = new RobotExtraButton(); + frame.setSize(300, 300); + frame.setVisible(true); + frame.addMouseListener(new MouseAdapter() { + public void mousePressed(MouseEvent e) { + System.out.println("PRESSED "+e); + } + public void mouseReleased(MouseEvent e) { + System.out.println("RELEASED "+e); + } + public void mouseClicked(MouseEvent e) { + System.out.println("CLICKED "+e); + } + }); + Util.waitForIdle(robot); + int [] buttonMask = new int[MouseInfo.getNumberOfButtons()]; // = InputEvent.getButtonDownMasks(); + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonMask[i] = InputEvent.getMaskForButton(i+1); + System.out.println("TEST: "+buttonMask[i]); + } + + try { + robot = new Robot(); + robot.mouseMove(frame.getLocationOnScreen().x + frame.getWidth()/2, frame.getLocationOnScreen().y + frame.getHeight()/2); + /* + if (MouseInfo.getNumberOfButtons() <= 3) { + System.out.println("Number Of Buttons = "+ MouseInfo.getNumberOfButtons() +". Finish!"); + return; + }*/ + + System.out.println("TEST: press 1"); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + Util.waitForIdle(robot); + + System.out.println("TEST: press 2"); + + robot.mousePress(InputEvent.BUTTON2_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON2_MASK); + Util.waitForIdle(robot); + System.out.println("TEST: press 3"); + + robot.mousePress(InputEvent.BUTTON3_MASK); + robot.delay(50); + robot.mouseRelease(InputEvent.BUTTON3_MASK); + Util.waitForIdle(robot); + System.out.println("--------------------------------------------------"); + for (int i = 0; i < buttonMask.length; i++){ + System.out.println("button would = " +i + " : value = " +buttonMask[i]); + robot.mousePress(buttonMask[i]); + robot.delay(50); + robot.mouseRelease(buttonMask[i]); + Util.waitForIdle(robot); + } + } catch (Exception e){ + e.printStackTrace(); + throw new RuntimeException("Test failed.", e); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_1.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,36 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that system property sun.awt.enableExtraMouseButtons is true by default + @author Andrei Dmitriev : area=awt.mouse + @run main SystemPropTest_1 + */ +//1) Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns false initially. +//2) Verifies that Toolkit.areExtraMouseButtonsEnabled() returns true by default. +// This must initlizes the Toolkit class. +//3) Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns true (default). +import java.awt.*; + +public class SystemPropTest_1 { + + public static void main(String []s){ + boolean propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + System.out.println("1. System.getProperty = " + propValue); + if (propValue){ + throw new RuntimeException("TEST FAILED(1) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED : Toolkit.areExtraMouseButtonsEnabled() returns false"); + } + + System.getProperties().list(System.out); + System.out.println("XXXX. System.getProperty = " + System.getProperty("sun.awt.enableExtraMouseButtons")); + + propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + System.out.println("2. System.getProperty = " + propValue); + if (!propValue){ + throw new RuntimeException("TEST FAILED(2) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + System.out.println("Test passed."); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_2.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,25 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that system property sun.awt.enableExtraMouseButtons might be set to true by the command line + @author Andrei Dmitriev : area=awt.mouse + @run main/othervm -Dsun.awt.enableExtraMouseButtons=true SystemPropTest_2 + */ +//1) Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns true if set through the command line. +//2) Verifies that Toolkit.areExtraMouseButtonsEnabled() returns true if the proprty is set through the command line. +import java.awt.*; + +public class SystemPropTest_2 { + + public static void main(String []s){ + boolean propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + System.out.println("System.getProperty = " + propValue); + if (!propValue){ + throw new RuntimeException("TEST FAILED : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED : Toolkit.areExtraMouseButtonsEnabled() returns false"); + } + System.out.println("Test passed."); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_3.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,26 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that system property sun.awt.enableExtraMouseButtons might be set to false by the command line + @author Andrei Dmitriev : area=awt.mouse + @run main/othervm -Dsun.awt.enableExtraMouseButtons=false SystemPropTest_3 + */ +//1) Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns false if set through the command line. +//2) Verifies that Toolkit.areExtraMouseButtonsEnabled() returns false if the proprty is set through the command line. +import java.awt.*; + +public class SystemPropTest_3 { + + public static void main(String []s){ + boolean propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + System.out.println("Test System.getProperty = " + System.getProperty("sun.awt.enableExtraMouseButtons")); + System.out.println("System.getProperty = " + propValue); + if (propValue){ + throw new RuntimeException("TEST FAILED : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED : Toolkit.areExtraMouseButtonsEnabled() returns true"); + } + System.out.println("Test passed."); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_4.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,42 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that system property sun.awt.enableExtraMouseButtons might be set to true by the System class API. + @author Andrei Dmitriev : area=awt.mouse + @run main SystemPropTest_4 + */ +//1) +// - Use System.setProperty("sun.awt.enableExtraMouseButtons", "true") +// - Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns true +// - Verifies that Toolkit.areExtraMouseButtonsEnabled() returns true. +//2) +// - Use System.setProperty("sun.awt.enableExtraMouseButtons", "false") +// - Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns false +// - Verifies that Toolkit.areExtraMouseButtonsEnabled() returns true still. + +import java.awt.*; + +public class SystemPropTest_4 { + public static void main(String []s){ + System.out.println("STAGE 1"); + System.setProperty("sun.awt.enableExtraMouseButtons", "true"); + boolean propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + if (!propValue){ + throw new RuntimeException("TEST FAILED(1) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED(1) : Toolkit.areExtraMouseButtonsEnabled() returns false"); + } + + System.out.println("STAGE 2"); + System.setProperty("sun.awt.enableExtraMouseButtons", "false"); + propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + if (propValue){ + throw new RuntimeException("TEST FAILED(2) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED(2) : Toolkit.areExtraMouseButtonsEnabled() returns false"); + } + System.out.println("Test passed."); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Toolkit/ToolkitPropertyTest/SystemPropTest_5.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,42 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that system property sun.awt.enableExtraMouseButtons might be set to false by the System class API. + @author Andrei Dmitriev : area=awt.mouse + @run main SystemPropTest_5 + */ +//1) +// - Use System.setProperty("sun.awt.enableExtraMouseButtons", "false") +// - Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns false +// - Verifies that Toolkit.areExtraMouseButtonsEnabled() returns false. +//2) +// - Use System.setProperty("sun.awt.enableExtraMouseButtons", "true") +// - Verifies that System.getProperty("sun.awt.enableExtraMouseButtons") returns true +// - Verifies that Toolkit.areExtraMouseButtonsEnabled() returns false still. + +import java.awt.*; + +public class SystemPropTest_5 { + public static void main(String []s){ + System.out.println("STAGE 1"); + System.setProperty("sun.awt.enableExtraMouseButtons", "false"); + boolean propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + if (propValue){ + throw new RuntimeException("TEST FAILED(1) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED(1) : Toolkit.areExtraMouseButtonsEnabled() returns true"); + } + + System.out.println("STAGE 2"); + System.setProperty("sun.awt.enableExtraMouseButtons", "true"); + propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + if (!propValue){ + throw new RuntimeException("TEST FAILED(2) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ + throw new RuntimeException("TEST FAILED(2) : Toolkit.areExtraMouseButtonsEnabled() returns true"); + } + System.out.println("Test passed."); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Disable.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,143 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that sun.awt.enableExtraMouseButtons = false consumes extra events + @author Andrei Dmitriev : area=awt.mouse + @run main/othervm -Dsun.awt.enableExtraMouseButtons=false ToolkitPropertyTest_Disable + */ + +import java.awt.*; +import java.awt.event.*; + +// Testcase 1: set to FALSE and check +// Testcase 2: set to FALSE and check that extra events are not coming +// check that standard events are coming + +public class ToolkitPropertyTest_Disable extends Frame { + static boolean propValue; + static Robot robot; + static int [] buttonsPressed; + static int [] buttonsReleased; + static int [] buttonsClicked; + + static boolean lessThenFourButtons; + + public static void main(String []s){ + propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + buttonsPressed = new int [MouseInfo.getNumberOfButtons()]; + buttonsReleased = new int [MouseInfo.getNumberOfButtons()]; + buttonsClicked = new int [MouseInfo.getNumberOfButtons()]; + + ToolkitPropertyTest_Disable frame = new ToolkitPropertyTest_Disable(); + frame.setSize(300, 300); + frame.setVisible(true); + + MouseAdapter ma1 = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + buttonsPressed[e.getButton() - 1] += 1; + System.out.println("PRESSED "+e); + } + public void mouseReleased(MouseEvent e) { + buttonsReleased[e.getButton() - 1] += 1; + System.out.println("RELEASED "+e); + } + public void mouseClicked(MouseEvent e) { + buttonsClicked[e.getButton() - 1] += 1; + System.out.println("CLICKED "+e); + } + }; + + try { + robot = new Robot(); + robot.delay(1000); + robot.mouseMove(frame.getLocationOnScreen().x + frame.getWidth()/2, frame.getLocationOnScreen().y + frame.getHeight()/2); + + System.out.println("Property = " + propValue); + testCase0(); + + testCase1(); + System.out.println("Number Of Buttons = "+ MouseInfo.getNumberOfButtons()); + + lessThenFourButtons = (MouseInfo.getNumberOfButtons() <= 3); + if ( !lessThenFourButtons ) { + frame.addMouseListener(ma1); + testCase2(); + } + } catch (Exception e){ + e.printStackTrace(); +// throw new RuntimeException(e); + } finally { +// frame.removeMouseListener(ma1); + } + } + + public static void testCase0(){ + if (propValue){ + throw new RuntimeException("TEST FAILED (0): System property sun.awt.enableExtraMouseButtons = " + propValue); + } + } + + public static void testCase1(){ + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled() == true){ + throw new RuntimeException("TEST FAILED (1): setting to FALSE. Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled() = " + Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()); + } + } + + public static void testCase2(){ + emptyArrays(); + int [] buttonMasks = new int[MouseInfo.getNumberOfButtons()]; // = InputEvent.getButtonDownMasks(); + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonMasks[i] = InputEvent.getMaskForButton(i+1); + System.out.println("TEST: "+buttonMasks[i]); + } + + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + System.out.println("button to press = " +(i+1) + " : value passed to robot = " +buttonMasks[i]); + try { + robot.mousePress(buttonMasks[i]); + robot.delay(70); + robot.mouseRelease(buttonMasks[i]); + robot.delay(200); + //no exception is thrown + if (i >= 3) { + throw new RuntimeException("TESTCASE 2 FAILED : robot accepted the extra button " + (i+1) + " instead of throwing an exception."); + } + } catch (IllegalArgumentException e){ + if (i >= 3) { + System.out.println("Passed: an exception caught for extra button."); + } else { + throw new RuntimeException("TESTCASE 2 FAILED : exception happen on standard button.", e); + } + } + } + robot.delay(2000); + if (MouseInfo.getNumberOfButtons() < 3) { + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + if (buttonsPressed[i] != 1 || buttonsReleased[i] != 1 || buttonsClicked[i] !=1 ) { + throw new RuntimeException("TESTCASE 2 FAILED : button " + (i+1) + " wasn't single pressed."); + } + } + } else { + for (int i = 0; i < 3; i++){ + if (buttonsPressed[i] != 1 || buttonsReleased[i] != 1 || buttonsClicked[i] !=1 ) { + throw new RuntimeException("TESTCASE 2 FAILED : button " + (i+1) + " wasn't single pressed."); + } + } + + for (int i = 3; i < MouseInfo.getNumberOfButtons(); i++){ + if (buttonsPressed[i] != 0 || buttonsReleased[i] != 0 || buttonsClicked[i] != 0 ) { + throw new RuntimeException("TESTCASE 2 FAILED : button " + (i+1) + " was pressed."); + } + } + } + } + + public static void emptyArrays(){ + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonsPressed[i] = 0; + buttonsReleased[i] = 0; + buttonsClicked[i] = 0; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,120 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that sun.awt.enableExtraMouseButtons is working + @author Andrei Dmitriev : area=awt.mouse + @run main/othervm -Dsun.awt.enableExtraMouseButtons=true ToolkitPropertyTest_Enable + */ + +import java.awt.*; +import java.awt.event.*; + +// Testcase 1: set to TRUE (via jtreg option) +// Testcase 2: set to TRUE and check that extra events are coming +// check that standard events are coming + +public class ToolkitPropertyTest_Enable extends Frame { + static boolean propValue; + static Robot robot; + static int [] buttonsPressed; + static int [] buttonsReleased; + static int [] buttonsClicked; + + public static void main(String []s){ + propValue = Boolean.parseBoolean(System.getProperty("sun.awt.enableExtraMouseButtons")); + buttonsPressed = new int [MouseInfo.getNumberOfButtons()]; + buttonsReleased = new int [MouseInfo.getNumberOfButtons()]; + buttonsClicked = new int [MouseInfo.getNumberOfButtons()]; + + ToolkitPropertyTest_Enable frame = new ToolkitPropertyTest_Enable(); + frame.setSize(300, 300); + frame.setVisible(true); + + MouseAdapter ma1 = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + buttonsPressed[e.getButton() - 1] += 1; + System.out.println("PRESSED "+e); + } + public void mouseReleased(MouseEvent e) { + buttonsReleased[e.getButton() - 1] += 1; + System.out.println("RELEASED "+e); + } + public void mouseClicked(MouseEvent e) { + buttonsClicked[e.getButton() - 1] += 1; + System.out.println("CLICKED "+e); + } + }; + // frame.addMouseListener(ma1); + + try { + robot = new Robot(); + robot.delay(1000); + robot.mouseMove(frame.getLocationOnScreen().x + frame.getWidth()/2, frame.getLocationOnScreen().y + frame.getHeight()/2); + + System.out.println("Property = " + propValue); + testCase0(); + + testCase1(); + System.out.println("Number Of Buttons = "+ MouseInfo.getNumberOfButtons()); + + boolean lessThenFourButtons = (MouseInfo.getNumberOfButtons() <= 3); + if ( !lessThenFourButtons ) { + frame.addMouseListener(ma1); + testCase2(); + // testCase3(); + // testCase4(); + frame.removeMouseListener(ma1); + } + } catch (Exception e){ + e.printStackTrace(); + throw new RuntimeException(e); + } + + } + + public static void testCase0(){ + if (!propValue){ + throw new RuntimeException("TEST FAILED (0) : System property sun.awt.enableExtraMouseButtons = " + propValue); + } + } + + public static void testCase1(){ + if (Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled() == false){ + throw new RuntimeException("TEST FAILED (1) : setting to TRUE. enabled = " + Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()); + } + } + + public static void testCase2(){ + emptyArrays(); + //we can't post a message from an unexistent button + int [] buttonMasks = new int[MouseInfo.getNumberOfButtons()]; // = InputEvent.getButtonDownMasks(); + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonMasks[i] = InputEvent.getMaskForButton(i+1); + System.out.println("TEST: "+buttonMasks[i]); + } + + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + System.out.println("button to press = " +(i+1) + " : value passed to robot = " +buttonMasks[i]); + robot.mousePress(buttonMasks[i]); + robot.delay(70); + robot.mouseRelease(buttonMasks[i]); + robot.delay(200); + } + robot.delay(1000); + + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + if (buttonsPressed[i] != 1 || buttonsReleased[i] != 1 || buttonsClicked[i] !=1 ) { + throw new RuntimeException("TESTCASE 2 FAILED : button " + (i+1) + " wasn't single pressed|released|clicked : "+ buttonsPressed[i] +" : "+ buttonsReleased[i] +" : "+ buttonsClicked[i]); + } + } + } + + public static void emptyArrays(){ + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonsPressed[i] = 0; + buttonsReleased[i] = 0; + buttonsClicked[i] = 0; + } + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/event/InputEvent/ButtonArraysEquality/ButtonArraysEquality.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,83 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that InputEvents button masks arrays are the same + @author Andrei Dmitriev : area=awt.event + @run main ButtonArraysEquality + */ + +import java.awt.*; +import java.awt.event.*; +import java.lang.reflect.*; +import java.security.AccessController; +import java.security.PrivilegedAction; + +// get array InputEvent.BUTTON_MASK via reflection +// get array InputEvent.BUTTON_DOWN_MASK via reflection +// compare their lengths and values + +public class ButtonArraysEquality { + static int [] eventDownMask = new int []{InputEvent.BUTTON1_DOWN_MASK, InputEvent.BUTTON2_DOWN_MASK, InputEvent.BUTTON3_DOWN_MASK}; + + public static void main(String []s){ + int [] buttonDownMasksAPI = new int [MouseInfo.getNumberOfButtons()]; + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonDownMasksAPI[i] = InputEvent.getMaskForButton(i+1); + System.out.println("TEST: "+buttonDownMasksAPI[i]); + } + + // getButtonDownMasks() + Object obj = AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + try { + Class clazz = Class.forName("java.awt.event.InputEvent"); + Method method = clazz.getDeclaredMethod("getButtonDownMasks",new Class [] {}); + if (method != null) { + method.setAccessible(true); + return method.invoke(null, (Object[])null); + } + }catch (Exception e){ + throw new RuntimeException("Test failed. Exception occured:", e); + } + return null; + } + }); + + int [] buttonDownMasks = new int [Array.getLength(obj)]; + checkNullAndPutValuesToArray(buttonDownMasks, obj); + + //check lengths: array shouldn't contain less elements then the number of buttons on a mouse + if (buttonDownMasks.length < buttonDownMasksAPI.length){ + throw new RuntimeException("Test failed. The lengths array is less then the number of buttons"); + } + + // verify values for first three buttons + for (int i = 0; i < 3; i++) { + if (eventDownMask[i] != buttonDownMasks[i]) + { + System.out.println("Test : "+ i + " | " + " | " +eventDownMask[i] + " | "+ buttonDownMasks[i]); + throw new RuntimeException("Failure: masks are not correct for standard buttons"); + } + } + + // verify values for extra buttons if any + for (int i = 3; i < MouseInfo.getNumberOfButtons(); i++) { + if (buttonDownMasksAPI[i] != buttonDownMasks[i]) { + throw new RuntimeException("Failure: masks are not the same for extra buttons"); + } + } + System.out.println("Test passed."); + } + + public static void checkNullAndPutValuesToArray(int [] array, Object obj){ + if (obj == null){ + throw new RuntimeException("Test failed. The array obtained via reflection is "+obj); + } + + for (int i = 0; i < Array.getLength(obj); i++){ + System.out.println("Test (Reflection): "+ Array.getInt(obj, i)); + array[i] = Array.getInt(obj, i); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/event/MouseEvent/AcceptExtraButton/AcceptExtraButton.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,53 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that MouseEvent CTOR accepts extra mouse button numbers + @author Andrei Dmitriev : area=awt.event + @run main AcceptExtraButton + */ + +//package acceptextrabutton; + +import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseAdapter; + +public class AcceptExtraButton extends Frame { + static int [] eventID = new int []{MouseEvent.MOUSE_PRESSED, MouseEvent.MOUSE_RELEASED, MouseEvent.MOUSE_CLICKED}; + + public static void main(String []s){ + AcceptExtraButton f = new AcceptExtraButton(); + f.setSize(300, 300); + f.setVisible(true); + + for (int buttonId = 0; buttonId<eventID.length; buttonId++) { + for (int button = 0; button <= MouseInfo.getNumberOfButtons(); button++){ + System.out.println("button == "+button); + MouseEvent me = new MouseEvent(f, + eventID[buttonId], + System.currentTimeMillis(), + 0, //MouseEvent.BUTTON1_DOWN_MASK, modifiers + 100, 100, // x, y + 150, 150, // x, y on screen + 1, //clickCount + false, //popupTrigger + button );// MouseEvent.NOBUTTON : button + + System.out.println("dispatching >>>"+me); + f.dispatchEvent( ( AWTEvent )me ); + } + } + MouseAdapter ma1 = new MouseAdapter() { + public void mousePressed(MouseEvent e) { + System.out.println("PRESSED "+e); + } + public void mouseReleased(MouseEvent e) { + System.out.println("RELEASED "+e); + } + public void mouseClicked(MouseEvent e) { + System.out.println("CLICKED "+e); + } + }; + f.addMouseListener(ma1); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,89 @@ +/* + test %I% %E% + @bug 6315717 + @summary verifies that MouseEvent could be constructed correctly for mouse extra buttons in regard to sun.awt.enableExtraMouseButtons property + @author Andrei Dmitriev : area=awt.event + @run main CTORRestrictions + */ + +/* + * verify that user can create the MouseEvent? with button1|2|3|4|5|... when property "sun.awt.enableExtraMouseButtons" is true by default + */ +import java.awt.*; +import java.awt.event.*; + +public class CTORRestrictions{ + static Frame frame = new Frame("MouseEvent Test Frame"); + static Point mousePosition; + static Point mousePositionOnScreen; + + public static void main(String []s){ + Robot robot = null; + try { + robot = new Robot(); + } catch (AWTException ex) { + throw new RuntimeException("Test Failed", ex); + } + frame.setSize (200,200); + frame.setLocation (300, 400); + frame.setVisible(true); + robot.delay(1000); + System.out.println("sun.awt.enableExtraMouseButtons = "+Toolkit.getDefaultToolkit().getDesktopProperty("sun.awt.enableExtraMouseButtons")); + mousePosition = new Point(100, 100); + mousePositionOnScreen = new Point(frame.getLocationOnScreen().x + mousePosition.x, + frame.getLocationOnScreen().y + mousePosition.y); + + /* + * On Linux the native system count a wheel (both directions) as two more buttons on a mouse. + * So, MouseInfo.getNumberOfButtons() would report 5 buttons on a three-button mouse. + * On Windows it would still report that MouseInfo.getNumberOfButtons() == 3. + * We should handle XToolkit case and iterate through the buttons + * up to (MouseInfo.getNumberOfButtons() - 2) value. + */ + int numberOfButtons; + if (Toolkit.getDefaultToolkit().getClass().getName().equals("sun.awt.windows.WToolkit")){ + numberOfButtons = MouseInfo.getNumberOfButtons(); + } else { + numberOfButtons = MouseInfo.getNumberOfButtons() - 2; + } + System.out.println("Stage 1. Number of buttons = "+ numberOfButtons); + + for (int buttonId = 1; buttonId <= numberOfButtons; buttonId++){ + postMouseEventNewCtor(buttonId); + } + + System.out.println("Stage 2. Number of buttons = "+ numberOfButtons); + for (int buttonId = 1; buttonId <= numberOfButtons; buttonId++){ + postMouseEventOldCtor(buttonId); + } + System.out.println("Test passed."); + } + + public static void postMouseEventNewCtor(int buttonId) { + MouseEvent me = new MouseEvent(frame, + MouseEvent.MOUSE_PRESSED, + System.currentTimeMillis(), + MouseEvent.BUTTON1_DOWN_MASK, + mousePosition.x, mousePosition.y, + mousePositionOnScreen.x, + mousePositionOnScreen.y, + 1, + false, //popupTrigger + buttonId //button + ); + frame.dispatchEvent( ( AWTEvent )me ); + } + + public static void postMouseEventOldCtor(int buttonId) { + MouseEvent meOld = new MouseEvent(frame, + MouseEvent.MOUSE_PRESSED, + System.currentTimeMillis(), + MouseEvent.BUTTON1_DOWN_MASK, + mousePosition.x, mousePosition.y, + 1, + false, //popupTrigger + buttonId //button + ); + frame.dispatchEvent( ( AWTEvent )meOld ); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/event/MouseEvent/CTORRestrictions/CTORRestrictions_Disable.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,101 @@ +/* + test %I% %E% + @bug 6315717 + @summary verifies that MouseEvent could be constructed correctly for mouse extra buttons in regard to sun.awt.enableExtraMouseButtons property + @author Andrei Dmitriev : area=awt.event + @run main/othervm -Dsun.awt.enableExtraMouseButtons=false CTORRestrictions_Disable + */ + +/* + * verify that user can't create the MouseEvent? with button4|5|... when property "sun.awt.enableExtraMouseButtons"=false + * verify that user can create the MouseEvent? with button1|2|3 when property "sun.awt.enableExtraMouseButtons"=false + */ + +import java.awt.*; +import java.awt.event.*; + +public class CTORRestrictions_Disable { + static Frame frame = new Frame("MouseEvent Test Frame"); + static Point mousePosition; + static Point mousePositionOnScreen; + + public static void main(String []s){ + Robot robot = null; + try { + robot = new Robot(); + } catch (AWTException ex) { + throw new RuntimeException("Test Failed", ex); + } + frame.setSize (200,200); + frame.setLocation (300, 400); + frame.setVisible(true); + robot.delay(1000); + System.out.println(Toolkit.getDefaultToolkit().getDesktopProperty("sun.awt.enableExtraMouseButtons")); + mousePosition = new Point(100, 100); + mousePositionOnScreen = new Point(frame.getLocationOnScreen().x + mousePosition.x, + frame.getLocationOnScreen().y + mousePosition.y); + + System.out.println("Stage 1"); + for (int buttonId = 1; buttonId <= MouseInfo.getNumberOfButtons(); buttonId++){ + try { + postMouseEventNewCtor(buttonId); + if (buttonId > 3) { + throw new RuntimeException("Stage 1 FAILED: MouseEvent CTOR accepted the extra button " + (buttonId+1) + " instead of throwing an exception."); + } + } catch (IllegalArgumentException e){ + if (buttonId > 3) { + System.out.println("Passed: an exception caught for extra button."); + } else { + throw new RuntimeException("Stage 1 FAILED : exception happen on standard button.", e); + } + } + } + + System.out.println("Stage 2"); + for (int buttonId = 1; buttonId <= MouseInfo.getNumberOfButtons(); buttonId++){ + try { + postMouseEventOldCtor(buttonId); + if (buttonId > 3) { + throw new RuntimeException("Stage 2 FAILED: MouseEvent CTOR accepted the extra button " + (buttonId+1) + " instead of throwing an exception."); + } + } catch (IllegalArgumentException e){ + if (buttonId > 3) { + System.out.println("Passed: an exception caught for extra button."); + } else { + throw new RuntimeException("Stage 2 FAILED : exception happen on standard button.", e); + } + } + } + System.out.println("Test passed."); + } + + public static void postMouseEventNewCtor(int buttonId) { + MouseEvent me = new MouseEvent(frame, + MouseEvent.MOUSE_PRESSED, + System.currentTimeMillis(), + MouseEvent.BUTTON1_DOWN_MASK, + mousePosition.x, mousePosition.y, + mousePositionOnScreen.x, + mousePositionOnScreen.y, + 1, + false, //popupTrigger + buttonId //button + ); + frame.dispatchEvent( ( AWTEvent )me ); + } + + public static void postMouseEventOldCtor(int buttonId) { + MouseEvent meOld = new MouseEvent(frame, + MouseEvent.MOUSE_PRESSED, + System.currentTimeMillis(), + MouseEvent.BUTTON1_DOWN_MASK, + mousePosition.x, mousePosition.y, + 1, + false, //popupTrigger + buttonId //button + ); + frame.dispatchEvent( ( AWTEvent )meOld ); + } +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/event/MouseEvent/CheckGetMaskForButton/CheckGetMaskForButton.java Tue Sep 16 12:17:02 2008 +0400 @@ -0,0 +1,65 @@ +/* + @test %I% %E% + @bug 6315717 + @summary verifies that InputEvent.getMaskForButton() returns the same values as in InputEvent.BUTTON_DOWN_MASK + @author Andrei Dmitriev : area=awt.event + @run main CheckGetMaskForButton +*/ + +import java.awt.*; +import java.awt.event.InputEvent; +import java.lang.reflect.*; +import java.security.AccessController; +import java.security.PrivilegedAction; + +public class CheckGetMaskForButton{ + static Robot robot; + + public static void main(String []s){ + System.out.println("Number Of Buttons = "+ MouseInfo.getNumberOfButtons()); + CheckGetMaskForButton f = new CheckGetMaskForButton(); + int [] buttonMasksViaAPI = new int[MouseInfo.getNumberOfButtons()]; + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + buttonMasksViaAPI[i] = InputEvent.getMaskForButton(i+1); + System.out.println("Test (API): "+ buttonMasksViaAPI[i]); + } + + //get same array via reflection + Object obj = AccessController.doPrivileged( + new PrivilegedAction() { + public Object run() { + try { + Class clazz = Class.forName("java.awt.event.InputEvent"); + Method method = clazz.getDeclaredMethod("getButtonDownMasks",new Class [] {}); + if (method != null) { + method.setAccessible(true); + return method.invoke(null, (Object[])null); + } + }catch (Exception e){ + throw new RuntimeException("Test failed. Exception occured:", e); + } + return null; + } + }); + + if (obj == null){ + throw new RuntimeException("Test failed. The value obtained via reflection is "+obj); + } + + int [] buttonDownMasksViaReflection = new int [Array.getLength(obj)]; + //check that length of API array greater or equals then Reflect array. + if (Array.getLength(obj) < buttonMasksViaAPI.length){ + throw new RuntimeException("Test failed. The length of API array greater or equals then the length of Reflect array."); + } + + //Check that the values obtained via reflection from InputEvent.BUTTON_DOWN_MASK are the + // same as for standard API. + for (int i = 0; i < MouseInfo.getNumberOfButtons(); i++){ + System.out.println("Test (Reflection): "+ Array.getInt(obj, i)); + if (buttonMasksViaAPI[i] != Array.getInt(obj, i)){ + throw new RuntimeException("Test failed. Values of InputEvent array are different for API and Reflection invocations"); + } + } + System.out.println("Test passed."); + } +}