1 /* 2 * Copyright (c) 1996, 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 23 * questions. 24 */ 25 26 package java.awt.event; 27 28 import java.awt.Component; 29 import java.io.ObjectStreamException; 30 31 import sun.awt.AWTAccessor; 32 import sun.awt.AppContext; 33 import sun.awt.SunToolkit; 34 35 /** 36 * A low-level event which indicates that a Component has gained or lost the 37 * input focus. This low-level event is generated by a Component (such as a 38 * TextField). The event is passed to every {@code FocusListener} or 39 * {@code FocusAdapter} object which registered to receive such events 40 * using the Component's {@code addFocusListener} method. 41 * ({@code FocusAdapter} objects implement the {@code FocusListener} 42 * interface.) Each such listener object gets this {@code FocusEvent} when 43 * the event occurs. 44 * <p> 45 * There are two levels of focus events: permanent and temporary. Permanent 46 * focus change events occur when focus is directly moved from one Component to 47 * another, such as through a call to requestFocus() or as the user uses the 48 * TAB key to traverse Components. Temporary focus change events occur when 49 * focus is temporarily lost for a Component as the indirect result of another 50 * operation, such as Window deactivation or a Scrollbar drag. In this case, 51 * the original focus state will automatically be restored once that operation 52 * is finished, or, for the case of Window deactivation, when the Window is 53 * reactivated. Both permanent and temporary focus events are delivered using 54 * the FOCUS_GAINED and FOCUS_LOST event ids; the level may be distinguished in 55 * the event using the isTemporary() method. 56 * <p> 57 * Every {@code FocusEvent} records its cause - the reason why this event was 58 * generated. The cause is assigned during the focus event creation and may be 59 * retrieved by calling {@link #getCause}. 60 * <p> 61 * An unspecified behavior will be caused if the {@code id} parameter 62 * of any particular {@code FocusEvent} instance is not 63 * in the range from {@code FOCUS_FIRST} to {@code FOCUS_LAST}. 64 * 65 * @see FocusAdapter 66 * @see FocusListener 67 * @see <a href="http://docs.oracle.com/javase/tutorial/uiswing/events/focuslistener.html">Tutorial: Writing a Focus Listener</a> 68 * 69 * @author Carl Quinn 70 * @author Amy Fowler 71 * @since 1.1 72 */ 73 public class FocusEvent extends ComponentEvent { 74 75 /** 76 * This enum represents the cause of a {@code FocusEvent}- the reason why it 77 * occurred. Possible reasons include mouse events, keyboard focus 78 * traversal, window activation. 79 * If no cause is provided then the reason is {@code UNKNOWN}. 80 * 81 * @since 9 82 */ 83 public enum Cause { 84 /** 85 * The default value. 86 */ 87 UNKNOWN, 88 /** 89 * An activating mouse event. 90 */ 91 MOUSE_EVENT, 92 /** 93 * A focus traversal action with unspecified direction. 94 */ 95 TRAVERSAL, 96 /** 97 * An up-cycle focus traversal action. 98 */ 99 TRAVERSAL_UP, 100 /** 101 * A down-cycle focus traversal action. 102 */ 103 TRAVERSAL_DOWN, 104 /** 105 * A forward focus traversal action. 106 */ 107 TRAVERSAL_FORWARD, 108 /** 109 * A backward focus traversal action. 110 */ 111 TRAVERSAL_BACKWARD, 112 /** 113 * Restoring focus after a focus request has been rejected. 114 */ 115 ROLLBACK, 116 /** 117 * A system action causing an unexpected focus change. 118 */ 119 UNEXPECTED, 120 /** 121 * An activation of a toplevel window. 122 */ 123 ACTIVATION, 124 /** 125 * Clearing global focus owner. 126 */ 127 CLEAR_GLOBAL_FOCUS_OWNER 128 } 129 130 /** 131 * The first number in the range of ids used for focus events. 132 */ 133 public static final int FOCUS_FIRST = 1004; 134 135 /** 136 * The last number in the range of ids used for focus events. 137 */ 138 public static final int FOCUS_LAST = 1005; 139 140 /** 141 * This event indicates that the Component is now the focus owner. 142 */ 143 public static final int FOCUS_GAINED = FOCUS_FIRST; //Event.GOT_FOCUS 144 145 /** 146 * This event indicates that the Component is no longer the focus owner. 147 */ 148 public static final int FOCUS_LOST = 1 + FOCUS_FIRST; //Event.LOST_FOCUS 149 150 private final Cause cause; 151 152 /** 153 * A focus event can have two different levels, permanent and temporary. 154 * It will be set to true if some operation takes away the focus 155 * temporarily and intends on getting it back once the event is completed. 156 * Otherwise it will be set to false. 157 * 158 * @serial 159 * @see #isTemporary 160 */ 161 boolean temporary; 162 163 /** 164 * The other Component involved in this focus change. For a FOCUS_GAINED 165 * event, this is the Component that lost focus. For a FOCUS_LOST event, 166 * this is the Component that gained focus. If this focus change occurs 167 * with a native application, a Java application in a different VM, or with 168 * no other Component, then the opposite Component is null. 169 * 170 * @see #getOppositeComponent 171 * @since 1.4 172 */ 173 transient Component opposite; 174 175 /* 176 * JDK 1.1 serialVersionUID 177 */ 178 private static final long serialVersionUID = 523753786457416396L; 179 180 /** 181 * Constructs a {@code FocusEvent} object with the 182 * specified temporary state, opposite {@code Component} and the 183 * {@code Cause.UNKNOWN} cause. 184 * The opposite {@code Component} is the other 185 * {@code Component} involved in this focus change. 186 * For a {@code FOCUS_GAINED} event, this is the 187 * {@code Component} that lost focus. For a 188 * {@code FOCUS_LOST} event, this is the {@code Component} 189 * that gained focus. If this focus change occurs with a native 190 * application, with a Java application in a different VM, 191 * or with no other {@code Component}, then the opposite 192 * {@code Component} is {@code null}. 193 * <p> This method throws an 194 * {@code IllegalArgumentException} if {@code source} 195 * is {@code null}. 196 * 197 * @param source The {@code Component} that originated the event 198 * @param id An integer indicating the type of event. 199 * For information on allowable values, see 200 * the class description for {@link FocusEvent} 201 * @param temporary Equals {@code true} if the focus change is temporary; 202 * {@code false} otherwise 203 * @param opposite The other Component involved in the focus change, 204 * or {@code null} 205 * @throws IllegalArgumentException if {@code source} equals {@code null} 206 * @see #getSource() 207 * @see #getID() 208 * @see #isTemporary() 209 * @see #getOppositeComponent() 210 * @see Cause#UNKNOWN 211 * @since 1.4 212 */ 213 public FocusEvent(Component source, int id, boolean temporary, 214 Component opposite) { 215 this(source, id, temporary, opposite, Cause.UNKNOWN); 216 } 217 218 /** 219 * Constructs a {@code FocusEvent} object with the 220 * specified temporary state, opposite {@code Component} and the cause. 221 * The opposite {@code Component} is the other 222 * {@code Component} involved in this focus change. 223 * For a {@code FOCUS_GAINED} event, this is the 224 * {@code Component} that lost focus. For a 225 * {@code FOCUS_LOST} event, this is the {@code Component} 226 * that gained focus. If this focus change occurs with a native 227 * application, with a Java application in a different VM, 228 * or with no other {@code Component}, then the opposite 229 * {@code Component} is {@code null}. 230 * <p> This method throws an 231 * {@code IllegalArgumentException} if {@code source} or {@code cause} 232 * is {@code null}. 233 * 234 * @param source The {@code Component} that originated the event 235 * @param id An integer indicating the type of event. 236 * For information on allowable values, see 237 * the class description for {@link FocusEvent} 238 * @param temporary Equals {@code true} if the focus change is temporary; 239 * {@code false} otherwise 240 * @param opposite The other Component involved in the focus change, 241 * or {@code null} 242 * @param cause The focus event cause. 243 * @throws IllegalArgumentException if {@code source} equals {@code null} 244 * or if {@code cause} equals {@code null} 245 * @see #getSource() 246 * @see #getID() 247 * @see #isTemporary() 248 * @see #getOppositeComponent() 249 * @see Cause 250 * @since 9 251 */ 252 public FocusEvent(Component source, int id, boolean temporary, 253 Component opposite, Cause cause) { 254 super(source, id); 255 if (cause == null) { 256 throw new IllegalArgumentException("null cause"); 257 } 258 this.temporary = temporary; 259 this.opposite = opposite; 260 this.cause = cause; 261 } 262 263 /** 264 * Constructs a {@code FocusEvent} object and identifies 265 * whether or not the change is temporary. 266 * <p> This method throws an 267 * {@code IllegalArgumentException} if {@code source} 268 * is {@code null}. 269 * 270 * @param source The {@code Component} that originated the event 271 * @param id An integer indicating the type of event. 272 * For information on allowable values, see 273 * the class description for {@link FocusEvent} 274 * @param temporary Equals {@code true} if the focus change is temporary; 275 * {@code false} otherwise 276 * @throws IllegalArgumentException if {@code source} equals {@code null} 277 * @see #getSource() 278 * @see #getID() 279 * @see #isTemporary() 280 */ 281 public FocusEvent(Component source, int id, boolean temporary) { 282 this(source, id, temporary, null); 283 } 284 285 /** 286 * Constructs a {@code FocusEvent} object and identifies it 287 * as a permanent change in focus. 288 * <p> This method throws an 289 * {@code IllegalArgumentException} if {@code source} 290 * is {@code null}. 291 * 292 * @param source The {@code Component} that originated the event 293 * @param id An integer indicating the type of event. 294 * For information on allowable values, see 295 * the class description for {@link FocusEvent} 296 * @throws IllegalArgumentException if {@code source} equals {@code null} 297 * @see #getSource() 298 * @see #getID() 299 */ 300 public FocusEvent(Component source, int id) { 301 this(source, id, false); 302 } 303 304 /** 305 * Identifies the focus change event as temporary or permanent. 306 * 307 * @return {@code true} if the focus change is temporary; 308 * {@code false} otherwise 309 */ 310 public boolean isTemporary() { 311 return temporary; 312 } 313 314 /** 315 * Returns the other Component involved in this focus change. For a 316 * FOCUS_GAINED event, this is the Component that lost focus. For a 317 * FOCUS_LOST event, this is the Component that gained focus. If this 318 * focus change occurs with a native application, with a Java application 319 * in a different VM or context, or with no other Component, then null is 320 * returned. 321 * 322 * @return the other Component involved in the focus change, or null 323 * @since 1.4 324 */ 325 public Component getOppositeComponent() { 326 if (opposite == null) { 327 return null; 328 } 329 330 return (SunToolkit.targetToAppContext(opposite) == 331 AppContext.getAppContext()) 332 ? opposite 333 : null; 334 } 335 336 /** 337 * Returns a parameter string identifying this event. 338 * This method is useful for event-logging and for debugging. 339 * 340 * @return a string identifying the event and its attributes 341 */ 342 public String paramString() { 343 String typeStr; 344 switch(id) { 345 case FOCUS_GAINED: 346 typeStr = "FOCUS_GAINED"; 347 break; 348 case FOCUS_LOST: 349 typeStr = "FOCUS_LOST"; 350 break; 351 default: 352 typeStr = "unknown type"; 353 } 354 return typeStr + (temporary ? ",temporary" : ",permanent") + 355 ",opposite=" + getOppositeComponent() + ",cause=" + getCause(); 356 } 357 358 /** 359 * Returns the event cause. 360 * 361 * @return one of {@link Cause} values 362 * @since 9 363 */ 364 public final Cause getCause() { 365 return cause; 366 } 367 368 // Ensure that the deserialized object is compatible 369 @SuppressWarnings("serial") 370 Object readResolve() throws ObjectStreamException { 371 if (cause != null) { 372 return this; 373 } 374 FocusEvent focusEvent = new FocusEvent(new Component(){}, getID(), 375 isTemporary(), getOppositeComponent()); 376 focusEvent.setSource(null); 377 focusEvent.consumed = consumed; 378 379 AWTAccessor.AWTEventAccessor accessor = 380 AWTAccessor.getAWTEventAccessor(); 381 accessor.setBData(focusEvent, accessor.getBData(this)); 382 return focusEvent; 383 } 384 385 386 }