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