001 /*
002 * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.awt.event;
027
028 import java.awt.Component;
029 import java.awt.GraphicsEnvironment;
030 import java.awt.Point;
031 import java.awt.Toolkit;
032 import java.io.IOException;
033 import java.io.ObjectInputStream;
034 import java.awt.IllegalComponentStateException;
035
036 /**
037 * An event which indicates that a mouse action occurred in a component.
038 * A mouse action is considered to occur in a particular component if and only
039 * if the mouse cursor is over the unobscured part of the component's bounds
040 * when the action happens.
041 * For lightweight components, such as Swing's components, mouse events
042 * are only dispatched to the component if the mouse event type has been
043 * enabled on the component. A mouse event type is enabled by adding the
044 * appropriate mouse-based {@code EventListener} to the component
045 * ({@link MouseListener} or {@link MouseMotionListener}), or by invoking
046 * {@link Component#enableEvents(long)} with the appropriate mask parameter
047 * ({@code AWTEvent.MOUSE_EVENT_MASK} or {@code AWTEvent.MOUSE_MOTION_EVENT_MASK}).
048 * If the mouse event type has not been enabled on the component, the
049 * corresponding mouse events are dispatched to the first ancestor that
050 * has enabled the mouse event type.
051 *<p>
052 * For example, if a {@code MouseListener} has been added to a component, or
053 * {@code enableEvents(AWTEvent.MOUSE_EVENT_MASK)} has been invoked, then all
054 * the events defined by {@code MouseListener} are dispatched to the component.
055 * On the other hand, if a {@code MouseMotionListener} has not been added and
056 * {@code enableEvents} has not been invoked with
057 * {@code AWTEvent.MOUSE_MOTION_EVENT_MASK}, then mouse motion events are not
058 * dispatched to the component. Instead the mouse motion events are
059 * dispatched to the first ancestors that has enabled mouse motion
060 * events.
061 * <P>
062 * This low-level event is generated by a component object for:
063 * <ul>
064 * <li>Mouse Events
065 * <ul>
066 * <li>a mouse button is pressed
067 * <li>a mouse button is released
068 * <li>a mouse button is clicked (pressed and released)
069 * <li>the mouse cursor enters the unobscured part of component's geometry
070 * <li>the mouse cursor exits the unobscured part of component's geometry
071 * </ul>
072 * <li> Mouse Motion Events
073 * <ul>
074 * <li>the mouse is moved
075 * <li>the mouse is dragged
076 * </ul>
077 * </ul>
078 * <P>
079 * A <code>MouseEvent</code> object is passed to every
080 * <code>MouseListener</code>
081 * or <code>MouseAdapter</code> object which is registered to receive
082 * the "interesting" mouse events using the component's
083 * <code>addMouseListener</code> method.
084 * (<code>MouseAdapter</code> objects implement the
085 * <code>MouseListener</code> interface.) Each such listener object
086 * gets a <code>MouseEvent</code> containing the mouse event.
087 * <P>
088 * A <code>MouseEvent</code> object is also passed to every
089 * <code>MouseMotionListener</code> or
090 * <code>MouseMotionAdapter</code> object which is registered to receive
091 * mouse motion events using the component's
092 * <code>addMouseMotionListener</code>
093 * method. (<code>MouseMotionAdapter</code> objects implement the
094 * <code>MouseMotionListener</code> interface.) Each such listener object
095 * gets a <code>MouseEvent</code> containing the mouse motion event.
096 * <P>
097 * When a mouse button is clicked, events are generated and sent to the
098 * registered <code>MouseListener</code>s.
099 * The state of modal keys can be retrieved using {@link InputEvent#getModifiers}
100 * and {@link InputEvent#getModifiersEx}.
101 * The button mask returned by {@link InputEvent#getModifiers} reflects
102 * only the button that changed state, not the current state of all buttons.
103 * (Note: Due to overlap in the values of ALT_MASK/BUTTON2_MASK and
104 * META_MASK/BUTTON3_MASK, this is not always true for mouse events involving
105 * modifier keys).
106 * To get the state of all buttons and modifier keys, use
107 * {@link InputEvent#getModifiersEx}.
108 * The button which has changed state is returned by {@link MouseEvent#getButton}
109 * <P>
110 * For example, if the first mouse button is pressed, events are sent in the
111 * following order:
112 * <PRE>
113 * <b >id </b > <b >modifiers </b > <b >button </b >
114 * <code>MOUSE_PRESSED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
115 * <code>MOUSE_RELEASED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
116 * <code>MOUSE_CLICKED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
117 * </PRE>
118 * When multiple mouse buttons are pressed, each press, release, and click
119 * results in a separate event.
120 * <P>
121 * For example, if the user presses <b>button 1</b> followed by
122 * <b>button 2</b>, and then releases them in the same order,
123 * the following sequence of events is generated:
124 * <PRE>
125 * <b >id </b > <b >modifiers </b > <b >button </b >
126 * <code>MOUSE_PRESSED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
127 * <code>MOUSE_PRESSED</code>: <code>BUTTON2_MASK</code> <code>BUTTON2</code>
128 * <code>MOUSE_RELEASED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
129 * <code>MOUSE_CLICKED</code>: <code>BUTTON1_MASK</code> <code>BUTTON1</code>
130 * <code>MOUSE_RELEASED</code>: <code>BUTTON2_MASK</code> <code>BUTTON2</code>
131 * <code>MOUSE_CLICKED</code>: <code>BUTTON2_MASK</code> <code>BUTTON2</code>
132 * </PRE>
133 * If <b>button 2</b> is released first, the
134 * <code>MOUSE_RELEASED</code>/<code>MOUSE_CLICKED</code> pair
135 * for <code>BUTTON2_MASK</code> arrives first,
136 * followed by the pair for <code>BUTTON1_MASK</code>.
137 * <p>
138 *
139 * <code>MOUSE_DRAGGED</code> events are delivered to the <code>Component</code>
140 * in which the mouse button was pressed until the mouse button is released
141 * (regardless of whether the mouse position is within the bounds of the
142 * <code>Component</code>). Due to platform-dependent Drag&Drop implementations,
143 * <code>MOUSE_DRAGGED</code> events may not be delivered during a native
144 * Drag&Drop operation.
145 *
146 * In a multi-screen environment mouse drag events are delivered to the
147 * <code>Component</code> even if the mouse position is outside the bounds of the
148 * <code>GraphicsConfiguration</code> associated with that
149 * <code>Component</code>. However, the reported position for mouse drag events
150 * in this case may differ from the actual mouse position:
151 * <ul>
152 * <li>In a multi-screen environment without a virtual device:
153 * <br>
154 * The reported coordinates for mouse drag events are clipped to fit within the
155 * bounds of the <code>GraphicsConfiguration</code> associated with
156 * the <code>Component</code>.
157 * <li>In a multi-screen environment with a virtual device:
158 * <br>
159 * The reported coordinates for mouse drag events are clipped to fit within the
160 * bounds of the virtual device associated with the <code>Component</code>.
161 * </ul>
162 *
163 * @author Carl Quinn
164 * 1.65, 06/05/07
165 *
166 * @see MouseAdapter
167 * @see MouseListener
168 * @see MouseMotionAdapter
169 * @see MouseMotionListener
170 * @see MouseWheelListener
171 * @see <a href="http://java.sun.com/docs/books/tutorial/post1.0/ui/mouselistener.html">Tutorial: Writing a Mouse Listener</a>
172 * @see <a href="http://java.sun.com/docs/books/tutorial/post1.0/ui/mousemotionlistener.html">Tutorial: Writing a Mouse Motion Listener</a>
173 *
174 * @since 1.1
175 */
176 public class MouseEvent extends InputEvent {
177
178 /**
179 * The first number in the range of ids used for mouse events.
180 */
181 public static final int MOUSE_FIRST = 500;
182
183 /**
184 * The last number in the range of ids used for mouse events.
185 */
186 public static final int MOUSE_LAST = 507;
187
188 /**
189 * The "mouse clicked" event. This <code>MouseEvent</code>
190 * occurs when a mouse button is pressed and released.
191 */
192 public static final int MOUSE_CLICKED = MOUSE_FIRST;
193
194 /**
195 * The "mouse pressed" event. This <code>MouseEvent</code>
196 * occurs when a mouse button is pushed down.
197 */
198 public static final int MOUSE_PRESSED = 1 + MOUSE_FIRST; //Event.MOUSE_DOWN
199
200 /**
201 * The "mouse released" event. This <code>MouseEvent</code>
202 * occurs when a mouse button is let up.
203 */
204 public static final int MOUSE_RELEASED = 2 + MOUSE_FIRST; //Event.MOUSE_UP
205
206 /**
207 * The "mouse moved" event. This <code>MouseEvent</code>
208 * occurs when the mouse position changes.
209 */
210 public static final int MOUSE_MOVED = 3 + MOUSE_FIRST; //Event.MOUSE_MOVE
211
212 /**
213 * The "mouse entered" event. This <code>MouseEvent</code>
214 * occurs when the mouse cursor enters the unobscured part of component's
215 * geometry.
216 */
217 public static final int MOUSE_ENTERED = 4 + MOUSE_FIRST; //Event.MOUSE_ENTER
218
219 /**
220 * The "mouse exited" event. This <code>MouseEvent</code>
221 * occurs when the mouse cursor exits the unobscured part of component's
222 * geometry.
223 */
224 public static final int MOUSE_EXITED = 5 + MOUSE_FIRST; //Event.MOUSE_EXIT
225
226 /**
227 * The "mouse dragged" event. This <code>MouseEvent</code>
228 * occurs when the mouse position changes while a mouse button is pressed.
229 */
230 public static final int MOUSE_DRAGGED = 6 + MOUSE_FIRST; //Event.MOUSE_DRAG
231
232 /**
233 * The "mouse wheel" event. This is the only <code>MouseWheelEvent</code>.
234 * It occurs when a mouse equipped with a wheel has its wheel rotated.
235 * @since 1.4
236 */
237 public static final int MOUSE_WHEEL = 7 + MOUSE_FIRST;
238
239 /**
240 * Indicates no mouse buttons; used by {@link #getButton}.
241 * @since 1.4
242 */
243 public static final int NOBUTTON = 0;
244
245 /**
246 * Indicates mouse button #1; used by {@link #getButton}.
247 * @since 1.4
248 */
249 public static final int BUTTON1 = 1;
250
251 /**
252 * Indicates mouse button #2; used by {@link #getButton}.
253 * @since 1.4
254 */
255 public static final int BUTTON2 = 2;
256
257 /**
258 * Indicates mouse button #3; used by {@link #getButton}.
259 * @since 1.4
260 */
261 public static final int BUTTON3 = 3;
262
263 /**
264 * The mouse event's x coordinate.
265 * The x value is relative to the component that fired the event.
266 *
267 * @serial
268 * @see #getX()
269 */
270 int x;
271
272 /**
273 * The mouse event's y coordinate.
274 * The y value is relative to the component that fired the event.
275 *
276 * @serial
277 * @see #getY()
278 */
279 int y;
280
281 /**
282 * The mouse event's x absolute coordinate.
283 * In a virtual device multi-screen environment in which the
284 * desktop area could span multiple physical screen devices,
285 * this coordinate is relative to the virtual coordinate system.
286 * Otherwise, this coordinate is relative to the coordinate system
287 * associated with the Component's GraphicsConfiguration.
288 *
289 * @serial
290 */
291 private int xAbs;
292
293 /**
294 * The mouse event's y absolute coordinate.
295 * In a virtual device multi-screen environment in which the
296 * desktop area could span multiple physical screen devices,
297 * this coordinate is relative to the virtual coordinate system.
298 * Otherwise, this coordinate is relative to the coordinate system
299 * associated with the Component's GraphicsConfiguration.
300 *
301 * @serial
302 */
303 private int yAbs;
304
305 /**
306 * Indicates the number of quick consecutive clicks of
307 * a mouse button.
308 * clickCount will be valid for only three mouse events :<BR>
309 * <code>MOUSE_CLICKED</code>,
310 * <code>MOUSE_PRESSED</code> and
311 * <code>MOUSE_RELEASED</code>.
312 * For the above, the <code>clickCount</code> will be at least 1.
313 * For all other events the count will be 0.
314 *
315 * @serial
316 * @see #getClickCount().
317 */
318 int clickCount;
319
320 /**
321 * Indicates which, if any, of the mouse buttons has changed state.
322 *
323 * The only legal values are the following constants:
324 * <code>NOBUTTON</code>,
325 * <code>BUTTON1</code>,
326 * <code>BUTTON2</code> or
327 * <code>BUTTON3</code>.
328 * @serial
329 * @see #getButton().
330 */
331 int button;
332
333 /**
334 * A property used to indicate whether a Popup Menu
335 * should appear with a certain gestures.
336 * If <code>popupTrigger</code> = <code>false</code>,
337 * no popup menu should appear. If it is <code>true</code>
338 * then a popup menu should appear.
339 *
340 * @serial
341 * @see java.awt.PopupMenu
342 * @see #isPopupTrigger()
343 */
344 boolean popupTrigger = false;
345
346 /*
347 * JDK 1.1 serialVersionUID
348 */
349 private static final long serialVersionUID = -991214153494842848L;
350
351 static {
352 /* ensure that the necessary native libraries are loaded */
353 NativeLibLoader.loadLibraries();
354 if (!GraphicsEnvironment.isHeadless()) {
355 initIDs();
356 }
357 }
358
359 /**
360 * Initialize JNI field and method IDs for fields that may be
361 accessed from C.
362 */
363 private static native void initIDs();
364
365 /**
366 * Returns the absolute x, y position of the event.
367 * In a virtual device multi-screen environment in which the
368 * desktop area could span multiple physical screen devices,
369 * these coordinates are relative to the virtual coordinate system.
370 * Otherwise, these coordinates are relative to the coordinate system
371 * associated with the Component's GraphicsConfiguration.
372 *
373 * @return a <code>Point</code> object containing the absolute x
374 * and y coordinates.
375 *
376 * @see java.awt.GraphicsConfiguration
377 * @since 1.6
378 */
379 public Point getLocationOnScreen() {
380 return new Point(xAbs, yAbs);
381 }
382
383 /**
384 * Returns the absolute horizontal x position of the event.
385 * In a virtual device multi-screen environment in which the
386 * desktop area could span multiple physical screen devices,
387 * this coordinate is relative to the virtual coordinate system.
388 * Otherwise, this coordinate is relative to the coordinate system
389 * associated with the Component's GraphicsConfiguration.
390 *
391 * @return x an integer indicating absolute horizontal position.
392 *
393 * @see java.awt.GraphicsConfiguration
394 * @since 1.6
395 */
396 public int getXOnScreen() {
397 return xAbs;
398 }
399
400 /**
401 * Returns the absolute vertical y position of the event.
402 * In a virtual device multi-screen environment in which the
403 * desktop area could span multiple physical screen devices,
404 * this coordinate is relative to the virtual coordinate system.
405 * Otherwise, this coordinate is relative to the coordinate system
406 * associated with the Component's GraphicsConfiguration.
407 *
408 * @return y an integer indicating absolute vertical position.
409 *
410 * @see java.awt.GraphicsConfiguration
411 * @since 1.6
412 */
413 public int getYOnScreen() {
414 return yAbs;
415 }
416
417 /**
418 * Constructs a <code>MouseEvent</code> object with the
419 * specified source component,
420 * type, modifiers, coordinates, and click count.
421 * <p>
422 * Note that passing in an invalid <code>id</code> results in
423 * unspecified behavior. Creating an invalid event (such
424 * as by using more than one of the old _MASKs, or modifier/button
425 * values which don't match) results in unspecified behavior.
426 * An invocation of the form
427 * <tt>MouseEvent(source, id, when, modifiers, x, y, clickCount, popupTrigger, button)</tt>
428 * behaves in exactly the same way as the invocation
429 * <tt> {@link #MouseEvent(Component, int, long, int, int, int,
430 * int, int, int, boolean, int) MouseEvent}(source, id, when, modifiers,
431 * x, y, xAbs, yAbs, clickCount, popupTrigger, button)</tt>
432 * where xAbs and yAbs defines as source's location on screen plus
433 * relative coordinates x and y.
434 * xAbs and yAbs are set to zero if the source is not showing.
435 * This method throws an
436 * <code>IllegalArgumentException</code> if <code>source</code>
437 * is <code>null</code>.
438 *
439 * @param source the <code>Component</code> that originated the event
440 * @param id the integer that identifies the event
441 * @param when a long int that gives the time the event occurred
442 * @param modifiers the modifier keys down during event (e.g. shift, ctrl,
443 * alt, meta)
444 * Either extended _DOWN_MASK or old _MASK modifiers
445 * should be used, but both models should not be mixed
446 * in one event. Use of the extended modifiers is
447 * preferred.
448 * @param x the horizontal x coordinate for the mouse location
449 * @param y the vertical y coordinate for the mouse location
450 * @param clickCount the number of mouse clicks associated with event
451 * @param popupTrigger a boolean, true if this event is a trigger for a
452 * popup menu
453 * @param button which of the mouse buttons has changed state.
454 * <code>NOBUTTON</code>,
455 * <code>BUTTON1</code>,
456 * <code>BUTTON2</code> or
457 * <code>BUTTON3</code>.
458 * @throws IllegalArgumentException if an invalid <code>button</code>
459 * value is passed in
460 * @throws IllegalArgumentException if <code>source</code> is null
461 * @since 1.4
462 */
463 public MouseEvent(Component source, int id, long when,
464 int modifiers, int x, int y, int clickCount,
465 boolean popupTrigger, int button) {
466 this (source, id, when, modifiers, x, y, 0, 0, clickCount,
467 popupTrigger, button);
468 Point eventLocationOnScreen = new Point(0, 0);
469 try {
470 eventLocationOnScreen = source.getLocationOnScreen();
471 this .xAbs = eventLocationOnScreen.x + x;
472 this .yAbs = eventLocationOnScreen.y + y;
473 } catch (IllegalComponentStateException e) {
474 this .xAbs = 0;
475 this .yAbs = 0;
476 }
477 }
478
479 /**
480 * Constructs a <code>MouseEvent</code> object with the
481 * specified source component,
482 * type, modifiers, coordinates, and click count.
483 * <p>Note that passing in an invalid <code>id</code> results in
484 * unspecified behavior.
485 * An invocation of the form
486 * <tt>MouseEvent(source, id, when, modifiers, x, y, clickCount, popupTrigger)</tt>
487 * behaves in exactly the same way as the invocation
488 * <tt> {@link #MouseEvent(Component, int, long, int, int, int,
489 * int, int, int, boolean, int) MouseEvent}(source, id, when, modifiers,
490 * x, y, xAbs, yAbs, clickCount, popupTrigger, MouseEvent.NOBUTTON)</tt>
491 * where xAbs and yAbs defines as source's location on screen plus
492 * relative coordinates x and y.
493 * xAbs and yAbs are set to zero if the source is not showing.
494 * This method throws an <code>IllegalArgumentException</code>
495 * if <code>source</code> is <code>null</code>.
496 *
497 * @param source the <code>Component</code> that originated the event
498 * @param id the integer that identifies the event
499 * @param when a long int that gives the time the event occurred
500 * @param modifiers the modifier keys down during event (e.g. shift, ctrl,
501 * alt, meta)
502 * Either extended _DOWN_MASK or old _MASK modifiers
503 * should be used, but both models should not be mixed
504 * in one event. Use of the extended modifiers is
505 * preferred.
506 * @param x the horizontal x coordinate for the mouse location
507 * @param y the vertical y coordinate for the mouse location
508 * @param clickCount the number of mouse clicks associated with event
509 * @param popupTrigger a boolean, true if this event is a trigger for a
510 * popup menu
511 * @throws IllegalArgumentException if <code>source</code> is null
512 */
513 public MouseEvent(Component source, int id, long when,
514 int modifiers, int x, int y, int clickCount,
515 boolean popupTrigger) {
516 this (source, id, when, modifiers, x, y, clickCount,
517 popupTrigger, NOBUTTON);
518 }
519
520 /**
521 * Constructs a <code>MouseEvent</code> object with the
522 * specified source component,
523 * type, modifiers, coordinates, absolute coordinates, and click count.
524 * <p>
525 * Note that passing in an invalid <code>id</code> results in
526 * unspecified behavior. Creating an invalid event (such
527 * as by using more than one of the old _MASKs, or modifier/button
528 * values which don't match) results in unspecified behavior.
529 * Even if inconsistent values for relative and absolute coordinates are
530 * passed to the constructor, the mouse event instance is still
531 * created and no exception is thrown.
532 * This method throws an
533 * <code>IllegalArgumentException</code> if <code>source</code>
534 * is <code>null</code>.
535 *
536 * @param source the <code>Component</code> that originated the event
537 * @param id the integer that identifies the event
538 * @param when a long int that gives the time the event occurred
539 * @param modifiers the modifier keys down during event (e.g. shift, ctrl,
540 * alt, meta)
541 * Either extended _DOWN_MASK or old _MASK modifiers
542 * should be used, but both models should not be mixed
543 * in one event. Use of the extended modifiers is
544 * preferred.
545 * @param x the horizontal x coordinate for the mouse location
546 * @param y the vertical y coordinate for the mouse location
547 * @param xAbs the absolute horizontal x coordinate for the mouse location
548 * @param yAbs the absolute vertical y coordinate for the mouse location
549 * @param clickCount the number of mouse clicks associated with event
550 * @param popupTrigger a boolean, true if this event is a trigger for a
551 * popup menu
552 * @param button which of the mouse buttons has changed state.
553 * <code>NOBUTTON</code>,
554 * <code>BUTTON1</code>,
555 * <code>BUTTON2</code> or
556 * <code>BUTTON3</code>.
557 * @throws IllegalArgumentException if an invalid <code>button</code>
558 * value is passed in
559 * @throws IllegalArgumentException if <code>source</code> is null
560 * @since 1.6
561 */
562 public MouseEvent(Component source, int id, long when,
563 int modifiers, int x, int y, int xAbs, int yAbs,
564 int clickCount, boolean popupTrigger, int button) {
565 super (source, id, when, modifiers);
566 this .x = x;
567 this .y = y;
568 this .xAbs = xAbs;
569 this .yAbs = yAbs;
570 this .clickCount = clickCount;
571 this .popupTrigger = popupTrigger;
572 if (button < NOBUTTON || button > BUTTON3) {
573 throw new IllegalArgumentException("Invalid button value");
574 }
575 this .button = button;
576 if ((getModifiers() != 0) && (getModifiersEx() == 0)) {
577 setNewModifiers();
578 } else if ((getModifiers() == 0)
579 && (getModifiersEx() != 0 || button != NOBUTTON)) {
580 setOldModifiers();
581 }
582 }
583
584 /**
585 * Returns the horizontal x position of the event relative to the
586 * source component.
587 *
588 * @return x an integer indicating horizontal position relative to
589 * the component
590 */
591 public int getX() {
592 return x;
593 }
594
595 /**
596 * Returns the vertical y position of the event relative to the
597 * source component.
598 *
599 * @return y an integer indicating vertical position relative to
600 * the component
601 */
602 public int getY() {
603 return y;
604 }
605
606 /**
607 * Returns the x,y position of the event relative to the source component.
608 *
609 * @return a <code>Point</code> object containing the x and y coordinates
610 * relative to the source component
611 *
612 */
613 public Point getPoint() {
614 int x;
615 int y;
616 synchronized (this ) {
617 x = this .x;
618 y = this .y;
619 }
620 return new Point(x, y);
621 }
622
623 /**
624 * Translates the event's coordinates to a new position
625 * by adding specified <code>x</code> (horizontal) and <code>y</code>
626 * (vertical) offsets.
627 *
628 * @param x the horizontal x value to add to the current x
629 * coordinate position
630 * @param y the vertical y value to add to the current y
631 coordinate position
632 */
633 public synchronized void translatePoint(int x, int y) {
634 this .x += x;
635 this .y += y;
636 }
637
638 /**
639 * Returns the number of mouse clicks associated with this event.
640 *
641 * @return integer value for the number of clicks
642 */
643 public int getClickCount() {
644 return clickCount;
645 }
646
647 /**
648 * Returns which, if any, of the mouse buttons has changed state.
649 *
650 * @return one of the following constants:
651 * <code>NOBUTTON</code>,
652 * <code>BUTTON1</code>,
653 * <code>BUTTON2</code> or
654 * <code>BUTTON3</code>.
655 * @since 1.4
656 */
657 public int getButton() {
658 return button;
659 }
660
661 /**
662 * Returns whether or not this mouse event is the popup menu
663 * trigger event for the platform.
664 * <p><b>Note</b>: Popup menus are triggered differently
665 * on different systems. Therefore, <code>isPopupTrigger</code>
666 * should be checked in both <code>mousePressed</code>
667 * and <code>mouseReleased</code>
668 * for proper cross-platform functionality.
669 *
670 * @return boolean, true if this event is the popup menu trigger
671 * for this platform
672 */
673 public boolean isPopupTrigger() {
674 return popupTrigger;
675 }
676
677 /**
678 * Returns a <code>String</code> describing the modifier keys and
679 * mouse buttons that were down during the event, such as "Shift",
680 * or "Ctrl+Shift". These strings can be localized by changing
681 * the <code>awt.properties</code> file.
682 * <p>
683 * Note that <code>InputEvent.ALT_MASK</code> and
684 * <code>InputEvent.BUTTON2_MASK</code> have the same value,
685 * so the string "Alt" is returned for both modifiers. Likewise,
686 * <code>InputEvent.META_MASK</code> and
687 * <code>InputEvent.BUTTON3_MASK</code> have the same value,
688 * so the string "Meta" is returned for both modifiers.
689 *
690 * @param modifiers a modifier mask describing the modifier keys and
691 * mouse buttons that were down during the event
692 * @return string a text description of the combination of modifier
693 * keys and mouse buttons that were down during the event
694 * @see InputEvent#getModifiersExText(int)
695 * @since 1.4
696 */
697 public static String getMouseModifiersText(int modifiers) {
698 StringBuilder buf = new StringBuilder();
699 if ((modifiers & InputEvent.ALT_MASK) != 0) {
700 buf.append(Toolkit.getProperty("AWT.alt", "Alt"));
701 buf.append("+");
702 }
703 if ((modifiers & InputEvent.META_MASK) != 0) {
704 buf.append(Toolkit.getProperty("AWT.meta", "Meta"));
705 buf.append("+");
706 }
707 if ((modifiers & InputEvent.CTRL_MASK) != 0) {
708 buf.append(Toolkit.getProperty("AWT.control", "Ctrl"));
709 buf.append("+");
710 }
711 if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
712 buf.append(Toolkit.getProperty("AWT.shift", "Shift"));
713 buf.append("+");
714 }
715 if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
716 buf
717 .append(Toolkit.getProperty("AWT.altGraph",
718 "Alt Graph"));
719 buf.append("+");
720 }
721 if ((modifiers & InputEvent.BUTTON1_MASK) != 0) {
722 buf.append(Toolkit.getProperty("AWT.button1", "Button1"));
723 buf.append("+");
724 }
725 if ((modifiers & InputEvent.BUTTON2_MASK) != 0) {
726 buf.append(Toolkit.getProperty("AWT.button2", "Button2"));
727 buf.append("+");
728 }
729 if ((modifiers & InputEvent.BUTTON3_MASK) != 0) {
730 buf.append(Toolkit.getProperty("AWT.button3", "Button3"));
731 buf.append("+");
732 }
733 if (buf.length() > 0) {
734 buf.setLength(buf.length() - 1); // remove trailing '+'
735 }
736 return buf.toString();
737 }
738
739 /**
740 * Returns a parameter string identifying this event.
741 * This method is useful for event-logging and for debugging.
742 *
743 * @return a string identifying the event and its attributes
744 */
745 public String paramString() {
746 StringBuilder str = new StringBuilder(80);
747
748 switch (id) {
749 case MOUSE_PRESSED:
750 str.append("MOUSE_PRESSED");
751 break;
752 case MOUSE_RELEASED:
753 str.append("MOUSE_RELEASED");
754 break;
755 case MOUSE_CLICKED:
756 str.append("MOUSE_CLICKED");
757 break;
758 case MOUSE_ENTERED:
759 str.append("MOUSE_ENTERED");
760 break;
761 case MOUSE_EXITED:
762 str.append("MOUSE_EXITED");
763 break;
764 case MOUSE_MOVED:
765 str.append("MOUSE_MOVED");
766 break;
767 case MOUSE_DRAGGED:
768 str.append("MOUSE_DRAGGED");
769 break;
770 case MOUSE_WHEEL:
771 str.append("MOUSE_WHEEL");
772 break;
773 default:
774 str.append("unknown type");
775 }
776
777 // (x,y) coordinates
778 str.append(",(").append(x).append(",").append(y).append(")");
779 str.append(",absolute(").append(xAbs).append(",").append(yAbs)
780 .append(")");
781
782 str.append(",button=").append(getButton());
783
784 if (getModifiers() != 0) {
785 str.append(",modifiers=").append(
786 getMouseModifiersText(modifiers));
787 }
788
789 if (getModifiersEx() != 0) {
790 str.append(",extModifiers=").append(
791 getModifiersExText(modifiers));
792 }
793
794 str.append(",clickCount=").append(clickCount);
795
796 return str.toString();
797 }
798
799 /**
800 * Sets new modifiers by the old ones.
801 * Also sets button.
802 */
803 private void setNewModifiers() {
804 if ((modifiers & BUTTON1_MASK) != 0) {
805 modifiers |= BUTTON1_DOWN_MASK;
806 }
807 if ((modifiers & BUTTON2_MASK) != 0) {
808 modifiers |= BUTTON2_DOWN_MASK;
809 }
810 if ((modifiers & BUTTON3_MASK) != 0) {
811 modifiers |= BUTTON3_DOWN_MASK;
812 }
813 if (id == MOUSE_PRESSED || id == MOUSE_RELEASED
814 || id == MOUSE_CLICKED) {
815 if ((modifiers & BUTTON1_MASK) != 0) {
816 button = BUTTON1;
817 modifiers &= ~BUTTON2_MASK & ~BUTTON3_MASK;
818 if (id != MOUSE_PRESSED) {
819 modifiers &= ~BUTTON1_DOWN_MASK;
820 }
821 } else if ((modifiers & BUTTON2_MASK) != 0) {
822 button = BUTTON2;
823 modifiers &= ~BUTTON1_MASK & ~BUTTON3_MASK;
824 if (id != MOUSE_PRESSED) {
825 modifiers &= ~BUTTON2_DOWN_MASK;
826 }
827 } else if ((modifiers & BUTTON3_MASK) != 0) {
828 button = BUTTON3;
829 modifiers &= ~BUTTON1_MASK & ~BUTTON2_MASK;
830 if (id != MOUSE_PRESSED) {
831 modifiers &= ~BUTTON3_DOWN_MASK;
832 }
833 }
834 }
835 if ((modifiers & InputEvent.ALT_MASK) != 0) {
836 modifiers |= InputEvent.ALT_DOWN_MASK;
837 }
838 if ((modifiers & InputEvent.META_MASK) != 0) {
839 modifiers |= InputEvent.META_DOWN_MASK;
840 }
841 if ((modifiers & InputEvent.SHIFT_MASK) != 0) {
842 modifiers |= InputEvent.SHIFT_DOWN_MASK;
843 }
844 if ((modifiers & InputEvent.CTRL_MASK) != 0) {
845 modifiers |= InputEvent.CTRL_DOWN_MASK;
846 }
847 if ((modifiers & InputEvent.ALT_GRAPH_MASK) != 0) {
848 modifiers |= InputEvent.ALT_GRAPH_DOWN_MASK;
849 }
850 }
851
852 /**
853 * Sets old modifiers by the new ones.
854 */
855 private void setOldModifiers() {
856 if (id == MOUSE_PRESSED || id == MOUSE_RELEASED
857 || id == MOUSE_CLICKED) {
858 switch (button) {
859 case BUTTON1:
860 modifiers |= BUTTON1_MASK;
861 break;
862 case BUTTON2:
863 modifiers |= BUTTON2_MASK;
864 break;
865 case BUTTON3:
866 modifiers |= BUTTON3_MASK;
867 break;
868 }
869 } else {
870 if ((modifiers & BUTTON1_DOWN_MASK) != 0) {
871 modifiers |= BUTTON1_MASK;
872 }
873 if ((modifiers & BUTTON2_DOWN_MASK) != 0) {
874 modifiers |= BUTTON2_MASK;
875 }
876 if ((modifiers & BUTTON3_DOWN_MASK) != 0) {
877 modifiers |= BUTTON3_MASK;
878 }
879 }
880 if ((modifiers & ALT_DOWN_MASK) != 0) {
881 modifiers |= ALT_MASK;
882 }
883 if ((modifiers & META_DOWN_MASK) != 0) {
884 modifiers |= META_MASK;
885 }
886 if ((modifiers & SHIFT_DOWN_MASK) != 0) {
887 modifiers |= SHIFT_MASK;
888 }
889 if ((modifiers & CTRL_DOWN_MASK) != 0) {
890 modifiers |= CTRL_MASK;
891 }
892 if ((modifiers & ALT_GRAPH_DOWN_MASK) != 0) {
893 modifiers |= ALT_GRAPH_MASK;
894 }
895 }
896
897 /**
898 * Sets new modifiers by the old ones.
899 * @serial
900 */
901 private void readObject(ObjectInputStream s) throws IOException,
902 ClassNotFoundException {
903 s.defaultReadObject();
904 if (getModifiers() != 0 && getModifiersEx() == 0) {
905 setNewModifiers();
906 }
907 }
908 }
|