/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* 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.
*/
/**
* <code>InputMethodManager</code> is an abstract class that manages the input
* method environment of JVM. There is only one <code>InputMethodManager</code>
* instance in JVM that is executed under a separate daemon thread.
* <code>InputMethodManager</code> 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()</code>. 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
* <code>InputMethodManager</code> that the user wants to switch input methods.</LI>
*
* <LI>
* <code>InputMethodManager</code> displays a pop-up menu to choose an input method.</LI>
*
* <LI>
* <code>InputMethodManager</code> notifies the current <code>InputContext</code> of
* the selected <code>InputMethod</code>.</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()</code> to notify
* <code>InputMethodManager</code> 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
*/
/**
* Object for global locking
*/
/**
* The InputMethodManager instance
*/
/**
* 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
*/
if (inputMethodManager != null) {
return inputMethodManager;
}
synchronized(LOCK) {
if (inputMethodManager == null) {
// 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();
}
}
}
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.
*/
/**
* 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.
*/
/**
* 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.
*/
/**
* 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.
*/
/**
* Tries to find an input method locator for the given locale.
* Returns null if no available input method locator supports
* the locale.
*/
/**
* Gets the default keyboard locale of the underlying operating system.
*/
/**
* Returns whether multiple input methods are available or not
*/
abstract boolean hasMultipleInputMethods();
}
/**
* <code>ExecutableInputMethodManager</code> is the implementation of the
* <code>InputMethodManager</code> class. It is runnable as a separate
* thread in the AWT environment.
* <code>InputMethodManager.getInstance()</code> creates an instance of
* <code>ExecutableInputMethodManager</code> and executes it as a deamon
* thread.
*
* @see InputMethodManager
*/
implements Runnable
{
// the input context that's informed about selections from the user interface
// Menu item string for the trigger menu.
// popup menu for selecting an input method
// locator and name of host adapter
// locators for Java input methods
// component that is requesting input method switch
// must be Frame or Dialog
// input context that is requesting input method switch
// IM preference stuff
// set up host adapter locator
try {
if (toolkit instanceof InputMethodSupport) {
if (hostAdapterDescriptor != null) {
}
}
} catch (AWTException e) {
// if we can't get a descriptor, we'll just have to do without native input methods
}
}
synchronized void initialize() {
selectInputMethodMenuTitle = Toolkit.getProperty("AWT.InputMethodSelectionMenu", "Select Input Method");
}
public void run() {
// If there are no multiple input methods to choose from, wait forever
while (!hasMultipleInputMethods()) {
try {
synchronized (this) {
wait();
}
} catch (InterruptedException e) {
}
}
// Loop for processing input method change requests
while (true) {
try {
if (requestComponent != null) {
} else {
// show the popup menu within the event thread
public void run() {
}
});
}
} catch (InterruptedException ie) {
} catch (InvocationTargetException ite) {
// should we do anything under these exceptions?
}
}
}
// Shows Input Method Menu on the EDT of requester component
// to avoid side effects. See 6544309.
return;
}
class AWTInvocationLock {}
new InvocationEvent(requester,
new Runnable() {
public void run() {
}
},
lock,
true);
synchronized (lock) {
while (!event.isDispatched()) {
}
}
if (eventThrowable != null) {
throw new InvocationTargetException(eventThrowable);
}
}
// don't throw this exception until 4237852 is fixed
// throw new IllegalStateException("Can't have two active InputContext at the same time");
}
}
return;
// if busy with the current request, ignore this request.
if (requestComponent != null)
return;
notify();
}
// no Frame or Dialog found in containment hierarchy.
return;
}
}
}
return triggerMenuString;
}
/*
* Returns true if the environment indicates there are multiple input methods
*/
boolean hasMultipleInputMethods() {
|| (javaInputMethodCount > 1));
}
private synchronized void waitForChangeRequest() {
try {
while (requestComponent == null) {
wait();
}
} catch (InterruptedException e) {
}
}
/*
* initializes the input method locator list for all
* installed input method descriptors.
*/
private void initializeInputMethodLocatorList() {
synchronized (javaInputMethodLocatorList) {
try {
for (InputMethodDescriptor descriptor :
}
return null;
}
});
} catch (PrivilegedActionException e) {
e.printStackTrace();
}
}
if (hasMultipleInputMethods()) {
// initialize preferences
userRoot = getUserRoot();
}
} else {
// indicate to clients not to offer the menu
}
}
private void showInputMethodMenu() {
if (!hasMultipleInputMethods()) {
return;
}
// initialize pop-up menu
// we have to rebuild the menu each time because
// some input methods (such as IIIMP) may change
// their list of supported locales dynamically
// get information about the currently selected input method
// ??? if there's no current input context, what's the point
// of showing the menu?
// Add menu item for host adapter
if (hostAdapterLocator != null) {
}
// Add menu items for other input methods
}
synchronized (this) {
}
}
if (inputContext != null) {
return locator.getActionCommandString();
}
}
return null;
}
if (index != -1) {
}
} else {
break;
}
}
}
if (postIndex == -1) {
} else {
if (postIndex == -1) {
} else {
}
}
}
return;
// tell the input context about the change
if (requestInputContext != null) {
// remember the selection
}
}
// look for preferred input method first
return locator;
}
}
// Update the locator list
}
}
return null;
}
if (toolkit instanceof InputMethodSupport) {
} else {
return Locale.getDefault();
}
}
/**
* Returns a InputMethodLocator object that the
* user prefers for the given locale.
*
* @param locale Locale for which the user prefers the input method.
*/
if (!hasMultipleInputMethods()) {
// No need to look for a preferred Java input method
return null;
}
// look for the cached preference first.
if (preferredLocator != null) {
return preferredLocator;
}
// look for the preference in the user preference tree
// get the locator object
if (descriptorName != null) {
// check for the host adapter first
if (hostAdapterLocator != null &&
if (advertised != null) {
}
return preferredLocator;
}
// look for Java input methods
if (advertised != null) {
}
return preferredLocator;
}
}
// maybe preferred input method information is bogus.
}
return null;
}
return null;
}
// create locale node relative path
// look for the descriptor
try {
return nodePath;
}
}
} catch (BackingStoreException bse) {
}
// search at parent's node
}
return null;
}
return null;
}
}
/**
* Writes the preferred input method descriptor class name into
* the user's Preferences tree in accordance with the given locale.
*
* @param inputMethodLocator input method locator to remember.
*/
if (preferredLocale == null) {
// check available locales of the input method
try {
} else {
// there is no way to know which locale is the preferred one, so do nothing.
return;
}
} catch (AWTException ae) {
// do nothing here, either.
return;
}
}
// for regions that have only one language, we need to regard
// "xx_YY" as "xx" when putting the preference into tree
}
}
}
// obtain node
// write in the preference tree
return;
}
} else {
}
return localePath;
}
// record it
if (descriptorName != null) {
} else {
}
}
}
return Preferences.userRoot();
}
});
}
advertised = locale;
// for Japanese, Korean, and Thai, check whether the input method supports
// language or language_COUNTRY.
}
}
}
}
return advertised;
}
}