1/* 2 * Copyright (c) 1998, 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 26package sun.awt.im; 27 28import java.awt.AWTException; 29import java.awt.CheckboxMenuItem; 30import java.awt.Component; 31import java.awt.Dialog; 32import java.awt.EventQueue; 33import java.awt.Frame; 34import java.awt.PopupMenu; 35import java.awt.Menu; 36import java.awt.MenuItem; 37import java.awt.Toolkit; 38import sun.awt.AppContext; 39import java.awt.event.ActionEvent; 40import java.awt.event.ActionListener; 41import java.awt.event.InvocationEvent; 42import java.awt.im.spi.InputMethodDescriptor; 43import java.lang.reflect.InvocationTargetException; 44import java.security.AccessController; 45import java.security.PrivilegedAction; 46import java.security.PrivilegedActionException; 47import java.security.PrivilegedExceptionAction; 48import java.util.Hashtable; 49import java.util.Iterator; 50import java.util.Locale; 51import java.util.ServiceLoader; 52import java.util.Vector; 53import java.util.Set; 54import java.util.prefs.BackingStoreException; 55import java.util.prefs.Preferences; 56import sun.awt.InputMethodSupport; 57import sun.awt.SunToolkit; 58 59/** 60 * {@code InputMethodManager} is an abstract class that manages the input 61 * method environment of JVM. There is only one {@code InputMethodManager} 62 * instance in JVM that is executed under a separate daemon thread. 63 * {@code InputMethodManager} performs the following: 64 * <UL> 65 * <LI> 66 * Keeps track of the current input context.</LI> 67 * 68 * <LI> 69 * Provides a user interface to switch input methods and notifies the current 70 * input context about changes made from the user interface.</LI> 71 * </UL> 72 * 73 * The mechanism for supporting input method switch is as follows. (Note that 74 * this may change in future releases.) 75 * 76 * <UL> 77 * <LI> 78 * One way is to use platform-dependent window manager's menu (known as the <I>Window 79 * menu </I>in Motif and the <I>System menu</I> or <I>Control menu</I> in 80 * Win32) on each window which is popped up by clicking the left top box of 81 * a window (known as <I>Window menu button</I> in Motif and <I>System menu 82 * button</I> in Win32). This happens to be common in both Motif and Win32.</LI> 83 * 84 * <LI> 85 * When more than one input method descriptor can be found or the only input 86 * method descriptor found supports multiple locales, a menu item 87 * is added to the window (manager) menu. This item label is obtained invoking 88 * {@code getTriggerMenuString()}. If null is returned by this method, it 89 * means that there is only input method or none in the environment. Frame and Dialog 90 * invoke this method.</LI> 91 * 92 * <LI> 93 * This menu item means a trigger switch to the user to pop up a selection 94 * menu.</LI> 95 * 96 * <LI> 97 * When the menu item of the window (manager) menu has been selected by the 98 * user, Frame/Dialog invokes {@code notifyChangeRequest()} to notify 99 * {@code InputMethodManager} that the user wants to switch input methods.</LI> 100 * 101 * <LI> 102 * {@code InputMethodManager} displays a pop-up menu to choose an input method.</LI> 103 * 104 * <LI> 105 * {@code InputMethodManager} notifies the current {@code InputContext} of 106 * the selected {@code InputMethod}.</LI> 107 * </UL> 108 * 109 * <UL> 110 * <LI> 111 * The other way is to use user-defined hot key combination to show the pop-up menu to 112 * choose an input method. This is useful for the platforms which do not provide a 113 * way to add a menu item in the window (manager) menu.</LI> 114 * 115 * <LI> 116 * When the hot key combination is typed by the user, the component which has the input 117 * focus invokes {@code notifyChangeRequestByHotKey()} to notify 118 * {@code InputMethodManager} that the user wants to switch input methods.</LI> 119 * 120 * <LI> 121 * This results in a popup menu and notification to the current input context, 122 * as above.</LI> 123 * </UL> 124 * 125 * @see java.awt.im.spi.InputMethod 126 * @see sun.awt.im.InputContext 127 * @see sun.awt.im.InputMethodAdapter 128 * @author JavaSoft International 129 */ 130 131public abstract class InputMethodManager { 132 133 /** 134 * InputMethodManager thread name 135 */ 136 private static final String threadName = "AWT-InputMethodManager"; 137 138 /** 139 * Object for global locking 140 */ 141 private static final Object LOCK = new Object(); 142 143 /** 144 * The InputMethodManager instance 145 */ 146 private static InputMethodManager inputMethodManager; 147 148 /** 149 * Returns the instance of InputMethodManager. This method creates 150 * the instance that is unique in the Java VM if it has not been 151 * created yet. 152 * 153 * @return the InputMethodManager instance 154 */ 155 public static final InputMethodManager getInstance() { 156 if (inputMethodManager != null) { 157 return inputMethodManager; 158 } 159 synchronized(LOCK) { 160 if (inputMethodManager == null) { 161 ExecutableInputMethodManager imm = new ExecutableInputMethodManager(); 162 163 // Initialize the input method manager and start a 164 // daemon thread if the user has multiple input methods 165 // to choose from. Otherwise, just keep the instance. 166 if (imm.hasMultipleInputMethods()) { 167 imm.initialize(); 168 Thread immThread = 169 new Thread(null, imm, threadName, 0, false); 170 immThread.setDaemon(true); 171 immThread.setPriority(Thread.NORM_PRIORITY + 1); 172 immThread.start(); 173 } 174 inputMethodManager = imm; 175 } 176 } 177 return inputMethodManager; 178 } 179 180 /** 181 * Gets a string for the trigger menu item that should be added to 182 * the window manager menu. If no need to display the trigger menu 183 * item, null is returned. 184 */ 185 public abstract String getTriggerMenuString(); 186 187 /** 188 * Notifies InputMethodManager that input method change has been 189 * requested by the user. This notification triggers a popup menu 190 * for user selection. 191 * 192 * @param comp Component that has accepted the change 193 * request. This component has to be a Frame or Dialog. 194 */ 195 public abstract void notifyChangeRequest(Component comp); 196 197 /** 198 * Notifies InputMethodManager that input method change has been 199 * requested by the user using the hot key combination. This 200 * notification triggers a popup menu for user selection. 201 * 202 * @param comp Component that has accepted the change 203 * request. This component has the input focus. 204 */ 205 public abstract void notifyChangeRequestByHotKey(Component comp); 206 207 /** 208 * Sets the current input context so that it will be notified 209 * of input method changes initiated from the user interface. 210 * Set to real input context when activating; to null when 211 * deactivating. 212 */ 213 abstract void setInputContext(InputContext inputContext); 214 215 /** 216 * Tries to find an input method locator for the given locale. 217 * Returns null if no available input method locator supports 218 * the locale. 219 */ 220 abstract InputMethodLocator findInputMethod(Locale forLocale); 221 222 /** 223 * Gets the default keyboard locale of the underlying operating system. 224 */ 225 abstract Locale getDefaultKeyboardLocale(); 226 227 /** 228 * Returns whether multiple input methods are available or not 229 */ 230 abstract boolean hasMultipleInputMethods(); 231 232} 233