1 /* 2 * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt.event; 27 28 import java.awt.Component; 29 import java.awt.GraphicsEnvironment; 30 import java.awt.Point; 31 import java.awt.Toolkit; 32 import java.io.IOException; 33 import java.io.ObjectInputStream; 34 import java.awt.IllegalComponentStateException; 35 import java.awt.MouseInfo; 36 37 import sun.awt.AWTAccessor; 38 import sun.awt.SunToolkit; 39 40 /** 41 * An event which indicates that a mouse action occurred in a component. 42 * A mouse action is considered to occur in a particular component if and only 43 * if the mouse cursor is over the unobscured part of the component's bounds 44 * when the action happens. 45 * For lightweight components, such as Swing's components, mouse events 46 * are only dispatched to the component if the mouse event type has been 47 * enabled on the component. A mouse event type is enabled by adding the 48 * appropriate mouse-based {@code EventListener} to the component 49 * ({@link MouseListener} or {@link MouseMotionListener}), or by invoking 50 * {@link Component#enableEvents(long)} with the appropriate mask parameter 51 * ({@code AWTEvent.MOUSE_EVENT_MASK} or {@code AWTEvent.MOUSE_MOTION_EVENT_MASK}). 52 * If the mouse event type has not been enabled on the component, the 53 * corresponding mouse events are dispatched to the first ancestor that 54 * has enabled the mouse event type. 55 *<p> 56 * For example, if a {@code MouseListener} has been added to a component, or 57 * {@code enableEvents(AWTEvent.MOUSE_EVENT_MASK)} has been invoked, then all 58 * the events defined by {@code MouseListener} are dispatched to the component. 59 * On the other hand, if a {@code MouseMotionListener} has not been added and 60 * {@code enableEvents} has not been invoked with 61 * {@code AWTEvent.MOUSE_MOTION_EVENT_MASK}, then mouse motion events are not 62 * dispatched to the component. Instead the mouse motion events are 63 * dispatched to the first ancestors that has enabled mouse motion 64 * events. 65 * <P> 66 * This low-level event is generated by a component object for: 67 * <ul> 68 * <li>Mouse Events 69 * <ul> 70 * <li>a mouse button is pressed 71 * <li>a mouse button is released 72 * <li>a mouse button is clicked (pressed and released) 73 * <li>the mouse cursor enters the unobscured part of component's geometry 74 * <li>the mouse cursor exits the unobscured part of component's geometry 75 * </ul> 76 * <li> Mouse Motion Events 77 * <ul> 78 * <li>the mouse is moved 79 * <li>the mouse is dragged 80 * </ul> 81 * </ul> 82 * <P> 83 * A {@code MouseEvent} object is passed to every 84 * {@code MouseListener} 85 * or {@code MouseAdapter} object which is registered to receive 86 * the "interesting" mouse events using the component's 87 * {@code addMouseListener} method. 88 * ({@code MouseAdapter} objects implement the 89 * {@code MouseListener} interface.) Each such listener object 90 * gets a {@code MouseEvent} containing the mouse event. 91 * <P> 92 * A {@code MouseEvent} object is also passed to every 93 * {@code MouseMotionListener} or 94 * {@code MouseMotionAdapter} object which is registered to receive 95 * mouse motion events using the component's 96 * {@code addMouseMotionListener} 97 * method. ({@code MouseMotionAdapter} objects implement the 98 * {@code MouseMotionListener} interface.) Each such listener object 99 * gets a {@code MouseEvent} containing the mouse motion event. 100 * <P> 101 * When a mouse button is clicked, events are generated and sent to the 102 * registered {@code MouseListener}s. 103 * The state of modal keys can be retrieved using {@link InputEvent#getModifiers} 104 * and {@link InputEvent#getModifiersEx}. 105 * The button mask returned by {@link InputEvent#getModifiers} reflects 106 * only the button that changed state, not the current state of all buttons. 107 * (Note: Due to overlap in the values of ALT_MASK/BUTTON2_MASK and 108 * META_MASK/BUTTON3_MASK, this is not always true for mouse events involving 109 * modifier keys). 110 * To get the state of all buttons and modifier keys, use 111 * {@link InputEvent#getModifiersEx}. 112 * The button which has changed state is returned by {@link MouseEvent#getButton} 113 * <P> 114 * For example, if the first mouse button is pressed, events are sent in the 115 * following order: 116 * <pre><b> 117 * id modifiers button</b>{@code 118 * MOUSE_PRESSED: BUTTON1_MASK BUTTON1 119 * MOUSE_RELEASED: BUTTON1_MASK BUTTON1 120 * MOUSE_CLICKED: BUTTON1_MASK BUTTON1 121 * }</pre> 122 * When multiple mouse buttons are pressed, each press, release, and click 123 * results in a separate event. 124 * <P> 125 * For example, if the user presses <b>button 1</b> followed by 126 * <b>button 2</b>, and then releases them in the same order, 127 * the following sequence of events is generated: 128 * <pre><b> 129 * id modifiers button</b>{@code 130 * MOUSE_PRESSED: BUTTON1_MASK BUTTON1 131 * MOUSE_PRESSED: BUTTON2_MASK BUTTON2 132 * MOUSE_RELEASED: BUTTON1_MASK BUTTON1 133 * MOUSE_CLICKED: BUTTON1_MASK BUTTON1 134 * MOUSE_RELEASED: BUTTON2_MASK BUTTON2 135 * MOUSE_CLICKED: BUTTON2_MASK BUTTON2 136 * }</pre> 137 * If <b>button 2</b> is released first, the 138 * {@code MOUSE_RELEASED}/{@code MOUSE_CLICKED} pair 139 * for {@code BUTTON2_MASK} arrives first, 140 * followed by the pair for {@code BUTTON1_MASK}. 141 * <p> 142 * Some extra mouse buttons are added to extend the standard set of buttons 143 * represented by the following constants:{@code BUTTON1}, {@code BUTTON2}, and {@code BUTTON3}. 144 * Extra buttons have no assigned {@code BUTTONx} 145 * constants as well as their button masks have no assigned {@code BUTTONx_DOWN_MASK} 146 * constants. Nevertheless, ordinal numbers starting from 4 may be 147 * used as button numbers (button ids). Values obtained by the 148 * {@link InputEvent#getMaskForButton(int) getMaskForButton(button)} method may be used 149 * as button masks. 150 * <p> 151 * {@code MOUSE_DRAGGED} events are delivered to the {@code Component} 152 * in which the mouse button was pressed until the mouse button is released 153 * (regardless of whether the mouse position is within the bounds of the 154 * {@code Component}). Due to platform-dependent Drag&Drop implementations, 155 * {@code MOUSE_DRAGGED} events may not be delivered during a native 156 * Drag&Drop operation. 157 * 158 * In a multi-screen environment mouse drag events are delivered to the 159 * {@code Component} even if the mouse position is outside the bounds of the 160 * {@code GraphicsConfiguration} associated with that 161 * {@code Component}. However, the reported position for mouse drag events 162 * in this case may differ from the actual mouse position: 163 * <ul> 164 * <li>In a multi-screen environment without a virtual device: 165 * <br> 166 * The reported coordinates for mouse drag events are clipped to fit within the 167 * bounds of the {@code GraphicsConfiguration} associated with 168 * the {@code Component}. 169 * <li>In a multi-screen environment with a virtual device: 170 * <br> 171 * The reported coordinates for mouse drag events are clipped to fit within the 172 * bounds of the virtual device associated with the {@code Component}. 173 * </ul> 174 * <p> 175 * An unspecified behavior will be caused if the {@code id} parameter 176 * of any particular {@code MouseEvent} instance is not 177 * in the range from {@code MOUSE_FIRST} to {@code MOUSE_LAST}-1 178 * ({@code MOUSE_WHEEL} is not acceptable). 179 * 180 * @author Carl Quinn 181 * 182 * @see MouseAdapter 183 * @see MouseListener 184 * @see MouseMotionAdapter 185 * @see MouseMotionListener 186 * @see MouseWheelListener 187 * @see <a href="http://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html">Tutorial: Writing a Mouse Listener</a> 188 * @see <a href="http://docs.oracle.com/javase/tutorial/uiswing/events/mousemotionlistener.html">Tutorial: Writing a Mouse Motion Listener</a> 189 * 190 * @since 1.1 191 */ 192 public class MouseEvent extends InputEvent { 193 194 /** 195 * The first number in the range of ids used for mouse events. 196 */ 197 public static final int MOUSE_FIRST = 500; 198 199 /** 200 * The last number in the range of ids used for mouse events. 201 */ 202 public static final int MOUSE_LAST = 507; 203 204 /** 205 * The "mouse clicked" event. This {@code MouseEvent} 206 * occurs when a mouse button is pressed and released. 207 */ 208 public static final int MOUSE_CLICKED = MOUSE_FIRST; 209 210 /** 211 * The "mouse pressed" event. This {@code MouseEvent} 212 * occurs when a mouse button is pushed down. 213 */ 214 public static final int MOUSE_PRESSED = 1 + MOUSE_FIRST; //Event.MOUSE_DOWN 215 216 /** 217 * The "mouse released" event. This {@code MouseEvent} 218 * occurs when a mouse button is let up. 219 */ 220 public static final int MOUSE_RELEASED = 2 + MOUSE_FIRST; //Event.MOUSE_UP 221 222 /** 223 * The "mouse moved" event. This {@code MouseEvent} 224 * occurs when the mouse position changes. 225 */ 226 public static final int MOUSE_MOVED = 3 + MOUSE_FIRST; //Event.MOUSE_MOVE 227 228 /** 229 * The "mouse entered" event. This {@code MouseEvent} 230 * occurs when the mouse cursor enters the unobscured part of component's 231 * geometry. 232 */ 233 public static final int MOUSE_ENTERED = 4 + MOUSE_FIRST; //Event.MOUSE_ENTER 234 235 /** 236 * The "mouse exited" event. This {@code MouseEvent} 237 * occurs when the mouse cursor exits the unobscured part of component's 238 * geometry. 239 */ 240 public static final int MOUSE_EXITED = 5 + MOUSE_FIRST; //Event.MOUSE_EXIT 241 242 /** 243 * The "mouse dragged" event. This {@code MouseEvent} 244 * occurs when the mouse position changes while a mouse button is pressed. 245 */ 246 public static final int MOUSE_DRAGGED = 6 + MOUSE_FIRST; //Event.MOUSE_DRAG 247 248 /** 249 * The "mouse wheel" event. This is the only {@code MouseWheelEvent}. 250 * It occurs when a mouse equipped with a wheel has its wheel rotated. 251 * @since 1.4 252 */ 253 public static final int MOUSE_WHEEL = 7 + MOUSE_FIRST; 254 255 /** 256 * Indicates no mouse buttons; used by {@link #getButton}. 257 * @since 1.4 258 */ 259 public static final int NOBUTTON = 0; 260 261 /** 262 * Indicates mouse button #1; used by {@link #getButton}. 263 * @since 1.4 264 */ 265 public static final int BUTTON1 = 1; 266 267 /** 268 * Indicates mouse button #2; used by {@link #getButton}. 269 * @since 1.4 270 */ 271 public static final int BUTTON2 = 2; 272 273 /** 274 * Indicates mouse button #3; used by {@link #getButton}. 275 * @since 1.4 276 */ 277 public static final int BUTTON3 = 3; 278 279 /** 280 * The mouse event's x coordinate. 281 * The x value is relative to the component that fired the event. 282 * 283 * @serial 284 * @see #getX() 285 */ 286 int x; 287 288 /** 289 * The mouse event's y coordinate. 290 * The y value is relative to the component that fired the event. 291 * 292 * @serial 293 * @see #getY() 294 */ 295 int y; 296 297 /** 298 * The mouse event's x absolute coordinate. 299 * In a virtual device multi-screen environment in which the 300 * desktop area could span multiple physical screen devices, 301 * this coordinate is relative to the virtual coordinate system. 302 * Otherwise, this coordinate is relative to the coordinate system 303 * associated with the Component's GraphicsConfiguration. 304 * 305 * @serial 306 */ 307 private int xAbs; 308 309 /** 310 * The mouse event's y absolute coordinate. 311 * In a virtual device multi-screen environment in which the 312 * desktop area could span multiple physical screen devices, 313 * this coordinate is relative to the virtual coordinate system. 314 * Otherwise, this coordinate is relative to the coordinate system 315 * associated with the Component's GraphicsConfiguration. 316 * 317 * @serial 318 */ 319 private int yAbs; 320 321 /** 322 * Indicates the number of quick consecutive clicks of 323 * a mouse button. 324 * clickCount will be valid for only three mouse events :<BR> 325 * {@code MOUSE_CLICKED}, 326 * {@code MOUSE_PRESSED} and 327 * {@code MOUSE_RELEASED}. 328 * For the above, the {@code clickCount} will be at least 1. 329 * For all other events the count will be 0. 330 * 331 * @serial 332 * @see #getClickCount() 333 */ 334 int clickCount; 335 336 /** 337 * Indicates whether the event is a result of a touch event. 338 */ 339 private boolean causedByTouchEvent; 340 341 /** 342 * Indicates which, if any, of the mouse buttons has changed state. 343 * 344 * The valid values are ranged from 0 to the value returned by the 345 * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} method. 346 * This range already includes constants {@code NOBUTTON}, {@code BUTTON1}, 347 * {@code BUTTON2}, and {@code BUTTON3} 348 * if these buttons are present. So it is allowed to use these constants too. 349 * For example, for a mouse with two buttons this field may contain the following values: 350 * <ul> 351 * <li> 0 ({@code NOBUTTON}) 352 * <li> 1 ({@code BUTTON1}) 353 * <li> 2 ({@code BUTTON2}) 354 * </ul> 355 * If a mouse has 5 buttons, this field may contain the following values: 356 * <ul> 357 * <li> 0 ({@code NOBUTTON}) 358 * <li> 1 ({@code BUTTON1}) 359 * <li> 2 ({@code BUTTON2}) 360 * <li> 3 ({@code BUTTON3}) 361 * <li> 4 362 * <li> 5 363 * </ul> 364 * If support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled()} disabled by Java 365 * then the field may not contain the value larger than {@code BUTTON3}. 366 * @serial 367 * @see #getButton() 368 * @see java.awt.Toolkit#areExtraMouseButtonsEnabled() 369 */ 370 int button; 371 372 /** 373 * A property used to indicate whether a Popup Menu 374 * should appear with a certain gestures. 375 * If {@code popupTrigger} = {@code false}, 376 * no popup menu should appear. If it is {@code true} 377 * then a popup menu should appear. 378 * 379 * @serial 380 * @see java.awt.PopupMenu 381 * @see #isPopupTrigger() 382 */ 383 boolean popupTrigger = false; 384 385 /* 386 * JDK 1.1 serialVersionUID 387 */ 388 private static final long serialVersionUID = -991214153494842848L; 389 390 /** 391 * A number of buttons available on the mouse at the {@code Toolkit} machinery startup. 392 */ 393 private static int cachedNumberOfButtons; 394 395 static { 396 /* ensure that the necessary native libraries are loaded */ 397 NativeLibLoader.loadLibraries(); 398 if (!GraphicsEnvironment.isHeadless()) { 399 initIDs(); 400 } 401 final Toolkit tk = Toolkit.getDefaultToolkit(); 402 if (tk instanceof SunToolkit) { 403 cachedNumberOfButtons = ((SunToolkit)tk).getNumberOfButtons(); 404 } else { 405 //It's expected that some toolkits (Headless, 406 //whatever besides SunToolkit) could also operate. 407 cachedNumberOfButtons = 3; 408 } 409 AWTAccessor.setMouseEventAccessor( 410 new AWTAccessor.MouseEventAccessor() { 411 public boolean isCausedByTouchEvent(MouseEvent ev) { 412 return ev.causedByTouchEvent; 413 } 414 415 public void setCausedByTouchEvent(MouseEvent ev, 416 boolean causedByTouchEvent) { 417 ev.causedByTouchEvent = causedByTouchEvent; 418 } 419 }); 420 } 421 422 /** 423 * Initialize JNI field and method IDs for fields that may be 424 * accessed from C. 425 */ 426 private static native void initIDs(); 427 428 /** 429 * Returns the absolute x, y position of the event. 430 * In a virtual device multi-screen environment in which the 431 * desktop area could span multiple physical screen devices, 432 * these coordinates are relative to the virtual coordinate system. 433 * Otherwise, these coordinates are relative to the coordinate system 434 * associated with the Component's GraphicsConfiguration. 435 * 436 * @return a {@code Point} object containing the absolute x 437 * and y coordinates. 438 * 439 * @see java.awt.GraphicsConfiguration 440 * @since 1.6 441 */ 442 public Point getLocationOnScreen(){ 443 return new Point(xAbs, yAbs); 444 } 445 446 /** 447 * Returns the absolute horizontal x position of the event. 448 * In a virtual device multi-screen environment in which the 449 * desktop area could span multiple physical screen devices, 450 * this coordinate is relative to the virtual coordinate system. 451 * Otherwise, this coordinate is relative to the coordinate system 452 * associated with the Component's GraphicsConfiguration. 453 * 454 * @return x an integer indicating absolute horizontal position. 455 * 456 * @see java.awt.GraphicsConfiguration 457 * @since 1.6 458 */ 459 public int getXOnScreen() { 460 return xAbs; 461 } 462 463 /** 464 * Returns the absolute vertical y position of the event. 465 * In a virtual device multi-screen environment in which the 466 * desktop area could span multiple physical screen devices, 467 * this coordinate is relative to the virtual coordinate system. 468 * Otherwise, this coordinate is relative to the coordinate system 469 * associated with the Component's GraphicsConfiguration. 470 * 471 * @return y an integer indicating absolute vertical position. 472 * 473 * @see java.awt.GraphicsConfiguration 474 * @since 1.6 475 */ 476 public int getYOnScreen() { 477 return yAbs; 478 } 479 480 /** 481 * Constructs a {@code MouseEvent} object with the 482 * specified source component, 483 * type, time, modifiers, coordinates, click count, popupTrigger flag, 484 * and button number. 485 * <p> 486 * Creating an invalid event (such 487 * as by using more than one of the old _MASKs, or modifier/button 488 * values which don't match) results in unspecified behavior. 489 * An invocation of the form 490 * {@code MouseEvent(source, id, when, modifiers, x, y, clickCount, popupTrigger, button)} 491 * behaves in exactly the same way as the invocation 492 * {@link #MouseEvent(Component, int, long, int, int, int, 493 * int, int, int, boolean, int) MouseEvent(source, id, when, modifiers, 494 * x, y, xAbs, yAbs, clickCount, popupTrigger, button)} 495 * where xAbs and yAbs defines as source's location on screen plus 496 * relative coordinates x and y. 497 * xAbs and yAbs are set to zero if the source is not showing. 498 * This method throws an 499 * {@code IllegalArgumentException} if {@code source} 500 * is {@code null}. 501 * 502 * @param source The {@code Component} that originated the event 503 * @param id An integer indicating the type of event. 504 * For information on allowable values, see 505 * the class description for {@link MouseEvent} 506 * @param when A long integer that gives the time the event occurred. 507 * Passing negative or zero value 508 * is not recommended 509 * @param modifiers a modifier mask describing the modifier keys and mouse 510 * buttons (for example, shift, ctrl, alt, and meta) that 511 * are down during the event. 512 * Only extended modifiers are allowed to be used as a 513 * value for this parameter (see the {@link InputEvent#getModifiersEx} 514 * class for the description of extended modifiers). 515 * Passing negative parameter 516 * is not recommended. 517 * Zero value means that no modifiers were passed 518 * @param x The horizontal x coordinate for the mouse location. 519 * It is allowed to pass negative values 520 * @param y The vertical y coordinate for the mouse location. 521 * It is allowed to pass negative values 522 * @param clickCount The number of mouse clicks associated with event. 523 * Passing negative value 524 * is not recommended 525 * @param popupTrigger A boolean that equals {@code true} if this event 526 * is a trigger for a popup menu 527 * @param button An integer that indicates, which of the mouse buttons has 528 * changed its state. 529 * The following rules are applied to this parameter: 530 * <ul> 531 * <li>If support for the extended mouse buttons is 532 * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java 533 * then it is allowed to create {@code MouseEvent} objects only with the standard buttons: 534 * {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2}, and 535 * {@code BUTTON3}. 536 * <li> If support for the extended mouse buttons is 537 * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java 538 * then it is allowed to create {@code MouseEvent} objects with 539 * the standard buttons. 540 * In case the support for extended mouse buttons is 541 * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java, then 542 * in addition to the standard buttons, {@code MouseEvent} objects can be created 543 * using buttons from the range starting from 4 to 544 * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} 545 * if the mouse has more than three buttons. 546 * </ul> 547 * @throws IllegalArgumentException if {@code button} is less than zero 548 * @throws IllegalArgumentException if {@code source} is null 549 * @throws IllegalArgumentException if {@code button} is greater than BUTTON3 550 * and the support for extended mouse buttons is 551 * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java 552 * @throws IllegalArgumentException if {@code button} is greater than the 553 * {@link java.awt.MouseInfo#getNumberOfButtons() current number of buttons} 554 * and the support for extended mouse buttons is 555 * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} 556 * by Java 557 * @throws IllegalArgumentException if an invalid {@code button} 558 * value is passed in 559 * @throws IllegalArgumentException if {@code source} is null 560 * @see #getSource() 561 * @see #getID() 562 * @see #getWhen() 563 * @see #getModifiers() 564 * @see #getX() 565 * @see #getY() 566 * @see #getClickCount() 567 * @see #isPopupTrigger() 568 * @see #getButton() 569 * @since 1.4 570 */ 571 public MouseEvent(Component source, int id, long when, int modifiers, 572 int x, int y, int clickCount, boolean popupTrigger, 573 int button) 574 { 575 this(source, id, when, modifiers, x, y, 0, 0, clickCount, popupTrigger, button); 576 Point eventLocationOnScreen = new Point(0, 0); 577 try { 578 eventLocationOnScreen = source.getLocationOnScreen(); 579 this.xAbs = eventLocationOnScreen.x + x; 580 this.yAbs = eventLocationOnScreen.y + y; 581 } catch (IllegalComponentStateException e){ 582 this.xAbs = 0; 583 this.yAbs = 0; 584 } 585 } 586 587 /** 588 * Constructs a {@code MouseEvent} object with the 589 * specified source component, 590 * type, modifiers, coordinates, click count, and popupTrigger flag. 591 * An invocation of the form 592 * {@code MouseEvent(source, id, when, modifiers, x, y, clickCount, popupTrigger)} 593 * behaves in exactly the same way as the invocation 594 * {@link #MouseEvent(Component, int, long, int, int, int, 595 * int, int, int, boolean, int) MouseEvent(source, id, when, modifiers, 596 * x, y, xAbs, yAbs, clickCount, popupTrigger, MouseEvent.NOBUTTON)} 597 * where xAbs and yAbs defines as source's location on screen plus 598 * relative coordinates x and y. 599 * xAbs and yAbs are set to zero if the source is not showing. 600 * This method throws an {@code IllegalArgumentException} 601 * if {@code source} is {@code null}. 602 * 603 * @param source The {@code Component} that originated the event 604 * @param id An integer indicating the type of event. 605 * For information on allowable values, see 606 * the class description for {@link MouseEvent} 607 * @param when A long integer that gives the time the event occurred. 608 * Passing negative or zero value 609 * is not recommended 610 * @param modifiers a modifier mask describing the modifier keys and mouse 611 * buttons (for example, shift, ctrl, alt, and meta) that 612 * are down during the event. 613 * Only extended modifiers are allowed to be used as a 614 * value for this parameter (see the {@link InputEvent#getModifiersEx} 615 * class for the description of extended modifiers). 616 * Passing negative parameter 617 * is not recommended. 618 * Zero value means that no modifiers were passed 619 * @param x The horizontal x coordinate for the mouse location. 620 * It is allowed to pass negative values 621 * @param y The vertical y coordinate for the mouse location. 622 * It is allowed to pass negative values 623 * @param clickCount The number of mouse clicks associated with event. 624 * Passing negative value 625 * is not recommended 626 * @param popupTrigger A boolean that equals {@code true} if this event 627 * is a trigger for a popup menu 628 * @throws IllegalArgumentException if {@code source} is null 629 * @see #getSource() 630 * @see #getID() 631 * @see #getWhen() 632 * @see #getModifiers() 633 * @see #getX() 634 * @see #getY() 635 * @see #getClickCount() 636 * @see #isPopupTrigger() 637 */ 638 public MouseEvent(Component source, int id, long when, int modifiers, 639 int x, int y, int clickCount, boolean popupTrigger) { 640 this(source, id, when, modifiers, x, y, clickCount, popupTrigger, NOBUTTON); 641 } 642 643 644 /* if the button is an extra button and it is released or clicked then in Xsystem its state 645 is not modified. Exclude this button number from ExtModifiers mask.*/ 646 private transient boolean shouldExcludeButtonFromExtModifiers = false; 647 648 /** 649 * {@inheritDoc} 650 */ 651 public int getModifiersEx() { 652 int tmpModifiers = modifiers; 653 if (shouldExcludeButtonFromExtModifiers) { 654 tmpModifiers &= ~(InputEvent.getMaskForButton(getButton())); 655 } 656 return tmpModifiers & ~JDK_1_3_MODIFIERS; 657 } 658 659 /** 660 * Constructs a {@code MouseEvent} object with the 661 * specified source component, 662 * type, time, modifiers, coordinates, absolute coordinates, click count, popupTrigger flag, 663 * and button number. 664 * <p> 665 * Creating an invalid event (such 666 * as by using more than one of the old _MASKs, or modifier/button 667 * values which don't match) results in unspecified behavior. 668 * Even if inconsistent values for relative and absolute coordinates are 669 * passed to the constructor, the mouse event instance is still 670 * created and no exception is thrown. 671 * This method throws an 672 * {@code IllegalArgumentException} if {@code source} 673 * is {@code null}. 674 * 675 * @param source The {@code Component} that originated the event 676 * @param id An integer indicating the type of event. 677 * For information on allowable values, see 678 * the class description for {@link MouseEvent} 679 * @param when A long integer that gives the time the event occurred. 680 * Passing negative or zero value 681 * is not recommended 682 * @param modifiers a modifier mask describing the modifier keys and mouse 683 * buttons (for example, shift, ctrl, alt, and meta) that 684 * are down during the event. 685 * Only extended modifiers are allowed to be used as a 686 * value for this parameter (see the {@link InputEvent#getModifiersEx} 687 * class for the description of extended modifiers). 688 * Passing negative parameter 689 * is not recommended. 690 * Zero value means that no modifiers were passed 691 * @param x The horizontal x coordinate for the mouse location. 692 * It is allowed to pass negative values 693 * @param y The vertical y coordinate for the mouse location. 694 * It is allowed to pass negative values 695 * @param xAbs The absolute horizontal x coordinate for the mouse location 696 * It is allowed to pass negative values 697 * @param yAbs The absolute vertical y coordinate for the mouse location 698 * It is allowed to pass negative values 699 * @param clickCount The number of mouse clicks associated with event. 700 * Passing negative value 701 * is not recommended 702 * @param popupTrigger A boolean that equals {@code true} if this event 703 * is a trigger for a popup menu 704 * @param button An integer that indicates, which of the mouse buttons has 705 * changed its state. 706 * The following rules are applied to this parameter: 707 * <ul> 708 * <li>If support for the extended mouse buttons is 709 * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java 710 * then it is allowed to create {@code MouseEvent} objects only with the standard buttons: 711 * {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2}, and 712 * {@code BUTTON3}. 713 * <li> If support for the extended mouse buttons is 714 * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java 715 * then it is allowed to create {@code MouseEvent} objects with 716 * the standard buttons. 717 * In case the support for extended mouse buttons is 718 * {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java, then 719 * in addition to the standard buttons, {@code MouseEvent} objects can be created 720 * using buttons from the range starting from 4 to 721 * {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} 722 * if the mouse has more than three buttons. 723 * </ul> 724 * @throws IllegalArgumentException if {@code button} is less than zero 725 * @throws IllegalArgumentException if {@code source} is null 726 * @throws IllegalArgumentException if {@code button} is greater than BUTTON3 727 * and the support for extended mouse buttons is 728 * {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java 729 * @throws IllegalArgumentException if {@code button} is greater than the 730 * {@link java.awt.MouseInfo#getNumberOfButtons() 731 * current number of buttons} and the support 732 * for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} 733 * by Java 734 * @throws IllegalArgumentException if an invalid {@code button} 735 * value is passed in 736 * @throws IllegalArgumentException if {@code source} is null 737 * @see #getSource() 738 * @see #getID() 739 * @see #getWhen() 740 * @see #getModifiers() 741 * @see #getX() 742 * @see #getY() 743 * @see #getXOnScreen() 744 * @see #getYOnScreen() 745 * @see #getClickCount() 746 * @see #isPopupTrigger() 747 * @see #getButton() 748 * @see #button 749 * @see Toolkit#areExtraMouseButtonsEnabled() 750 * @see java.awt.MouseInfo#getNumberOfButtons() 751 * @see InputEvent#getMaskForButton(int) 752 * @since 1.6 753 */ 754 @SuppressWarnings("deprecation") 755 public MouseEvent(Component source, int id, long when, int modifiers, 756 int x, int y, int xAbs, int yAbs, 757 int clickCount, boolean popupTrigger, int button) 758 { 759 super(source, id, when, modifiers); 760 this.x = x; 761 this.y = y; 762 this.xAbs = xAbs; 763 this.yAbs = yAbs; 764 this.clickCount = clickCount; 765 this.popupTrigger = popupTrigger; 766 if (button < NOBUTTON){ 767 throw new IllegalArgumentException("Invalid button value :" + button); 768 } 769 if (button > BUTTON3) { 770 if (!Toolkit.getDefaultToolkit().areExtraMouseButtonsEnabled()){ 771 throw new IllegalArgumentException("Extra mouse events are disabled " + button); 772 } else { 773 if (button > cachedNumberOfButtons) { 774 throw new IllegalArgumentException("Nonexistent button " + button); 775 } 776 } 777 // XToolkit: extra buttons are not reporting about their state correctly. 778 // Being pressed they report the state=0 both on the press and on the release. 779 // For 1-3 buttons the state value equals zero on press and non-zero on release. 780 // Other modifiers like Shift, ALT etc seem report well with extra buttons. 781 // The problem reveals as follows: one button is pressed and then another button is pressed and released. 782 // So, the getModifiersEx() would not be zero due to a first button and we will skip this modifier. 783 // This may have to be moved into the peer code instead if possible. 784 785 if (getModifiersEx() != 0) { //There is at least one more button in a pressed state. 786 if (id == MouseEvent.MOUSE_RELEASED || id == MouseEvent.MOUSE_CLICKED){ 787 shouldExcludeButtonFromExtModifiers = true; 788 } 789 } 790 } 791 792 this.button = button; 793 794 if ((getModifiers() != 0) && (getModifiersEx() == 0)) { 795 setNewModifiers(); 796 } else if ((getModifiers() == 0) && 797 (getModifiersEx() != 0 || button != NOBUTTON) && 798 (button <= BUTTON3)) 799 { 800 setOldModifiers(); 801 } 802 } 803 804 /** 805 * Returns the horizontal x position of the event relative to the 806 * source component. 807 * 808 * @return x an integer indicating horizontal position relative to 809 * the component 810 */ 811 public int getX() { 812 return x; 813 } 814 815 /** 816 * Returns the vertical y position of the event relative to the 817 * source component. 818 * 819 * @return y an integer indicating vertical position relative to 820 * the component 821 */ 822 public int getY() { 823 return y; 824 } 825 826 /** 827 * Returns the x,y position of the event relative to the source component. 828 * 829 * @return a {@code Point} object containing the x and y coordinates 830 * relative to the source component 831 * 832 */ 833 public Point getPoint() { 834 int x; 835 int y; 836 synchronized (this) { 837 x = this.x; 838 y = this.y; 839 } 840 return new Point(x, y); 841 } 842 843 /** 844 * Translates the event's coordinates to a new position 845 * by adding specified {@code x} (horizontal) and {@code y} 846 * (vertical) offsets. 847 * 848 * @param x the horizontal x value to add to the current x 849 * coordinate position 850 * @param y the vertical y value to add to the current y 851 coordinate position 852 */ 853 public synchronized void translatePoint(int x, int y) { 854 this.x += x; 855 this.y += y; 856 } 857 858 /** 859 * Returns the number of mouse clicks associated with this event. 860 * 861 * @return integer value for the number of clicks 862 */ 863 public int getClickCount() { 864 return clickCount; 865 } 866 867 /** 868 * Returns which, if any, of the mouse buttons has changed state. 869 * The returned value is ranged 870 * from 0 to the {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} 871 * value. 872 * The returned value includes at least the following constants: 873 * <ul> 874 * <li> {@code NOBUTTON} 875 * <li> {@code BUTTON1} 876 * <li> {@code BUTTON2} 877 * <li> {@code BUTTON3} 878 * </ul> 879 * It is allowed to use those constants to compare with the returned button number in the application. 880 * For example, 881 * <pre> 882 * if (anEvent.getButton() == MouseEvent.BUTTON1) { 883 * </pre> 884 * In particular, for a mouse with one, two, or three buttons this method may return the following values: 885 * <ul> 886 * <li> 0 ({@code NOBUTTON}) 887 * <li> 1 ({@code BUTTON1}) 888 * <li> 2 ({@code BUTTON2}) 889 * <li> 3 ({@code BUTTON3}) 890 * </ul> 891 * Button numbers greater than {@code BUTTON3} have no constant identifier. 892 * So if a mouse with five buttons is 893 * installed, this method may return the following values: 894 * <ul> 895 * <li> 0 ({@code NOBUTTON}) 896 * <li> 1 ({@code BUTTON1}) 897 * <li> 2 ({@code BUTTON2}) 898 * <li> 3 ({@code BUTTON3}) 899 * <li> 4 900 * <li> 5 901 * </ul> 902 * <p> 903 * Note: If support for extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java 904 * then the AWT event subsystem does not produce mouse events for the extended mouse 905 * buttons. So it is not expected that this method returns anything except {@code NOBUTTON}, {@code BUTTON1}, 906 * {@code BUTTON2}, {@code BUTTON3}. 907 * 908 * @return one of the values from 0 to {@link java.awt.MouseInfo#getNumberOfButtons() MouseInfo.getNumberOfButtons()} 909 * if support for the extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() enabled} by Java. 910 * That range includes {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2}, {@code BUTTON3}; 911 * <br> 912 * {@code NOBUTTON}, {@code BUTTON1}, {@code BUTTON2} or {@code BUTTON3} 913 * if support for the extended mouse buttons is {@link Toolkit#areExtraMouseButtonsEnabled() disabled} by Java 914 * @since 1.4 915 * @see Toolkit#areExtraMouseButtonsEnabled() 916 * @see java.awt.MouseInfo#getNumberOfButtons() 917 * @see #MouseEvent(Component, int, long, int, int, int, int, int, int, boolean, int) 918 * @see InputEvent#getMaskForButton(int) 919 */ 920 public int getButton() { 921 return button; 922 } 923 924 /** 925 * Returns whether or not this mouse event is the popup menu 926 * trigger event for the platform. 927 * <p><b>Note</b>: Popup menus are triggered differently 928 * on different systems. Therefore, {@code isPopupTrigger} 929 * should be checked in both {@code mousePressed} 930 * and {@code mouseReleased} 931 * for proper cross-platform functionality. 932 * 933 * @return boolean, true if this event is the popup menu trigger 934 * for this platform 935 */ 936 public boolean isPopupTrigger() { 937 return popupTrigger; 938 } 939 940 /** 941 * Returns a {@code String} instance describing the modifier keys and 942 * mouse buttons that were down during the event, such as "Shift", 943 * or "Ctrl+Shift". These strings can be localized by changing 944 * the {@code awt.properties} file. 945 * <p> 946 * Note that the {@code InputEvent.ALT_MASK} and 947 * {@code InputEvent.BUTTON2_MASK} have equal values, 948 * so the "Alt" string is returned for both modifiers. Likewise, 949 * the {@code InputEvent.META_MASK} and 950 * {@code InputEvent.BUTTON3_MASK} have equal values, 951 * so the "Meta" string is returned for both modifiers. 952 * <p> 953 * Note that passing negative parameter is incorrect, 954 * and will cause the returning an unspecified string. 955 * Zero parameter means that no modifiers were passed and will 956 * cause the returning an empty string. 957 * 958 * @param modifiers A modifier mask describing the modifier keys and 959 * mouse buttons that were down during the event 960 * @return string string text description of the combination of modifier 961 * keys and mouse buttons that were down during the event 962 * @see InputEvent#getModifiersExText(int) 963 * @since 1.4 964 */ 965 @SuppressWarnings("deprecation") 966 public static String getMouseModifiersText(int modifiers) { 967 StringBuilder buf = new StringBuilder(); 968 if ((modifiers & InputEvent.ALT_MASK) != 0) { 969 buf.append(Toolkit.getProperty("AWT.alt", "Alt")); 970 buf.append("+"); 971 } 972 if ((modifiers & InputEvent.META_MASK) != 0) { 973 buf.append(Toolkit.getProperty("AWT.meta", "Meta")); 974 buf.append("+"); 975 } 976 if ((modifiers & InputEvent.CTRL_MASK) != 0) { 977 buf.append(Toolkit.getProperty("AWT.control", "Ctrl")); 978 buf.append("+"); 979 } 980 if ((modifiers & InputEvent.SHIFT_MASK) != 0) { 981 buf.append(Toolkit.getProperty("AWT.shift", "Shift")); 982 buf.append("+"); 983 } 984 if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) { 985 buf.append(Toolkit.getProperty("AWT.altGraph", "Alt Graph")); 986 buf.append("+"); 987 } 988 if ((modifiers & InputEvent.BUTTON1_MASK) != 0) { 989 buf.append(Toolkit.getProperty("AWT.button1", "Button1")); 990 buf.append("+"); 991 } 992 if ((modifiers & InputEvent.BUTTON2_MASK) != 0) { 993 buf.append(Toolkit.getProperty("AWT.button2", "Button2")); 994 buf.append("+"); 995 } 996 if ((modifiers & InputEvent.BUTTON3_MASK) != 0) { 997 buf.append(Toolkit.getProperty("AWT.button3", "Button3")); 998 buf.append("+"); 999 } 1000 1001 int mask; 1002 1003 // TODO: add a toolkit field that holds a number of button on the mouse. 1004 // As the method getMouseModifiersText() is static and obtain 1005 // an integer as a parameter then we may not restrict this with the number 1006 // of buttons installed on the mouse. 1007 // It's a temporary solution. We need to somehow hold the number of buttons somewhere else. 1008 for (int i = 1; i <= cachedNumberOfButtons; i++){ 1009 mask = InputEvent.getMaskForButton(i); 1010 if ((modifiers & mask) != 0 && 1011 buf.indexOf(Toolkit.getProperty("AWT.button"+i, "Button"+i)) == -1) //1,2,3 buttons may already be there; so don't duplicate it. 1012 { 1013 buf.append(Toolkit.getProperty("AWT.button"+i, "Button"+i)); 1014 buf.append("+"); 1015 } 1016 } 1017 1018 if (buf.length() > 0) { 1019 buf.setLength(buf.length()-1); // remove trailing '+' 1020 } 1021 return buf.toString(); 1022 } 1023 1024 /** 1025 * Returns a parameter string identifying this event. 1026 * This method is useful for event-logging and for debugging. 1027 * 1028 * @return a string identifying the event and its attributes 1029 */ 1030 @SuppressWarnings("deprecation") 1031 public String paramString() { 1032 StringBuilder str = new StringBuilder(80); 1033 1034 switch(id) { 1035 case MOUSE_PRESSED: 1036 str.append("MOUSE_PRESSED"); 1037 break; 1038 case MOUSE_RELEASED: 1039 str.append("MOUSE_RELEASED"); 1040 break; 1041 case MOUSE_CLICKED: 1042 str.append("MOUSE_CLICKED"); 1043 break; 1044 case MOUSE_ENTERED: 1045 str.append("MOUSE_ENTERED"); 1046 break; 1047 case MOUSE_EXITED: 1048 str.append("MOUSE_EXITED"); 1049 break; 1050 case MOUSE_MOVED: 1051 str.append("MOUSE_MOVED"); 1052 break; 1053 case MOUSE_DRAGGED: 1054 str.append("MOUSE_DRAGGED"); 1055 break; 1056 case MOUSE_WHEEL: 1057 str.append("MOUSE_WHEEL"); 1058 break; 1059 default: 1060 str.append("unknown type"); 1061 } 1062 1063 // (x,y) coordinates 1064 str.append(",(").append(x).append(",").append(y).append(")"); 1065 str.append(",absolute(").append(xAbs).append(",").append(yAbs).append(")"); 1066 1067 if (id != MOUSE_DRAGGED && id != MOUSE_MOVED){ 1068 str.append(",button=").append(getButton()); 1069 } 1070 1071 if (getModifiers() != 0) { 1072 str.append(",modifiers=").append(getMouseModifiersText(modifiers)); 1073 } 1074 1075 if (getModifiersEx() != 0) { 1076 //Using plain "modifiers" here does show an excluded extended buttons in the string event representation. 1077 //getModifiersEx() solves the problem. 1078 str.append(",extModifiers=").append(getModifiersExText(getModifiersEx())); 1079 } 1080 1081 str.append(",clickCount=").append(clickCount); 1082 1083 return str.toString(); 1084 } 1085 1086 /** 1087 * Sets new modifiers by the old ones. 1088 * Also sets button. 1089 */ 1090 @SuppressWarnings("deprecation") 1091 private void setNewModifiers() { 1092 if ((modifiers & BUTTON1_MASK) != 0) { 1093 modifiers |= BUTTON1_DOWN_MASK; 1094 } 1095 if ((modifiers & BUTTON2_MASK) != 0) { 1096 modifiers |= BUTTON2_DOWN_MASK; 1097 } 1098 if ((modifiers & BUTTON3_MASK) != 0) { 1099 modifiers |= BUTTON3_DOWN_MASK; 1100 } 1101 if (id == MOUSE_PRESSED 1102 || id == MOUSE_RELEASED 1103 || id == MOUSE_CLICKED) 1104 { 1105 if ((modifiers & BUTTON1_MASK) != 0) { 1106 button = BUTTON1; 1107 modifiers &= ~BUTTON2_MASK & ~BUTTON3_MASK; 1108 if (id != MOUSE_PRESSED) { 1109 modifiers &= ~BUTTON1_DOWN_MASK; 1110 } 1111 } else if ((modifiers & BUTTON2_MASK) != 0) { 1112 button = BUTTON2; 1113 modifiers &= ~BUTTON1_MASK & ~BUTTON3_MASK; 1114 if (id != MOUSE_PRESSED) { 1115 modifiers &= ~BUTTON2_DOWN_MASK; 1116 } 1117 } else if ((modifiers & BUTTON3_MASK) != 0) { 1118 button = BUTTON3; 1119 modifiers &= ~BUTTON1_MASK & ~BUTTON2_MASK; 1120 if (id != MOUSE_PRESSED) { 1121 modifiers &= ~BUTTON3_DOWN_MASK; 1122 } 1123 } 1124 } 1125 if ((modifiers & InputEvent.ALT_MASK) != 0) { 1126 modifiers |= InputEvent.ALT_DOWN_MASK; 1127 } 1128 if ((modifiers & InputEvent.META_MASK) != 0) { 1129 modifiers |= InputEvent.META_DOWN_MASK; 1130 } 1131 if ((modifiers & InputEvent.SHIFT_MASK) != 0) { 1132 modifiers |= InputEvent.SHIFT_DOWN_MASK; 1133 } 1134 if ((modifiers & InputEvent.CTRL_MASK) != 0) { 1135 modifiers |= InputEvent.CTRL_DOWN_MASK; 1136 } 1137 if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) { 1138 modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK; 1139 } 1140 } 1141 1142 /** 1143 * Sets old modifiers by the new ones. 1144 */ 1145 @SuppressWarnings("deprecation") 1146 private void setOldModifiers() { 1147 if (id == MOUSE_PRESSED 1148 || id == MOUSE_RELEASED 1149 || id == MOUSE_CLICKED) 1150 { 1151 switch(button) { 1152 case BUTTON1: 1153 modifiers |= BUTTON1_MASK; 1154 break; 1155 case BUTTON2: 1156 modifiers |= BUTTON2_MASK; 1157 break; 1158 case BUTTON3: 1159 modifiers |= BUTTON3_MASK; 1160 break; 1161 } 1162 } else { 1163 if ((modifiers & BUTTON1_DOWN_MASK) != 0) { 1164 modifiers |= BUTTON1_MASK; 1165 } 1166 if ((modifiers & BUTTON2_DOWN_MASK) != 0) { 1167 modifiers |= BUTTON2_MASK; 1168 } 1169 if ((modifiers & BUTTON3_DOWN_MASK) != 0) { 1170 modifiers |= BUTTON3_MASK; 1171 } 1172 } 1173 if ((modifiers & ALT_DOWN_MASK) != 0) { 1174 modifiers |= ALT_MASK; 1175 } 1176 if ((modifiers & META_DOWN_MASK) != 0) { 1177 modifiers |= META_MASK; 1178 } 1179 if ((modifiers & SHIFT_DOWN_MASK) != 0) { 1180 modifiers |= SHIFT_MASK; 1181 } 1182 if ((modifiers & CTRL_DOWN_MASK) != 0) { 1183 modifiers |= CTRL_MASK; 1184 } 1185 if ((modifiers & ALT_GRAPH_DOWN_MASK) != 0) { 1186 modifiers |= ALT_GRAPH_MASK; 1187 } 1188 } 1189 1190 /** 1191 * Sets new modifiers by the old ones. 1192 * @serial 1193 */ 1194 @SuppressWarnings("deprecation") 1195 private void readObject(ObjectInputStream s) 1196 throws IOException, ClassNotFoundException { 1197 s.defaultReadObject(); 1198 if (getModifiers() != 0 && getModifiersEx() == 0) { 1199 setNewModifiers(); 1200 } 1201 } 1202 }