History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/awt/im/InputMethodContext.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/awt/im/InputMethodContext.java+378−0
@@ -0,0 +1,378 @@
1+/*
2+ * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.awt.im;
27+
28+import java.awt.AWTEvent;
29+import java.awt.Component;
30+import java.awt.GraphicsEnvironment;
31+import java.awt.HeadlessException;
32+import java.awt.Rectangle;
33+import java.awt.Toolkit;
34+import java.awt.Window;
35+import java.awt.event.KeyEvent;
36+import java.awt.event.InputMethodEvent;
37+import java.awt.font.TextHitInfo;
38+import java.awt.im.InputMethodRequests;
39+import java.awt.im.spi.InputMethod;
40+import java.security.AccessController;
41+import java.text.AttributedCharacterIterator;
42+import java.text.AttributedCharacterIterator.Attribute;
43+import java.text.AttributedString;
44+import java.text.CharacterIterator;
45+import javax.swing.JFrame;
46+import sun.awt.InputMethodSupport;
47+import sun.security.action.GetPropertyAction;
48+
49+/**
50+ * The InputMethodContext class provides methods that input methods
51+ * can use to communicate with their client components.
52+ * It is a subclass of InputContext, which provides methods for use by
53+ * components.
54+ *
55+ * @author JavaSoft International
56+ */
57+
58+public class InputMethodContext
59+ extends sun.awt.im.InputContext
60+ implements java.awt.im.spi.InputMethodContext {
61+
62+ private boolean dispatchingCommittedText;
63+
64+ // Creation of the context's composition area handler is
65+ // delayed until we really need a composition area.
66+ private CompositionAreaHandler compositionAreaHandler;
67+ private Object compositionAreaHandlerLock = new Object();
68+
69+ static private boolean belowTheSpotInputRequested;
70+ private boolean inputMethodSupportsBelowTheSpot;
71+
72+ static {
73+ // check whether we should use below-the-spot input
74+ // get property from command line
75+ String inputStyle = (String) AccessController.doPrivileged
76+ (new GetPropertyAction("java.awt.im.style", null));
77+ // get property from awt.properties file
78+ if (inputStyle == null) {
79+ inputStyle = Toolkit.getDefaultToolkit().
80+ getProperty("java.awt.im.style", null);
81+ }
82+ belowTheSpotInputRequested = "below-the-spot".equals(inputStyle);
83+ }
84+
85+ /**
86+ * Constructs an InputMethodContext.
87+ */
88+ public InputMethodContext() {
89+ super();
90+ }
91+
92+ void setInputMethodSupportsBelowTheSpot(boolean supported) {
93+ inputMethodSupportsBelowTheSpot = supported;
94+ }
95+
96+ boolean useBelowTheSpotInput() {
97+ return belowTheSpotInputRequested && inputMethodSupportsBelowTheSpot;
98+ }
99+
100+ private boolean haveActiveClient() {
101+ Component client = getClientComponent();
102+ return client != null
103+ && client.getInputMethodRequests() != null;
104+ }
105+
106+ // implements java.awt.im.spi.InputMethodContext.dispatchInputMethodEvent
107+ public void dispatchInputMethodEvent(int id,
108+ AttributedCharacterIterator text, int committedCharacterCount,
109+ TextHitInfo caret, TextHitInfo visiblePosition) {
110+ // We need to record the client component as the source so
111+ // that we have correct information if we later have to break up this
112+ // event into key events.
113+ Component source;
114+
115+ source = getClientComponent();
116+ if (source != null) {
117+ InputMethodEvent event = new InputMethodEvent(source,
118+ id, text, committedCharacterCount, caret, visiblePosition);
119+
120+ if (haveActiveClient() && !useBelowTheSpotInput()) {
121+ source.dispatchEvent(event);
122+ } else {
123+ getCompositionAreaHandler(true).processInputMethodEvent(event);
124+ }
125+ }
126+ }
127+
128+ /**
129+ * Dispatches committed text to a client component.
130+ * Called by composition window.
131+ *
132+ * @param client The component that the text should get dispatched to.
133+ * @param text The iterator providing access to the committed
134+ * (and possible composed) text.
135+ * @param committedCharacterCount The number of committed characters in the text.
136+ */
137+ synchronized void dispatchCommittedText(Component client,
138+ AttributedCharacterIterator text,
139+ int committedCharacterCount) {
140+ // note that the client is not always the current client component -
141+ // some host input method adapters may dispatch input method events
142+ // through the Java event queue, and we may have switched clients while
143+ // the event was in the queue.
144+ if (committedCharacterCount == 0
145+ || text.getEndIndex() <= text.getBeginIndex()) {
146+ return;
147+ }
148+ long time = System.currentTimeMillis();
149+ dispatchingCommittedText = true;
150+ try {
151+ InputMethodRequests req = client.getInputMethodRequests();
152+ if (req != null) {
153+ // active client -> send text as InputMethodEvent
154+ int beginIndex = text.getBeginIndex();
155+ AttributedCharacterIterator toBeCommitted =
156+ (new AttributedString(text, beginIndex, beginIndex + committedCharacterCount)).getIterator();
157+
158+ InputMethodEvent inputEvent = new InputMethodEvent(
159+ client,
160+ InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
161+ toBeCommitted,
162+ committedCharacterCount,
163+ null, null);
164+
165+ client.dispatchEvent(inputEvent);
166+ } else {
167+ // passive client -> send text as KeyEvents
168+ char keyChar = text.first();
169+ while (committedCharacterCount-- > 0 && keyChar != CharacterIterator.DONE) {
170+ KeyEvent keyEvent = new KeyEvent(client, KeyEvent.KEY_TYPED,
171+ time, 0, KeyEvent.VK_UNDEFINED, keyChar);
172+ client.dispatchEvent(keyEvent);
173+ keyChar = text.next();
174+ }
175+ }
176+ } finally {
177+ dispatchingCommittedText = false;
178+ }
179+ }
180+
181+ public void dispatchEvent(AWTEvent event) {
182+ // some host input method adapters may dispatch input method events
183+ // through the Java event queue. If the component that the event is
184+ // intended for isn't an active client, or if we're using below-the-spot
185+ // input, we need to dispatch this event
186+ // to the input window. Note that that component is not necessarily the
187+ // current client component, since we may have switched clients while
188+ // the event was in the queue.
189+ if (event instanceof InputMethodEvent) {
190+ if (((Component) event.getSource()).getInputMethodRequests() == null
191+ || (useBelowTheSpotInput() && !dispatchingCommittedText)) {
192+ getCompositionAreaHandler(true).processInputMethodEvent((InputMethodEvent) event);
193+ }
194+ } else {
195+ // make sure we don't dispatch our own key events back to the input method
196+ if (!dispatchingCommittedText) {
197+ super.dispatchEvent(event);
198+ }
199+ }
200+ }
201+
202+ /**
203+ * Gets this context's composition area handler, creating it if necessary.
204+ * If requested, it grabs the composition area for use by this context.
205+ * The composition area's text is not updated.
206+ */
207+ private CompositionAreaHandler getCompositionAreaHandler(boolean grab) {
208+ synchronized(compositionAreaHandlerLock) {
209+ if (compositionAreaHandler == null) {
210+ compositionAreaHandler = new CompositionAreaHandler(this);
211+ }
212+ compositionAreaHandler.setClientComponent(getClientComponent());
213+ if (grab) {
214+ compositionAreaHandler.grabCompositionArea(false);
215+ }
216+
217+ return compositionAreaHandler;
218+ }
219+ }
220+
221+ /**
222+ * Grabs the composition area for use by this context.
223+ * If doUpdate is true, updates the composition area with previously sent
224+ * composed text.
225+ */
226+ void grabCompositionArea(boolean doUpdate) {
227+ synchronized(compositionAreaHandlerLock) {
228+ if (compositionAreaHandler != null) {
229+ compositionAreaHandler.grabCompositionArea(doUpdate);
230+ } else {
231+ // if this context hasn't seen a need for a composition area yet,
232+ // just close it without creating the machinery
233+ CompositionAreaHandler.closeCompositionArea();
234+ }
235+ }
236+ }
237+
238+ /**
239+ * Releases and closes the composition area if it is currently owned by
240+ * this context's composition area handler.
241+ */
242+ void releaseCompositionArea() {
243+ synchronized(compositionAreaHandlerLock) {
244+ if (compositionAreaHandler != null) {
245+ compositionAreaHandler.releaseCompositionArea();
246+ }
247+ }
248+ }
249+
250+ /**
251+ * Calls CompositionAreaHandler.isCompositionAreaVisible() to see
252+ * whether the composition area is visible or not.
253+ * Notice that this method is always called on the AWT event dispatch
254+ * thread.
255+ */
256+ boolean isCompositionAreaVisible() {
257+ if (compositionAreaHandler != null) {
258+ return compositionAreaHandler.isCompositionAreaVisible();
259+ }
260+
261+ return false;
262+ }
263+ /**
264+ * Calls CompositionAreaHandler.setCompositionAreaVisible to
265+ * show or hide the composition area.
266+ * As isCompositionAreaVisible method, it is always called
267+ * on AWT event dispatch thread.
268+ */
269+ void setCompositionAreaVisible(boolean visible) {
270+ if (compositionAreaHandler != null) {
271+ compositionAreaHandler.setCompositionAreaVisible(visible);
272+ }
273+ }
274+
275+ /**
276+ * Calls the current client component's implementation of getTextLocation.
277+ */
278+ public Rectangle getTextLocation(TextHitInfo offset) {
279+ return getReq().getTextLocation(offset);
280+ }
281+
282+ /**
283+ * Calls the current client component's implementation of getLocationOffset.
284+ */
285+ public TextHitInfo getLocationOffset(int x, int y) {
286+ return getReq().getLocationOffset(x, y);
287+ }
288+
289+ /**
290+ * Calls the current client component's implementation of getInsertPositionOffset.
291+ */
292+ public int getInsertPositionOffset() {
293+ return getReq().getInsertPositionOffset();
294+ }
295+
296+ /**
297+ * Calls the current client component's implementation of getCommittedText.
298+ */
299+ public AttributedCharacterIterator getCommittedText(int beginIndex,
300+ int endIndex,
301+ Attribute[] attributes) {
302+ return getReq().getCommittedText(beginIndex, endIndex, attributes);
303+ }
304+
305+ /**
306+ * Calls the current client component's implementation of getCommittedTextLength.
307+ */
308+ public int getCommittedTextLength() {
309+ return getReq().getCommittedTextLength();
310+ }
311+
312+
313+ /**
314+ * Calls the current client component's implementation of cancelLatestCommittedText.
315+ */
316+ public AttributedCharacterIterator cancelLatestCommittedText(Attribute[] attributes) {
317+ return getReq().cancelLatestCommittedText(attributes);
318+ }
319+
320+ /**
321+ * Calls the current client component's implementation of getSelectedText.
322+ */
323+ public AttributedCharacterIterator getSelectedText(Attribute[] attributes) {
324+ return getReq().getSelectedText(attributes);
325+ }
326+
327+ private InputMethodRequests getReq() {
328+ if (haveActiveClient() && !useBelowTheSpotInput()) {
329+ return getClientComponent().getInputMethodRequests();
330+ } else {
331+ return getCompositionAreaHandler(false);
332+ }
333+ }
334+
335+ // implements java.awt.im.spi.InputMethodContext.createInputMethodWindow
336+ public Window createInputMethodWindow(String title, boolean attachToInputContext) {
337+ InputContext context = attachToInputContext ? this : null;
338+ return createInputMethodWindow(title, context, false);
339+ }
340+
341+ // implements java.awt.im.spi.InputMethodContext.createInputMethodJFrame
342+ public JFrame createInputMethodJFrame(String title, boolean attachToInputContext) {
343+ InputContext context = attachToInputContext ? this : null;
344+ return (JFrame)createInputMethodWindow(title, context, true);
345+ }
346+
347+ static Window createInputMethodWindow(String title, InputContext context, boolean isSwing) {
348+ if (GraphicsEnvironment.isHeadless()) {
349+ throw new HeadlessException();
350+ }
351+ if (isSwing) {
352+ return new InputMethodJFrame(title, context);
353+ } else {
354+ Toolkit toolkit = Toolkit.getDefaultToolkit();
355+ if (toolkit instanceof InputMethodSupport) {
356+ return ((InputMethodSupport)toolkit).createInputMethodWindow(
357+ title, context);
358+ }
359+ }
360+ throw new InternalError("Input methods must be supported");
361+ }
362+
363+ /**
364+ * @see java.awt.im.spi.InputMethodContext#enableClientWindowNotification
365+ */
366+ public void enableClientWindowNotification(InputMethod inputMethod, boolean enable) {
367+ super.enableClientWindowNotification(inputMethod, enable);
368+ }
369+
370+ /**
371+ * Disables or enables decorations for the composition window.
372+ */
373+ void setCompositionAreaUndecorated(boolean undecorated) {
374+ if (compositionAreaHandler != null) {
375+ compositionAreaHandler.setCompositionAreaUndecorated(undecorated);
376+ }
377+ }
378+}