Source Code Cross Referenced for InputContext.java in  » 6.0-JDK-Modules-sun » awt » sun » awt » im » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules sun » awt » sun.awt.im 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1997-2006 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package sun.awt.im;
0027:
0028:        import java.awt.AWTEvent;
0029:        import java.awt.AWTKeyStroke;
0030:        import java.awt.Component;
0031:        import java.awt.EventQueue;
0032:        import java.awt.Frame;
0033:        import java.awt.Rectangle;
0034:        import java.awt.Toolkit;
0035:        import java.awt.Window;
0036:        import java.awt.event.ComponentEvent;
0037:        import java.awt.event.ComponentListener;
0038:        import java.awt.event.FocusEvent;
0039:        import java.awt.event.InputEvent;
0040:        import java.awt.event.InputMethodEvent;
0041:        import java.awt.event.KeyEvent;
0042:        import java.awt.event.WindowEvent;
0043:        import java.awt.event.WindowListener;
0044:        import java.awt.im.InputMethodRequests;
0045:        import java.awt.im.spi.InputMethod;
0046:        import java.lang.Character.Subset;
0047:        import java.security.AccessController;
0048:        import java.security.PrivilegedAction;
0049:        import java.text.MessageFormat;
0050:        import java.util.HashMap;
0051:        import java.util.Iterator;
0052:        import java.util.Locale;
0053:        import java.util.logging.*;
0054:        import java.util.prefs.BackingStoreException;
0055:        import java.util.prefs.Preferences;
0056:        import sun.awt.SunToolkit;
0057:
0058:        /**
0059:         * This InputContext class contains parts of the implementation of
0060:         * java.text.im.InputContext. These parts have been moved
0061:         * here to avoid exposing protected members that are needed by the
0062:         * subclass InputMethodContext.
0063:         *
0064:         * @see java.awt.im.InputContext
0065:         * @version 1.63 05/05/07
0066:         * @author JavaSoft Asia/Pacific
0067:         */
0068:
0069:        public class InputContext extends java.awt.im.InputContext implements 
0070:                ComponentListener, WindowListener {
0071:            private static final Logger log = Logger
0072:                    .getLogger("sun.awt.im.InputContext");
0073:            // The current input method is represented by two objects:
0074:            // a locator is used to keep information about the selected
0075:            // input method and locale until we actually need a real input
0076:            // method; only then the input method itself is created.
0077:            // Once there is an input method, the input method's locale
0078:            // takes precedence over locale information in the locator.
0079:            private InputMethodLocator inputMethodLocator;
0080:            private InputMethod inputMethod;
0081:            private boolean inputMethodCreationFailed;
0082:
0083:            // holding bin for previously used input method instances, but not the current one
0084:            private HashMap usedInputMethods;
0085:
0086:            // the current client component is kept until the user focusses on a different
0087:            // client component served by the same input context. When that happens, we call
0088:            // endComposition so that text doesn't jump from one component to another.
0089:            private Component currentClientComponent;
0090:            private Component awtFocussedComponent;
0091:            private boolean isInputMethodActive;
0092:            private Subset[] characterSubsets = null;
0093:
0094:            // true if composition area has been set to invisible when focus was lost
0095:            private boolean compositionAreaHidden = false;
0096:
0097:            // The input context for whose input method we may have to call hideWindows
0098:            private static InputContext inputMethodWindowContext;
0099:
0100:            // Previously active input method to decide whether we need to call 
0101:            // InputMethodAdapter.stopListening() on activateInputMethod()
0102:            private static InputMethod previousInputMethod = null;
0103:
0104:            // true if the current input method requires client window change notification
0105:            private boolean clientWindowNotificationEnabled = false;
0106:            // client window to which this input context is listening
0107:            private Window clientWindowListened;
0108:            // cache location notification
0109:            private Rectangle clientWindowLocation = null;
0110:            // holding the state of clientWindowNotificationEnabled of only non-current input methods
0111:            private HashMap perInputMethodState;
0112:
0113:            // Input Method selection hot key stuff
0114:            private static AWTKeyStroke inputMethodSelectionKey;
0115:            private static boolean inputMethodSelectionKeyInitialized = false;
0116:            private static final String inputMethodSelectionKeyPath = "/java/awt/im/selectionKey";
0117:            private static final String inputMethodSelectionKeyCodeName = "keyCode";
0118:            private static final String inputMethodSelectionKeyModifiersName = "modifiers";
0119:
0120:            /**
0121:             * Constructs an InputContext.
0122:             */
0123:            protected InputContext() {
0124:                InputMethodManager imm = InputMethodManager.getInstance();
0125:                synchronized (InputContext.class) {
0126:                    if (!inputMethodSelectionKeyInitialized) {
0127:                        inputMethodSelectionKeyInitialized = true;
0128:                        if (imm.hasMultipleInputMethods()) {
0129:                            initializeInputMethodSelectionKey();
0130:                        }
0131:                    }
0132:                }
0133:                selectInputMethod(imm.getDefaultKeyboardLocale());
0134:            }
0135:
0136:            /**
0137:             * @see java.awt.im.InputContext#selectInputMethod
0138:             * @exception NullPointerException when the locale is null.
0139:             */
0140:            public synchronized boolean selectInputMethod(Locale locale) {
0141:                if (locale == null) {
0142:                    throw new NullPointerException();
0143:                }
0144:
0145:                // see whether the current input method supports the locale
0146:                if (inputMethod != null) {
0147:                    if (inputMethod.setLocale(locale)) {
0148:                        return true;
0149:                    }
0150:                } else if (inputMethodLocator != null) {
0151:                    // This is not 100% correct, since the input method
0152:                    // may support the locale without advertising it.
0153:                    // But before we try instantiations and setLocale,
0154:                    // we look for an input method that's more confident.
0155:                    if (inputMethodLocator.isLocaleAvailable(locale)) {
0156:                        inputMethodLocator = inputMethodLocator
0157:                                .deriveLocator(locale);
0158:                        return true;
0159:                    }
0160:                }
0161:
0162:                // see whether there's some other input method that supports the locale
0163:                InputMethodLocator newLocator = InputMethodManager
0164:                        .getInstance().findInputMethod(locale);
0165:                if (newLocator != null) {
0166:                    changeInputMethod(newLocator);
0167:                    return true;
0168:                }
0169:
0170:                // make one last desperate effort with the current input method
0171:                // ??? is this good? This is pretty high cost for something that's likely to fail.
0172:                if (inputMethod == null && inputMethodLocator != null) {
0173:                    inputMethod = getInputMethod();
0174:                    if (inputMethod != null) {
0175:                        return inputMethod.setLocale(locale);
0176:                    }
0177:                }
0178:                return false;
0179:            }
0180:
0181:            /**
0182:             * @see java.awt.im.InputContext#getLocale
0183:             */
0184:            public Locale getLocale() {
0185:                if (inputMethod != null) {
0186:                    return inputMethod.getLocale();
0187:                } else if (inputMethodLocator != null) {
0188:                    return inputMethodLocator.getLocale();
0189:                } else {
0190:                    return null;
0191:                }
0192:            }
0193:
0194:            /**
0195:             * @see java.awt.im.InputContext#setCharacterSubsets
0196:             */
0197:            public void setCharacterSubsets(Subset[] subsets) {
0198:                if (subsets == null) {
0199:                    characterSubsets = null;
0200:                } else {
0201:                    characterSubsets = new Subset[subsets.length];
0202:                    System.arraycopy(subsets, 0, characterSubsets, 0,
0203:                            characterSubsets.length);
0204:                }
0205:                if (inputMethod != null) {
0206:                    inputMethod.setCharacterSubsets(subsets);
0207:                }
0208:            }
0209:
0210:            /**
0211:             * @see java.awt.im.InputContext#reconvert
0212:             * @since 1.3
0213:             * @exception UnsupportedOperationException when input method is null
0214:             */
0215:            public synchronized void reconvert() {
0216:                InputMethod inputMethod = getInputMethod();
0217:                if (inputMethod == null) {
0218:                    throw new UnsupportedOperationException();
0219:                }
0220:                inputMethod.reconvert();
0221:            }
0222:
0223:            /**
0224:             * @see java.awt.im.InputContext#dispatchEvent
0225:             */
0226:            public void dispatchEvent(AWTEvent event) {
0227:
0228:                if (event instanceof  InputMethodEvent) {
0229:                    return;
0230:                }
0231:
0232:                // Ignore focus events that relate to the InputMethodWindow of this context.
0233:                // This is a workaround.  Should be removed after 4452384 is fixed.
0234:                if (event instanceof  FocusEvent) {
0235:                    Component opposite = ((FocusEvent) event)
0236:                            .getOppositeComponent();
0237:                    if ((opposite != null)
0238:                            && (getComponentWindow(opposite) instanceof  InputMethodWindow)
0239:                            && (opposite.getInputContext() == this )) {
0240:                        return;
0241:                    }
0242:                }
0243:
0244:                InputMethod inputMethod = getInputMethod();
0245:                int id = event.getID();
0246:
0247:                switch (id) {
0248:                case FocusEvent.FOCUS_GAINED:
0249:                    focusGained((Component) event.getSource());
0250:                    break;
0251:
0252:                case FocusEvent.FOCUS_LOST:
0253:                    focusLost((Component) event.getSource(),
0254:                            ((FocusEvent) event).isTemporary());
0255:                    break;
0256:
0257:                case KeyEvent.KEY_PRESSED:
0258:                    if (checkInputMethodSelectionKey((KeyEvent) event)) {
0259:                        // pop up the input method selection menu
0260:                        InputMethodManager.getInstance()
0261:                                .notifyChangeRequestByHotKey(
0262:                                        (Component) event.getSource());
0263:                        break;
0264:                    }
0265:
0266:                    // fall through
0267:
0268:                default:
0269:                    if ((inputMethod != null) && (event instanceof  InputEvent)) {
0270:                        inputMethod.dispatchEvent(event);
0271:                    }
0272:                }
0273:            }
0274:
0275:            /**
0276:             * Handles focus gained events for any component that's using
0277:             * this input context.
0278:             * These events are generated by AWT when the keyboard focus
0279:             * moves to a component.
0280:             * Besides actual client components, the source components
0281:             * may also be the composition area or any component in an
0282:             * input method window.
0283:             * <p>
0284:             * When handling the focus event for a client component, this
0285:             * method checks whether the input context was previously
0286:             * active for a different client component, and if so, calls
0287:             * endComposition for the previous client component.
0288:             *
0289:             * @param source the component gaining the focus
0290:             */
0291:            private void focusGained(Component source) {
0292:
0293:                /*
0294:                 * NOTE: When a Container is removing its Component which
0295:                 * invokes this.removeNotify(), the Container has the global
0296:                 * Component lock. It is possible to happen that an
0297:                 * application thread is calling this.removeNotify() while an
0298:                 * AWT event queue thread is dispatching a focus event via
0299:                 * this.dispatchEvent(). If an input method uses AWT
0300:                 * components (e.g., IIIMP status window), it causes deadlock,
0301:                 * for example, Component.show()/hide() in this situation
0302:                 * because hide/show tried to obtain the lock.  Therefore,
0303:                 * it's necessary to obtain the global Component lock before
0304:                 * activating or deactivating an input method.
0305:                 */
0306:                synchronized (source.getTreeLock()) {
0307:                    synchronized (this ) {
0308:                        if (source instanceof  CompositionArea) {
0309:                            // no special handling for this one
0310:                        } else if (getComponentWindow(source) instanceof  InputMethodWindow) {
0311:                            // no special handling for this one either
0312:                        } else {
0313:                            if (!source.isDisplayable()) {
0314:                                // Component is being disposed
0315:                                return;
0316:                            }
0317:
0318:                            // Focus went to a real client component.
0319:                            // Check whether we're switching between client components
0320:                            // that share an input context. We can't do that earlier
0321:                            // than here because we don't want to end composition
0322:                            // until we really know we're switching to a different component
0323:                            if (inputMethod != null) {
0324:                                if (currentClientComponent != null
0325:                                        && currentClientComponent != source) {
0326:                                    if (!isInputMethodActive) {
0327:                                        activateInputMethod(false);
0328:                                    }
0329:                                    endComposition();
0330:                                    deactivateInputMethod(false);
0331:                                }
0332:                            }
0333:
0334:                            currentClientComponent = source;
0335:                        }
0336:
0337:                        awtFocussedComponent = source;
0338:                        if (inputMethod instanceof  InputMethodAdapter) {
0339:                            ((InputMethodAdapter) inputMethod)
0340:                                    .setAWTFocussedComponent(source);
0341:                        }
0342:
0343:                        // it's possible that the input method is still active because
0344:                        // we suppressed a deactivate cause by an input method window
0345:                        // coming up
0346:                        if (!isInputMethodActive) {
0347:                            activateInputMethod(true);
0348:                        }
0349:
0350:                        // If the client component is an active client with the below-the-spot 
0351:                        // input style, then make the composition window undecorated without a title bar.
0352:                        InputMethodContext inputContext = ((InputMethodContext) this );
0353:                        if (!inputContext.isCompositionAreaVisible()) {
0354:                            InputMethodRequests req = source
0355:                                    .getInputMethodRequests();
0356:                            if (req != null
0357:                                    && inputContext.useBelowTheSpotInput()) {
0358:                                inputContext
0359:                                        .setCompositionAreaUndecorated(true);
0360:                            } else {
0361:                                inputContext
0362:                                        .setCompositionAreaUndecorated(false);
0363:                            }
0364:                        }
0365:                        // restores the composition area if it was set to invisible 
0366:                        // when focus got lost
0367:                        if (compositionAreaHidden == true) {
0368:                            ((InputMethodContext) this )
0369:                                    .setCompositionAreaVisible(true);
0370:                            compositionAreaHidden = false;
0371:                        }
0372:                    }
0373:                }
0374:            }
0375:
0376:            /**
0377:             * Activates the current input method of this input context, and grabs
0378:             * the composition area for use by this input context.
0379:             * If updateCompositionArea is true, the text in the composition area
0380:             * is updated (set to false if the text is going to change immediately
0381:             * to avoid screen flicker).
0382:             */
0383:            private void activateInputMethod(boolean updateCompositionArea) {
0384:                // call hideWindows() if this input context uses a different
0385:                // input method than the previously activated one
0386:                if (inputMethodWindowContext != null
0387:                        && inputMethodWindowContext != this 
0388:                        && inputMethodWindowContext.inputMethodLocator != null
0389:                        && !inputMethodWindowContext.inputMethodLocator
0390:                                .sameInputMethod(inputMethodLocator)
0391:                        && inputMethodWindowContext.inputMethod != null) {
0392:                    inputMethodWindowContext.inputMethod.hideWindows();
0393:                }
0394:                inputMethodWindowContext = this ;
0395:
0396:                if (inputMethod != null) {
0397:                    if (previousInputMethod != inputMethod
0398:                            && previousInputMethod instanceof  InputMethodAdapter) {
0399:                        // let the host adapter pass through the input events for the
0400:                        // new input method
0401:                        ((InputMethodAdapter) previousInputMethod)
0402:                                .stopListening();
0403:                    }
0404:                    previousInputMethod = null;
0405:
0406:                    if (log.isLoggable(Level.FINE))
0407:                        log.fine("Current client component "
0408:                                + currentClientComponent);
0409:                    if (inputMethod instanceof  InputMethodAdapter) {
0410:                        ((InputMethodAdapter) inputMethod)
0411:                                .setClientComponent(currentClientComponent);
0412:                    }
0413:                    inputMethod.activate();
0414:                    isInputMethodActive = true;
0415:
0416:                    if (perInputMethodState != null) {
0417:                        Boolean state = (Boolean) perInputMethodState
0418:                                .remove(inputMethod);
0419:                        if (state != null) {
0420:                            clientWindowNotificationEnabled = state
0421:                                    .booleanValue();
0422:                        }
0423:                    }
0424:                    if (clientWindowNotificationEnabled) {
0425:                        if (!addedClientWindowListeners()) {
0426:                            addClientWindowListeners();
0427:                        }
0428:                        synchronized (this ) {
0429:                            if (clientWindowListened != null) {
0430:                                notifyClientWindowChange(clientWindowListened);
0431:                            }
0432:                        }
0433:                    } else {
0434:                        if (addedClientWindowListeners()) {
0435:                            removeClientWindowListeners();
0436:                        }
0437:                    }
0438:                }
0439:                InputMethodManager.getInstance().setInputContext(this );
0440:
0441:                ((InputMethodContext) this )
0442:                        .grabCompositionArea(updateCompositionArea);
0443:            }
0444:
0445:            static Window getComponentWindow(Component component) {
0446:                while (true) {
0447:                    if (component == null) {
0448:                        return null;
0449:                    } else if (component instanceof  Window) {
0450:                        return (Window) component;
0451:                    } else {
0452:                        component = component.getParent();
0453:                    }
0454:                }
0455:            }
0456:
0457:            /**
0458:             * Handles focus lost events for any component that's using
0459:             * this input context.
0460:             * These events are generated by AWT when the keyboard focus
0461:             * moves away from a component.
0462:             * Besides actual client components, the source components
0463:             * may also be the composition area or any component in an
0464:             * input method window.
0465:             *
0466:             * @param source the component losing the focus
0467:             * @isTemporary whether the focus change is temporary
0468:             */
0469:            private void focusLost(Component source, boolean isTemporary) {
0470:
0471:                // see the note on synchronization in focusGained
0472:                synchronized (source.getTreeLock()) {
0473:                    synchronized (this ) {
0474:
0475:                        // We need to suppress deactivation if removeNotify has been called earlier.
0476:                        // This is indicated by isInputMethodActive == false.
0477:                        if (isInputMethodActive) {
0478:                            deactivateInputMethod(isTemporary);
0479:                        }
0480:
0481:                        awtFocussedComponent = null;
0482:                        if (inputMethod instanceof  InputMethodAdapter) {
0483:                            ((InputMethodAdapter) inputMethod)
0484:                                    .setAWTFocussedComponent(null);
0485:                        }
0486:
0487:                        // hides the composition area if currently it is visible
0488:                        InputMethodContext inputContext = ((InputMethodContext) this );
0489:                        if (inputContext.isCompositionAreaVisible()) {
0490:                            inputContext.setCompositionAreaVisible(false);
0491:                            compositionAreaHidden = true;
0492:                        }
0493:                    }
0494:                }
0495:            }
0496:
0497:            /**
0498:             * Checks the key event is the input method selection key or not.
0499:             */
0500:            private boolean checkInputMethodSelectionKey(KeyEvent event) {
0501:                if (inputMethodSelectionKey != null) {
0502:                    AWTKeyStroke aKeyStroke = AWTKeyStroke
0503:                            .getAWTKeyStrokeForEvent(event);
0504:                    return inputMethodSelectionKey.equals(aKeyStroke);
0505:                } else {
0506:                    return false;
0507:                }
0508:            }
0509:
0510:            private void deactivateInputMethod(boolean isTemporary) {
0511:                InputMethodManager.getInstance().setInputContext(null);
0512:                if (inputMethod != null) {
0513:                    isInputMethodActive = false;
0514:                    inputMethod.deactivate(isTemporary);
0515:                    previousInputMethod = inputMethod;
0516:                }
0517:            }
0518:
0519:            /**
0520:             * Switches from the current input method to the one described by newLocator.
0521:             * The current input method, if any, is asked to end composition, deactivated,
0522:             * and saved for future use. The newLocator is made the current locator. If
0523:             * the input context is active, an input method instance for the new locator
0524:             * is obtained; otherwise this is deferred until required.
0525:             */
0526:            synchronized void changeInputMethod(InputMethodLocator newLocator) {
0527:                // If we don't have a locator yet, this must be a new input context.
0528:                // If we created a new input method here, we might get into an
0529:                // infinite loop: create input method -> create some input method window ->
0530:                // create new input context -> add input context to input method manager's context list ->
0531:                // call changeInputMethod on it.
0532:                // So, just record the locator. dispatchEvent will create the input method when needed.
0533:                if (inputMethodLocator == null) {
0534:                    inputMethodLocator = newLocator;
0535:                    inputMethodCreationFailed = false;
0536:                    return;
0537:                }
0538:
0539:                // If the same input method is specified, just keep it.
0540:                // Adjust the locale if necessary.
0541:                if (inputMethodLocator.sameInputMethod(newLocator)) {
0542:                    Locale newLocale = newLocator.getLocale();
0543:                    if (newLocale != null
0544:                            && inputMethodLocator.getLocale() != newLocale) {
0545:                        if (inputMethod != null) {
0546:                            inputMethod.setLocale(newLocale);
0547:                        }
0548:                        inputMethodLocator = newLocator;
0549:                    }
0550:                    return;
0551:                }
0552:
0553:                // Switch out the old input method
0554:                Locale savedLocale = inputMethodLocator.getLocale();
0555:                boolean wasInputMethodActive = isInputMethodActive;
0556:                boolean wasCompositionEnabledSupported = false;
0557:                boolean wasCompositionEnabled = false;
0558:                if (inputMethod != null) {
0559:                    try {
0560:                        wasCompositionEnabled = inputMethod
0561:                                .isCompositionEnabled();
0562:                        wasCompositionEnabledSupported = true;
0563:                    } catch (UnsupportedOperationException e) {
0564:                    }
0565:
0566:                    if (currentClientComponent != null) {
0567:                        if (!isInputMethodActive) {
0568:                            activateInputMethod(false);
0569:                        }
0570:                        endComposition();
0571:                        deactivateInputMethod(false);
0572:                        if (inputMethod instanceof  InputMethodAdapter) {
0573:                            ((InputMethodAdapter) inputMethod)
0574:                                    .setClientComponent(null);
0575:                        }
0576:                    }
0577:                    savedLocale = inputMethod.getLocale();
0578:
0579:                    // keep the input method instance around for future use
0580:                    if (usedInputMethods == null) {
0581:                        usedInputMethods = new HashMap(5);
0582:                    }
0583:                    if (perInputMethodState == null) {
0584:                        perInputMethodState = new HashMap(5);
0585:                    }
0586:                    usedInputMethods
0587:                            .put(inputMethodLocator.deriveLocator(null),
0588:                                    inputMethod);
0589:                    perInputMethodState.put(inputMethod, new Boolean(
0590:                            clientWindowNotificationEnabled));
0591:                    enableClientWindowNotification(inputMethod, false);
0592:                    if (this  == inputMethodWindowContext) {
0593:                        inputMethod.hideWindows();
0594:                        inputMethodWindowContext = null;
0595:                    }
0596:                    inputMethodLocator = null;
0597:                    inputMethod = null;
0598:                    inputMethodCreationFailed = false;
0599:                }
0600:
0601:                // Switch in the new input method
0602:                if (newLocator.getLocale() == null && savedLocale != null
0603:                        && newLocator.isLocaleAvailable(savedLocale)) {
0604:                    newLocator = newLocator.deriveLocator(savedLocale);
0605:                }
0606:                inputMethodLocator = newLocator;
0607:                inputMethodCreationFailed = false;
0608:
0609:                // activate the new input method if the old one was active
0610:                if (wasInputMethodActive) {
0611:                    inputMethod = getInputMethodInstance();
0612:                    if (inputMethod instanceof  InputMethodAdapter) {
0613:                        ((InputMethodAdapter) inputMethod)
0614:                                .setAWTFocussedComponent(awtFocussedComponent);
0615:                    }
0616:                    activateInputMethod(true);
0617:                }
0618:
0619:                // enable/disable composition if the old one supports querying enable/disable 
0620:                if (wasCompositionEnabledSupported) {
0621:                    inputMethod = getInputMethod();
0622:                    if (inputMethod != null) {
0623:                        try {
0624:                            inputMethod
0625:                                    .setCompositionEnabled(wasCompositionEnabled);
0626:                        } catch (UnsupportedOperationException e) {
0627:                        }
0628:                    }
0629:                }
0630:            }
0631:
0632:            /**
0633:             * Returns the client component.
0634:             */
0635:            Component getClientComponent() {
0636:                return currentClientComponent;
0637:            }
0638:
0639:            /**
0640:             * @see java.awt.im.InputContext#removeNotify
0641:             * @exception NullPointerException when the component is null.
0642:             */
0643:            public synchronized void removeNotify(Component component) {
0644:                if (component == null) {
0645:                    throw new NullPointerException();
0646:                }
0647:
0648:                if (inputMethod == null) {
0649:                    if (component == currentClientComponent) {
0650:                        currentClientComponent = null;
0651:                    }
0652:                    return;
0653:                }
0654:
0655:                // We may or may not get a FOCUS_LOST event for this component,
0656:                // so do the deactivation stuff here too.
0657:                if (component == awtFocussedComponent) {
0658:                    focusLost(component, false);
0659:                }
0660:
0661:                if (component == currentClientComponent) {
0662:                    if (isInputMethodActive) {
0663:                        // component wasn't the one that had the focus
0664:                        deactivateInputMethod(false);
0665:                    }
0666:                    inputMethod.removeNotify();
0667:                    if (clientWindowNotificationEnabled
0668:                            && addedClientWindowListeners()) {
0669:                        removeClientWindowListeners();
0670:                    }
0671:                    currentClientComponent = null;
0672:                    if (inputMethod instanceof  InputMethodAdapter) {
0673:                        ((InputMethodAdapter) inputMethod)
0674:                                .setClientComponent(null);
0675:                    }
0676:
0677:                    // removeNotify() can be issued from a thread other than the event dispatch
0678:                    // thread.  In that case, avoid possible deadlock between Component.AWTTreeLock 
0679:                    // and InputMethodContext.compositionAreaHandlerLock by releasing the composition
0680:                    // area on the event dispatch thread.
0681:                    if (EventQueue.isDispatchThread()) {
0682:                        ((InputMethodContext) this ).releaseCompositionArea();
0683:                    } else {
0684:                        EventQueue.invokeLater(new Runnable() {
0685:                            public void run() {
0686:                                ((InputMethodContext) InputContext.this )
0687:                                        .releaseCompositionArea();
0688:                            }
0689:                        });
0690:                    }
0691:                }
0692:            }
0693:
0694:            /**
0695:             * @see java.awt.im.InputContext#dispose
0696:             * @exception IllegalStateException when the currentClientComponent is not null
0697:             */
0698:            public synchronized void dispose() {
0699:                if (currentClientComponent != null) {
0700:                    throw new IllegalStateException(
0701:                            "Can't dispose InputContext while it's active");
0702:                }
0703:                if (inputMethod != null) {
0704:                    if (this  == inputMethodWindowContext) {
0705:                        inputMethod.hideWindows();
0706:                        inputMethodWindowContext = null;
0707:                    }
0708:                    if (inputMethod == previousInputMethod) {
0709:                        previousInputMethod = null;
0710:                    }
0711:                    if (clientWindowNotificationEnabled) {
0712:                        if (addedClientWindowListeners()) {
0713:                            removeClientWindowListeners();
0714:                        }
0715:                        clientWindowNotificationEnabled = false;
0716:                    }
0717:                    inputMethod.dispose();
0718:
0719:                    // in case the input method enabled the client window
0720:                    // notification in dispose(), which shouldn't happen, it
0721:                    // needs to be cleaned up again.
0722:                    if (clientWindowNotificationEnabled) {
0723:                        enableClientWindowNotification(inputMethod, false);
0724:                    }
0725:
0726:                    inputMethod = null;
0727:                }
0728:                inputMethodLocator = null;
0729:                if (usedInputMethods != null && !usedInputMethods.isEmpty()) {
0730:                    Iterator iterator = usedInputMethods.values().iterator();
0731:                    usedInputMethods = null;
0732:                    while (iterator.hasNext()) {
0733:                        ((InputMethod) iterator.next()).dispose();
0734:                    }
0735:                }
0736:
0737:                // cleanup client window notification variables
0738:                clientWindowNotificationEnabled = false;
0739:                clientWindowListened = null;
0740:                perInputMethodState = null;
0741:            }
0742:
0743:            /**
0744:             * @see java.awt.im.InputContext#getInputMethodControlObject
0745:             */
0746:            public synchronized Object getInputMethodControlObject() {
0747:                InputMethod inputMethod = getInputMethod();
0748:
0749:                if (inputMethod != null) {
0750:                    return inputMethod.getControlObject();
0751:                } else {
0752:                    return null;
0753:                }
0754:            }
0755:
0756:            /**
0757:             * @see java.awt.im.InputContext#setCompositionEnabled(boolean)
0758:             * @exception UnsupportedOperationException when input method is null
0759:             */
0760:            public void setCompositionEnabled(boolean enable) {
0761:                InputMethod inputMethod = getInputMethod();
0762:
0763:                if (inputMethod == null) {
0764:                    throw new UnsupportedOperationException();
0765:                }
0766:                inputMethod.setCompositionEnabled(enable);
0767:            }
0768:
0769:            /**
0770:             * @see java.awt.im.InputContext#isCompositionEnabled
0771:             * @exception UnsupportedOperationException when input method is null
0772:             */
0773:            public boolean isCompositionEnabled() {
0774:                InputMethod inputMethod = getInputMethod();
0775:
0776:                if (inputMethod == null) {
0777:                    throw new UnsupportedOperationException();
0778:                }
0779:                return inputMethod.isCompositionEnabled();
0780:            }
0781:
0782:            /**
0783:             * @return a string with information about the current input method.
0784:             * @exception UnsupportedOperationException when input method is null
0785:             */
0786:            public String getInputMethodInfo() {
0787:                InputMethod inputMethod = getInputMethod();
0788:
0789:                if (inputMethod == null) {
0790:                    throw new UnsupportedOperationException("Null input method");
0791:                }
0792:
0793:                String inputMethodInfo = null;
0794:                if (inputMethod instanceof  InputMethodAdapter) {
0795:                    // returns the information about the host native input method.
0796:                    inputMethodInfo = ((InputMethodAdapter) inputMethod)
0797:                            .getNativeInputMethodInfo();
0798:                }
0799:
0800:                // extracts the information from the InputMethodDescriptor
0801:                // associated with the current java input method.
0802:                if (inputMethodInfo == null && inputMethodLocator != null) {
0803:                    inputMethodInfo = inputMethodLocator.getDescriptor()
0804:                            .getInputMethodDisplayName(getLocale(),
0805:                                    SunToolkit.getStartupLocale());
0806:                }
0807:
0808:                if (inputMethodInfo != null && !inputMethodInfo.equals("")) {
0809:                    return inputMethodInfo;
0810:                }
0811:
0812:                // do our best to return something useful.
0813:                return inputMethod.toString() + "-"
0814:                        + inputMethod.getLocale().toString();
0815:            }
0816:
0817:            /**
0818:             * Turns off the native IM. The native IM is diabled when
0819:             * the deactive method of InputMethod is called. It is 
0820:             * delayed until the active method is called on a different
0821:             * peer component. This method is provided to explicitly disable
0822:             * the native IM.
0823:             */
0824:            public void disableNativeIM() {
0825:                InputMethod inputMethod = getInputMethod();
0826:                if (inputMethod != null
0827:                        && inputMethod instanceof  InputMethodAdapter) {
0828:                    ((InputMethodAdapter) inputMethod).disableInputMethod();
0829:                }
0830:            }
0831:
0832:            private synchronized InputMethod getInputMethod() {
0833:                if (inputMethod != null) {
0834:                    return inputMethod;
0835:                }
0836:
0837:                if (inputMethodCreationFailed) {
0838:                    return null;
0839:                }
0840:
0841:                inputMethod = getInputMethodInstance();
0842:                return inputMethod;
0843:            }
0844:
0845:            /**
0846:             * Returns an instance of the input method described by
0847:             * the current input method locator. This may be an input
0848:             * method that was previously used and switched out of,
0849:             * or a new instance. The locale, character subsets, and
0850:             * input method context of the input method are set.
0851:             *
0852:             * The inputMethodCreationFailed field is set to true if the
0853:             * instantiation failed.
0854:             *
0855:             * @return an InputMethod instance
0856:             * @see java.awt.im.spi.InputMethod#setInputMethodContext
0857:             * @see java.awt.im.spi.InputMethod#setLocale
0858:             * @see java.awt.im.spi.InputMethod#setCharacterSubsets
0859:             */
0860:            private InputMethod getInputMethodInstance() {
0861:                InputMethodLocator locator = inputMethodLocator;
0862:                if (locator == null) {
0863:                    inputMethodCreationFailed = true;
0864:                    return null;
0865:                }
0866:
0867:                Locale locale = locator.getLocale();
0868:                InputMethod inputMethodInstance = null;
0869:
0870:                // see whether we have a previously used input method
0871:                if (usedInputMethods != null) {
0872:                    inputMethodInstance = (InputMethod) usedInputMethods
0873:                            .remove(locator.deriveLocator(null));
0874:                    if (inputMethodInstance != null) {
0875:                        if (locale != null) {
0876:                            inputMethodInstance.setLocale(locale);
0877:                        }
0878:                        inputMethodInstance
0879:                                .setCharacterSubsets(characterSubsets);
0880:                        Boolean state = (Boolean) perInputMethodState
0881:                                .remove(inputMethodInstance);
0882:                        if (state != null) {
0883:                            enableClientWindowNotification(inputMethodInstance,
0884:                                    state.booleanValue());
0885:                        }
0886:                        ((InputMethodContext) this )
0887:                                .setInputMethodSupportsBelowTheSpot((!(inputMethodInstance instanceof  InputMethodAdapter))
0888:                                        || ((InputMethodAdapter) inputMethodInstance)
0889:                                                .supportsBelowTheSpot());
0890:                        return inputMethodInstance;
0891:                    }
0892:                }
0893:
0894:                // need to create new instance
0895:                try {
0896:                    inputMethodInstance = locator.getDescriptor()
0897:                            .createInputMethod();
0898:
0899:                    if (locale != null) {
0900:                        inputMethodInstance.setLocale(locale);
0901:                    }
0902:                    inputMethodInstance
0903:                            .setInputMethodContext((InputMethodContext) this );
0904:                    inputMethodInstance.setCharacterSubsets(characterSubsets);
0905:
0906:                } catch (Exception e) {
0907:                    logCreationFailed(e);
0908:
0909:                    // there are a number of bad things that can happen while creating
0910:                    // the input method. In any case, we just continue without an
0911:                    // input method.
0912:                    inputMethodCreationFailed = true;
0913:
0914:                    // if the instance has been created, then it means either
0915:                    // setLocale() or setInputMethodContext() failed.
0916:                    if (inputMethodInstance != null) {
0917:                        inputMethodInstance = null;
0918:                    }
0919:                } catch (LinkageError e) {
0920:                    logCreationFailed(e);
0921:
0922:                    // same as above
0923:                    inputMethodCreationFailed = true;
0924:                }
0925:                ((InputMethodContext) this )
0926:                        .setInputMethodSupportsBelowTheSpot((!(inputMethodInstance instanceof  InputMethodAdapter))
0927:                                || ((InputMethodAdapter) inputMethodInstance)
0928:                                        .supportsBelowTheSpot());
0929:                return inputMethodInstance;
0930:            }
0931:
0932:            private void logCreationFailed(Throwable throwable) {
0933:                String errorTextFormat = Toolkit.getProperty(
0934:                        "AWT.InputMethodCreationFailed",
0935:                        "Could not create {0}. Reason: {1}");
0936:                Object[] args = {
0937:                        inputMethodLocator.getDescriptor()
0938:                                .getInputMethodDisplayName(null,
0939:                                        Locale.getDefault()),
0940:                        throwable.getLocalizedMessage() };
0941:                MessageFormat mf = new MessageFormat(errorTextFormat);
0942:                Logger logger = Logger.getLogger("sun.awt.im");
0943:                logger.config(mf.format(args));
0944:            }
0945:
0946:            InputMethodLocator getInputMethodLocator() {
0947:                if (inputMethod != null) {
0948:                    return inputMethodLocator.deriveLocator(inputMethod
0949:                            .getLocale());
0950:                }
0951:                return inputMethodLocator;
0952:            }
0953:
0954:            /**
0955:             * @see java.awt.im.InputContext#endComposition
0956:             */
0957:            public synchronized void endComposition() {
0958:                if (inputMethod != null) {
0959:                    inputMethod.endComposition();
0960:                }
0961:            }
0962:
0963:            /**
0964:             * @see java.awt.im.spi.InputMethodContext#enableClientWindowNotification
0965:             */
0966:            synchronized void enableClientWindowNotification(
0967:                    InputMethod requester, boolean enable) {
0968:                // in case this request is not from the current input method,
0969:                // store the request and handle it when this requesting input
0970:                // method becomes the current one.
0971:                if (requester != inputMethod) {
0972:                    if (perInputMethodState == null) {
0973:                        perInputMethodState = new HashMap(5);
0974:                    }
0975:                    perInputMethodState.put(requester, new Boolean(enable));
0976:                    return;
0977:                }
0978:
0979:                if (clientWindowNotificationEnabled != enable) {
0980:                    clientWindowLocation = null;
0981:                    clientWindowNotificationEnabled = enable;
0982:                }
0983:                if (clientWindowNotificationEnabled) {
0984:                    if (!addedClientWindowListeners()) {
0985:                        addClientWindowListeners();
0986:                    }
0987:                    if (clientWindowListened != null) {
0988:                        clientWindowLocation = null;
0989:                        notifyClientWindowChange(clientWindowListened);
0990:                    }
0991:                } else {
0992:                    if (addedClientWindowListeners()) {
0993:                        removeClientWindowListeners();
0994:                    }
0995:                }
0996:            }
0997:
0998:            private synchronized void notifyClientWindowChange(Window window) {
0999:                if (inputMethod == null) {
1000:                    return;
1001:                }
1002:
1003:                // if the window is invisible or iconified, send null to the input method.
1004:                if (!window.isVisible()
1005:                        || ((window instanceof  Frame) && ((Frame) window)
1006:                                .getState() == Frame.ICONIFIED)) {
1007:                    clientWindowLocation = null;
1008:                    inputMethod.notifyClientWindowChange(null);
1009:                    return;
1010:                }
1011:                Rectangle location = window.getBounds();
1012:                if (clientWindowLocation == null
1013:                        || !clientWindowLocation.equals(location)) {
1014:                    clientWindowLocation = location;
1015:                    inputMethod.notifyClientWindowChange(clientWindowLocation);
1016:                }
1017:            }
1018:
1019:            private synchronized void addClientWindowListeners() {
1020:                Component client = getClientComponent();
1021:                if (client == null) {
1022:                    return;
1023:                }
1024:                Window window = getComponentWindow(client);
1025:                if (window == null) {
1026:                    return;
1027:                }
1028:                window.addComponentListener(this );
1029:                window.addWindowListener(this );
1030:                clientWindowListened = window;
1031:            }
1032:
1033:            private synchronized void removeClientWindowListeners() {
1034:                clientWindowListened.removeComponentListener(this );
1035:                clientWindowListened.removeWindowListener(this );
1036:                clientWindowListened = null;
1037:            }
1038:
1039:            /**
1040:             * Returns true if listeners have been set up for client window
1041:             * change notification.
1042:             */
1043:            private boolean addedClientWindowListeners() {
1044:                return clientWindowListened != null;
1045:            }
1046:
1047:            /*
1048:             * ComponentListener and WindowListener implementation
1049:             */
1050:            public void componentResized(ComponentEvent e) {
1051:                notifyClientWindowChange((Window) e.getComponent());
1052:            }
1053:
1054:            public void componentMoved(ComponentEvent e) {
1055:                notifyClientWindowChange((Window) e.getComponent());
1056:            }
1057:
1058:            public void componentShown(ComponentEvent e) {
1059:                notifyClientWindowChange((Window) e.getComponent());
1060:            }
1061:
1062:            public void componentHidden(ComponentEvent e) {
1063:                notifyClientWindowChange((Window) e.getComponent());
1064:            }
1065:
1066:            public void windowOpened(WindowEvent e) {
1067:            }
1068:
1069:            public void windowClosing(WindowEvent e) {
1070:            }
1071:
1072:            public void windowClosed(WindowEvent e) {
1073:            }
1074:
1075:            public void windowIconified(WindowEvent e) {
1076:                notifyClientWindowChange(e.getWindow());
1077:            }
1078:
1079:            public void windowDeiconified(WindowEvent e) {
1080:                notifyClientWindowChange(e.getWindow());
1081:            }
1082:
1083:            public void windowActivated(WindowEvent e) {
1084:            }
1085:
1086:            public void windowDeactivated(WindowEvent e) {
1087:            }
1088:
1089:            /**
1090:             * Initializes the input method selection key definition in preference trees
1091:             */
1092:            private void initializeInputMethodSelectionKey() {
1093:                AccessController.doPrivileged(new PrivilegedAction() {
1094:                    public Object run() {
1095:                        // Look in user's tree
1096:                        Preferences root = Preferences.userRoot();
1097:                        inputMethodSelectionKey = getInputMethodSelectionKeyStroke(root);
1098:
1099:                        if (inputMethodSelectionKey == null) {
1100:                            // Look in system's tree
1101:                            root = Preferences.systemRoot();
1102:                            inputMethodSelectionKey = getInputMethodSelectionKeyStroke(root);
1103:                        }
1104:                        return null;
1105:                    }
1106:                });
1107:            }
1108:
1109:            private AWTKeyStroke getInputMethodSelectionKeyStroke(
1110:                    Preferences root) {
1111:                try {
1112:                    if (root.nodeExists(inputMethodSelectionKeyPath)) {
1113:                        Preferences node = root
1114:                                .node(inputMethodSelectionKeyPath);
1115:                        int keyCode = node.getInt(
1116:                                inputMethodSelectionKeyCodeName,
1117:                                KeyEvent.VK_UNDEFINED);
1118:                        if (keyCode != KeyEvent.VK_UNDEFINED) {
1119:                            int modifiers = node.getInt(
1120:                                    inputMethodSelectionKeyModifiersName, 0);
1121:                            return AWTKeyStroke.getAWTKeyStroke(keyCode,
1122:                                    modifiers);
1123:                        }
1124:                    }
1125:                } catch (BackingStoreException bse) {
1126:                }
1127:
1128:                return null;
1129:            }
1130:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.