1 /*
2  * Copyright (c) 2003, 2016, 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 package sun.awt;
26 
27 import java.awt.Component;
28 import java.awt.Window;
29 import java.awt.Canvas;
30 import java.awt.Scrollbar;
31 import java.awt.Panel;
32 
33 import java.awt.event.FocusEvent;
34 
35 import java.awt.peer.KeyboardFocusManagerPeer;
36 import java.awt.peer.ComponentPeer;
37 
38 import sun.awt.AWTAccessor.ComponentAccessor;
39 import sun.util.logging.PlatformLogger;
40 
41 public abstract class KeyboardFocusManagerPeerImpl implements KeyboardFocusManagerPeer {
42 
43     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.focus.KeyboardFocusManagerPeerImpl");
44 
45     private static class KfmAccessor {
46         private static AWTAccessor.KeyboardFocusManagerAccessor instance =
47                 AWTAccessor.getKeyboardFocusManagerAccessor();
48     }
49 
50     // The constants are copied from java.awt.KeyboardFocusManager
51     public static final int SNFH_FAILURE         = 0;
52     public static final int SNFH_SUCCESS_HANDLED = 1;
53     public static final int SNFH_SUCCESS_PROCEED = 2;
54 
55     @Override
clearGlobalFocusOwner(Window activeWindow)56     public void clearGlobalFocusOwner(Window activeWindow) {
57         if (activeWindow != null) {
58             Component focusOwner = activeWindow.getFocusOwner();
59             if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
60                 focusLog.fine("Clearing global focus owner " + focusOwner);
61             }
62             if (focusOwner != null) {
63                 FocusEvent fl = new FocusEvent(focusOwner, FocusEvent.FOCUS_LOST, false, null,
64                                                      FocusEvent.Cause.CLEAR_GLOBAL_FOCUS_OWNER);
65                 SunToolkit.postPriorityEvent(fl);
66             }
67         }
68     }
69 
70     /*
71      * WARNING: Don't call it on the Toolkit thread.
72      *
73      * Checks if the component:
74      * 1) accepts focus on click (in general)
75      * 2) may be a focus owner (in particular)
76      */
shouldFocusOnClick(Component component)77     public static boolean shouldFocusOnClick(Component component) {
78         boolean acceptFocusOnClick = false;
79 
80         // A component is generally allowed to accept focus on click
81         // if its peer is focusable. There're some exceptions though.
82 
83 
84         // CANVAS & SCROLLBAR accept focus on click
85         final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
86         if (component instanceof Canvas ||
87             component instanceof Scrollbar)
88         {
89             acceptFocusOnClick = true;
90 
91         // PANEL, empty only, accepts focus on click
92         } else if (component instanceof Panel) {
93             acceptFocusOnClick = (((Panel)component).getComponentCount() == 0);
94 
95 
96         // Other components
97         } else {
98             ComponentPeer peer = (component != null ? acc.getPeer(component) : null);
99             acceptFocusOnClick = (peer != null ? peer.isFocusable() : false);
100         }
101         return acceptFocusOnClick && acc.canBeFocusOwner(component);
102     }
103 
104     /*
105      * Posts proper lost/gain focus events to the event queue.
106      */
107     @SuppressWarnings("deprecation")
deliverFocus(Component lightweightChild, Component target, boolean temporary, boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause, Component currentFocusOwner)108     public static boolean deliverFocus(Component lightweightChild,
109                                        Component target,
110                                        boolean temporary,
111                                        boolean focusedWindowChangeAllowed,
112                                        long time,
113                                        FocusEvent.Cause cause,
114                                        Component currentFocusOwner) // provided by the descendant peers
115     {
116         if (lightweightChild == null) {
117             lightweightChild = target;
118         }
119 
120         Component currentOwner = currentFocusOwner;
121         if (currentOwner != null && !currentOwner.isDisplayable()) {
122             currentOwner = null;
123         }
124         if (currentOwner != null) {
125             FocusEvent fl = new FocusEvent(currentOwner, FocusEvent.FOCUS_LOST,
126                                                  false, lightweightChild, cause);
127 
128             if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
129                 focusLog.finer("Posting focus event: " + fl);
130             }
131             SunToolkit.postEvent(SunToolkit.targetToAppContext(currentOwner), fl);
132         }
133 
134         FocusEvent fg = new FocusEvent(lightweightChild, FocusEvent.FOCUS_GAINED,
135                                              false, currentOwner, cause);
136 
137         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
138             focusLog.finer("Posting focus event: " + fg);
139         }
140         SunToolkit.postEvent(SunToolkit.targetToAppContext(lightweightChild), fg);
141         return true;
142     }
143 
144     // WARNING: Don't call it on the Toolkit thread.
requestFocusFor(Component target, FocusEvent.Cause cause)145     public static void requestFocusFor(Component target, FocusEvent.Cause cause) {
146         AWTAccessor.getComponentAccessor().requestFocus(target, cause);
147     }
148 
149     // WARNING: Don't call it on the Toolkit thread.
shouldNativelyFocusHeavyweight(Component heavyweight, Component descendant, boolean temporary, boolean focusedWindowChangeAllowed, long time, FocusEvent.Cause cause)150     public static int shouldNativelyFocusHeavyweight(Component heavyweight,
151                                                      Component descendant,
152                                                      boolean temporary,
153                                                      boolean focusedWindowChangeAllowed,
154                                                      long time,
155                                                      FocusEvent.Cause cause)
156     {
157         return KfmAccessor.instance.shouldNativelyFocusHeavyweight(
158             heavyweight, descendant, temporary, focusedWindowChangeAllowed,
159                 time, cause);
160     }
161 
removeLastFocusRequest(Component heavyweight)162     public static void removeLastFocusRequest(Component heavyweight) {
163         KfmAccessor.instance.removeLastFocusRequest(heavyweight);
164     }
165 
166     // WARNING: Don't call it on the Toolkit thread.
processSynchronousLightweightTransfer(Component heavyweight, Component descendant, boolean temporary, boolean focusedWindowChangeAllowed, long time)167     public static boolean processSynchronousLightweightTransfer(Component heavyweight,
168                                                                 Component descendant,
169                                                                 boolean temporary,
170                                                                 boolean focusedWindowChangeAllowed,
171                                                                 long time)
172     {
173         return KfmAccessor.instance.processSynchronousLightweightTransfer(
174             heavyweight, descendant, temporary, focusedWindowChangeAllowed,
175                 time);
176     }
177 }
178