38 import sun.awt.AppContext; 39 import java.awt.event.ActionEvent; 40 import java.awt.event.ActionListener; 41 import java.awt.event.InvocationEvent; 42 import java.awt.im.spi.InputMethodDescriptor; 43 import java.lang.reflect.InvocationTargetException; 44 import java.security.AccessController; 45 import java.security.PrivilegedAction; 46 import java.security.PrivilegedActionException; 47 import java.security.PrivilegedExceptionAction; 48 import java.util.Hashtable; 49 import java.util.Iterator; 50 import java.util.Locale; 51 import java.util.ServiceLoader; 52 import java.util.Vector; 53 import java.util.Set; 54 import java.util.prefs.BackingStoreException; 55 import java.util.prefs.Preferences; 56 import sun.awt.InputMethodSupport; 57 import sun.awt.SunToolkit; 58 59 /** 60 * {@code ExecutableInputMethodManager} is the implementation of the 61 * {@code InputMethodManager} class. It is runnable as a separate 62 * thread in the AWT environment. 63 * {@code InputMethodManager.getInstance()} creates an instance of 64 * {@code ExecutableInputMethodManager} and executes it as a deamon 65 * thread. 66 * 67 * @see InputMethodManager 68 */ 69 class ExecutableInputMethodManager extends InputMethodManager 70 implements Runnable 71 { 72 // the input context that's informed about selections from the user interface 73 private InputContext currentInputContext; 74 75 // Menu item string for the trigger menu. 76 private String triggerMenuString; 77 78 // popup menu for selecting an input method 79 private InputMethodPopupMenu selectionMenu; 80 private static String selectInputMethodMenuTitle; 81 82 // locator and name of host adapter 83 private InputMethodLocator hostAdapterLocator; 84 85 // locators for Java input methods 86 private int javaInputMethodCount; // number of Java input methods found 87 private Vector<InputMethodLocator> javaInputMethodLocatorList; 88 89 // component that is requesting input method switch 90 // must be Frame or Dialog 91 private Component requestComponent; 92 93 // input context that is requesting input method switch 94 private InputContext requestInputContext; 95 96 // IM preference stuff 97 private static final String preferredIMNode = "/sun/awt/im/preferredInputMethod"; 98 private static final String descriptorKey = "descriptor"; 99 private Hashtable<String, InputMethodLocator> preferredLocatorCache = new Hashtable<>(); 100 private Preferences userRoot; 101 102 ExecutableInputMethodManager() { 103 104 // set up host adapter locator 105 Toolkit toolkit = Toolkit.getDefaultToolkit(); 106 try { 107 if (toolkit instanceof InputMethodSupport) { 108 InputMethodDescriptor hostAdapterDescriptor = 109 ((InputMethodSupport)toolkit) 110 .getInputMethodAdapterDescriptor(); 111 if (hostAdapterDescriptor != null) { 195 } 196 } 197 198 void setInputContext(InputContext inputContext) { 199 if (currentInputContext != null && inputContext != null) { 200 // don't throw this exception until 4237852 is fixed 201 // throw new IllegalStateException("Can't have two active InputContext at the same time"); 202 } 203 currentInputContext = inputContext; 204 } 205 206 public synchronized void notifyChangeRequest(Component comp) { 207 if (!(comp instanceof Frame || comp instanceof Dialog)) 208 return; 209 210 // if busy with the current request, ignore this request. 211 if (requestComponent != null) 212 return; 213 214 requestComponent = comp; 215 notify(); 216 } 217 218 public synchronized void notifyChangeRequestByHotKey(Component comp) { 219 while (!(comp instanceof Frame || comp instanceof Dialog)) { 220 if (comp == null) { 221 // no Frame or Dialog found in containment hierarchy. 222 return; 223 } 224 comp = comp.getParent(); 225 } 226 227 notifyChangeRequest(comp); 228 } 229 230 public String getTriggerMenuString() { 231 return triggerMenuString; 232 } 233 234 /* 235 * Returns true if the environment indicates there are multiple input methods 236 */ 237 boolean hasMultipleInputMethods() { 238 return ((hostAdapterLocator != null) && (javaInputMethodCount > 0) 271 e.printStackTrace(); 272 } 273 javaInputMethodCount = javaInputMethodLocatorList.size(); 274 } 275 276 if (hasMultipleInputMethods()) { 277 // initialize preferences 278 if (userRoot == null) { 279 userRoot = getUserRoot(); 280 } 281 } else { 282 // indicate to clients not to offer the menu 283 triggerMenuString = null; 284 } 285 } 286 287 private void showInputMethodMenu() { 288 289 if (!hasMultipleInputMethods()) { 290 requestComponent = null; 291 return; 292 } 293 294 // initialize pop-up menu 295 selectionMenu = InputMethodPopupMenu.getInstance(requestComponent, selectInputMethodMenuTitle); 296 297 // we have to rebuild the menu each time because 298 // some input methods (such as IIIMP) may change 299 // their list of supported locales dynamically 300 selectionMenu.removeAll(); 301 302 // get information about the currently selected input method 303 // ??? if there's no current input context, what's the point 304 // of showing the menu? 305 String currentSelection = getCurrentSelection(); 306 307 // Add menu item for host adapter 308 if (hostAdapterLocator != null) { 309 selectionMenu.addOneInputMethodToMenu(hostAdapterLocator, currentSelection); 310 selectionMenu.addSeparator(); 311 } 312 313 // Add menu items for other input methods 314 for (int i = 0; i < javaInputMethodLocatorList.size(); i++) { 315 InputMethodLocator locator = javaInputMethodLocatorList.get(i); 316 selectionMenu.addOneInputMethodToMenu(locator, currentSelection); 317 } 318 319 synchronized (this) { 320 selectionMenu.addToComponent(requestComponent); 321 requestInputContext = currentInputContext; 322 selectionMenu.show(requestComponent, 60, 80); // TODO: get proper x, y... 323 requestComponent = null; 324 } 325 } 326 327 private String getCurrentSelection() { 328 InputContext inputContext = currentInputContext; 329 if (inputContext != null) { 330 InputMethodLocator locator = inputContext.getInputMethodLocator(); 331 if (locator != null) { 332 return locator.getActionCommandString(); 333 } 334 } 335 return null; 336 } 337 338 synchronized void changeInputMethod(String choice) { 339 InputMethodLocator locator = null; 340 341 String inputMethodName = choice; 342 String localeString = null; 343 int index = choice.indexOf('\n'); | 38 import sun.awt.AppContext; 39 import java.awt.event.ActionEvent; 40 import java.awt.event.ActionListener; 41 import java.awt.event.InvocationEvent; 42 import java.awt.im.spi.InputMethodDescriptor; 43 import java.lang.reflect.InvocationTargetException; 44 import java.security.AccessController; 45 import java.security.PrivilegedAction; 46 import java.security.PrivilegedActionException; 47 import java.security.PrivilegedExceptionAction; 48 import java.util.Hashtable; 49 import java.util.Iterator; 50 import java.util.Locale; 51 import java.util.ServiceLoader; 52 import java.util.Vector; 53 import java.util.Set; 54 import java.util.prefs.BackingStoreException; 55 import java.util.prefs.Preferences; 56 import sun.awt.InputMethodSupport; 57 import sun.awt.SunToolkit; 58 import javax.swing.JDialog; 59 import javax.swing.JFrame; 60 import javax.swing.JRootPane; 61 import java.awt.KeyboardFocusManager; 62 63 /** 64 * {@code ExecutableInputMethodManager} is the implementation of the 65 * {@code InputMethodManager} class. It is runnable as a separate 66 * thread in the AWT environment. 67 * {@code InputMethodManager.getInstance()} creates an instance of 68 * {@code ExecutableInputMethodManager} and executes it as a deamon 69 * thread. 70 * 71 * @see InputMethodManager 72 */ 73 class ExecutableInputMethodManager extends InputMethodManager 74 implements Runnable 75 { 76 // the input context that's informed about selections from the user interface 77 private InputContext currentInputContext; 78 79 // Menu item string for the trigger menu. 80 private String triggerMenuString; 81 82 // popup menu for selecting an input method 83 private InputMethodPopupMenu selectionMenu; 84 private static String selectInputMethodMenuTitle; 85 86 // locator and name of host adapter 87 private InputMethodLocator hostAdapterLocator; 88 89 // locators for Java input methods 90 private int javaInputMethodCount; // number of Java input methods found 91 private Vector<InputMethodLocator> javaInputMethodLocatorList; 92 93 // component that is requesting input method switch 94 // must be Frame or Dialog 95 private Component requestComponent; 96 private Component invokerComponent; 97 98 // input context that is requesting input method switch 99 private InputContext requestInputContext; 100 101 // IM preference stuff 102 private static final String preferredIMNode = "/sun/awt/im/preferredInputMethod"; 103 private static final String descriptorKey = "descriptor"; 104 private Hashtable<String, InputMethodLocator> preferredLocatorCache = new Hashtable<>(); 105 private Preferences userRoot; 106 107 ExecutableInputMethodManager() { 108 109 // set up host adapter locator 110 Toolkit toolkit = Toolkit.getDefaultToolkit(); 111 try { 112 if (toolkit instanceof InputMethodSupport) { 113 InputMethodDescriptor hostAdapterDescriptor = 114 ((InputMethodSupport)toolkit) 115 .getInputMethodAdapterDescriptor(); 116 if (hostAdapterDescriptor != null) { 200 } 201 } 202 203 void setInputContext(InputContext inputContext) { 204 if (currentInputContext != null && inputContext != null) { 205 // don't throw this exception until 4237852 is fixed 206 // throw new IllegalStateException("Can't have two active InputContext at the same time"); 207 } 208 currentInputContext = inputContext; 209 } 210 211 public synchronized void notifyChangeRequest(Component comp) { 212 if (!(comp instanceof Frame || comp instanceof Dialog)) 213 return; 214 215 // if busy with the current request, ignore this request. 216 if (requestComponent != null) 217 return; 218 219 requestComponent = comp; 220 if (comp instanceof JDialog) { 221 if (!(comp.getParent() instanceof JFrame)) 222 invokerComponent = comp; 223 } 224 if (invokerComponent==null) { 225 invokerComponent = KeyboardFocusManager.getCurrentKeyboardFocusManager() 226 .getFocusOwner(); 227 if (invokerComponent !=null && !invokerComponent.isShowing()) 228 invokerComponent = comp; 229 } 230 if (invokerComponent==null) 231 invokerComponent = comp; 232 notify(); 233 } 234 235 public synchronized void notifyChangeRequestByHotKey(Component comp) { 236 invokerComponent = comp; 237 while (!(comp instanceof Frame || comp instanceof Dialog)) { 238 if (comp == null) { 239 // no Frame or Dialog found in containment hierarchy. 240 return; 241 } 242 comp = comp.getParent(); 243 } 244 245 notifyChangeRequest(comp); 246 } 247 248 public String getTriggerMenuString() { 249 return triggerMenuString; 250 } 251 252 /* 253 * Returns true if the environment indicates there are multiple input methods 254 */ 255 boolean hasMultipleInputMethods() { 256 return ((hostAdapterLocator != null) && (javaInputMethodCount > 0) 289 e.printStackTrace(); 290 } 291 javaInputMethodCount = javaInputMethodLocatorList.size(); 292 } 293 294 if (hasMultipleInputMethods()) { 295 // initialize preferences 296 if (userRoot == null) { 297 userRoot = getUserRoot(); 298 } 299 } else { 300 // indicate to clients not to offer the menu 301 triggerMenuString = null; 302 } 303 } 304 305 private void showInputMethodMenu() { 306 307 if (!hasMultipleInputMethods()) { 308 requestComponent = null; 309 invokerComponent = null; 310 return; 311 } 312 313 // initialize pop-up menu 314 if (requestComponent != null && requestComponent.equals(invokerComponent)) { 315 selectionMenu = InputMethodPopupMenu.getAWTInstance(requestComponent, 316 selectInputMethodMenuTitle); 317 } else { 318 selectionMenu = InputMethodPopupMenu.getInstance(requestComponent, 319 selectInputMethodMenuTitle); 320 } 321 if (invokerComponent instanceof JRootPane) { 322 if (selectionMenu.isVisible()) { 323 synchronized (this) { 324 requestComponent = null; 325 invokerComponent = null; 326 } 327 return; 328 } 329 } 330 331 // we have to rebuild the menu each time because 332 // some input methods (such as IIIMP) may change 333 // their list of supported locales dynamically 334 selectionMenu.removeAll(); 335 336 // get information about the currently selected input method 337 // ??? if there's no current input context, what's the point 338 // of showing the menu? 339 String currentSelection = getCurrentSelection(); 340 341 // Add menu item for host adapter 342 if (hostAdapterLocator != null) { 343 selectionMenu.addOneInputMethodToMenu(hostAdapterLocator, currentSelection); 344 selectionMenu.addSeparator(); 345 } 346 347 // Add menu items for other input methods 348 for (int i = 0; i < javaInputMethodLocatorList.size(); i++) { 349 InputMethodLocator locator = javaInputMethodLocatorList.get(i); 350 selectionMenu.addOneInputMethodToMenu(locator, currentSelection); 351 } 352 353 synchronized (this) { 354 if (requestComponent == null){ 355 requestInputContext = currentInputContext; 356 selectionMenu.show(requestComponent, 0, 0); 357 } else { 358 int offsetX = 60; 359 int offsetY = 80; 360 selectionMenu.addToComponent(requestComponent); 361 requestInputContext = currentInputContext; 362 if (requestComponent.getSize().width < offsetX * 2) 363 offsetX = requestComponent.getSize().width / 2; 364 if (requestComponent.getSize().height < offsetY * 2) 365 offsetY = requestComponent.getSize().height / 2; 366 selectionMenu.show(requestComponent, offsetX, offsetY); 367 } 368 requestComponent = null; 369 invokerComponent = null; 370 371 } 372 } 373 374 private String getCurrentSelection() { 375 InputContext inputContext = currentInputContext; 376 if (inputContext != null) { 377 InputMethodLocator locator = inputContext.getInputMethodLocator(); 378 if (locator != null) { 379 return locator.getActionCommandString(); 380 } 381 } 382 return null; 383 } 384 385 synchronized void changeInputMethod(String choice) { 386 InputMethodLocator locator = null; 387 388 String inputMethodName = choice; 389 String localeString = null; 390 int index = choice.indexOf('\n'); |