1 /*
2 * Copyright (c) 1995, 2014, 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
24 */
25 package java.awt;
26
27 import java.awt.dnd.DropTarget;
28
29 import java.awt.event.*;
30
31 import java.awt.peer.ContainerPeer;
32 import java.awt.peer.ComponentPeer;
33 import java.awt.peer.LightweightPeer;
34
35 import java.beans.PropertyChangeListener;
36
37 import java.io.IOException;
38 import java.io.ObjectInputStream;
39 import java.io.ObjectOutputStream;
40 import java.io.ObjectStreamField;
41 import java.io.PrintStream;
42 import java.io.PrintWriter;
43
44 import java.security.AccessController;
45
46 import java.util.EventListener;
47 import java.util.HashSet;
48 import java.util.Set;
49
50 import javax.accessibility.*;
51
52 import sun.util.logging.PlatformLogger;
53
54 import sun.awt.AppContext;
55 import sun.awt.AWTAccessor;
56 import sun.awt.CausedFocusEvent;
57 import sun.awt.PeerEvent;
58 import sun.awt.SunToolkit;
59
60 import sun.awt.dnd.SunDropTargetEvent;
61
62 import sun.java2d.pipe.Region;
63
3304 }
3305 }
3306 }
3307 }
3308
3309 if (reset) {
3310 KeyboardFocusManager.setMostRecentFocusOwner(window, null);
3311 }
3312 }
3313
3314 void clearCurrentFocusCycleRootOnHide() {
3315 KeyboardFocusManager kfm =
3316 KeyboardFocusManager.getCurrentKeyboardFocusManager();
3317 Container cont = kfm.getCurrentFocusCycleRoot();
3318
3319 if (cont == this || isParentOf(cont)) {
3320 kfm.setGlobalCurrentFocusCycleRootPriv(null);
3321 }
3322 }
3323
3324 @Override
3325 void clearLightweightDispatcherOnRemove(Component removedComponent) {
3326 if (dispatcher != null) {
3327 dispatcher.removeReferences(removedComponent);
3328 } else {
3329 //It is a Lightweight Container, should clear parent`s Dispatcher
3330 super.clearLightweightDispatcherOnRemove(removedComponent);
3331 }
3332 }
3333
3334 final Container getTraversalRoot() {
3335 if (isFocusCycleRoot()) {
3336 return findTraversalRoot();
3337 }
3338
3339 return super.getTraversalRoot();
3340 }
3341
3342 /**
3343 * Sets the focus traversal policy that will manage keyboard traversal of
3344 * this Container's children, if this Container is a focus cycle root. If
3345 * the argument is null, this Container inherits its policy from its focus-
3346 * cycle-root ancestor. If the argument is non-null, this policy will be
3347 * inherited by all focus-cycle-root children that have no keyboard-
3348 * traversal policy of their own (as will, recursively, their focus-cycle-
3349 * root children).
3350 * <p>
3351 * If this Container is not a focus cycle root, the policy will be
3352 * remembered, but will not be used or inherited by this or any other
3353 * Containers until this Container is made a focus cycle root.
4414 * because we must keep serialization compatibility.
4415 *
4416 * @author Timothy Prinzing
4417 */
4418 class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
4419
4420 /*
4421 * JDK 1.1 serialVersionUID
4422 */
4423 private static final long serialVersionUID = 5184291520170872969L;
4424 /*
4425 * Our own mouse event for when we're dragged over from another hw
4426 * container
4427 */
4428 private static final int LWD_MOUSE_DRAGGED_OVER = 1500;
4429
4430 private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.LightweightDispatcher");
4431
4432 LightweightDispatcher(Container nativeContainer) {
4433 this.nativeContainer = nativeContainer;
4434 mouseEventTarget = null;
4435 eventMask = 0;
4436 }
4437
4438 /*
4439 * Clean up any resources allocated when dispatcher was created;
4440 * should be called from Container.removeNotify
4441 */
4442 void dispose() {
4443 //System.out.println("Disposing lw dispatcher");
4444 stopListeningForOtherDrags();
4445 mouseEventTarget = null;
4446 targetLastEntered = null;
4447 targetLastEnteredDT = null;
4448 }
4449
4450 /**
4451 * Enables events to subcomponents.
4452 */
4453 void enableEvents(long events) {
4454 eventMask |= events;
4455 }
4456
4457 /**
4458 * Dispatches an event to a sub-component if necessary, and
4459 * returns whether or not the event was forwarded to a
4460 * sub-component.
4461 *
4462 * @param e the event
4463 */
4464 boolean dispatchEvent(AWTEvent e) {
4465 boolean ret = false;
4466
4467 /*
4514 return ((modifiers & (InputEvent.BUTTON1_DOWN_MASK
4515 | InputEvent.BUTTON2_DOWN_MASK
4516 | InputEvent.BUTTON3_DOWN_MASK)) != 0);
4517 }
4518
4519 /**
4520 * This method attempts to distribute a mouse event to a lightweight
4521 * component. It tries to avoid doing any unnecessary probes down
4522 * into the component tree to minimize the overhead of determining
4523 * where to route the event, since mouse movement events tend to
4524 * come in large and frequent amounts.
4525 */
4526 private boolean processMouseEvent(MouseEvent e) {
4527 int id = e.getID();
4528 Component mouseOver = // sensitive to mouse events
4529 nativeContainer.getMouseEventTarget(e.getX(), e.getY(),
4530 Container.INCLUDE_SELF);
4531
4532 trackMouseEnterExit(mouseOver, e);
4533
4534 // 4508327 : MOUSE_CLICKED should only go to the recipient of
4535 // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
4536 // MOUSE_CLICKED.
4537 if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
4538 mouseEventTarget = (mouseOver != nativeContainer) ? mouseOver: null;
4539 isCleaned = false;
4540 }
4541
4542 if (mouseEventTarget != null) {
4543 switch (id) {
4544 case MouseEvent.MOUSE_ENTERED:
4545 case MouseEvent.MOUSE_EXITED:
4546 break;
4547 case MouseEvent.MOUSE_PRESSED:
4548 retargetMouseEvent(mouseEventTarget, id, e);
4549 break;
4550 case MouseEvent.MOUSE_RELEASED:
4551 retargetMouseEvent(mouseEventTarget, id, e);
4552 break;
4553 case MouseEvent.MOUSE_CLICKED:
4554 // 4508327: MOUSE_CLICKED should never be dispatched to a Component
4555 // other than that which received the MOUSE_PRESSED event. If the
4556 // mouse is now over a different Component, don't dispatch the event.
4557 // The previous fix for a similar problem was associated with bug
4558 // 4155217.
4559 if (mouseOver == mouseEventTarget) {
4560 retargetMouseEvent(mouseOver, id, e);
4561 }
4562 break;
4563 case MouseEvent.MOUSE_MOVED:
4564 retargetMouseEvent(mouseEventTarget, id, e);
4565 break;
4566 case MouseEvent.MOUSE_DRAGGED:
4567 if (isMouseGrab(e)) {
4568 retargetMouseEvent(mouseEventTarget, id, e);
4569 }
4570 break;
4571 case MouseEvent.MOUSE_WHEEL:
4572 // This may send it somewhere that doesn't have MouseWheelEvents
4573 // enabled. In this case, Component.dispatchEventImpl() will
4574 // retarget the event to a parent that DOES have the events enabled.
4575 if (eventLog.isLoggable(PlatformLogger.Level.FINEST) && (mouseOver != null)) {
4576 eventLog.finest("retargeting mouse wheel to " +
4577 mouseOver.getName() + ", " +
4578 mouseOver.getClass());
4579 }
4580 retargetMouseEvent(mouseOver, id, e);
4581 break;
4582 }
4583 //Consuming of wheel events is implemented in "retargetMouseEvent".
4584 if (id != MouseEvent.MOUSE_WHEEL) {
4585 e.consume();
4586 }
4587 } else if (isCleaned && id != MouseEvent.MOUSE_WHEEL) {
4588 //After mouseEventTarget was removed and cleaned should consume all events
4589 //until new mouseEventTarget is found
4590 e.consume();
4591 }
4592 return e.isConsumed();
4593 }
4594
4595 private boolean processDropTargetEvent(SunDropTargetEvent e) {
4596 int id = e.getID();
4597 int x = e.getX();
4598 int y = e.getY();
4599
4600 /*
4601 * Fix for BugTraq ID 4395290.
4602 * It is possible that SunDropTargetEvent's Point is outside of the
4603 * native container bounds. In this case we truncate coordinates.
4604 */
4605 if (!nativeContainer.contains(x, y)) {
4606 final Dimension d = nativeContainer.getSize();
4607 if (d.width <= x) {
4608 x = d.width - 1;
4609 } else if (x < 0) {
4610 x = 0;
4635 }
4636
4637 /*
4638 * Generates dnd enter/exit events as mouse moves over lw components
4639 * @param targetOver Target mouse is over (including native container)
4640 * @param e SunDropTarget mouse event in native container
4641 */
4642 private void trackDropTargetEnterExit(Component targetOver, MouseEvent e) {
4643 int id = e.getID();
4644 if (id == MouseEvent.MOUSE_ENTERED && isMouseDTInNativeContainer) {
4645 // This can happen if a lightweight component which initiated the
4646 // drag has an associated drop target. MOUSE_ENTERED comes when the
4647 // mouse is in the native container already. To propagate this event
4648 // properly we should null out targetLastEntered.
4649 targetLastEnteredDT = null;
4650 } else if (id == MouseEvent.MOUSE_ENTERED) {
4651 isMouseDTInNativeContainer = true;
4652 } else if (id == MouseEvent.MOUSE_EXITED) {
4653 isMouseDTInNativeContainer = false;
4654 }
4655 targetLastEnteredDT = retargetMouseEnterExit(targetOver, e,
4656 targetLastEnteredDT,
4657 isMouseDTInNativeContainer);
4658 }
4659
4660 /*
4661 * Generates enter/exit events as mouse moves over lw components
4662 * @param targetOver Target mouse is over (including native container)
4663 * @param e Mouse event in native container
4664 */
4665 private void trackMouseEnterExit(Component targetOver, MouseEvent e) {
4666 if (e instanceof SunDropTargetEvent) {
4667 trackDropTargetEnterExit(targetOver, e);
4668 return;
4669 }
4670 int id = e.getID();
4671
4672 if ( id != MouseEvent.MOUSE_EXITED &&
4673 id != MouseEvent.MOUSE_DRAGGED &&
4674 id != LWD_MOUSE_DRAGGED_OVER &&
4675 !isMouseInNativeContainer) {
4676 // any event but an exit or drag means we're in the native container
4677 isMouseInNativeContainer = true;
4678 startListeningForOtherDrags();
4679 } else if (id == MouseEvent.MOUSE_EXITED) {
4680 isMouseInNativeContainer = false;
4681 stopListeningForOtherDrags();
4682 }
4683 targetLastEntered = retargetMouseEnterExit(targetOver, e,
4684 targetLastEntered,
4685 isMouseInNativeContainer);
4686 }
4687
4688 private Component retargetMouseEnterExit(Component targetOver, MouseEvent e,
4689 Component lastEntered,
4690 boolean inNativeContainer) {
4691 int id = e.getID();
4692 Component targetEnter = inNativeContainer ? targetOver : null;
4693
4694 if (lastEntered != targetEnter) {
4695 if (lastEntered != null) {
4696 retargetMouseEvent(lastEntered, MouseEvent.MOUSE_EXITED, e);
4697 }
4698 if (id == MouseEvent.MOUSE_EXITED) {
4699 // consume native exit event if we generate one
4700 e.consume();
4701 }
4702
4703 if (targetEnter != null) {
4704 retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);
4705 }
4927
4928 // --- member variables -------------------------------
4929
4930 /**
4931 * The windowed container that might be hosting events for
4932 * subcomponents.
4933 */
4934 private Container nativeContainer;
4935
4936 /**
4937 * This variable is not used, but kept for serialization compatibility
4938 */
4939 private Component focus;
4940
4941 /**
4942 * The current subcomponent being hosted by this windowed
4943 * component that has events being forwarded to it. If this
4944 * is null, there are currently no events being forwarded to
4945 * a subcomponent.
4946 */
4947 private transient Component mouseEventTarget;
4948
4949 /**
4950 * The last component entered by the {@code MouseEvent}.
4951 */
4952 private transient Component targetLastEntered;
4953
4954 /**
4955 * The last component entered by the {@code SunDropTargetEvent}.
4956 */
4957 private transient Component targetLastEnteredDT;
4958
4959 /**
4960 * Indicates whether {@code mouseEventTarget} was removed and nulled
4961 */
4962 private transient boolean isCleaned;
4963
4964 /**
4965 * Is the mouse over the native container.
4966 */
4967 private transient boolean isMouseInNativeContainer = false;
4968
4969 /**
4970 * Is DnD over the native container.
4971 */
4972 private transient boolean isMouseDTInNativeContainer = false;
4973
4974 /**
4975 * This variable is not used, but kept for serialization compatibility
4976 */
4977 private Cursor nativeCursor;
4978
4979 /**
4980 * The event mask for contained lightweight components. Lightweight
4981 * components need a windowed container to host window-related
4982 * events. This separate mask indicates events that have been
4983 * requested by contained lightweight components without effecting
4984 * the mask of the windowed component itself.
4985 */
4986 private long eventMask;
4987
4988 /**
4989 * The kind of events routed to lightweight components from windowed
4990 * hosts.
4991 */
4992 private static final long PROXY_EVENT_MASK =
4993 AWTEvent.FOCUS_EVENT_MASK |
4994 AWTEvent.KEY_EVENT_MASK |
4995 AWTEvent.MOUSE_EVENT_MASK |
4996 AWTEvent.MOUSE_MOTION_EVENT_MASK |
4997 AWTEvent.MOUSE_WHEEL_EVENT_MASK;
4998
4999 private static final long MOUSE_MASK =
5000 AWTEvent.MOUSE_EVENT_MASK |
5001 AWTEvent.MOUSE_MOTION_EVENT_MASK |
5002 AWTEvent.MOUSE_WHEEL_EVENT_MASK;
5003
5004 void removeReferences(Component removedComponent) {
5005 if (mouseEventTarget == removedComponent) {
5006 isCleaned = true;
5007 mouseEventTarget = null;
5008 }
5009 if (targetLastEntered == removedComponent) {
5010 targetLastEntered = null;
5011 }
5012 if (targetLastEnteredDT == removedComponent) {
5013 targetLastEnteredDT = null;
5014 }
5015 }
5016 }
|
1 /*
2 * Copyright (c) 1995, 2015, 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
24 */
25 package java.awt;
26
27 import java.awt.dnd.DropTarget;
28
29 import java.awt.event.*;
30
31 import java.awt.peer.ContainerPeer;
32 import java.awt.peer.ComponentPeer;
33 import java.awt.peer.LightweightPeer;
34
35 import java.beans.PropertyChangeListener;
36
37 import java.io.IOException;
38 import java.io.ObjectInputStream;
39 import java.io.ObjectOutputStream;
40 import java.io.ObjectStreamField;
41 import java.io.PrintStream;
42 import java.io.PrintWriter;
43
44 import java.lang.ref.WeakReference;
45 import java.security.AccessController;
46
47 import java.util.EventListener;
48 import java.util.HashSet;
49 import java.util.Set;
50
51 import javax.accessibility.*;
52
53 import sun.util.logging.PlatformLogger;
54
55 import sun.awt.AppContext;
56 import sun.awt.AWTAccessor;
57 import sun.awt.CausedFocusEvent;
58 import sun.awt.PeerEvent;
59 import sun.awt.SunToolkit;
60
61 import sun.awt.dnd.SunDropTargetEvent;
62
63 import sun.java2d.pipe.Region;
64
3305 }
3306 }
3307 }
3308 }
3309
3310 if (reset) {
3311 KeyboardFocusManager.setMostRecentFocusOwner(window, null);
3312 }
3313 }
3314
3315 void clearCurrentFocusCycleRootOnHide() {
3316 KeyboardFocusManager kfm =
3317 KeyboardFocusManager.getCurrentKeyboardFocusManager();
3318 Container cont = kfm.getCurrentFocusCycleRoot();
3319
3320 if (cont == this || isParentOf(cont)) {
3321 kfm.setGlobalCurrentFocusCycleRootPriv(null);
3322 }
3323 }
3324
3325 final Container getTraversalRoot() {
3326 if (isFocusCycleRoot()) {
3327 return findTraversalRoot();
3328 }
3329
3330 return super.getTraversalRoot();
3331 }
3332
3333 /**
3334 * Sets the focus traversal policy that will manage keyboard traversal of
3335 * this Container's children, if this Container is a focus cycle root. If
3336 * the argument is null, this Container inherits its policy from its focus-
3337 * cycle-root ancestor. If the argument is non-null, this policy will be
3338 * inherited by all focus-cycle-root children that have no keyboard-
3339 * traversal policy of their own (as will, recursively, their focus-cycle-
3340 * root children).
3341 * <p>
3342 * If this Container is not a focus cycle root, the policy will be
3343 * remembered, but will not be used or inherited by this or any other
3344 * Containers until this Container is made a focus cycle root.
4405 * because we must keep serialization compatibility.
4406 *
4407 * @author Timothy Prinzing
4408 */
4409 class LightweightDispatcher implements java.io.Serializable, AWTEventListener {
4410
4411 /*
4412 * JDK 1.1 serialVersionUID
4413 */
4414 private static final long serialVersionUID = 5184291520170872969L;
4415 /*
4416 * Our own mouse event for when we're dragged over from another hw
4417 * container
4418 */
4419 private static final int LWD_MOUSE_DRAGGED_OVER = 1500;
4420
4421 private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.LightweightDispatcher");
4422
4423 LightweightDispatcher(Container nativeContainer) {
4424 this.nativeContainer = nativeContainer;
4425 mouseEventTarget = new WeakReference<>(null);
4426 targetLastEntered = new WeakReference<>(null);
4427 targetLastEnteredDT = new WeakReference<>(null);
4428 eventMask = 0;
4429 }
4430
4431 /*
4432 * Clean up any resources allocated when dispatcher was created;
4433 * should be called from Container.removeNotify
4434 */
4435 void dispose() {
4436 //System.out.println("Disposing lw dispatcher");
4437 stopListeningForOtherDrags();
4438 mouseEventTarget.clear();
4439 targetLastEntered.clear();
4440 targetLastEnteredDT.clear();
4441 }
4442
4443 /**
4444 * Enables events to subcomponents.
4445 */
4446 void enableEvents(long events) {
4447 eventMask |= events;
4448 }
4449
4450 /**
4451 * Dispatches an event to a sub-component if necessary, and
4452 * returns whether or not the event was forwarded to a
4453 * sub-component.
4454 *
4455 * @param e the event
4456 */
4457 boolean dispatchEvent(AWTEvent e) {
4458 boolean ret = false;
4459
4460 /*
4507 return ((modifiers & (InputEvent.BUTTON1_DOWN_MASK
4508 | InputEvent.BUTTON2_DOWN_MASK
4509 | InputEvent.BUTTON3_DOWN_MASK)) != 0);
4510 }
4511
4512 /**
4513 * This method attempts to distribute a mouse event to a lightweight
4514 * component. It tries to avoid doing any unnecessary probes down
4515 * into the component tree to minimize the overhead of determining
4516 * where to route the event, since mouse movement events tend to
4517 * come in large and frequent amounts.
4518 */
4519 private boolean processMouseEvent(MouseEvent e) {
4520 int id = e.getID();
4521 Component mouseOver = // sensitive to mouse events
4522 nativeContainer.getMouseEventTarget(e.getX(), e.getY(),
4523 Container.INCLUDE_SELF);
4524
4525 trackMouseEnterExit(mouseOver, e);
4526
4527 Component met = mouseEventTarget.get();
4528 // 4508327 : MOUSE_CLICKED should only go to the recipient of
4529 // the accompanying MOUSE_PRESSED, so don't reset mouseEventTarget on a
4530 // MOUSE_CLICKED.
4531 if (!isMouseGrab(e) && id != MouseEvent.MOUSE_CLICKED) {
4532 met = (mouseOver != nativeContainer) ? mouseOver : null;
4533 mouseEventTarget = new WeakReference<>(met);
4534 }
4535
4536 if (met != null) {
4537 switch (id) {
4538 case MouseEvent.MOUSE_ENTERED:
4539 case MouseEvent.MOUSE_EXITED:
4540 break;
4541 case MouseEvent.MOUSE_PRESSED:
4542 retargetMouseEvent(met, id, e);
4543 break;
4544 case MouseEvent.MOUSE_RELEASED:
4545 retargetMouseEvent(met, id, e);
4546 break;
4547 case MouseEvent.MOUSE_CLICKED:
4548 // 4508327: MOUSE_CLICKED should never be dispatched to a Component
4549 // other than that which received the MOUSE_PRESSED event. If the
4550 // mouse is now over a different Component, don't dispatch the event.
4551 // The previous fix for a similar problem was associated with bug
4552 // 4155217.
4553 if (mouseOver == met) {
4554 retargetMouseEvent(mouseOver, id, e);
4555 }
4556 break;
4557 case MouseEvent.MOUSE_MOVED:
4558 retargetMouseEvent(met, id, e);
4559 break;
4560 case MouseEvent.MOUSE_DRAGGED:
4561 if (isMouseGrab(e)) {
4562 retargetMouseEvent(met, id, e);
4563 }
4564 break;
4565 case MouseEvent.MOUSE_WHEEL:
4566 // This may send it somewhere that doesn't have MouseWheelEvents
4567 // enabled. In this case, Component.dispatchEventImpl() will
4568 // retarget the event to a parent that DOES have the events enabled.
4569 if (eventLog.isLoggable(PlatformLogger.Level.FINEST) && (mouseOver != null)) {
4570 eventLog.finest("retargeting mouse wheel to " +
4571 mouseOver.getName() + ", " +
4572 mouseOver.getClass());
4573 }
4574 retargetMouseEvent(mouseOver, id, e);
4575 break;
4576 }
4577 //Consuming of wheel events is implemented in "retargetMouseEvent".
4578 if (id != MouseEvent.MOUSE_WHEEL) {
4579 e.consume();
4580 }
4581 }
4582 return e.isConsumed();
4583 }
4584
4585 private boolean processDropTargetEvent(SunDropTargetEvent e) {
4586 int id = e.getID();
4587 int x = e.getX();
4588 int y = e.getY();
4589
4590 /*
4591 * Fix for BugTraq ID 4395290.
4592 * It is possible that SunDropTargetEvent's Point is outside of the
4593 * native container bounds. In this case we truncate coordinates.
4594 */
4595 if (!nativeContainer.contains(x, y)) {
4596 final Dimension d = nativeContainer.getSize();
4597 if (d.width <= x) {
4598 x = d.width - 1;
4599 } else if (x < 0) {
4600 x = 0;
4625 }
4626
4627 /*
4628 * Generates dnd enter/exit events as mouse moves over lw components
4629 * @param targetOver Target mouse is over (including native container)
4630 * @param e SunDropTarget mouse event in native container
4631 */
4632 private void trackDropTargetEnterExit(Component targetOver, MouseEvent e) {
4633 int id = e.getID();
4634 if (id == MouseEvent.MOUSE_ENTERED && isMouseDTInNativeContainer) {
4635 // This can happen if a lightweight component which initiated the
4636 // drag has an associated drop target. MOUSE_ENTERED comes when the
4637 // mouse is in the native container already. To propagate this event
4638 // properly we should null out targetLastEntered.
4639 targetLastEnteredDT = null;
4640 } else if (id == MouseEvent.MOUSE_ENTERED) {
4641 isMouseDTInNativeContainer = true;
4642 } else if (id == MouseEvent.MOUSE_EXITED) {
4643 isMouseDTInNativeContainer = false;
4644 }
4645 Component tle = retargetMouseEnterExit(targetOver, e,
4646 targetLastEnteredDT.get(),
4647 isMouseDTInNativeContainer);
4648 targetLastEnteredDT = new WeakReference<>(tle);
4649 }
4650
4651 /*
4652 * Generates enter/exit events as mouse moves over lw components
4653 * @param targetOver Target mouse is over (including native container)
4654 * @param e Mouse event in native container
4655 */
4656 private void trackMouseEnterExit(Component targetOver, MouseEvent e) {
4657 if (e instanceof SunDropTargetEvent) {
4658 trackDropTargetEnterExit(targetOver, e);
4659 return;
4660 }
4661 int id = e.getID();
4662
4663 if ( id != MouseEvent.MOUSE_EXITED &&
4664 id != MouseEvent.MOUSE_DRAGGED &&
4665 id != LWD_MOUSE_DRAGGED_OVER &&
4666 !isMouseInNativeContainer) {
4667 // any event but an exit or drag means we're in the native container
4668 isMouseInNativeContainer = true;
4669 startListeningForOtherDrags();
4670 } else if (id == MouseEvent.MOUSE_EXITED) {
4671 isMouseInNativeContainer = false;
4672 stopListeningForOtherDrags();
4673 }
4674 Component tle = retargetMouseEnterExit(targetOver, e,
4675 targetLastEntered.get(),
4676 isMouseInNativeContainer);
4677 targetLastEntered = new WeakReference<>(tle);
4678 }
4679
4680 private Component retargetMouseEnterExit(Component targetOver, MouseEvent e,
4681 Component lastEntered,
4682 boolean inNativeContainer) {
4683 int id = e.getID();
4684 Component targetEnter = inNativeContainer ? targetOver : null;
4685
4686 if (lastEntered != targetEnter) {
4687 if (lastEntered != null) {
4688 retargetMouseEvent(lastEntered, MouseEvent.MOUSE_EXITED, e);
4689 }
4690 if (id == MouseEvent.MOUSE_EXITED) {
4691 // consume native exit event if we generate one
4692 e.consume();
4693 }
4694
4695 if (targetEnter != null) {
4696 retargetMouseEvent(targetEnter, MouseEvent.MOUSE_ENTERED, e);
4697 }
4919
4920 // --- member variables -------------------------------
4921
4922 /**
4923 * The windowed container that might be hosting events for
4924 * subcomponents.
4925 */
4926 private Container nativeContainer;
4927
4928 /**
4929 * This variable is not used, but kept for serialization compatibility
4930 */
4931 private Component focus;
4932
4933 /**
4934 * The current subcomponent being hosted by this windowed
4935 * component that has events being forwarded to it. If this
4936 * is null, there are currently no events being forwarded to
4937 * a subcomponent.
4938 */
4939 private transient WeakReference<Component> mouseEventTarget;
4940
4941 /**
4942 * The last component entered by the {@code MouseEvent}.
4943 */
4944 private transient WeakReference<Component> targetLastEntered;
4945
4946 /**
4947 * The last component entered by the {@code SunDropTargetEvent}.
4948 */
4949 private transient WeakReference<Component> targetLastEnteredDT;
4950
4951 /**
4952 * Is the mouse over the native container.
4953 */
4954 private transient boolean isMouseInNativeContainer = false;
4955
4956 /**
4957 * Is DnD over the native container.
4958 */
4959 private transient boolean isMouseDTInNativeContainer = false;
4960
4961 /**
4962 * This variable is not used, but kept for serialization compatibility
4963 */
4964 private Cursor nativeCursor;
4965
4966 /**
4967 * The event mask for contained lightweight components. Lightweight
4968 * components need a windowed container to host window-related
4969 * events. This separate mask indicates events that have been
4970 * requested by contained lightweight components without effecting
4971 * the mask of the windowed component itself.
4972 */
4973 private long eventMask;
4974
4975 /**
4976 * The kind of events routed to lightweight components from windowed
4977 * hosts.
4978 */
4979 private static final long PROXY_EVENT_MASK =
4980 AWTEvent.FOCUS_EVENT_MASK |
4981 AWTEvent.KEY_EVENT_MASK |
4982 AWTEvent.MOUSE_EVENT_MASK |
4983 AWTEvent.MOUSE_MOTION_EVENT_MASK |
4984 AWTEvent.MOUSE_WHEEL_EVENT_MASK;
4985
4986 private static final long MOUSE_MASK =
4987 AWTEvent.MOUSE_EVENT_MASK |
4988 AWTEvent.MOUSE_MOTION_EVENT_MASK |
4989 AWTEvent.MOUSE_WHEEL_EVENT_MASK;
4990 }
|