feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
319
jdkSrc/jdk8/sun/awt/im/CompositionArea.java
Normal file
319
jdkSrc/jdk8/sun/awt/im/CompositionArea.java
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, 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.AWTEvent;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.InputMethodEvent;
|
||||
import java.awt.event.InputMethodListener;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.event.WindowAdapter;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.TextHitInfo;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.im.InputMethodRequests;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.border.LineBorder;
|
||||
|
||||
/**
|
||||
* A composition area is used to display text that's being composed
|
||||
* using an input method in its own user interface environment,
|
||||
* typically in a root window.
|
||||
*
|
||||
* @author JavaSoft International
|
||||
*/
|
||||
|
||||
// This class is final due to the 6607310 fix. Refer to the CR for details.
|
||||
public final class CompositionArea extends JPanel implements InputMethodListener {
|
||||
|
||||
private CompositionAreaHandler handler;
|
||||
|
||||
private TextLayout composedTextLayout;
|
||||
private TextHitInfo caret = null;
|
||||
private JFrame compositionWindow;
|
||||
private final static int TEXT_ORIGIN_X = 5;
|
||||
private final static int TEXT_ORIGIN_Y = 15;
|
||||
private final static int PASSIVE_WIDTH = 480;
|
||||
private final static int WIDTH_MARGIN=10;
|
||||
private final static int HEIGHT_MARGIN=3;
|
||||
|
||||
CompositionArea() {
|
||||
// create composition window with localized title
|
||||
String windowTitle = Toolkit.getProperty("AWT.CompositionWindowTitle", "Input Window");
|
||||
compositionWindow =
|
||||
(JFrame)InputMethodContext.createInputMethodWindow(windowTitle, null, true);
|
||||
|
||||
setOpaque(true);
|
||||
setBorder(LineBorder.createGrayLineBorder());
|
||||
setForeground(Color.black);
|
||||
setBackground(Color.white);
|
||||
|
||||
// if we get the focus, we still want to let the client's
|
||||
// input context handle the event
|
||||
enableInputMethods(true);
|
||||
enableEvents(AWTEvent.KEY_EVENT_MASK);
|
||||
|
||||
compositionWindow.getContentPane().add(this);
|
||||
compositionWindow.addWindowListener(new FrameWindowAdapter());
|
||||
addInputMethodListener(this);
|
||||
compositionWindow.enableInputMethods(false);
|
||||
compositionWindow.pack();
|
||||
Dimension windowSize = compositionWindow.getSize();
|
||||
Dimension screenSize = (getToolkit()).getScreenSize();
|
||||
compositionWindow.setLocation(screenSize.width - windowSize.width-20,
|
||||
screenSize.height - windowSize.height-100);
|
||||
compositionWindow.setVisible(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the composition area handler that currently owns this
|
||||
* composition area, and its input context.
|
||||
*/
|
||||
synchronized void setHandlerInfo(CompositionAreaHandler handler, InputContext inputContext) {
|
||||
this.handler = handler;
|
||||
((InputMethodWindow) compositionWindow).setInputContext(inputContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.awt.Component#getInputMethodRequests
|
||||
*/
|
||||
public InputMethodRequests getInputMethodRequests() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
// returns a 0-width rectangle
|
||||
private Rectangle getCaretRectangle(TextHitInfo caret) {
|
||||
int caretLocation = 0;
|
||||
TextLayout layout = composedTextLayout;
|
||||
if (layout != null) {
|
||||
caretLocation = Math.round(layout.getCaretInfo(caret)[0]);
|
||||
}
|
||||
Graphics g = getGraphics();
|
||||
FontMetrics metrics = null;
|
||||
try {
|
||||
metrics = g.getFontMetrics();
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
return new Rectangle(TEXT_ORIGIN_X + caretLocation,
|
||||
TEXT_ORIGIN_Y - metrics.getAscent(),
|
||||
0, metrics.getAscent() + metrics.getDescent());
|
||||
}
|
||||
|
||||
public void paint(Graphics g) {
|
||||
super.paint(g);
|
||||
g.setColor(getForeground());
|
||||
TextLayout layout = composedTextLayout;
|
||||
if (layout != null) {
|
||||
layout.draw((Graphics2D) g, TEXT_ORIGIN_X, TEXT_ORIGIN_Y);
|
||||
}
|
||||
if (caret != null) {
|
||||
Rectangle rectangle = getCaretRectangle(caret);
|
||||
g.setXORMode(getBackground());
|
||||
g.fillRect(rectangle.x, rectangle.y, 1, rectangle.height);
|
||||
g.setPaintMode();
|
||||
}
|
||||
}
|
||||
|
||||
// shows/hides the composition window
|
||||
void setCompositionAreaVisible(boolean visible) {
|
||||
compositionWindow.setVisible(visible);
|
||||
}
|
||||
|
||||
// returns true if composition area is visible
|
||||
boolean isCompositionAreaVisible() {
|
||||
return compositionWindow.isVisible();
|
||||
}
|
||||
|
||||
// workaround for the Solaris focus lost problem
|
||||
class FrameWindowAdapter extends WindowAdapter {
|
||||
public void windowActivated(WindowEvent e) {
|
||||
requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
// InputMethodListener methods - just forward to the current handler
|
||||
public void inputMethodTextChanged(InputMethodEvent event) {
|
||||
handler.inputMethodTextChanged(event);
|
||||
}
|
||||
|
||||
public void caretPositionChanged(InputMethodEvent event) {
|
||||
handler.caretPositionChanged(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text and caret to be displayed in this composition area.
|
||||
* Shows the window if it contains text, hides it if not.
|
||||
*/
|
||||
void setText(AttributedCharacterIterator composedText, TextHitInfo caret) {
|
||||
composedTextLayout = null;
|
||||
if (composedText == null) {
|
||||
// there's no composed text to display, so hide the window
|
||||
compositionWindow.setVisible(false);
|
||||
this.caret = null;
|
||||
} else {
|
||||
/* since we have composed text, make sure the window is shown.
|
||||
This is necessary to get a valid graphics object. See 6181385.
|
||||
*/
|
||||
if (!compositionWindow.isVisible()) {
|
||||
compositionWindow.setVisible(true);
|
||||
}
|
||||
|
||||
Graphics g = getGraphics();
|
||||
|
||||
if (g == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
updateWindowLocation();
|
||||
|
||||
FontRenderContext context = ((Graphics2D)g).getFontRenderContext();
|
||||
composedTextLayout = new TextLayout(composedText, context);
|
||||
Rectangle2D bounds = composedTextLayout.getBounds();
|
||||
|
||||
this.caret = caret;
|
||||
|
||||
// Resize the composition area to just fit the text.
|
||||
FontMetrics metrics = g.getFontMetrics();
|
||||
Rectangle2D maxCharBoundsRec = metrics.getMaxCharBounds(g);
|
||||
int newHeight = (int)maxCharBoundsRec.getHeight() + HEIGHT_MARGIN;
|
||||
int newFrameHeight = newHeight +compositionWindow.getInsets().top
|
||||
+compositionWindow.getInsets().bottom;
|
||||
// If it's a passive client, set the width always to PASSIVE_WIDTH (480px)
|
||||
InputMethodRequests req = handler.getClientInputMethodRequests();
|
||||
int newWidth = (req==null) ? PASSIVE_WIDTH : (int)bounds.getWidth() + WIDTH_MARGIN;
|
||||
int newFrameWidth = newWidth + compositionWindow.getInsets().left
|
||||
+ compositionWindow.getInsets().right;
|
||||
setPreferredSize(new Dimension(newWidth, newHeight));
|
||||
compositionWindow.setSize(new Dimension(newFrameWidth, newFrameHeight));
|
||||
|
||||
// show the composed text
|
||||
paint(g);
|
||||
}
|
||||
finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the caret to be displayed in this composition area.
|
||||
* The text is not changed.
|
||||
*/
|
||||
void setCaret(TextHitInfo caret) {
|
||||
this.caret = caret;
|
||||
if (compositionWindow.isVisible()) {
|
||||
Graphics g = getGraphics();
|
||||
try {
|
||||
paint(g);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Positions the composition window near (usually below) the
|
||||
* insertion point in the client component if the client
|
||||
* component is an active client (below-the-spot input).
|
||||
*/
|
||||
void updateWindowLocation() {
|
||||
InputMethodRequests req = handler.getClientInputMethodRequests();
|
||||
if (req == null) {
|
||||
// not an active client
|
||||
return;
|
||||
}
|
||||
|
||||
Point windowLocation = new Point();
|
||||
|
||||
Rectangle caretRect = req.getTextLocation(null);
|
||||
Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
Dimension windowSize = compositionWindow.getSize();
|
||||
final int SPACING = 2;
|
||||
|
||||
if (caretRect.x + windowSize.width > screenSize.width) {
|
||||
windowLocation.x = screenSize.width - windowSize.width;
|
||||
} else {
|
||||
windowLocation.x = caretRect.x;
|
||||
}
|
||||
|
||||
if (caretRect.y + caretRect.height + SPACING + windowSize.height > screenSize.height) {
|
||||
windowLocation.y = caretRect.y - SPACING - windowSize.height;
|
||||
} else {
|
||||
windowLocation.y = caretRect.y + caretRect.height + SPACING;
|
||||
}
|
||||
|
||||
compositionWindow.setLocation(windowLocation);
|
||||
}
|
||||
|
||||
// support for InputMethodRequests methods
|
||||
Rectangle getTextLocation(TextHitInfo offset) {
|
||||
Rectangle rectangle = getCaretRectangle(offset);
|
||||
Point location = getLocationOnScreen();
|
||||
rectangle.translate(location.x, location.y);
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
TextHitInfo getLocationOffset(int x, int y) {
|
||||
TextLayout layout = composedTextLayout;
|
||||
if (layout == null) {
|
||||
return null;
|
||||
} else {
|
||||
Point location = getLocationOnScreen();
|
||||
x -= location.x + TEXT_ORIGIN_X;
|
||||
y -= location.y + TEXT_ORIGIN_Y;
|
||||
if (layout.getBounds().contains(x, y)) {
|
||||
return layout.hitTestChar(x, y);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Disables or enables decorations of the composition window
|
||||
void setCompositionAreaUndecorated(boolean setUndecorated){
|
||||
if (compositionWindow.isDisplayable()){
|
||||
compositionWindow.removeNotify();
|
||||
}
|
||||
compositionWindow.setUndecorated(setUndecorated);
|
||||
compositionWindow.pack();
|
||||
}
|
||||
|
||||
// Proclaim serial compatibility with 1.7.0
|
||||
private static final long serialVersionUID = -1057247068746557444L;
|
||||
|
||||
}
|
||||
354
jdkSrc/jdk8/sun/awt/im/CompositionAreaHandler.java
Normal file
354
jdkSrc/jdk8/sun/awt/im/CompositionAreaHandler.java
Normal file
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, 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.Component;
|
||||
import java.awt.Container;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.event.InputMethodEvent;
|
||||
import java.awt.event.InputMethodListener;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.font.TextHitInfo;
|
||||
import java.awt.im.InputMethodRequests;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedCharacterIterator.Attribute;
|
||||
import java.text.AttributedString;
|
||||
|
||||
/**
|
||||
* A composition area handler handles events and input method requests for
|
||||
* the composition area. Typically each input method context has its own
|
||||
* composition area handler if it supports passive clients or below-the-spot
|
||||
* input, but all handlers share a single composition area.
|
||||
*
|
||||
* @author JavaSoft International
|
||||
*/
|
||||
|
||||
class CompositionAreaHandler implements InputMethodListener,
|
||||
InputMethodRequests {
|
||||
|
||||
private static CompositionArea compositionArea;
|
||||
private static Object compositionAreaLock = new Object();
|
||||
private static CompositionAreaHandler compositionAreaOwner; // synchronized through compositionArea
|
||||
|
||||
private AttributedCharacterIterator composedText;
|
||||
private TextHitInfo caret = null;
|
||||
private WeakReference<Component> clientComponent = new WeakReference<>(null);
|
||||
private InputMethodContext inputMethodContext;
|
||||
|
||||
/**
|
||||
* Constructs the composition area handler.
|
||||
*/
|
||||
CompositionAreaHandler(InputMethodContext context) {
|
||||
inputMethodContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the composition area.
|
||||
*/
|
||||
private void createCompositionArea() {
|
||||
synchronized(compositionAreaLock) {
|
||||
compositionArea = new CompositionArea();
|
||||
if (compositionAreaOwner != null) {
|
||||
compositionArea.setHandlerInfo(compositionAreaOwner, inputMethodContext);
|
||||
}
|
||||
// If the client component is an active client using below-the-spot style, then
|
||||
// make the composition window undecorated without a title bar.
|
||||
Component client = clientComponent.get();
|
||||
if(client != null){
|
||||
InputMethodRequests req = client.getInputMethodRequests();
|
||||
if (req != null && inputMethodContext.useBelowTheSpotInput()) {
|
||||
setCompositionAreaUndecorated(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setClientComponent(Component clientComponent) {
|
||||
this.clientComponent = new WeakReference<>(clientComponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Grabs the composition area, makes this handler its owner, and installs
|
||||
* the handler and its input context into the composition area for event
|
||||
* and input method request handling.
|
||||
* If doUpdate is true, updates the composition area with previously sent
|
||||
* composed text.
|
||||
*/
|
||||
|
||||
void grabCompositionArea(boolean doUpdate) {
|
||||
synchronized (compositionAreaLock) {
|
||||
if (compositionAreaOwner != this) {
|
||||
compositionAreaOwner = this;
|
||||
if (compositionArea != null) {
|
||||
compositionArea.setHandlerInfo(this, inputMethodContext);
|
||||
}
|
||||
if (doUpdate) {
|
||||
// Create the composition area if necessary
|
||||
if ((composedText != null) && (compositionArea == null)) {
|
||||
createCompositionArea();
|
||||
}
|
||||
if (compositionArea != null) {
|
||||
compositionArea.setText(composedText, caret);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases and closes the composition area if it is currently owned by
|
||||
* this composition area handler.
|
||||
*/
|
||||
void releaseCompositionArea() {
|
||||
synchronized (compositionAreaLock) {
|
||||
if (compositionAreaOwner == this) {
|
||||
compositionAreaOwner = null;
|
||||
if (compositionArea != null) {
|
||||
compositionArea.setHandlerInfo(null, null);
|
||||
compositionArea.setText(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases and closes the composition area if it has been created,
|
||||
* independent of the current owner.
|
||||
*/
|
||||
static void closeCompositionArea() {
|
||||
if (compositionArea != null) {
|
||||
synchronized (compositionAreaLock) {
|
||||
compositionAreaOwner = null;
|
||||
compositionArea.setHandlerInfo(null, null);
|
||||
compositionArea.setText(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the composition area is currently visible
|
||||
*/
|
||||
boolean isCompositionAreaVisible() {
|
||||
if (compositionArea != null) {
|
||||
return compositionArea.isCompositionAreaVisible();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shows or hides the composition Area
|
||||
*/
|
||||
void setCompositionAreaVisible(boolean visible) {
|
||||
if (compositionArea != null) {
|
||||
compositionArea.setCompositionAreaVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
void processInputMethodEvent(InputMethodEvent event) {
|
||||
if (event.getID() == InputMethodEvent.INPUT_METHOD_TEXT_CHANGED) {
|
||||
inputMethodTextChanged(event);
|
||||
} else {
|
||||
caretPositionChanged(event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* set the compositionArea frame decoration
|
||||
*/
|
||||
void setCompositionAreaUndecorated(boolean undecorated) {
|
||||
if (compositionArea != null) {
|
||||
compositionArea.setCompositionAreaUndecorated(undecorated);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// InputMethodListener methods
|
||||
//
|
||||
|
||||
private static final Attribute[] IM_ATTRIBUTES =
|
||||
{ TextAttribute.INPUT_METHOD_HIGHLIGHT };
|
||||
|
||||
public void inputMethodTextChanged(InputMethodEvent event) {
|
||||
AttributedCharacterIterator text = event.getText();
|
||||
int committedCharacterCount = event.getCommittedCharacterCount();
|
||||
|
||||
// extract composed text and prepare it for display
|
||||
composedText = null;
|
||||
caret = null;
|
||||
if (text != null
|
||||
&& committedCharacterCount < text.getEndIndex() - text.getBeginIndex()) {
|
||||
|
||||
// Create the composition area if necessary
|
||||
if (compositionArea == null) {
|
||||
createCompositionArea();
|
||||
}
|
||||
|
||||
// copy the composed text
|
||||
AttributedString composedTextString;
|
||||
composedTextString = new AttributedString(text,
|
||||
text.getBeginIndex() + committedCharacterCount, // skip over committed text
|
||||
text.getEndIndex(), IM_ATTRIBUTES);
|
||||
composedTextString.addAttribute(TextAttribute.FONT, compositionArea.getFont());
|
||||
composedText = composedTextString.getIterator();
|
||||
caret = event.getCaret();
|
||||
}
|
||||
|
||||
if (compositionArea != null) {
|
||||
compositionArea.setText(composedText, caret);
|
||||
}
|
||||
|
||||
// send any committed text to the text component
|
||||
if (committedCharacterCount > 0) {
|
||||
inputMethodContext.dispatchCommittedText(((Component) event.getSource()),
|
||||
text, committedCharacterCount);
|
||||
|
||||
// this may have changed the text location, so reposition the window
|
||||
if (isCompositionAreaVisible()) {
|
||||
compositionArea.updateWindowLocation();
|
||||
}
|
||||
}
|
||||
|
||||
// event has been handled, so consume it
|
||||
event.consume();
|
||||
}
|
||||
|
||||
public void caretPositionChanged(InputMethodEvent event) {
|
||||
if (compositionArea != null) {
|
||||
compositionArea.setCaret(event.getCaret());
|
||||
}
|
||||
|
||||
// event has been handled, so consume it
|
||||
event.consume();
|
||||
}
|
||||
|
||||
//
|
||||
// InputMethodRequests methods
|
||||
//
|
||||
|
||||
/**
|
||||
* Returns the input method request handler of the client component.
|
||||
* When using the composition window for an active client (below-the-spot
|
||||
* input), input method requests that do not relate to the display of
|
||||
* the composed text are forwarded to the client component.
|
||||
*/
|
||||
InputMethodRequests getClientInputMethodRequests() {
|
||||
Component client = clientComponent.get();
|
||||
if (client != null) {
|
||||
return client.getInputMethodRequests();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Rectangle getTextLocation(TextHitInfo offset) {
|
||||
synchronized (compositionAreaLock) {
|
||||
if (compositionAreaOwner == this && isCompositionAreaVisible()) {
|
||||
return compositionArea.getTextLocation(offset);
|
||||
} else if (composedText != null) {
|
||||
// there's composed text, but it's not displayed, so fake a rectangle
|
||||
return new Rectangle(0, 0, 0, 10);
|
||||
} else {
|
||||
InputMethodRequests requests = getClientInputMethodRequests();
|
||||
if (requests != null) {
|
||||
return requests.getTextLocation(offset);
|
||||
} else {
|
||||
// passive client, no composed text, so fake a rectangle
|
||||
return new Rectangle(0, 0, 0, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public TextHitInfo getLocationOffset(int x, int y) {
|
||||
synchronized (compositionAreaLock) {
|
||||
if (compositionAreaOwner == this && isCompositionAreaVisible()) {
|
||||
return compositionArea.getLocationOffset(x, y);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int getInsertPositionOffset() {
|
||||
InputMethodRequests req = getClientInputMethodRequests();
|
||||
if (req != null) {
|
||||
return req.getInsertPositionOffset();
|
||||
}
|
||||
|
||||
// we don't have access to the client component's text.
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static final AttributedCharacterIterator EMPTY_TEXT =
|
||||
(new AttributedString("")).getIterator();
|
||||
|
||||
public AttributedCharacterIterator getCommittedText(int beginIndex,
|
||||
int endIndex,
|
||||
Attribute[] attributes) {
|
||||
InputMethodRequests req = getClientInputMethodRequests();
|
||||
if(req != null) {
|
||||
return req.getCommittedText(beginIndex, endIndex, attributes);
|
||||
}
|
||||
|
||||
// we don't have access to the client component's text.
|
||||
return EMPTY_TEXT;
|
||||
}
|
||||
|
||||
public int getCommittedTextLength() {
|
||||
InputMethodRequests req = getClientInputMethodRequests();
|
||||
if(req != null) {
|
||||
return req.getCommittedTextLength();
|
||||
}
|
||||
|
||||
// we don't have access to the client component's text.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
public AttributedCharacterIterator cancelLatestCommittedText(Attribute[] attributes) {
|
||||
InputMethodRequests req = getClientInputMethodRequests();
|
||||
if(req != null) {
|
||||
return req.cancelLatestCommittedText(attributes);
|
||||
}
|
||||
|
||||
// we don't have access to the client component's text.
|
||||
return null;
|
||||
}
|
||||
|
||||
public AttributedCharacterIterator getSelectedText(Attribute[] attributes) {
|
||||
InputMethodRequests req = getClientInputMethodRequests();
|
||||
if(req != null) {
|
||||
return req.getSelectedText(attributes);
|
||||
}
|
||||
|
||||
// we don't have access to the client component's text.
|
||||
return EMPTY_TEXT;
|
||||
}
|
||||
|
||||
}
|
||||
632
jdkSrc/jdk8/sun/awt/im/ExecutableInputMethodManager.java
Normal file
632
jdkSrc/jdk8/sun/awt/im/ExecutableInputMethodManager.java
Normal file
@@ -0,0 +1,632 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2012, 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.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
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>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
|
||||
*/
|
||||
class ExecutableInputMethodManager extends InputMethodManager
|
||||
implements Runnable
|
||||
{
|
||||
// the input context that's informed about selections from the user interface
|
||||
private InputContext currentInputContext;
|
||||
|
||||
// Menu item string for the trigger menu.
|
||||
private String triggerMenuString;
|
||||
|
||||
// popup menu for selecting an input method
|
||||
private InputMethodPopupMenu selectionMenu;
|
||||
private static String selectInputMethodMenuTitle;
|
||||
|
||||
// locator and name of host adapter
|
||||
private InputMethodLocator hostAdapterLocator;
|
||||
|
||||
// locators for Java input methods
|
||||
private int javaInputMethodCount; // number of Java input methods found
|
||||
private Vector<InputMethodLocator> javaInputMethodLocatorList;
|
||||
|
||||
// component that is requesting input method switch
|
||||
// must be Frame or Dialog
|
||||
private Component requestComponent;
|
||||
|
||||
// input context that is requesting input method switch
|
||||
private InputContext requestInputContext;
|
||||
|
||||
// IM preference stuff
|
||||
private static final String preferredIMNode = "/sun/awt/im/preferredInputMethod";
|
||||
private static final String descriptorKey = "descriptor";
|
||||
private Hashtable<String, InputMethodLocator> preferredLocatorCache = new Hashtable<>();
|
||||
private Preferences userRoot;
|
||||
|
||||
ExecutableInputMethodManager() {
|
||||
|
||||
// set up host adapter locator
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
try {
|
||||
if (toolkit instanceof InputMethodSupport) {
|
||||
InputMethodDescriptor hostAdapterDescriptor =
|
||||
((InputMethodSupport)toolkit)
|
||||
.getInputMethodAdapterDescriptor();
|
||||
if (hostAdapterDescriptor != null) {
|
||||
hostAdapterLocator = new InputMethodLocator(hostAdapterDescriptor, null, null);
|
||||
}
|
||||
}
|
||||
} catch (AWTException e) {
|
||||
// if we can't get a descriptor, we'll just have to do without native input methods
|
||||
}
|
||||
|
||||
javaInputMethodLocatorList = new Vector<InputMethodLocator>();
|
||||
initializeInputMethodLocatorList();
|
||||
}
|
||||
|
||||
synchronized void initialize() {
|
||||
selectInputMethodMenuTitle = Toolkit.getProperty("AWT.InputMethodSelectionMenu", "Select Input Method");
|
||||
|
||||
triggerMenuString = selectInputMethodMenuTitle;
|
||||
}
|
||||
|
||||
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) {
|
||||
waitForChangeRequest();
|
||||
initializeInputMethodLocatorList();
|
||||
try {
|
||||
if (requestComponent != null) {
|
||||
showInputMethodMenuOnRequesterEDT(requestComponent);
|
||||
} else {
|
||||
// show the popup menu within the event thread
|
||||
EventQueue.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
showInputMethodMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
} 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.
|
||||
private void showInputMethodMenuOnRequesterEDT(Component requester)
|
||||
throws InterruptedException, InvocationTargetException {
|
||||
|
||||
if (requester == null){
|
||||
return;
|
||||
}
|
||||
|
||||
class AWTInvocationLock {}
|
||||
Object lock = new AWTInvocationLock();
|
||||
|
||||
InvocationEvent event =
|
||||
new InvocationEvent(requester,
|
||||
new Runnable() {
|
||||
public void run() {
|
||||
showInputMethodMenu();
|
||||
}
|
||||
},
|
||||
lock,
|
||||
true);
|
||||
|
||||
AppContext requesterAppContext = SunToolkit.targetToAppContext(requester);
|
||||
synchronized (lock) {
|
||||
SunToolkit.postEvent(requesterAppContext, event);
|
||||
while (!event.isDispatched()) {
|
||||
lock.wait();
|
||||
}
|
||||
}
|
||||
|
||||
Throwable eventThrowable = event.getThrowable();
|
||||
if (eventThrowable != null) {
|
||||
throw new InvocationTargetException(eventThrowable);
|
||||
}
|
||||
}
|
||||
|
||||
void setInputContext(InputContext inputContext) {
|
||||
if (currentInputContext != null && inputContext != null) {
|
||||
// don't throw this exception until 4237852 is fixed
|
||||
// throw new IllegalStateException("Can't have two active InputContext at the same time");
|
||||
}
|
||||
currentInputContext = inputContext;
|
||||
}
|
||||
|
||||
public synchronized void notifyChangeRequest(Component comp) {
|
||||
if (!(comp instanceof Frame || comp instanceof Dialog))
|
||||
return;
|
||||
|
||||
// if busy with the current request, ignore this request.
|
||||
if (requestComponent != null)
|
||||
return;
|
||||
|
||||
requestComponent = comp;
|
||||
notify();
|
||||
}
|
||||
|
||||
public synchronized void notifyChangeRequestByHotKey(Component comp) {
|
||||
while (!(comp instanceof Frame || comp instanceof Dialog)) {
|
||||
if (comp == null) {
|
||||
// no Frame or Dialog found in containment hierarchy.
|
||||
return;
|
||||
}
|
||||
comp = comp.getParent();
|
||||
}
|
||||
|
||||
notifyChangeRequest(comp);
|
||||
}
|
||||
|
||||
public String getTriggerMenuString() {
|
||||
return triggerMenuString;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the environment indicates there are multiple input methods
|
||||
*/
|
||||
boolean hasMultipleInputMethods() {
|
||||
return ((hostAdapterLocator != null) && (javaInputMethodCount > 0)
|
||||
|| (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) {
|
||||
javaInputMethodLocatorList.clear();
|
||||
try {
|
||||
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
|
||||
public Object run() {
|
||||
for (InputMethodDescriptor descriptor :
|
||||
ServiceLoader.loadInstalled(InputMethodDescriptor.class)) {
|
||||
ClassLoader cl = descriptor.getClass().getClassLoader();
|
||||
javaInputMethodLocatorList.add(new InputMethodLocator(descriptor, cl, null));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} catch (PrivilegedActionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
javaInputMethodCount = javaInputMethodLocatorList.size();
|
||||
}
|
||||
|
||||
if (hasMultipleInputMethods()) {
|
||||
// initialize preferences
|
||||
if (userRoot == null) {
|
||||
userRoot = getUserRoot();
|
||||
}
|
||||
} else {
|
||||
// indicate to clients not to offer the menu
|
||||
triggerMenuString = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void showInputMethodMenu() {
|
||||
|
||||
if (!hasMultipleInputMethods()) {
|
||||
requestComponent = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize pop-up menu
|
||||
selectionMenu = InputMethodPopupMenu.getInstance(requestComponent, selectInputMethodMenuTitle);
|
||||
|
||||
// we have to rebuild the menu each time because
|
||||
// some input methods (such as IIIMP) may change
|
||||
// their list of supported locales dynamically
|
||||
selectionMenu.removeAll();
|
||||
|
||||
// get information about the currently selected input method
|
||||
// ??? if there's no current input context, what's the point
|
||||
// of showing the menu?
|
||||
String currentSelection = getCurrentSelection();
|
||||
|
||||
// Add menu item for host adapter
|
||||
if (hostAdapterLocator != null) {
|
||||
selectionMenu.addOneInputMethodToMenu(hostAdapterLocator, currentSelection);
|
||||
selectionMenu.addSeparator();
|
||||
}
|
||||
|
||||
// Add menu items for other input methods
|
||||
for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
|
||||
InputMethodLocator locator = javaInputMethodLocatorList.get(i);
|
||||
selectionMenu.addOneInputMethodToMenu(locator, currentSelection);
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
selectionMenu.addToComponent(requestComponent);
|
||||
requestInputContext = currentInputContext;
|
||||
selectionMenu.show(requestComponent, 60, 80); // TODO: get proper x, y...
|
||||
requestComponent = null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getCurrentSelection() {
|
||||
InputContext inputContext = currentInputContext;
|
||||
if (inputContext != null) {
|
||||
InputMethodLocator locator = inputContext.getInputMethodLocator();
|
||||
if (locator != null) {
|
||||
return locator.getActionCommandString();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
synchronized void changeInputMethod(String choice) {
|
||||
InputMethodLocator locator = null;
|
||||
|
||||
String inputMethodName = choice;
|
||||
String localeString = null;
|
||||
int index = choice.indexOf('\n');
|
||||
if (index != -1) {
|
||||
localeString = choice.substring(index + 1);
|
||||
inputMethodName = choice.substring(0, index);
|
||||
}
|
||||
if (hostAdapterLocator.getActionCommandString().equals(inputMethodName)) {
|
||||
locator = hostAdapterLocator;
|
||||
} else {
|
||||
for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
|
||||
InputMethodLocator candidate = javaInputMethodLocatorList.get(i);
|
||||
String name = candidate.getActionCommandString();
|
||||
if (name.equals(inputMethodName)) {
|
||||
locator = candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (locator != null && localeString != null) {
|
||||
String language = "", country = "", variant = "";
|
||||
int postIndex = localeString.indexOf('_');
|
||||
if (postIndex == -1) {
|
||||
language = localeString;
|
||||
} else {
|
||||
language = localeString.substring(0, postIndex);
|
||||
int preIndex = postIndex + 1;
|
||||
postIndex = localeString.indexOf('_', preIndex);
|
||||
if (postIndex == -1) {
|
||||
country = localeString.substring(preIndex);
|
||||
} else {
|
||||
country = localeString.substring(preIndex, postIndex);
|
||||
variant = localeString.substring(postIndex + 1);
|
||||
}
|
||||
}
|
||||
Locale locale = new Locale(language, country, variant);
|
||||
locator = locator.deriveLocator(locale);
|
||||
}
|
||||
|
||||
if (locator == null)
|
||||
return;
|
||||
|
||||
// tell the input context about the change
|
||||
if (requestInputContext != null) {
|
||||
requestInputContext.changeInputMethod(locator);
|
||||
requestInputContext = null;
|
||||
|
||||
// remember the selection
|
||||
putPreferredInputMethod(locator);
|
||||
}
|
||||
}
|
||||
|
||||
InputMethodLocator findInputMethod(Locale locale) {
|
||||
// look for preferred input method first
|
||||
InputMethodLocator locator = getPreferredInputMethod(locale);
|
||||
if (locator != null) {
|
||||
return locator;
|
||||
}
|
||||
|
||||
if (hostAdapterLocator != null && hostAdapterLocator.isLocaleAvailable(locale)) {
|
||||
return hostAdapterLocator.deriveLocator(locale);
|
||||
}
|
||||
|
||||
// Update the locator list
|
||||
initializeInputMethodLocatorList();
|
||||
|
||||
for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
|
||||
InputMethodLocator candidate = javaInputMethodLocatorList.get(i);
|
||||
if (candidate.isLocaleAvailable(locale)) {
|
||||
return candidate.deriveLocator(locale);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Locale getDefaultKeyboardLocale() {
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
if (toolkit instanceof InputMethodSupport) {
|
||||
return ((InputMethodSupport)toolkit).getDefaultKeyboardLocale();
|
||||
} 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.
|
||||
*/
|
||||
private synchronized InputMethodLocator getPreferredInputMethod(Locale locale) {
|
||||
InputMethodLocator preferredLocator = null;
|
||||
|
||||
if (!hasMultipleInputMethods()) {
|
||||
// No need to look for a preferred Java input method
|
||||
return null;
|
||||
}
|
||||
|
||||
// look for the cached preference first.
|
||||
preferredLocator = preferredLocatorCache.get(locale.toString().intern());
|
||||
if (preferredLocator != null) {
|
||||
return preferredLocator;
|
||||
}
|
||||
|
||||
// look for the preference in the user preference tree
|
||||
String nodePath = findPreferredInputMethodNode(locale);
|
||||
String descriptorName = readPreferredInputMethod(nodePath);
|
||||
Locale advertised;
|
||||
|
||||
// get the locator object
|
||||
if (descriptorName != null) {
|
||||
// check for the host adapter first
|
||||
if (hostAdapterLocator != null &&
|
||||
hostAdapterLocator.getDescriptor().getClass().getName().equals(descriptorName)) {
|
||||
advertised = getAdvertisedLocale(hostAdapterLocator, locale);
|
||||
if (advertised != null) {
|
||||
preferredLocator = hostAdapterLocator.deriveLocator(advertised);
|
||||
preferredLocatorCache.put(locale.toString().intern(), preferredLocator);
|
||||
}
|
||||
return preferredLocator;
|
||||
}
|
||||
// look for Java input methods
|
||||
for (int i = 0; i < javaInputMethodLocatorList.size(); i++) {
|
||||
InputMethodLocator locator = javaInputMethodLocatorList.get(i);
|
||||
InputMethodDescriptor descriptor = locator.getDescriptor();
|
||||
if (descriptor.getClass().getName().equals(descriptorName)) {
|
||||
advertised = getAdvertisedLocale(locator, locale);
|
||||
if (advertised != null) {
|
||||
preferredLocator = locator.deriveLocator(advertised);
|
||||
preferredLocatorCache.put(locale.toString().intern(), preferredLocator);
|
||||
}
|
||||
return preferredLocator;
|
||||
}
|
||||
}
|
||||
|
||||
// maybe preferred input method information is bogus.
|
||||
writePreferredInputMethod(nodePath, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String findPreferredInputMethodNode(Locale locale) {
|
||||
if (userRoot == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// create locale node relative path
|
||||
String nodePath = preferredIMNode + "/" + createLocalePath(locale);
|
||||
|
||||
// look for the descriptor
|
||||
while (!nodePath.equals(preferredIMNode)) {
|
||||
try {
|
||||
if (userRoot.nodeExists(nodePath)) {
|
||||
if (readPreferredInputMethod(nodePath) != null) {
|
||||
return nodePath;
|
||||
}
|
||||
}
|
||||
} catch (BackingStoreException bse) {
|
||||
}
|
||||
|
||||
// search at parent's node
|
||||
nodePath = nodePath.substring(0, nodePath.lastIndexOf('/'));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String readPreferredInputMethod(String nodePath) {
|
||||
if ((userRoot == null) || (nodePath == null)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return userRoot.node(nodePath).get(descriptorKey, 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.
|
||||
*/
|
||||
private synchronized void putPreferredInputMethod(InputMethodLocator locator) {
|
||||
InputMethodDescriptor descriptor = locator.getDescriptor();
|
||||
Locale preferredLocale = locator.getLocale();
|
||||
|
||||
if (preferredLocale == null) {
|
||||
// check available locales of the input method
|
||||
try {
|
||||
Locale[] availableLocales = descriptor.getAvailableLocales();
|
||||
if (availableLocales.length == 1) {
|
||||
preferredLocale = availableLocales[0];
|
||||
} 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
|
||||
if (preferredLocale.equals(Locale.JAPAN)) {
|
||||
preferredLocale = Locale.JAPANESE;
|
||||
}
|
||||
if (preferredLocale.equals(Locale.KOREA)) {
|
||||
preferredLocale = Locale.KOREAN;
|
||||
}
|
||||
if (preferredLocale.equals(new Locale("th", "TH"))) {
|
||||
preferredLocale = new Locale("th");
|
||||
}
|
||||
|
||||
// obtain node
|
||||
String path = preferredIMNode + "/" + createLocalePath(preferredLocale);
|
||||
|
||||
// write in the preference tree
|
||||
writePreferredInputMethod(path, descriptor.getClass().getName());
|
||||
preferredLocatorCache.put(preferredLocale.toString().intern(),
|
||||
locator.deriveLocator(preferredLocale));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private String createLocalePath(Locale locale) {
|
||||
String language = locale.getLanguage();
|
||||
String country = locale.getCountry();
|
||||
String variant = locale.getVariant();
|
||||
String localePath = null;
|
||||
if (!variant.equals("")) {
|
||||
localePath = "_" + language + "/_" + country + "/_" + variant;
|
||||
} else if (!country.equals("")) {
|
||||
localePath = "_" + language + "/_" + country;
|
||||
} else {
|
||||
localePath = "_" + language;
|
||||
}
|
||||
|
||||
return localePath;
|
||||
}
|
||||
|
||||
private void writePreferredInputMethod(String path, String descriptorName) {
|
||||
if (userRoot != null) {
|
||||
Preferences node = userRoot.node(path);
|
||||
|
||||
// record it
|
||||
if (descriptorName != null) {
|
||||
node.put(descriptorKey, descriptorName);
|
||||
} else {
|
||||
node.remove(descriptorKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Preferences getUserRoot() {
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Preferences>() {
|
||||
public Preferences run() {
|
||||
return Preferences.userRoot();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Locale getAdvertisedLocale(InputMethodLocator locator, Locale locale) {
|
||||
Locale advertised = null;
|
||||
|
||||
if (locator.isLocaleAvailable(locale)) {
|
||||
advertised = locale;
|
||||
} else if (locale.getLanguage().equals("ja")) {
|
||||
// for Japanese, Korean, and Thai, check whether the input method supports
|
||||
// language or language_COUNTRY.
|
||||
if (locator.isLocaleAvailable(Locale.JAPAN)) {
|
||||
advertised = Locale.JAPAN;
|
||||
} else if (locator.isLocaleAvailable(Locale.JAPANESE)) {
|
||||
advertised = Locale.JAPANESE;
|
||||
}
|
||||
} else if (locale.getLanguage().equals("ko")) {
|
||||
if (locator.isLocaleAvailable(Locale.KOREA)) {
|
||||
advertised = Locale.KOREA;
|
||||
} else if (locator.isLocaleAvailable(Locale.KOREAN)) {
|
||||
advertised = Locale.KOREAN;
|
||||
}
|
||||
} else if (locale.getLanguage().equals("th")) {
|
||||
if (locator.isLocaleAvailable(new Locale("th", "TH"))) {
|
||||
advertised = new Locale("th", "TH");
|
||||
} else if (locator.isLocaleAvailable(new Locale("th"))) {
|
||||
advertised = new Locale("th");
|
||||
}
|
||||
}
|
||||
|
||||
return advertised;
|
||||
}
|
||||
}
|
||||
1068
jdkSrc/jdk8/sun/awt/im/InputContext.java
Normal file
1068
jdkSrc/jdk8/sun/awt/im/InputContext.java
Normal file
File diff suppressed because it is too large
Load Diff
117
jdkSrc/jdk8/sun/awt/im/InputMethodAdapter.java
Normal file
117
jdkSrc/jdk8/sun/awt/im/InputMethodAdapter.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2012, 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.Component;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.im.spi.InputMethod;
|
||||
|
||||
/**
|
||||
* An input method adapter interfaces with the native input methods
|
||||
* on a host platform. In general, it looks to the input method
|
||||
* framework like a Java input method (that may support a few more
|
||||
* locales than a typical Java input method). However, since it
|
||||
* often has to work in a slightly hostile environment that's not
|
||||
* designed for easy integration into the Java input method
|
||||
* framework, it gets some special treatment that's not available
|
||||
* to Java input methods.
|
||||
* <p>
|
||||
* Licensees are free to modify this class as necessary to implement
|
||||
* their host input method adapters.
|
||||
*
|
||||
* @author JavaSoft International
|
||||
*/
|
||||
|
||||
public abstract class InputMethodAdapter implements InputMethod {
|
||||
|
||||
private Component clientComponent;
|
||||
|
||||
void setClientComponent(Component client) {
|
||||
clientComponent = client;
|
||||
}
|
||||
|
||||
protected Component getClientComponent() {
|
||||
return clientComponent;
|
||||
}
|
||||
|
||||
protected boolean haveActiveClient() {
|
||||
return clientComponent != null && clientComponent.getInputMethodRequests() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the input method adapter about the component that has the AWT
|
||||
* focus if it's using the input context owning this adapter instance.
|
||||
*/
|
||||
protected void setAWTFocussedComponent(Component component) {
|
||||
// ignore - adapters can override if needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether host input methods can support below-the-spot input.
|
||||
* Returns false by default.
|
||||
*/
|
||||
protected boolean supportsBelowTheSpot() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Informs the input method adapter not to listen to the native events.
|
||||
*/
|
||||
protected void stopListening() {
|
||||
// ignore - adapters can override if needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies client Window location or status changes
|
||||
*/
|
||||
public void notifyClientWindowChange(Rectangle location) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts reconvertion. An implementing host adapter has to override
|
||||
* this method if it can support reconvert().
|
||||
* @exception UnsupportedOperationException when the adapter does not override
|
||||
* the method.
|
||||
*/
|
||||
public void reconvert() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable the native input method. This method is provided for explicitly
|
||||
* turning off the native IM. The native IM is not turned off
|
||||
* when the native input method is deactivated. This method is
|
||||
* always called on AWT EDT. See details in bug 6226489.
|
||||
*/
|
||||
public abstract void disableInputMethod();
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string with information about the native input method, or
|
||||
* null.
|
||||
*/
|
||||
public abstract String getNativeInputMethodInfo();
|
||||
}
|
||||
377
jdkSrc/jdk8/sun/awt/im/InputMethodContext.java
Normal file
377
jdkSrc/jdk8/sun/awt/im/InputMethodContext.java
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Copyright (c) 1997, 2011, 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.AWTEvent;
|
||||
import java.awt.Component;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.HeadlessException;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.InputMethodEvent;
|
||||
import java.awt.font.TextHitInfo;
|
||||
import java.awt.im.InputMethodRequests;
|
||||
import java.awt.im.spi.InputMethod;
|
||||
import java.security.AccessController;
|
||||
import java.text.AttributedCharacterIterator;
|
||||
import java.text.AttributedCharacterIterator.Attribute;
|
||||
import java.text.AttributedString;
|
||||
import java.text.CharacterIterator;
|
||||
import javax.swing.JFrame;
|
||||
import sun.awt.InputMethodSupport;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* The InputMethodContext class provides methods that input methods
|
||||
* can use to communicate with their client components.
|
||||
* It is a subclass of InputContext, which provides methods for use by
|
||||
* components.
|
||||
*
|
||||
* @author JavaSoft International
|
||||
*/
|
||||
|
||||
public class InputMethodContext
|
||||
extends sun.awt.im.InputContext
|
||||
implements java.awt.im.spi.InputMethodContext {
|
||||
|
||||
private boolean dispatchingCommittedText;
|
||||
|
||||
// Creation of the context's composition area handler is
|
||||
// delayed until we really need a composition area.
|
||||
private CompositionAreaHandler compositionAreaHandler;
|
||||
private Object compositionAreaHandlerLock = new Object();
|
||||
|
||||
static private boolean belowTheSpotInputRequested;
|
||||
private boolean inputMethodSupportsBelowTheSpot;
|
||||
|
||||
static {
|
||||
// check whether we should use below-the-spot input
|
||||
// get property from command line
|
||||
String inputStyle = AccessController.doPrivileged
|
||||
(new GetPropertyAction("java.awt.im.style", null));
|
||||
// get property from awt.properties file
|
||||
if (inputStyle == null) {
|
||||
inputStyle = Toolkit.getProperty("java.awt.im.style", null);
|
||||
}
|
||||
belowTheSpotInputRequested = "below-the-spot".equals(inputStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an InputMethodContext.
|
||||
*/
|
||||
public InputMethodContext() {
|
||||
super();
|
||||
}
|
||||
|
||||
void setInputMethodSupportsBelowTheSpot(boolean supported) {
|
||||
inputMethodSupportsBelowTheSpot = supported;
|
||||
}
|
||||
|
||||
boolean useBelowTheSpotInput() {
|
||||
return belowTheSpotInputRequested && inputMethodSupportsBelowTheSpot;
|
||||
}
|
||||
|
||||
private boolean haveActiveClient() {
|
||||
Component client = getClientComponent();
|
||||
return client != null
|
||||
&& client.getInputMethodRequests() != null;
|
||||
}
|
||||
|
||||
// implements java.awt.im.spi.InputMethodContext.dispatchInputMethodEvent
|
||||
public void dispatchInputMethodEvent(int id,
|
||||
AttributedCharacterIterator text, int committedCharacterCount,
|
||||
TextHitInfo caret, TextHitInfo visiblePosition) {
|
||||
// We need to record the client component as the source so
|
||||
// that we have correct information if we later have to break up this
|
||||
// event into key events.
|
||||
Component source;
|
||||
|
||||
source = getClientComponent();
|
||||
if (source != null) {
|
||||
InputMethodEvent event = new InputMethodEvent(source,
|
||||
id, text, committedCharacterCount, caret, visiblePosition);
|
||||
|
||||
if (haveActiveClient() && !useBelowTheSpotInput()) {
|
||||
source.dispatchEvent(event);
|
||||
} else {
|
||||
getCompositionAreaHandler(true).processInputMethodEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches committed text to a client component.
|
||||
* Called by composition window.
|
||||
*
|
||||
* @param client The component that the text should get dispatched to.
|
||||
* @param text The iterator providing access to the committed
|
||||
* (and possible composed) text.
|
||||
* @param committedCharacterCount The number of committed characters in the text.
|
||||
*/
|
||||
synchronized void dispatchCommittedText(Component client,
|
||||
AttributedCharacterIterator text,
|
||||
int committedCharacterCount) {
|
||||
// note that the client is not always the current client component -
|
||||
// some host input method adapters may dispatch input method events
|
||||
// through the Java event queue, and we may have switched clients while
|
||||
// the event was in the queue.
|
||||
if (committedCharacterCount == 0
|
||||
|| text.getEndIndex() <= text.getBeginIndex()) {
|
||||
return;
|
||||
}
|
||||
long time = System.currentTimeMillis();
|
||||
dispatchingCommittedText = true;
|
||||
try {
|
||||
InputMethodRequests req = client.getInputMethodRequests();
|
||||
if (req != null) {
|
||||
// active client -> send text as InputMethodEvent
|
||||
int beginIndex = text.getBeginIndex();
|
||||
AttributedCharacterIterator toBeCommitted =
|
||||
(new AttributedString(text, beginIndex, beginIndex + committedCharacterCount)).getIterator();
|
||||
|
||||
InputMethodEvent inputEvent = new InputMethodEvent(
|
||||
client,
|
||||
InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
|
||||
toBeCommitted,
|
||||
committedCharacterCount,
|
||||
null, null);
|
||||
|
||||
client.dispatchEvent(inputEvent);
|
||||
} else {
|
||||
// passive client -> send text as KeyEvents
|
||||
char keyChar = text.first();
|
||||
while (committedCharacterCount-- > 0 && keyChar != CharacterIterator.DONE) {
|
||||
KeyEvent keyEvent = new KeyEvent(client, KeyEvent.KEY_TYPED,
|
||||
time, 0, KeyEvent.VK_UNDEFINED, keyChar);
|
||||
client.dispatchEvent(keyEvent);
|
||||
keyChar = text.next();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
dispatchingCommittedText = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void dispatchEvent(AWTEvent event) {
|
||||
// some host input method adapters may dispatch input method events
|
||||
// through the Java event queue. If the component that the event is
|
||||
// intended for isn't an active client, or if we're using below-the-spot
|
||||
// input, we need to dispatch this event
|
||||
// to the input window. Note that that component is not necessarily the
|
||||
// current client component, since we may have switched clients while
|
||||
// the event was in the queue.
|
||||
if (event instanceof InputMethodEvent) {
|
||||
if (((Component) event.getSource()).getInputMethodRequests() == null
|
||||
|| (useBelowTheSpotInput() && !dispatchingCommittedText)) {
|
||||
getCompositionAreaHandler(true).processInputMethodEvent((InputMethodEvent) event);
|
||||
}
|
||||
} else {
|
||||
// make sure we don't dispatch our own key events back to the input method
|
||||
if (!dispatchingCommittedText) {
|
||||
super.dispatchEvent(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this context's composition area handler, creating it if necessary.
|
||||
* If requested, it grabs the composition area for use by this context.
|
||||
* The composition area's text is not updated.
|
||||
*/
|
||||
private CompositionAreaHandler getCompositionAreaHandler(boolean grab) {
|
||||
synchronized(compositionAreaHandlerLock) {
|
||||
if (compositionAreaHandler == null) {
|
||||
compositionAreaHandler = new CompositionAreaHandler(this);
|
||||
}
|
||||
compositionAreaHandler.setClientComponent(getClientComponent());
|
||||
if (grab) {
|
||||
compositionAreaHandler.grabCompositionArea(false);
|
||||
}
|
||||
|
||||
return compositionAreaHandler;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Grabs the composition area for use by this context.
|
||||
* If doUpdate is true, updates the composition area with previously sent
|
||||
* composed text.
|
||||
*/
|
||||
void grabCompositionArea(boolean doUpdate) {
|
||||
synchronized(compositionAreaHandlerLock) {
|
||||
if (compositionAreaHandler != null) {
|
||||
compositionAreaHandler.grabCompositionArea(doUpdate);
|
||||
} else {
|
||||
// if this context hasn't seen a need for a composition area yet,
|
||||
// just close it without creating the machinery
|
||||
CompositionAreaHandler.closeCompositionArea();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases and closes the composition area if it is currently owned by
|
||||
* this context's composition area handler.
|
||||
*/
|
||||
void releaseCompositionArea() {
|
||||
synchronized(compositionAreaHandlerLock) {
|
||||
if (compositionAreaHandler != null) {
|
||||
compositionAreaHandler.releaseCompositionArea();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls CompositionAreaHandler.isCompositionAreaVisible() to see
|
||||
* whether the composition area is visible or not.
|
||||
* Notice that this method is always called on the AWT event dispatch
|
||||
* thread.
|
||||
*/
|
||||
boolean isCompositionAreaVisible() {
|
||||
if (compositionAreaHandler != null) {
|
||||
return compositionAreaHandler.isCompositionAreaVisible();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
* Calls CompositionAreaHandler.setCompositionAreaVisible to
|
||||
* show or hide the composition area.
|
||||
* As isCompositionAreaVisible method, it is always called
|
||||
* on AWT event dispatch thread.
|
||||
*/
|
||||
void setCompositionAreaVisible(boolean visible) {
|
||||
if (compositionAreaHandler != null) {
|
||||
compositionAreaHandler.setCompositionAreaVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the current client component's implementation of getTextLocation.
|
||||
*/
|
||||
public Rectangle getTextLocation(TextHitInfo offset) {
|
||||
return getReq().getTextLocation(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the current client component's implementation of getLocationOffset.
|
||||
*/
|
||||
public TextHitInfo getLocationOffset(int x, int y) {
|
||||
return getReq().getLocationOffset(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the current client component's implementation of getInsertPositionOffset.
|
||||
*/
|
||||
public int getInsertPositionOffset() {
|
||||
return getReq().getInsertPositionOffset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the current client component's implementation of getCommittedText.
|
||||
*/
|
||||
public AttributedCharacterIterator getCommittedText(int beginIndex,
|
||||
int endIndex,
|
||||
Attribute[] attributes) {
|
||||
return getReq().getCommittedText(beginIndex, endIndex, attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the current client component's implementation of getCommittedTextLength.
|
||||
*/
|
||||
public int getCommittedTextLength() {
|
||||
return getReq().getCommittedTextLength();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls the current client component's implementation of cancelLatestCommittedText.
|
||||
*/
|
||||
public AttributedCharacterIterator cancelLatestCommittedText(Attribute[] attributes) {
|
||||
return getReq().cancelLatestCommittedText(attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the current client component's implementation of getSelectedText.
|
||||
*/
|
||||
public AttributedCharacterIterator getSelectedText(Attribute[] attributes) {
|
||||
return getReq().getSelectedText(attributes);
|
||||
}
|
||||
|
||||
private InputMethodRequests getReq() {
|
||||
if (haveActiveClient() && !useBelowTheSpotInput()) {
|
||||
return getClientComponent().getInputMethodRequests();
|
||||
} else {
|
||||
return getCompositionAreaHandler(false);
|
||||
}
|
||||
}
|
||||
|
||||
// implements java.awt.im.spi.InputMethodContext.createInputMethodWindow
|
||||
public Window createInputMethodWindow(String title, boolean attachToInputContext) {
|
||||
InputContext context = attachToInputContext ? this : null;
|
||||
return createInputMethodWindow(title, context, false);
|
||||
}
|
||||
|
||||
// implements java.awt.im.spi.InputMethodContext.createInputMethodJFrame
|
||||
public JFrame createInputMethodJFrame(String title, boolean attachToInputContext) {
|
||||
InputContext context = attachToInputContext ? this : null;
|
||||
return (JFrame)createInputMethodWindow(title, context, true);
|
||||
}
|
||||
|
||||
static Window createInputMethodWindow(String title, InputContext context, boolean isSwing) {
|
||||
if (GraphicsEnvironment.isHeadless()) {
|
||||
throw new HeadlessException();
|
||||
}
|
||||
if (isSwing) {
|
||||
return new InputMethodJFrame(title, context);
|
||||
} else {
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
if (toolkit instanceof InputMethodSupport) {
|
||||
return ((InputMethodSupport)toolkit).createInputMethodWindow(
|
||||
title, context);
|
||||
}
|
||||
}
|
||||
throw new InternalError("Input methods must be supported");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.awt.im.spi.InputMethodContext#enableClientWindowNotification
|
||||
*/
|
||||
public void enableClientWindowNotification(InputMethod inputMethod, boolean enable) {
|
||||
super.enableClientWindowNotification(inputMethod, enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables or enables decorations for the composition window.
|
||||
*/
|
||||
void setCompositionAreaUndecorated(boolean undecorated) {
|
||||
if (compositionAreaHandler != null) {
|
||||
compositionAreaHandler.setCompositionAreaUndecorated(undecorated);
|
||||
}
|
||||
}
|
||||
}
|
||||
74
jdkSrc/jdk8/sun/awt/im/InputMethodJFrame.java
Normal file
74
jdkSrc/jdk8/sun/awt/im/InputMethodJFrame.java
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2011, 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 javax.swing.JFrame;
|
||||
import javax.swing.JRootPane;
|
||||
|
||||
/**
|
||||
* Implements a Swing based input method window that provides the minimal
|
||||
* functionality as specified in
|
||||
* {@link java.awt.im.spi.InputMethodContext#createInputMethodJFrame}.
|
||||
*
|
||||
*/
|
||||
public class InputMethodJFrame
|
||||
extends JFrame
|
||||
implements InputMethodWindow {
|
||||
|
||||
InputContext inputContext = null;
|
||||
|
||||
/**
|
||||
* Constructs a Swing based input method window.
|
||||
*/
|
||||
public InputMethodJFrame(String title, InputContext context) {
|
||||
super(title);
|
||||
//InputMethodJFrame never has LookAndFeel decoration
|
||||
if(JFrame.isDefaultLookAndFeelDecorated())
|
||||
{
|
||||
this.setUndecorated(true);
|
||||
this.getRootPane().setWindowDecorationStyle(JRootPane.NONE);
|
||||
}
|
||||
if (context != null) {
|
||||
this.inputContext = context;
|
||||
}
|
||||
setFocusableWindowState(false);
|
||||
}
|
||||
|
||||
public void setInputContext(InputContext inputContext) {
|
||||
this.inputContext = inputContext;
|
||||
}
|
||||
|
||||
public java.awt.im.InputContext getInputContext() {
|
||||
if (inputContext != null) {
|
||||
return inputContext;
|
||||
} else {
|
||||
return super.getInputContext();
|
||||
}
|
||||
}
|
||||
|
||||
// Proclaim serial compatibility with 1.7.0
|
||||
private static final long serialVersionUID = -4705856747771842549L;
|
||||
}
|
||||
171
jdkSrc/jdk8/sun/awt/im/InputMethodLocator.java
Normal file
171
jdkSrc/jdk8/sun/awt/im/InputMethodLocator.java
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 1999, 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.im.spi.InputMethodDescriptor;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Provides complete information to make and handle the selection
|
||||
* of an input method and a locale. Immutable class.
|
||||
*/
|
||||
final class InputMethodLocator {
|
||||
|
||||
private InputMethodDescriptor descriptor;
|
||||
|
||||
// Currently `loader' is always the class loader for a
|
||||
// descriptor. `loader' is provided for future extensions to be
|
||||
// able to load input methods from somewhere else, and to support
|
||||
// per input method name space.
|
||||
private ClassLoader loader;
|
||||
|
||||
private Locale locale;
|
||||
|
||||
InputMethodLocator(InputMethodDescriptor descriptor, ClassLoader loader, Locale locale) {
|
||||
if (descriptor == null) {
|
||||
throw new NullPointerException("descriptor can't be null");
|
||||
}
|
||||
this.descriptor = descriptor;
|
||||
this.loader = loader;
|
||||
this.locale = locale;
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
if (other == null || this.getClass() != other.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InputMethodLocator otherLocator = (InputMethodLocator) other;
|
||||
if (!descriptor.getClass().equals(otherLocator.descriptor.getClass())) {
|
||||
return false;
|
||||
}
|
||||
if (loader == null && otherLocator.loader != null
|
||||
|| loader != null && !loader.equals(otherLocator.loader)) {
|
||||
return false;
|
||||
}
|
||||
if (locale == null && otherLocator.locale != null
|
||||
|| locale != null && !locale.equals(otherLocator.locale)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result = descriptor.hashCode();
|
||||
if (loader != null) {
|
||||
result |= loader.hashCode() << 10;
|
||||
}
|
||||
if (locale != null) {
|
||||
result |= locale.hashCode() << 20;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
InputMethodDescriptor getDescriptor() {
|
||||
return descriptor;
|
||||
}
|
||||
|
||||
ClassLoader getClassLoader() {
|
||||
return loader;
|
||||
}
|
||||
|
||||
Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether support for locale is available from
|
||||
* the input method.
|
||||
*/
|
||||
boolean isLocaleAvailable(Locale locale) {
|
||||
try {
|
||||
Locale[] locales = descriptor.getAvailableLocales();
|
||||
for (int i = 0; i < locales.length; i++) {
|
||||
if (locales[i].equals(locale)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (AWTException e) {
|
||||
// treat this as no locale available
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an input method locator that has locale forLocale,
|
||||
* but otherwise the same data as this locator. Does not
|
||||
* check whether the input method actually supports forLocale -
|
||||
* use {@link #isLocaleAvailable} for that.
|
||||
*/
|
||||
InputMethodLocator deriveLocator(Locale forLocale) {
|
||||
if (forLocale == locale) {
|
||||
return this;
|
||||
} else {
|
||||
return new InputMethodLocator(descriptor, loader, forLocale);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this and other describe the same input method
|
||||
* engine, ignoring the locale setting.
|
||||
*/
|
||||
boolean sameInputMethod(InputMethodLocator other) {
|
||||
if (other == this) {
|
||||
return true;
|
||||
}
|
||||
if (other == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!descriptor.getClass().equals(other.descriptor.getClass())) {
|
||||
return false;
|
||||
}
|
||||
if (loader == null && other.loader != null
|
||||
|| loader != null && !loader.equals(other.loader)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string that can be used as an action command string.
|
||||
* The first part of the string identifies the input method; it does
|
||||
* not include '\n'. If getLocale is not null, getLocale().toString()
|
||||
* is appended, separated by '\n'.
|
||||
*/
|
||||
String getActionCommandString() {
|
||||
String inputMethodString = descriptor.getClass().getName();
|
||||
if (locale == null) {
|
||||
return inputMethodString;
|
||||
} else {
|
||||
return inputMethodString + "\n" + locale.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
231
jdkSrc/jdk8/sun/awt/im/InputMethodManager.java
Normal file
231
jdkSrc/jdk8/sun/awt/im/InputMethodManager.java
Normal file
@@ -0,0 +1,231 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 2012, 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.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
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</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
|
||||
* user, Frame/Dialog invokes <code>notifyChangeRequest()</code> to notify
|
||||
* <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
|
||||
*/
|
||||
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(imm, threadName);
|
||||
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();
|
||||
|
||||
}
|
||||
275
jdkSrc/jdk8/sun/awt/im/InputMethodPopupMenu.java
Normal file
275
jdkSrc/jdk8/sun/awt/im/InputMethodPopupMenu.java
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2007, 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.Container;
|
||||
import java.awt.PopupMenu;
|
||||
import java.awt.Menu;
|
||||
import java.awt.MenuItem;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.im.spi.InputMethodDescriptor;
|
||||
import java.util.Locale;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuItem;
|
||||
|
||||
/**
|
||||
* <code>InputMethodPopupMenu</code> provides the popup selection menu
|
||||
*/
|
||||
|
||||
abstract class InputMethodPopupMenu implements ActionListener {
|
||||
|
||||
// Factory method to provide the menu, depending on the client, i.e.,
|
||||
// provide Swing popup menu if client is a swing app, otherwise AWT popup
|
||||
// is created.
|
||||
static InputMethodPopupMenu getInstance(Component client, String title) {
|
||||
if ((client instanceof JFrame) ||
|
||||
(client instanceof JDialog)) {
|
||||
return new JInputMethodPopupMenu(title);
|
||||
} else {
|
||||
return new AWTInputMethodPopupMenu(title);
|
||||
}
|
||||
}
|
||||
|
||||
abstract void show(Component c, int x, int y);
|
||||
|
||||
abstract void removeAll();
|
||||
|
||||
abstract void addSeparator();
|
||||
|
||||
abstract void addToComponent(Component c);
|
||||
|
||||
abstract Object createSubmenu(String label);
|
||||
|
||||
abstract void add(Object menuItem);
|
||||
|
||||
abstract void addMenuItem(String label, String command, String currentSelection);
|
||||
|
||||
abstract void addMenuItem(Object targetMenu, String label, String command,
|
||||
String currentSelection);
|
||||
|
||||
void addOneInputMethodToMenu(InputMethodLocator locator, String currentSelection) {
|
||||
InputMethodDescriptor descriptor = locator.getDescriptor();
|
||||
String label = descriptor.getInputMethodDisplayName(null, Locale.getDefault());
|
||||
String command = locator.getActionCommandString();
|
||||
Locale[] locales = null;
|
||||
int localeCount;
|
||||
try {
|
||||
locales = descriptor.getAvailableLocales();
|
||||
localeCount = locales.length;
|
||||
} catch (AWTException e) {
|
||||
// ??? should have better error handling -
|
||||
// tell user what happened, then remove this input method from the list.
|
||||
// For the time being, just show it disabled.
|
||||
localeCount = 0;
|
||||
}
|
||||
if (localeCount == 0) {
|
||||
// could be IIIMP adapter which has lost its connection
|
||||
addMenuItem(label, null, currentSelection);
|
||||
} else if (localeCount == 1) {
|
||||
if (descriptor.hasDynamicLocaleList()) {
|
||||
// try to make sure that what the user sees and what
|
||||
// we eventually select is consistent even if the locale
|
||||
// list changes in the meantime
|
||||
label = descriptor.getInputMethodDisplayName(locales[0], Locale.getDefault());
|
||||
command = locator.deriveLocator(locales[0]).getActionCommandString();
|
||||
}
|
||||
addMenuItem(label, command, currentSelection);
|
||||
} else {
|
||||
Object submenu = createSubmenu(label);
|
||||
add(submenu);
|
||||
for (int j = 0; j < localeCount; j++) {
|
||||
Locale locale = locales[j];
|
||||
String subLabel = getLocaleName(locale);
|
||||
String subCommand = locator.deriveLocator(locale).getActionCommandString();
|
||||
addMenuItem(submenu, subLabel, subCommand, currentSelection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether command indicates the same input method as currentSelection,
|
||||
* taking into account that command may not specify a locale where currentSelection does.
|
||||
*/
|
||||
static boolean isSelected(String command, String currentSelection) {
|
||||
if (command == null || currentSelection == null) {
|
||||
return false;
|
||||
}
|
||||
if (command.equals(currentSelection)) {
|
||||
return true;
|
||||
}
|
||||
// currentSelection may indicate a locale where command does not
|
||||
int index = currentSelection.indexOf('\n');
|
||||
if (index != -1 && currentSelection.substring(0, index).equals(command)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a localized locale name for input methods with the
|
||||
* given locale. It falls back to Locale.getDisplayName() and
|
||||
* then to Locale.toString() if no localized locale name is found.
|
||||
*
|
||||
* @param locale Locale for which localized locale name is obtained
|
||||
*/
|
||||
String getLocaleName(Locale locale) {
|
||||
String localeString = locale.toString();
|
||||
String localeName = Toolkit.getProperty("AWT.InputMethodLanguage." + localeString, null);
|
||||
if (localeName == null) {
|
||||
localeName = locale.getDisplayName();
|
||||
if (localeName == null || localeName.length() == 0)
|
||||
localeName = localeString;
|
||||
}
|
||||
return localeName;
|
||||
}
|
||||
|
||||
// ActionListener implementation
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
String choice = event.getActionCommand();
|
||||
((ExecutableInputMethodManager)InputMethodManager.getInstance()).changeInputMethod(choice);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class JInputMethodPopupMenu extends InputMethodPopupMenu {
|
||||
static JPopupMenu delegate = null;
|
||||
|
||||
JInputMethodPopupMenu(String title) {
|
||||
synchronized (this) {
|
||||
if (delegate == null) {
|
||||
delegate = new JPopupMenu(title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void show(Component c, int x, int y) {
|
||||
delegate.show(c, x, y);
|
||||
}
|
||||
|
||||
void removeAll() {
|
||||
delegate.removeAll();
|
||||
}
|
||||
|
||||
void addSeparator() {
|
||||
delegate.addSeparator();
|
||||
}
|
||||
|
||||
void addToComponent(Component c) {
|
||||
}
|
||||
|
||||
Object createSubmenu(String label) {
|
||||
return new JMenu(label);
|
||||
}
|
||||
|
||||
void add(Object menuItem) {
|
||||
delegate.add((JMenuItem)menuItem);
|
||||
}
|
||||
|
||||
void addMenuItem(String label, String command, String currentSelection) {
|
||||
addMenuItem(delegate, label, command, currentSelection);
|
||||
}
|
||||
|
||||
void addMenuItem(Object targetMenu, String label, String command, String currentSelection) {
|
||||
JMenuItem menuItem;
|
||||
if (isSelected(command, currentSelection)) {
|
||||
menuItem = new JCheckBoxMenuItem(label, true);
|
||||
} else {
|
||||
menuItem = new JMenuItem(label);
|
||||
}
|
||||
menuItem.setActionCommand(command);
|
||||
menuItem.addActionListener(this);
|
||||
menuItem.setEnabled(command != null);
|
||||
if (targetMenu instanceof JMenu) {
|
||||
((JMenu)targetMenu).add(menuItem);
|
||||
} else {
|
||||
((JPopupMenu)targetMenu).add(menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class AWTInputMethodPopupMenu extends InputMethodPopupMenu {
|
||||
static PopupMenu delegate = null;
|
||||
|
||||
AWTInputMethodPopupMenu(String title) {
|
||||
synchronized (this) {
|
||||
if (delegate == null) {
|
||||
delegate = new PopupMenu(title);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void show(Component c, int x, int y) {
|
||||
delegate.show(c, x, y);
|
||||
}
|
||||
|
||||
void removeAll() {
|
||||
delegate.removeAll();
|
||||
}
|
||||
|
||||
void addSeparator() {
|
||||
delegate.addSeparator();
|
||||
}
|
||||
|
||||
void addToComponent(Component c) {
|
||||
c.add(delegate);
|
||||
}
|
||||
|
||||
Object createSubmenu(String label) {
|
||||
return new Menu(label);
|
||||
}
|
||||
|
||||
void add(Object menuItem) {
|
||||
delegate.add((MenuItem)menuItem);
|
||||
}
|
||||
|
||||
void addMenuItem(String label, String command, String currentSelection) {
|
||||
addMenuItem(delegate, label, command, currentSelection);
|
||||
}
|
||||
|
||||
void addMenuItem(Object targetMenu, String label, String command, String currentSelection) {
|
||||
MenuItem menuItem;
|
||||
if (isSelected(command, currentSelection)) {
|
||||
menuItem = new CheckboxMenuItem(label, true);
|
||||
} else {
|
||||
menuItem = new MenuItem(label);
|
||||
}
|
||||
menuItem.setActionCommand(command);
|
||||
menuItem.addActionListener(this);
|
||||
menuItem.setEnabled(command != null);
|
||||
((Menu)targetMenu).add(menuItem);
|
||||
}
|
||||
}
|
||||
42
jdkSrc/jdk8/sun/awt/im/InputMethodWindow.java
Normal file
42
jdkSrc/jdk8/sun/awt/im/InputMethodWindow.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 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;
|
||||
|
||||
/**
|
||||
* Interface for input method windows that need special handling
|
||||
* by input method window.
|
||||
*
|
||||
*/
|
||||
public interface InputMethodWindow {
|
||||
|
||||
/**
|
||||
* Sets the input context that this input method window is attached to,
|
||||
* null to unattach the window.
|
||||
* @see java.awt.im.spi.InputMethodContext#createInputMethodWindow
|
||||
*/
|
||||
public void setInputContext(InputContext inputContext);
|
||||
|
||||
}
|
||||
67
jdkSrc/jdk8/sun/awt/im/SimpleInputMethodWindow.java
Normal file
67
jdkSrc/jdk8/sun/awt/im/SimpleInputMethodWindow.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2011, 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.Frame;
|
||||
|
||||
/**
|
||||
* Implements a simple input method window that provides the minimal
|
||||
* functionality as specified in
|
||||
* {@link java.awt.im.spi.InputMethodContext#createInputMethodWindow}.
|
||||
*
|
||||
*/
|
||||
public class SimpleInputMethodWindow
|
||||
extends Frame
|
||||
implements InputMethodWindow {
|
||||
|
||||
InputContext inputContext = null;
|
||||
|
||||
/**
|
||||
* Constructs a simple input method window.
|
||||
*/
|
||||
public SimpleInputMethodWindow(String title, InputContext context) {
|
||||
super(title);
|
||||
if (context != null) {
|
||||
this.inputContext = context;
|
||||
}
|
||||
setFocusableWindowState(false);
|
||||
}
|
||||
|
||||
public void setInputContext(InputContext inputContext) {
|
||||
this.inputContext = inputContext;
|
||||
}
|
||||
|
||||
public java.awt.im.InputContext getInputContext() {
|
||||
if (inputContext != null) {
|
||||
return inputContext;
|
||||
} else {
|
||||
return super.getInputContext();
|
||||
}
|
||||
}
|
||||
|
||||
// Proclaim serial compatibility with 1.7.0
|
||||
private static final long serialVersionUID = 5093376647036461555L;
|
||||
}
|
||||
Reference in New Issue
Block a user