| /* | |
| * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| package sun.awt.im; | |
| import java.awt.AWTException; | |
| import java.awt.CheckboxMenuItem; | |
| import java.awt.Component; | |
| import java.awt.Dialog; | |
| import java.awt.EventQueue; | |
| import java.awt.Frame; | |
| import java.awt.PopupMenu; | |
| import java.awt.Menu; | |
| import java.awt.MenuItem; | |
| import java.awt.Toolkit; | |
| import sun.awt.AppContext; | |
| import java.awt.event.ActionEvent; | |
| import java.awt.event.ActionListener; | |
| import java.awt.event.InvocationEvent; | |
| import java.awt.im.spi.InputMethodDescriptor; | |
| import java.lang.reflect.InvocationTargetException; | |
| import java.util.Hashtable; | |
| import java.util.Iterator; | |
| import java.util.Locale; | |
| import java.util.ServiceLoader; | |
| import java.util.Vector; | |
| import java.util.Set; | |
| import java.util.prefs.BackingStoreException; | |
| import java.util.prefs.Preferences; | |
| import sun.awt.InputMethodSupport; | |
| import sun.awt.SunToolkit; | |
| /** | |
| * {@code InputMethodManager} is an abstract class that manages the input | |
| * method environment of JVM. There is only one {@code InputMethodManager} | |
| * instance in JVM that is executed under a separate daemon thread. | |
| * {@code InputMethodManager} performs the following: | |
| * <UL> | |
| * <LI> | |
| * Keeps track of the current input context.</LI> | |
| * | |
| * <LI> | |
| * Provides a user interface to switch input methods and notifies the current | |
| * input context about changes made from the user interface.</LI> | |
| * </UL> | |
| * | |
| * The mechanism for supporting input method switch is as follows. (Note that | |
| * this may change in future releases.) | |
| * | |
| * <UL> | |
| * <LI> | |
| * One way is to use platform-dependent window manager's menu (known as the <I>Window | |
| * menu </I>in Motif and the <I>System menu</I> or <I>Control menu</I> in | |
| * Win32) on each window which is popped up by clicking the left top box of | |
| * a window (known as <I>Window menu button</I> in Motif and <I>System menu | |
| * button</I> in Win32). This happens to be common in both Motif and Win32.</LI> | |
| * | |
| * <LI> | |
| * When more than one input method descriptor can be found or the only input | |
| * method descriptor found supports multiple locales, a menu item | |
| * is added to the window (manager) menu. This item label is obtained invoking | |
| * {@code getTriggerMenuString()}. If null is returned by this method, it | |
| * means that there is only input method or none in the environment. Frame and Dialog | |
| * invoke this method.</LI> | |
| * | |
| * <LI> | |
| * This menu item means a trigger switch to the user to pop up a selection | |
| * menu.</LI> | |
| * | |
| * <LI> | |
| * When the menu item of the window (manager) menu has been selected by the | |
| * user, Frame/Dialog invokes {@code notifyChangeRequest()} to notify | |
| * {@code InputMethodManager} that the user wants to switch input methods.</LI> | |
| * | |
| * <LI> | |
| * {@code InputMethodManager} displays a pop-up menu to choose an input method.</LI> | |
| * | |
| * <LI> | |
| * {@code InputMethodManager} notifies the current {@code InputContext} of | |
| * the selected {@code InputMethod}.</LI> | |
| * </UL> | |
| * | |
| * <UL> | |
| * <LI> | |
| * The other way is to use user-defined hot key combination to show the pop-up menu to | |
| * choose an input method. This is useful for the platforms which do not provide a | |
| * way to add a menu item in the window (manager) menu.</LI> | |
| * | |
| * <LI> | |
| * When the hot key combination is typed by the user, the component which has the input | |
| * focus invokes {@code notifyChangeRequestByHotKey()} to notify | |
| * {@code InputMethodManager} that the user wants to switch input methods.</LI> | |
| * | |
| * <LI> | |
| * This results in a popup menu and notification to the current input context, | |
| * as above.</LI> | |
| * </UL> | |
| * | |
| * @see java.awt.im.spi.InputMethod | |
| * @see sun.awt.im.InputContext | |
| * @see sun.awt.im.InputMethodAdapter | |
| * @author JavaSoft International | |
| */ | |
| public abstract class InputMethodManager { | |
| /** | |
| * InputMethodManager thread name | |
| */ | |
| private static final String threadName = "AWT-InputMethodManager"; | |
| /** | |
| * Object for global locking | |
| */ | |
| private static final Object LOCK = new Object(); | |
| /** | |
| * The InputMethodManager instance | |
| */ | |
| private static InputMethodManager inputMethodManager; | |
| /** | |
| * Returns the instance of InputMethodManager. This method creates | |
| * the instance that is unique in the Java VM if it has not been | |
| * created yet. | |
| * | |
| * @return the InputMethodManager instance | |
| */ | |
| public static final InputMethodManager getInstance() { | |
| if (inputMethodManager != null) { | |
| return inputMethodManager; | |
| } | |
| synchronized(LOCK) { | |
| if (inputMethodManager == null) { | |
| ExecutableInputMethodManager imm = new ExecutableInputMethodManager(); | |
| // Initialize the input method manager and start a | |
| // daemon thread if the user has multiple input methods | |
| // to choose from. Otherwise, just keep the instance. | |
| if (imm.hasMultipleInputMethods()) { | |
| imm.initialize(); | |
| Thread immThread = | |
| new Thread(null, imm, threadName, 0, false); | |
| immThread.setDaemon(true); | |
| immThread.setPriority(Thread.NORM_PRIORITY + 1); | |
| immThread.start(); | |
| } | |
| inputMethodManager = imm; | |
| } | |
| } | |
| return inputMethodManager; | |
| } | |
| /** | |
| * Gets a string for the trigger menu item that should be added to | |
| * the window manager menu. If no need to display the trigger menu | |
| * item, null is returned. | |
| */ | |
| public abstract String getTriggerMenuString(); | |
| /** | |
| * Notifies InputMethodManager that input method change has been | |
| * requested by the user. This notification triggers a popup menu | |
| * for user selection. | |
| * | |
| * @param comp Component that has accepted the change | |
| * request. This component has to be a Frame or Dialog. | |
| */ | |
| public abstract void notifyChangeRequest(Component comp); | |
| /** | |
| * Notifies InputMethodManager that input method change has been | |
| * requested by the user using the hot key combination. This | |
| * notification triggers a popup menu for user selection. | |
| * | |
| * @param comp Component that has accepted the change | |
| * request. This component has the input focus. | |
| */ | |
| public abstract void notifyChangeRequestByHotKey(Component comp); | |
| /** | |
| * Sets the current input context so that it will be notified | |
| * of input method changes initiated from the user interface. | |
| * Set to real input context when activating; to null when | |
| * deactivating. | |
| */ | |
| abstract void setInputContext(InputContext inputContext); | |
| /** | |
| * Tries to find an input method locator for the given locale. | |
| * Returns null if no available input method locator supports | |
| * the locale. | |
| */ | |
| abstract InputMethodLocator findInputMethod(Locale forLocale); | |
| /** | |
| * Gets the default keyboard locale of the underlying operating system. | |
| */ | |
| abstract Locale getDefaultKeyboardLocale(); | |
| /** | |
| * Returns whether multiple input methods are available or not | |
| */ | |
| abstract boolean hasMultipleInputMethods(); | |
| } |