diff --git a/src/java.desktop/share/classes/java/awt/Container.java b/src/java.desktop/share/classes/java/awt/Container.java
index 1a6163eb4..88f3b8d04 100644
--- a/src/java.desktop/share/classes/java/awt/Container.java
+++ b/src/java.desktop/share/classes/java/awt/Container.java
@@ -678,6 +678,10 @@ public class Container extends Component {
}
}
+ public ComponentPeer getPeer(){
+ return peer;
+ }
+
/**
* Detects whether or not remove from current parent and adding to new parent requires call of
* removeNotify on the component. Since removeNotify destroys native window this might (not)
diff --git a/src/java.desktop/share/classes/javax/swing/JTextArea.java b/src/java.desktop/share/classes/javax/swing/JTextArea.java
index d64fa0272..ccf7dceca 100644
--- a/src/java.desktop/share/classes/javax/swing/JTextArea.java
+++ b/src/java.desktop/share/classes/javax/swing/JTextArea.java
@@ -547,7 +547,10 @@ public class JTextArea extends JTextComponent {
}
return rowHeight;
}
-
+
+ public FontMetrics getFontMetrics() {
+ return getFontMetrics(getFont());
+ }
/**
* Returns the number of columns in the TextArea.
*
diff --git a/src/java.desktop/share/classes/javax/swing/JTextField.java b/src/java.desktop/share/classes/javax/swing/JTextField.java
index b8e3ffe06..3bfe3cae1 100644
--- a/src/java.desktop/share/classes/javax/swing/JTextField.java
+++ b/src/java.desktop/share/classes/javax/swing/JTextField.java
@@ -409,7 +409,11 @@ public class JTextField extends JTextComponent implements SwingConstants {
}
return columnWidth;
}
-
+
+ public FontMetrics getFontMetrics() {
+ return getFontMetrics(getFont());
+ }
+
/**
* Returns the preferred size Dimensions
needed for this
* TextField
. If a non-zero number of columns has been
diff --git a/src/java.desktop/share/classes/sun/awt/im/InputContext.java b/src/java.desktop/share/classes/sun/awt/im/InputContext.java
index ad9d71be7..3d437ae8a 100644
--- a/src/java.desktop/share/classes/sun/awt/im/InputContext.java
+++ b/src/java.desktop/share/classes/sun/awt/im/InputContext.java
@@ -28,6 +28,7 @@ package sun.awt.im;
import java.awt.AWTEvent;
import java.awt.AWTKeyStroke;
import java.awt.Component;
+import java.awt.Cursor;
import java.awt.EventQueue;
import java.awt.Frame;
import java.awt.Rectangle;
@@ -39,6 +40,7 @@ import java.awt.event.FocusEvent;
import java.awt.event.InputEvent;
import java.awt.event.InputMethodEvent;
import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.awt.im.InputMethodRequests;
@@ -54,6 +56,7 @@ import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import sun.util.logging.PlatformLogger;
import sun.awt.SunToolkit;
+import sun.awt.X11InputMethod;
/**
* This InputContext class contains parts of the implementation of
@@ -249,13 +252,26 @@ public class InputContext extends java.awt.im.InputContext
focusLost((Component) event.getSource(), ((FocusEvent) event).isTemporary());
break;
+ case MouseEvent.MOUSE_RELEASED:
+ if(checkTextCursor((Component)event.getSource())) {
+ // focusGained((Component) event.getSource());
+ transCaretPositionToXIM((Component)event.getSource());
+ break;
+ }
+
case KeyEvent.KEY_PRESSED:
- if (checkInputMethodSelectionKey((KeyEvent)event)) {
+ if (event instanceof KeyEvent && checkInputMethodSelectionKey((KeyEvent)event)) {
// pop up the input method selection menu
InputMethodManager.getInstance().notifyChangeRequestByHotKey((Component)event.getSource());
break;
}
+ case KeyEvent.KEY_RELEASED:
+ if (event instanceof KeyEvent && checkDirectionKey((KeyEvent)event)) {
+ transCaretPositionToXIM((Component) event.getSource());
+ break;
+ }
+
// fall through
default:
@@ -359,7 +375,65 @@ public class InputContext extends java.awt.im.InputContext
}
}
}
-
+ /**
+ * fix fcitx position
+ */
+ private void transCaretPositionToXIM(Component source) {
+ synchronized (source.getTreeLock()) {
+ synchronized (this) {
+ if ("sun.awt.im.CompositionArea".equals(source.getClass().getName())) {
+ // no special handling for this one
+ } else if (getComponentWindow(source) instanceof InputMethodWindow) {
+ // no special handling for this one either
+ } else {
+ if (!source.isDisplayable()) {
+ // Component is being disposed
+ return;
+ }
+ currentClientComponent = source;
+ }
+ awtFocussedComponent = source;
+ if (inputMethod != null && inputMethod instanceof X11InputMethod) {
+ ((X11InputMethod)inputMethod).setXICTextCursorPosition(source);
+ }
+ InputMethodContext inputContext = ((InputMethodContext)this);
+ if (!inputContext.isCompositionAreaVisible()) {
+ InputMethodRequests req = source.getInputMethodRequests();
+ if (req != null && inputContext.useBelowTheSpotInput()) {
+ inputContext.setCompositionAreaUndecorated(true);
+ } else {
+ inputContext.setCompositionAreaUndecorated(false);
+ }
+ }
+ // restores the composition area if it was set to invisible
+ // when focus got lost
+ if (compositionAreaHidden == true) {
+ ((InputMethodContext)this).setCompositionAreaVisible(true);
+ compositionAreaHidden = false;
+ }
+
+ }
+ }
+ }
+ /**
+ * fix fcitx position
+ */
+ private boolean checkDirectionKey(KeyEvent event) {
+ // if (event.getKeyCode() >= 37 && event.getKeyCode() <=40) {
+ // return true;
+ // } else {
+ // return false;
+ // }
+ return true;
+ }
+ /**
+ * fix fcitx position
+ */
+ private boolean checkTextCursor(Component source) {
+ if(source.getCursor().getType()==Cursor.TEXT_CURSOR)
+ return true;
+ return false;
+ }
/**
* Activates the current input method of this input context, and grabs
* the composition area for use by this input context.
diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XInputMethod.java b/src/java.desktop/unix/classes/sun/awt/X11/XInputMethod.java
index 07c1334b8..01d5910de 100644
--- a/src/java.desktop/unix/classes/sun/awt/X11/XInputMethod.java
+++ b/src/java.desktop/unix/classes/sun/awt/X11/XInputMethod.java
@@ -28,15 +28,27 @@ package sun.awt.X11;
import java.awt.AWTException;
import java.awt.Component;
import java.awt.Container;
+import java.awt.geom.Point2D;
+import java.awt.FontMetrics;
+import java.awt.Point;
import java.awt.Rectangle;
import java.awt.im.spi.InputMethodContext;
import java.awt.peer.ComponentPeer;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.text.JTextComponent;
+
import sun.awt.AWTAccessor;
import sun.awt.X11InputMethod;
import sun.util.logging.PlatformLogger;
+
/**
* Input Method Adapter for XIM (without Motif)
*
@@ -83,8 +95,20 @@ public class XInputMethod extends X11InputMethod {
return 0;
return releaseXICNative(pData);
}
-
+
+
private static volatile long xicFocus = 0;
+
+ public void setXICTextCursorOffXY(ComponentPeer peer) {
+
+ if (peer == null) {
+ return;
+ }
+ xicFocus = ((XComponentPeer)peer).getContentWindow();
+ int[] result = getOffXYRelateToFrame(peer ,true);
+ setXICFocusNative(((XComponentPeer)peer).getContentWindow(),true,true,result);
+ // setXICTextCursorOffXYNative(((XComponentPeer)peer).getContentWindow(),result);
+ }
protected void setXICFocus(ComponentPeer peer,
boolean value, boolean active) {
@@ -92,9 +116,11 @@ public class XInputMethod extends X11InputMethod {
return;
}
xicFocus = ((XComponentPeer)peer).getContentWindow();
+ int[] result = getOffXYRelateToFrame(peer ,value);
setXICFocusNative(((XComponentPeer)peer).getContentWindow(),
value,
- active);
+ active,
+ result);
}
public static long getXICFocus() {
@@ -156,6 +182,71 @@ public class XInputMethod extends X11InputMethod {
return peer.getContentWindow();
}
+ protected int[] getOffXYRelateToFrame(ComponentPeer peer, boolean value) {
+ int[] result = null;
+ if(value && this.awtFocussedComponent!=null && this.awtFocussedComponent instanceof JTextComponent){
+ try {
+ Method method_getFontMetrics = null;
+ Method method_getEditor = null;
+ FontMetrics font_metrics = null;
+ Object editor = null;
+ int font_height = 0;
+ int caret_x = 0;
+ int caret_y = 0;
+ if(this.awtFocussedComponent instanceof JTextArea || this.awtFocussedComponent instanceof JTextField){
+ method_getFontMetrics = this.awtFocussedComponent.getClass().getMethod("getFontMetrics");
+ font_metrics = (FontMetrics)method_getFontMetrics.invoke(this.awtFocussedComponent);
+ font_height = font_metrics.getHeight();
+ JTextComponent jc = (JTextComponent)this.awtFocussedComponent;
+ if( jc.getCaret().getMagicCaretPosition() != null) {
+ caret_x = jc.getCaret().getMagicCaretPosition().x;
+ caret_y = jc.getCaret().getMagicCaretPosition().y;
+ }
+ }else {
+ method_getEditor = this.awtFocussedComponent.getClass().getMethod("getEditor");
+
+ editor = method_getEditor.invoke(this.awtFocussedComponent);
+
+ method_getFontMetrics = editor.getClass().getMethod("getFontMetrics",int.class);
+ font_metrics = (FontMetrics)method_getFontMetrics.invoke(editor, 0);
+ font_height = font_metrics.getHeight();
+ Method getCaretLocations = editor.getClass().getMethod("getCaretLocations", boolean.class);
+ Object[] locations = (Object[])getCaretLocations.invoke(editor, false);
+ Field point = locations[0].getClass().getField("myPoint");
+ Point2D pd = (Point2D)point.get(locations[0]);
+ caret_x = (int)pd.getX();
+ caret_y = (int)pd.getY();
+ }
+
+
+ Method method_getLocationOnScreen = this.awtFocussedComponent.getClass().getMethod("getLocationOnScreen");
+
+ Point point = (Point)method_getLocationOnScreen.invoke(this.awtFocussedComponent);
+
+ Method method_getNativeContainer = Component.class.getDeclaredMethod("getNativeContainer");
+ method_getNativeContainer.setAccessible(true);
+ Container c = (Container)method_getNativeContainer.invoke(awtFocussedComponent);
+ if(c!=null)
+ result = new int[]{point.x - c.getPeer().getLocationOnScreen().x + caret_x, point.y - c.getPeer().getLocationOnScreen().y + font_height + caret_y};
+
+ return result;
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ } catch (IllegalArgumentException e) {
+ e.printStackTrace();
+ } catch (InvocationTargetException e) {
+ e.printStackTrace();
+ } catch (NoSuchMethodException e) {
+ e.printStackTrace();
+ } catch (SecurityException e) {
+ e.printStackTrace();
+ } catch(NoSuchFieldException e) {
+ e.printStackTrace();
+ }
+ }
+ return result;
+ }
+
/*
* Native methods
*/
@@ -164,6 +255,6 @@ public class XInputMethod extends X11InputMethod {
private native boolean recreateXICNative(long window, long px11data, int ctxid);
private native int releaseXICNative(long px11data);
private native void setXICFocusNative(long window,
- boolean value, boolean active);
+ boolean value, boolean active, int[] offxy);
private native void adjustStatusWindow(long window);
}
diff --git a/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java b/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java
index d9c45ed97..834164ad8 100644
--- a/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java
+++ b/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java
@@ -33,6 +33,7 @@ import java.awt.AWTException;
import java.awt.event.InputMethodEvent;
import java.awt.font.TextAttribute;
import java.awt.font.TextHitInfo;
+import java.awt.Component;
import java.awt.peer.ComponentPeer;
import java.text.AttributedString;
import java.util.Map;
@@ -56,6 +57,10 @@ public abstract class X11InputMethod extends X11InputMethodBase {
public X11InputMethod() throws AWTException {
super();
}
+ /**
+ * fix fcitx position
+ */
+ public abstract void setXICTextCursorOffXY(ComponentPeer peer);
/**
* Reset the composition state to the current composition state.
@@ -380,6 +385,30 @@ public abstract class X11InputMethod extends X11InputMethodBase {
}
}
+ /**
+ * fix fcitx position
+ */
+ public synchronized void setXICTextCursorPosition(Component component){
+ if (component == null) {
+ return;
+ }
+ if (isActive) {
+ // deactivate/activate are being suppressed during a focus change -
+ // this may happen when an input method window is made visible
+ // boolean ac = haveActiveClient(); already set true in awt_InputMethod.c
+ setXICTextCursorOffXY(getPeer(awtFocussedComponent));
+
+ }
+ awtFocussedComponent = component;
+ // ComponentPeer lastXICFocussedComponentPeer = null;
+ // if (lastXICFocussedComponent != null) {
+ // lastXICFocussedComponentPeer = getPeer(lastXICFocussedComponent);
+ // }
+ ComponentPeer awtFocussedComponentPeer = getPeer(awtFocussedComponent);
+ if(awtFocussedComponent !=null )
+ setXICTextCursorOffXY(awtFocussedComponentPeer);
+ }
+
protected abstract boolean recreateXIC(int ctxid);
protected abstract int releaseXIC();
private static native boolean recreateX11InputMethod();
diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c
index 847c44b52..c619d3773 100644
--- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c
+++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c
@@ -436,13 +436,17 @@ setXICFocus(XIC ic, unsigned short req)
* Sets the focus window to the given XIC.
*/
static void
-setXICWindowFocus(XIC ic, Window w)
+setXICWindowFocus(XIC ic, Window w, int arr[2])
{
if (ic == NULL) {
(void)fprintf(stderr, "Couldn't find X Input Context\n");
return;
}
- (void) XSetICValues(ic, XNFocusWindow, w, NULL);
+ XPoint spot;
+ spot.x = arr[0];
+ spot.y = arr[1];
+ XVaNestedList xy = (XVaNestedList)XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
+ (void) XSetICValues(ic, XNFocusWindow, w, XNPreeditAttributes, xy, NULL);
}
/*
@@ -1468,7 +1472,8 @@ Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env,
jobject this,
jlong w,
jboolean req,
- jboolean active)
+ jboolean active,
+ jintArray arr)
{
X11InputMethodData *pX11IMData;
AWT_LOCK();
@@ -1489,7 +1494,17 @@ Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env,
* On Solaris2.6, setXICWindowFocus() has to be invoked
* before setting focus.
*/
- setXICWindowFocus(pX11IMData->current_ic, w);
+ int positions[2] = {100,50};
+ if (arr)
+ {
+ int length = (*env)->GetArrayLength(env,arr);
+ int *addArr = (*env)->GetIntArrayElements(env, arr, NULL);
+ for (int i= 0; i < length; ++i) {
+ positions[i] = *(addArr + i);
+ }
+ (*env)->ReleaseIntArrayElements(env, arr, addArr, 0);
+ }
+ setXICWindowFocus(pX11IMData->current_ic, w, positions);
setXICFocus(pX11IMData->current_ic, req);
currentX11InputMethodInstance = pX11IMData->x11inputmethod;
currentFocusWindow = w;