/*
* 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.
*/
/**
* This InputContext class contains parts of the implementation of
* java.text.im.InputContext. These parts have been moved
* here to avoid exposing protected members that are needed by the
* subclass InputMethodContext.
*
* @see java.awt.im.InputContext
*/
implements ComponentListener, WindowListener {
// The current input method is represented by two objects:
// a locator is used to keep information about the selected
// input method and locale until we actually need a real input
// method; only then the input method itself is created.
// Once there is an input method, the input method's locale
// takes precedence over locale information in the locator.
private boolean inputMethodCreationFailed;
// holding bin for previously used input method instances, but not the current one
// the current client component is kept until the user focusses on a different
// client component served by the same input context. When that happens, we call
// endComposition so that text doesn't jump from one component to another.
private boolean isInputMethodActive;
// true if composition area has been set to invisible when focus was lost
private boolean compositionAreaHidden = false;
// The input context for whose input method we may have to call hideWindows
// Previously active input method to decide whether we need to call
// InputMethodAdapter.stopListening() on activateInputMethod()
// true if the current input method requires client window change notification
private boolean clientWindowNotificationEnabled = false;
// client window to which this input context is listening
// cache location notification
// holding the state of clientWindowNotificationEnabled of only non-current input methods
// Input Method selection hot key stuff
private static boolean inputMethodSelectionKeyInitialized = false;
/**
* Constructs an InputContext.
*/
protected InputContext() {
synchronized (InputContext.class) {
if (imm.hasMultipleInputMethods()) {
}
}
}
}
/**
* @see java.awt.im.InputContext#selectInputMethod
* @exception NullPointerException when the locale is null.
*/
throw new NullPointerException();
}
// see whether the current input method supports the locale
if (inputMethod != null) {
return true;
}
} else if (inputMethodLocator != null) {
// This is not 100% correct, since the input method
// may support the locale without advertising it.
// But before we try instantiations and setLocale,
// we look for an input method that's more confident.
return true;
}
}
// see whether there's some other input method that supports the locale
if (newLocator != null) {
return true;
}
// make one last desperate effort with the current input method
// ??? is this good? This is pretty high cost for something that's likely to fail.
if (inputMethod != null) {
}
}
return false;
}
/**
* @see java.awt.im.InputContext#getLocale
*/
if (inputMethod != null) {
return inputMethod.getLocale();
} else if (inputMethodLocator != null) {
return inputMethodLocator.getLocale();
} else {
return null;
}
}
/**
* @see java.awt.im.InputContext#setCharacterSubsets
*/
} else {
}
if (inputMethod != null) {
}
}
/**
* @see java.awt.im.InputContext#reconvert
* @since 1.3
* @exception UnsupportedOperationException when input method is null
*/
public synchronized void reconvert() {
if (inputMethod == null) {
throw new UnsupportedOperationException();
}
}
/**
* @see java.awt.im.InputContext#dispatchEvent
*/
if (event instanceof InputMethodEvent) {
return;
}
// Ignore focus events that relate to the InputMethodWindow of this context.
// This is a workaround. Should be removed after 4452384 is fixed.
if (event instanceof FocusEvent) {
(opposite.getInputContext() == this)) {
return;
}
}
switch (id) {
case FocusEvent.FOCUS_GAINED:
break;
case FocusEvent.FOCUS_LOST:
break;
case KeyEvent.KEY_PRESSED:
// pop up the input method selection menu
break;
}
// fall through
default:
}
}
}
/**
* Handles focus gained events for any component that's using
* this input context.
* These events are generated by AWT when the keyboard focus
* moves to a component.
* Besides actual client components, the source components
* may also be the composition area or any component in an
* input method window.
* <p>
* When handling the focus event for a client component, this
* method checks whether the input context was previously
* active for a different client component, and if so, calls
* endComposition for the previous client component.
*
* @param source the component gaining the focus
*/
/*
* NOTE: When a Container is removing its Component which
* invokes this.removeNotify(), the Container has the global
* Component lock. It is possible to happen that an
* application thread is calling this.removeNotify() while an
* AWT event queue thread is dispatching a focus event via
* this.dispatchEvent(). If an input method uses AWT
* components (e.g., IIIMP status window), it causes deadlock,
* for example, Component.show()/hide() in this situation
* it's necessary to obtain the global Component lock before
* activating or deactivating an input method.
*/
synchronized (source.getTreeLock()) {
synchronized (this) {
// no special handling for this one
// no special handling for this one either
} else {
if (!source.isDisplayable()) {
// Component is being disposed
return;
}
// Focus went to a real client component.
// Check whether we're switching between client components
// that share an input context. We can't do that earlier
// than here because we don't want to end composition
// until we really know we're switching to a different component
if (inputMethod != null) {
if (!isInputMethodActive) {
activateInputMethod(false);
}
deactivateInputMethod(false);
}
}
}
if (inputMethod instanceof InputMethodAdapter) {
}
// it's possible that the input method is still active because
// we suppressed a deactivate cause by an input method window
// coming up
if (!isInputMethodActive) {
activateInputMethod(true);
}
// If the client component is an active client with the below-the-spot
// input style, then make the composition window undecorated without a title bar.
if (!inputContext.isCompositionAreaVisible()) {
} else {
}
}
// restores the composition area if it was set to invisible
// when focus got lost
if (compositionAreaHidden == true) {
((InputMethodContext)this).setCompositionAreaVisible(true);
compositionAreaHidden = false;
}
}
}
}
/**
* Activates the current input method of this input context, and grabs
* the composition area for use by this input context.
* If updateCompositionArea is true, the text in the composition area
* is updated (set to false if the text is going to change immediately
* to avoid screen flicker).
*/
// call hideWindows() if this input context uses a different
// input method than the previously activated one
}
inputMethodWindowContext = this;
if (inputMethod != null) {
if (previousInputMethod != inputMethod &&
previousInputMethod instanceof InputMethodAdapter) {
// let the host adapter pass through the input events for the
// new input method
}
if (log.isLoggable(PlatformLogger.FINE)) log.fine("Current client component " + currentClientComponent);
if (inputMethod instanceof InputMethodAdapter) {
}
isInputMethodActive = true;
if (perInputMethodState != null) {
}
}
if (!addedClientWindowListeners()) {
}
synchronized(this) {
if (clientWindowListened != null) {
}
}
} else {
if (addedClientWindowListeners()) {
}
}
}
}
while (true) {
return null;
} else {
}
}
}
/**
* Handles focus lost events for any component that's using
* this input context.
* These events are generated by AWT when the keyboard focus
* moves away from a component.
* Besides actual client components, the source components
* may also be the composition area or any component in an
* input method window.
*
* @param source the component losing the focus
* @isTemporary whether the focus change is temporary
*/
// see the note on synchronization in focusGained
synchronized (source.getTreeLock()) {
synchronized (this) {
// We need to suppress deactivation if removeNotify has been called earlier.
// This is indicated by isInputMethodActive == false.
if (isInputMethodActive) {
}
if (inputMethod instanceof InputMethodAdapter) {
}
// hides the composition area if currently it is visible
if (inputContext.isCompositionAreaVisible()) {
compositionAreaHidden = true;
}
}
}
}
/**
* Checks the key event is the input method selection key or not.
*/
if (inputMethodSelectionKey != null) {
} else {
return false;
}
}
if (inputMethod != null) {
isInputMethodActive = false;
}
}
/**
* Switches from the current input method to the one described by newLocator.
* The current input method, if any, is asked to end composition, deactivated,
* and saved for future use. The newLocator is made the current locator. If
* the input context is active, an input method instance for the new locator
* is obtained; otherwise this is deferred until required.
*/
// If we don't have a locator yet, this must be a new input context.
// If we created a new input method here, we might get into an
// infinite loop: create input method -> create some input method window ->
// create new input context -> add input context to input method manager's context list ->
// call changeInputMethod on it.
// So, just record the locator. dispatchEvent will create the input method when needed.
if (inputMethodLocator == null) {
inputMethodCreationFailed = false;
return;
}
// If the same input method is specified, just keep it.
// Adjust the locale if necessary.
if (inputMethod != null) {
}
}
return;
}
// Switch out the old input method
boolean wasInputMethodActive = isInputMethodActive;
boolean wasCompositionEnabledSupported = false;
boolean wasCompositionEnabled = false;
if (inputMethod != null) {
try {
wasCompositionEnabledSupported = true;
} catch (UnsupportedOperationException e) { }
if (currentClientComponent != null) {
if (!isInputMethodActive) {
activateInputMethod(false);
}
deactivateInputMethod(false);
if (inputMethod instanceof InputMethodAdapter) {
}
}
// keep the input method instance around for future use
if (usedInputMethods == null) {
}
if (perInputMethodState == null) {
}
if (this == inputMethodWindowContext) {
}
inputMethod = null;
inputMethodCreationFailed = false;
}
// Switch in the new input method
}
inputMethodCreationFailed = false;
// activate the new input method if the old one was active
if (wasInputMethodActive) {
if (inputMethod instanceof InputMethodAdapter) {
}
activateInputMethod(true);
}
if (inputMethod != null) {
try {
} catch (UnsupportedOperationException e) { }
}
}
}
/**
* Returns the client component.
*/
return currentClientComponent;
}
/**
* @see java.awt.im.InputContext#removeNotify
* @exception NullPointerException when the component is null.
*/
throw new NullPointerException();
}
if (inputMethod == null) {
if (component == currentClientComponent) {
}
return;
}
// We may or may not get a FOCUS_LOST event for this component,
// so do the deactivation stuff here too.
if (component == awtFocussedComponent) {
}
if (component == currentClientComponent) {
if (isInputMethodActive) {
// component wasn't the one that had the focus
deactivateInputMethod(false);
}
}
if (inputMethod instanceof InputMethodAdapter) {
}
// removeNotify() can be issued from a thread other than the event dispatch
// thread. In that case, avoid possible deadlock between Component.AWTTreeLock
// and InputMethodContext.compositionAreaHandlerLock by releasing the composition
// area on the event dispatch thread.
if (EventQueue.isDispatchThread()) {
((InputMethodContext)this).releaseCompositionArea();
} else {
public void run() {
}
});
}
}
}
/**
* @see java.awt.im.InputContext#dispose
* @exception IllegalStateException when the currentClientComponent is not null
*/
public synchronized void dispose() {
if (currentClientComponent != null) {
throw new IllegalStateException("Can't dispose InputContext while it's active");
}
if (inputMethod != null) {
if (this == inputMethodWindowContext) {
}
if (inputMethod == previousInputMethod) {
}
if (addedClientWindowListeners()) {
}
clientWindowNotificationEnabled = false;
}
// in case the input method enabled the client window
// notification in dispose(), which shouldn't happen, it
// needs to be cleaned up again.
}
inputMethod = null;
}
}
}
// cleanup client window notification variables
clientWindowNotificationEnabled = false;
}
/**
* @see java.awt.im.InputContext#getInputMethodControlObject
*/
if (inputMethod != null) {
return inputMethod.getControlObject();
} else {
return null;
}
}
/**
* @see java.awt.im.InputContext#setCompositionEnabled(boolean)
* @exception UnsupportedOperationException when input method is null
*/
if (inputMethod == null) {
throw new UnsupportedOperationException();
}
}
/**
* @see java.awt.im.InputContext#isCompositionEnabled
* @exception UnsupportedOperationException when input method is null
*/
public boolean isCompositionEnabled() {
if (inputMethod == null) {
throw new UnsupportedOperationException();
}
return inputMethod.isCompositionEnabled();
}
/**
* @return a string with information about the current input method.
* @exception UnsupportedOperationException when input method is null
*/
if (inputMethod == null) {
throw new UnsupportedOperationException("Null input method");
}
if (inputMethod instanceof InputMethodAdapter) {
// returns the information about the host native input method.
}
// extracts the information from the InputMethodDescriptor
// associated with the current java input method.
getStartupLocale());
}
return inputMethodInfo;
}
// do our best to return something useful.
}
/**
* Turns off the native IM. The native IM is diabled when
* the deactive method of InputMethod is called. It is
* delayed until the active method is called on a different
* peer component. This method is provided to explicitly disable
* the native IM.
*/
public void disableNativeIM() {
}
}
if (inputMethod != null) {
return inputMethod;
}
if (inputMethodCreationFailed) {
return null;
}
return inputMethod;
}
/**
* Returns an instance of the input method described by
* the current input method locator. This may be an input
* method that was previously used and switched out of,
* or a new instance. The locale, character subsets, and
* input method context of the input method are set.
*
* The inputMethodCreationFailed field is set to true if the
* instantiation failed.
*
* @return an InputMethod instance
* @see java.awt.im.spi.InputMethod#setInputMethodContext
* @see java.awt.im.spi.InputMethod#setLocale
* @see java.awt.im.spi.InputMethod#setCharacterSubsets
*/
inputMethodCreationFailed = true;
return null;
}
// see whether we have a previously used input method
if (usedInputMethods != null) {
if (inputMethodInstance != null) {
}
}
(!(inputMethodInstance instanceof InputMethodAdapter)) ||
return inputMethodInstance;
}
}
// need to create new instance
try {
}
} catch (Exception e) {
// there are a number of bad things that can happen while creating
// the input method. In any case, we just continue without an
// input method.
inputMethodCreationFailed = true;
// if the instance has been created, then it means either
// setLocale() or setInputMethodContext() failed.
if (inputMethodInstance != null) {
}
} catch (LinkageError e) {
// same as above
inputMethodCreationFailed = true;
}
(!(inputMethodInstance instanceof InputMethodAdapter)) ||
return inputMethodInstance;
}
"Could not create {0}. Reason: {1}");
}
if (inputMethod != null) {
}
return inputMethodLocator;
}
/**
* @see java.awt.im.InputContext#endComposition
*/
public synchronized void endComposition() {
if (inputMethod != null) {
}
}
/**
* @see java.awt.im.spi.InputMethodContext#enableClientWindowNotification
*/
boolean enable) {
// in case this request is not from the current input method,
// store the request and handle it when this requesting input
// method becomes the current one.
if (requester != inputMethod) {
if (perInputMethodState == null) {
}
return;
}
if (clientWindowNotificationEnabled != enable) {
}
if (!addedClientWindowListeners()) {
}
if (clientWindowListened != null) {
}
} else {
if (addedClientWindowListeners()) {
}
}
}
if (inputMethod == null) {
return;
}
// if the window is invisible or iconified, send null to the input method.
return;
}
}
}
private synchronized void addClientWindowListeners() {
return;
}
return;
}
window.addComponentListener(this);
window.addWindowListener(this);
}
private synchronized void removeClientWindowListeners() {
}
/**
* Returns true if listeners have been set up for client window
* change notification.
*/
private boolean addedClientWindowListeners() {
return clientWindowListened != null;
}
/*
* ComponentListener and WindowListener implementation
*/
}
}
}
}
}
}
/**
* Initializes the input method selection key definition in preference trees
*/
private void initializeInputMethodSelectionKey() {
// Look in user's tree
if (inputMethodSelectionKey == null) {
// Look in system's tree
}
return null;
}
});
}
try {
}
}
} catch (BackingStoreException bse) {
}
return null;
}
}