1 /*
2 * Copyright (c) 2011, 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
667 }
668 }
669 }
670
671 @Override
672 public void notifyUpdateCursor() {
673 getLWToolkit().getCursorManager().updateCursorLater(this);
674 }
675
676 @Override
677 public void notifyActivation(boolean activation, LWWindowPeer opposite) {
678 Window oppositeWindow = (opposite == null)? null : opposite.getTarget();
679 changeFocusedWindow(activation, oppositeWindow);
680 }
681
682 // MouseDown in non-client area
683 @Override
684 public void notifyNCMouseDown() {
685 // Ungrab except for a click on a Dialog with the grabbing owner
686 if (grabbingWindow != null &&
687 grabbingWindow != getOwnerFrameDialog(this))
688 {
689 grabbingWindow.ungrab();
690 }
691 }
692
693 // ---- EVENTS ---- //
694
695 /*
696 * Called by the delegate to dispatch the event to Java. Event
697 * coordinates are relative to non-client window are, i.e. the top-left
698 * point of the client area is (insets.top, insets.left).
699 */
700 @Override
701 public void notifyMouseEvent(int id, long when, int button,
702 int x, int y, int screenX, int screenY,
703 int modifiers, int clickCount, boolean popupTrigger,
704 byte[] bdata)
705 {
706 // TODO: fill "bdata" member of AWTEvent
707 Rectangle r = getBounds();
762 topmostTargetPeer);
763 }
764
765 // TODO: fill "bdata" member of AWTEvent
766
767 int eventButtonMask = (button > 0)? MouseEvent.getMaskForButton(button) : 0;
768 int otherButtonsPressed = modifiers & ~eventButtonMask;
769
770 // For pressed/dragged/released events OS X treats other
771 // mouse buttons as if they were BUTTON2, so we do the same
772 int targetIdx = (button > 3) ? MouseEvent.BUTTON2 - 1 : button - 1;
773
774 // MOUSE_ENTERED/EXITED are generated for the components strictly under
775 // mouse even when dragging. That's why we first update lastMouseEventPeer
776 // based on initial targetPeer value and only then recalculate targetPeer
777 // for MOUSE_DRAGGED/RELEASED events
778 if (id == MouseEvent.MOUSE_PRESSED) {
779
780 // Ungrab only if this window is not an owned window of the grabbing one.
781 if (!isGrabbing() && grabbingWindow != null &&
782 grabbingWindow != getOwnerFrameDialog(this))
783 {
784 grabbingWindow.ungrab();
785 }
786 if (otherButtonsPressed == 0) {
787 mouseClickButtons = eventButtonMask;
788 } else {
789 mouseClickButtons |= eventButtonMask;
790 }
791
792 // The window should be focused on mouse click. If it gets activated by the native platform,
793 // this request will be no op. It will take effect when:
794 // 1. A simple not focused window is clicked.
795 // 2. An active but not focused owner frame/dialog is clicked.
796 // The mouse event then will trigger a focus request "in window" to the component, so the window
797 // should gain focus before.
798 requestWindowFocus(CausedFocusEvent.Cause.MOUSE_EVENT);
799
800 mouseDownTarget[targetIdx] = targetPeer;
801 } else if (id == MouseEvent.MOUSE_DRAGGED) {
802 // Cocoa dragged event has the information about which mouse
1215 if (isSimpleWindow()) {
1216 LWWindowPeer ownerPeer = getOwnerFrameDialog(this);
1217 if (ownerPeer == null) {
1218 return false;
1219 }
1220 return focusable && ownerPeer.getTarget().isFocusableWindow();
1221 }
1222 return focusable;
1223 }
1224
1225 public boolean isSimpleWindow() {
1226 Window window = getTarget();
1227 return !(window instanceof Dialog || window instanceof Frame);
1228 }
1229
1230 @Override
1231 public void emulateActivation(boolean activate) {
1232 changeFocusedWindow(activate, null);
1233 }
1234
1235 /*
1236 * Changes focused window on java level.
1237 */
1238 protected void changeFocusedWindow(boolean becomesFocused, Window opposite) {
1239 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1240 focusLog.fine((becomesFocused?"gaining":"loosing") + " focus window: " + this);
1241 }
1242 if (skipNextFocusChange) {
1243 focusLog.fine("skipping focus change");
1244 skipNextFocusChange = false;
1245 return;
1246 }
1247 if (!isFocusableWindow() && becomesFocused) {
1248 focusLog.fine("the window is not focusable");
1249 return;
1250 }
1251 if (becomesFocused) {
1252 synchronized (getPeerTreeLock()) {
1253 if (blocker != null) {
1254 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
1255 focusLog.finest("the window is blocked by " + blocker);
1256 }
1257 return;
1258 }
1259 }
1260 }
1261
1262 // Note, the method is not called:
1263 // - when the opposite (gaining focus) window is an owned/owner window.
1264 // - for a simple window in any case.
1265 if (!becomesFocused &&
1266 (isGrabbing() || getOwnerFrameDialog(grabbingWindow) == this))
1267 {
1268 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1269 focusLog.fine("ungrabbing on " + grabbingWindow);
1270 }
1271 // ungrab a simple window if its owner looses activation.
1272 grabbingWindow.ungrab();
1273 }
1274
1275 KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
1276 kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null);
1277
1278 int eventID = becomesFocused ? WindowEvent.WINDOW_GAINED_FOCUS : WindowEvent.WINDOW_LOST_FOCUS;
1279 WindowEvent windowEvent = new TimedWindowEvent(getTarget(), eventID, opposite, System.currentTimeMillis());
1280
1281 // TODO: wrap in SequencedEvent
1282 postEvent(windowEvent);
1283 }
1284
1285 static LWWindowPeer getOwnerFrameDialog(LWWindowPeer peer) {
1286 Window owner = (peer != null ? peer.getTarget().getOwner() : null);
1287 while (owner != null && !(owner instanceof Frame || owner instanceof Dialog)) {
1288 owner = owner.getOwner();
1289 }
1290 return owner == null ? null :
1291 (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer(owner);
1292 }
1293
1294 /**
1295 * Returns the foremost modal blocker of this window, or null.
1296 */
1297 public LWWindowPeer getBlocker() {
1298 synchronized (getPeerTreeLock()) {
1299 LWWindowPeer blocker = this.blocker;
1300 if (blocker == null) {
1301 return null;
1302 }
1303 while (blocker.blocker != null) {
1304 blocker = blocker.blocker;
|
1 /*
2 * Copyright (c) 2011, 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
667 }
668 }
669 }
670
671 @Override
672 public void notifyUpdateCursor() {
673 getLWToolkit().getCursorManager().updateCursorLater(this);
674 }
675
676 @Override
677 public void notifyActivation(boolean activation, LWWindowPeer opposite) {
678 Window oppositeWindow = (opposite == null)? null : opposite.getTarget();
679 changeFocusedWindow(activation, oppositeWindow);
680 }
681
682 // MouseDown in non-client area
683 @Override
684 public void notifyNCMouseDown() {
685 // Ungrab except for a click on a Dialog with the grabbing owner
686 if (grabbingWindow != null &&
687 !grabbingWindow.isOneOfOwnersOf(this))
688 {
689 grabbingWindow.ungrab();
690 }
691 }
692
693 // ---- EVENTS ---- //
694
695 /*
696 * Called by the delegate to dispatch the event to Java. Event
697 * coordinates are relative to non-client window are, i.e. the top-left
698 * point of the client area is (insets.top, insets.left).
699 */
700 @Override
701 public void notifyMouseEvent(int id, long when, int button,
702 int x, int y, int screenX, int screenY,
703 int modifiers, int clickCount, boolean popupTrigger,
704 byte[] bdata)
705 {
706 // TODO: fill "bdata" member of AWTEvent
707 Rectangle r = getBounds();
762 topmostTargetPeer);
763 }
764
765 // TODO: fill "bdata" member of AWTEvent
766
767 int eventButtonMask = (button > 0)? MouseEvent.getMaskForButton(button) : 0;
768 int otherButtonsPressed = modifiers & ~eventButtonMask;
769
770 // For pressed/dragged/released events OS X treats other
771 // mouse buttons as if they were BUTTON2, so we do the same
772 int targetIdx = (button > 3) ? MouseEvent.BUTTON2 - 1 : button - 1;
773
774 // MOUSE_ENTERED/EXITED are generated for the components strictly under
775 // mouse even when dragging. That's why we first update lastMouseEventPeer
776 // based on initial targetPeer value and only then recalculate targetPeer
777 // for MOUSE_DRAGGED/RELEASED events
778 if (id == MouseEvent.MOUSE_PRESSED) {
779
780 // Ungrab only if this window is not an owned window of the grabbing one.
781 if (!isGrabbing() && grabbingWindow != null &&
782 !grabbingWindow.isOneOfOwnersOf(this))
783 {
784 grabbingWindow.ungrab();
785 }
786 if (otherButtonsPressed == 0) {
787 mouseClickButtons = eventButtonMask;
788 } else {
789 mouseClickButtons |= eventButtonMask;
790 }
791
792 // The window should be focused on mouse click. If it gets activated by the native platform,
793 // this request will be no op. It will take effect when:
794 // 1. A simple not focused window is clicked.
795 // 2. An active but not focused owner frame/dialog is clicked.
796 // The mouse event then will trigger a focus request "in window" to the component, so the window
797 // should gain focus before.
798 requestWindowFocus(CausedFocusEvent.Cause.MOUSE_EVENT);
799
800 mouseDownTarget[targetIdx] = targetPeer;
801 } else if (id == MouseEvent.MOUSE_DRAGGED) {
802 // Cocoa dragged event has the information about which mouse
1215 if (isSimpleWindow()) {
1216 LWWindowPeer ownerPeer = getOwnerFrameDialog(this);
1217 if (ownerPeer == null) {
1218 return false;
1219 }
1220 return focusable && ownerPeer.getTarget().isFocusableWindow();
1221 }
1222 return focusable;
1223 }
1224
1225 public boolean isSimpleWindow() {
1226 Window window = getTarget();
1227 return !(window instanceof Dialog || window instanceof Frame);
1228 }
1229
1230 @Override
1231 public void emulateActivation(boolean activate) {
1232 changeFocusedWindow(activate, null);
1233 }
1234
1235 private boolean isOneOfOwnersOf(LWWindowPeer peer) {
1236 Window owner = (peer != null ? peer.getTarget().getOwner() : null);
1237 while (owner != null) {
1238 if ((LWWindowPeer)owner.getPeer() == this) {
1239 return true;
1240 }
1241 owner = owner.getOwner();
1242 }
1243 return false;
1244 }
1245
1246 /*
1247 * Changes focused window on java level.
1248 */
1249 protected void changeFocusedWindow(boolean becomesFocused, Window opposite) {
1250 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1251 focusLog.fine((becomesFocused?"gaining":"loosing") + " focus window: " + this);
1252 }
1253 if (skipNextFocusChange) {
1254 focusLog.fine("skipping focus change");
1255 skipNextFocusChange = false;
1256 return;
1257 }
1258 if (!isFocusableWindow() && becomesFocused) {
1259 focusLog.fine("the window is not focusable");
1260 return;
1261 }
1262 if (becomesFocused) {
1263 synchronized (getPeerTreeLock()) {
1264 if (blocker != null) {
1265 if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
1266 focusLog.finest("the window is blocked by " + blocker);
1267 }
1268 return;
1269 }
1270 }
1271 }
1272
1273 // Note, the method is not called:
1274 // - when the opposite (gaining focus) window is an owned/owner window.
1275 // - for a simple window in any case.
1276 if (!becomesFocused &&
1277 (isGrabbing() || this.isOneOfOwnersOf(grabbingWindow)))
1278 {
1279 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1280 focusLog.fine("ungrabbing on " + grabbingWindow);
1281 }
1282 // ungrab a simple window if its owner looses activation.
1283 grabbingWindow.ungrab();
1284 }
1285
1286 KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
1287 kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null);
1288
1289 int eventID = becomesFocused ? WindowEvent.WINDOW_GAINED_FOCUS : WindowEvent.WINDOW_LOST_FOCUS;
1290 WindowEvent windowEvent = new TimedWindowEvent(getTarget(), eventID, opposite, System.currentTimeMillis());
1291
1292 // TODO: wrap in SequencedEvent
1293 postEvent(windowEvent);
1294 }
1295
1296 /*
1297 * Retrieves the owner of the peer.
1298 * Note: this method returns the owner which can be activated, (i.e. the instance
1299 * of Frame or Dialog may be returned).
1300 */
1301 static LWWindowPeer getOwnerFrameDialog(LWWindowPeer peer) {
1302 Window owner = (peer != null ? peer.getTarget().getOwner() : null);
1303 while (owner != null && !(owner instanceof Frame || owner instanceof Dialog)) {
1304 owner = owner.getOwner();
1305 }
1306 return owner == null ? null :
1307 (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer(owner);
1308 }
1309
1310 /**
1311 * Returns the foremost modal blocker of this window, or null.
1312 */
1313 public LWWindowPeer getBlocker() {
1314 synchronized (getPeerTreeLock()) {
1315 LWWindowPeer blocker = this.blocker;
1316 if (blocker == null) {
1317 return null;
1318 }
1319 while (blocker.blocker != null) {
1320 blocker = blocker.blocker;
|