# HG changeset patch # User clanger # Date 1526643879 -3600 # Fri May 18 12:44:39 2018 +0100 # Node ID f67830fa01637411518e29122904ce9d7b7cf4be # Parent 40c98f9b69fa9b5a0e829e36ef1fe563fd74e6af 8201429: Support AIX Input Method Editor (IME) for AWT Input Method Framework (IMF) diff --git a/make/lib/Awt2dLibraries.gmk b/make/lib/Awt2dLibraries.gmk --- a/make/lib/Awt2dLibraries.gmk +++ b/make/lib/Awt2dLibraries.gmk @@ -269,6 +269,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) LIBAWT_XAWT_DIRS := \ + $(wildcard $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libawt_xawt) \ $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libawt_xawt \ $(TOPDIR)/src/java.desktop/share/native/common/awt/debug \ $(TOPDIR)/src/java.desktop/share/native/common/awt/utility \ @@ -329,7 +330,7 @@ BUILD_LIBAWT_XAWT_awt_Font.c_CFLAGS := -w # initializing a declared 'extern' BUILD_LIBAWT_XAWT_debug_mem.c_CFLAGS := -w - endif + endif $(eval $(call SetupJdkLibrary, BUILD_LIBAWT_XAWT, \ NAME := awt_xawt, \ diff --git a/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java b/src/java.desktop/aix/classes/sun/awt/X11InputMethod.java copy from src/java.desktop/unix/classes/sun/awt/X11InputMethod.java copy to src/java.desktop/aix/classes/sun/awt/X11InputMethod.java --- a/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java +++ b/src/java.desktop/aix/classes/sun/awt/X11InputMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -25,147 +25,25 @@ package sun.awt; -import java.util.Collections; -import java.util.Locale; -import java.util.Map; -import java.util.HashMap; -import java.awt.AWTEvent; import java.awt.AWTException; -import java.awt.Component; -import java.awt.Container; import java.awt.EventQueue; -import java.awt.Window; -import java.awt.im.InputMethodHighlight; -import java.awt.im.spi.InputMethodContext; -import sun.awt.im.InputMethodAdapter; import java.awt.event.InputMethodEvent; import java.awt.font.TextAttribute; import java.awt.font.TextHitInfo; import java.awt.peer.ComponentPeer; -import java.lang.Character.Subset; import java.text.AttributedString; -import java.text.AttributedCharacterIterator; -import java.io.File; -import java.io.FileReader; -import java.io.BufferedReader; -import java.io.IOException; -import java.lang.ref.WeakReference; import sun.util.logging.PlatformLogger; -import java.util.StringTokenizer; -import java.util.regex.Pattern; - /** - * Input Method Adapter for XIM + * Input Method Adapter for XIM for AIX * * @author JavaSoft International */ -public abstract class X11InputMethod extends InputMethodAdapter { - private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11InputMethod"); - /* - * The following XIM* values must be the same as those defined in - * Xlib.h - */ - private static final int XIMReverse = (1<<0); - private static final int XIMUnderline = (1<<1); - private static final int XIMHighlight = (1<<2); - private static final int XIMPrimary = (1<<5); - private static final int XIMSecondary = (1<<6); - private static final int XIMTertiary = (1<<7); - - /* - * visible position values - */ - private static final int XIMVisibleToForward = (1<<8); - private static final int XIMVisibleToBackward = (1<<9); - private static final int XIMVisibleCenter = (1<<10); - private static final int XIMVisibleMask = (XIMVisibleToForward| - XIMVisibleToBackward| - XIMVisibleCenter); - - private Locale locale; - private static boolean isXIMOpened = false; - protected Container clientComponentWindow = null; - private Component awtFocussedComponent = null; - private Component lastXICFocussedComponent = null; - private boolean isLastXICActive = false; - private boolean isLastTemporary = false; - private boolean isActive = false; - private boolean isActiveClient = false; - private static Map[] highlightStyles; - private boolean disposed = false; - - //reset the XIC if necessary - private boolean needResetXIC = false; - private WeakReference needResetXICClient = new WeakReference<>(null); +public abstract class X11InputMethod extends X11InputMethodBase { - // The use of compositionEnableSupported is to reduce unnecessary - // native calls if set/isCompositionEnabled - // throws UnsupportedOperationException. - // It is set to false if that exception is thrown first time - // either of the two methods are called. - private boolean compositionEnableSupported = true; - // The savedCompositionState indicates the composition mode when - // endComposition or setCompositionEnabled is called. It doesn't always - // reflect the actual composition state because it doesn't get updated - // when the user changes the composition state through direct interaction - // with the input method. It is used to save the composition mode when - // focus is traversed across different client components sharing the - // same java input context. Also if set/isCompositionEnabled are not - // supported, it remains false. - private boolean savedCompositionState = false; - - // variables to keep track of preedit context. - // these variables need to be accessed within AWT_LOCK/UNLOCK - private String committedText = null; - private StringBuffer composedText = null; - private IntBuffer rawFeedbacks; - - // private data (X11InputMethodData structure defined in - // awt_InputMethod.c) for native methods - // this structure needs to be accessed within AWT_LOCK/UNLOCK - private transient long pData = 0; // accessed by native - - // Initialize highlight mapping table - static { - @SuppressWarnings({"unchecked", "rawtypes"}) - Map styles[] = new Map[4]; - HashMap map; - - // UNSELECTED_RAW_TEXT_HIGHLIGHT - map = new HashMap<>(1); - map.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); - styles[0] = Collections.unmodifiableMap(map); - - // SELECTED_RAW_TEXT_HIGHLIGHT - map = new HashMap<>(1); - map.put(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON); - styles[1] = Collections.unmodifiableMap(map); - - // UNSELECTED_CONVERTED_TEXT_HIGHLIGHT - map = new HashMap<>(1); - map.put(TextAttribute.INPUT_METHOD_UNDERLINE, - TextAttribute.UNDERLINE_LOW_ONE_PIXEL); - styles[2] = Collections.unmodifiableMap(map); - - // SELECTED_CONVERTED_TEXT_HIGHLIGHT - map = new HashMap<>(1); - map.put(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON); - styles[3] = Collections.unmodifiableMap(map); - - highlightStyles = styles; - } - - static { - initIDs(); - } - - /** - * Initialize JNI field and method IDs for fields that may be - accessed from C. - */ - private static native void initIDs(); + // to keep the instance of activating if IM resumed + static protected X11InputMethod activatedInstance = null; /** * Constructs an X11InputMethod instance. It initializes the XIM @@ -174,114 +52,14 @@ * @exception AWTException if XOpenIM() failed. */ public X11InputMethod() throws AWTException { - // supports only the locale in which the VM is started - locale = X11InputMethodDescriptor.getSupportedLocale(); - if (initXIM() == false) { - throw new AWTException("Cannot open X Input Method"); - } - } - - @SuppressWarnings("deprecation") - protected void finalize() throws Throwable { - dispose(); - super.finalize(); - } - - /** - * Invokes openIM() that invokes XOpenIM() if it's not opened yet. - * @return true if openXIM() is successful or it's already been opened. - */ - private synchronized boolean initXIM() { - if (isXIMOpened == false) - isXIMOpened = openXIM(); - return isXIMOpened; - } - - protected abstract boolean openXIM(); - - protected boolean isDisposed() { - return disposed; - } - - protected abstract void setXICFocus(ComponentPeer peer, - boolean value, boolean active); - - /** - * Does nothing - this adapter doesn't use the input method context. - * - * @see java.awt.im.spi.InputMethod#setInputMethodContext - */ - public void setInputMethodContext(InputMethodContext context) { - } - - /** - * Set locale to input. If input method doesn't support specified locale, - * false will be returned and its behavior is not changed. - * - * @param lang locale to input - * @return the true is returned when specified locale is supported. - */ - public boolean setLocale(Locale lang) { - if (lang.equals(locale)) { - return true; - } - // special compatibility rule for Japanese and Korean - if (locale.equals(Locale.JAPAN) && lang.equals(Locale.JAPANESE) || - locale.equals(Locale.KOREA) && lang.equals(Locale.KOREAN)) { - return true; - } - return false; - } - - /** - * Returns current input locale. - */ - public Locale getLocale() { - return locale; - } - - /** - * Does nothing - XIM doesn't let you specify which characters you expect. - * - * @see java.awt.im.spi.InputMethod#setCharacterSubsets - */ - public void setCharacterSubsets(Subset[] subsets) { - } - - /** - * Dispatch event to input method. InputContext dispatch event with this - * method. Input method set consume flag if event is consumed in - * input method. - * - * @param e event - */ - public void dispatchEvent(AWTEvent e) { - } - - - protected final void resetXICifneeded(){ - /* needResetXIC is used to indicate whether to call - resetXIC on the active client. resetXIC will always be - called on the passive client when endComposition is called. - */ - if (needResetXIC && haveActiveClient() && - getClientComponent() != needResetXICClient.get()){ - resetXIC(); - - // needs to reset the last xic focussed component. - lastXICFocussedComponent = null; - isLastXICActive = false; - - needResetXICClient.clear(); - needResetXIC = false; - } + super(); } /** * Reset the composition state to the current composition state. */ - private void resetCompositionState() { - if (compositionEnableSupported) { + protected void resetCompositionState() { + if (compositionEnableSupported && haveActiveClient()) { try { /* Restore the composition mode to the last saved composition mode. */ @@ -293,35 +71,26 @@ } /** - * Query and then return the current composition state. - * @return the composition state if isCompositionEnabled call - * is successful. Otherwise, it returns false. - */ - private boolean getCompositionState() { - boolean compositionState = false; - if (compositionEnableSupported) { - try { - compositionState = isCompositionEnabled(); - } catch (UnsupportedOperationException e) { - compositionEnableSupported = false; - } - } - return compositionState; - } - - /** * Activate input method. */ public synchronized void activate() { + activatedInstance = this; clientComponentWindow = getClientComponentWindow(); if (clientComponentWindow == null) return; - if (lastXICFocussedComponent != null){ + if (lastXICFocussedComponent != null) { if (log.isLoggable(PlatformLogger.Level.FINE)) { log.fine("XICFocused {0}, AWTFocused {1}", lastXICFocussedComponent, awtFocussedComponent); } + if (lastXICFocussedComponent != awtFocussedComponent) { + ComponentPeer lastXICFocussedComponentPeer = getPeer(lastXICFocussedComponent); + if (lastXICFocussedComponentPeer != null) { + setXICFocus(lastXICFocussedComponentPeer, false, isLastXICActive); + } + } + lastXICFocussedComponent = null; } if (pData == 0) { @@ -334,34 +103,20 @@ /* reset input context if necessary and set the XIC focus */ resetXICifneeded(); - ComponentPeer lastXICFocussedComponentPeer = null; ComponentPeer awtFocussedComponentPeer = getPeer(awtFocussedComponent); - - if (lastXICFocussedComponent != null) { - lastXICFocussedComponentPeer = getPeer(lastXICFocussedComponent); - } + setStatusAreaVisible(true, pData); - /* If the last XIC focussed component has a different peer as the - current focussed component, change the XIC focus to the newly - focussed component. - */ - if (isLastTemporary || lastXICFocussedComponentPeer != awtFocussedComponentPeer || - isLastXICActive != haveActiveClient()) { - if (lastXICFocussedComponentPeer != null) { - setXICFocus(lastXICFocussedComponentPeer, false, isLastXICActive); - } - if (awtFocussedComponentPeer != null) { - setXICFocus(awtFocussedComponentPeer, true, haveActiveClient()); - } - lastXICFocussedComponent = awtFocussedComponent; - isLastXICActive = haveActiveClient(); + if (awtFocussedComponentPeer != null) { + setXICFocus(awtFocussedComponentPeer, true, haveActiveClient()); } - resetCompositionState(); + lastXICFocussedComponent = awtFocussedComponent; + isLastXICActive = haveActiveClient(); isActive = true; + if (savedCompositionState) { + resetCompositionState(); + } } - protected abstract boolean createXIC(); - /** * Deactivate input method. */ @@ -385,197 +140,38 @@ Last note, getCompositionState should be called before setXICFocus since setXICFocus here sets the XIC to 0. */ + activatedInstance = null; savedCompositionState = getCompositionState(); - if (isTemporary){ + if (isTemporary) { //turn the status window off... turnoffStatusWindow(); + /* Delay resetting the XIC focus until activate is called and the newly + * Focused component has a different peer as the last focused component. + */ + lastXICFocussedComponent = awtFocussedComponent; + } else { + if (awtFocussedComponent != null ) { + ComponentPeer awtFocussedComponentPeer = getPeer(awtFocussedComponent); + if (awtFocussedComponentPeer != null) { + setXICFocus(awtFocussedComponentPeer, false, isAc); + } + } + lastXICFocussedComponent = null; } - /* Delay resetting the XIC focus until activate is called and the newly - focussed component has a different peer as the last focussed component. - */ - lastXICFocussedComponent = awtFocussedComponent; isLastXICActive = isAc; isLastTemporary = isTemporary; isActive = false; - } - - /** - * Explicitly disable the native IME. Native IME is not disabled when - * deactivate is called. - */ - public void disableInputMethod() { - if (lastXICFocussedComponent != null) { - setXICFocus(getPeer(lastXICFocussedComponent), false, isLastXICActive); - lastXICFocussedComponent = null; - isLastXICActive = false; - - resetXIC(); - needResetXICClient.clear(); - needResetXIC = false; - } + setStatusAreaVisible(false, pData); } // implements java.awt.im.spi.InputMethod.hideWindows public void hideWindows() { - // ??? need real implementation - } - - /** - * @see java.awt.Toolkit#mapInputMethodHighlight - */ - public static Map mapInputMethodHighlight(InputMethodHighlight highlight) { - int index; - int state = highlight.getState(); - if (state == InputMethodHighlight.RAW_TEXT) { - index = 0; - } else if (state == InputMethodHighlight.CONVERTED_TEXT) { - index = 2; - } else { - return null; - } - if (highlight.isSelected()) { - index += 1; - } - return highlightStyles[index]; - } - - /** - * @see sun.awt.im.InputMethodAdapter#setAWTFocussedComponent - */ - protected void setAWTFocussedComponent(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(); - setXICFocus(getPeer(awtFocussedComponent), false, ac); - setXICFocus(getPeer(component), true, ac); - } - awtFocussedComponent = component; - } - - /** - * @see sun.awt.im.InputMethodAdapter#stopListening - */ - protected void stopListening() { - // It is desirable to disable XIM by calling XSetICValues with - // XNPreeditState == XIMPreeditDisable. But Solaris 2.6 and - // Solaris 7 do not implement this correctly without a patch, - // so just call resetXIC here. Prior endComposition call commits - // the existing composed text. - endComposition(); - // disable the native input method so that the other input - // method could get the input focus. - disableInputMethod(); - if (needResetXIC) { - resetXIC(); - needResetXICClient.clear(); - needResetXIC = false; - } - } - - /** - * Returns the Window instance in which the client component is - * contained. If not found, null is returned. (IS THIS POSSIBLE?) - */ - // NOTE: This method may be called by privileged threads. - // DO NOT INVOKE CLIENT CODE ON THIS THREAD! - private Window getClientComponentWindow() { - Component client = getClientComponent(); - Container container; - - if (client instanceof Container) { - container = (Container) client; - } else { - container = getParent(client); - } - - while (container != null && !(container instanceof java.awt.Window)) { - container = getParent(container); + if (pData != 0) { + setStatusAreaVisible(false, pData); + turnoffStatusWindow(); } - return (Window) container; - } - - protected abstract Container getParent(Component client); - - /** - * Returns peer of the given client component. If the given client component - * doesn't have peer, peer of the native container of the client is returned. - */ - protected abstract ComponentPeer getPeer(Component client); - - /** - * Used to protect preedit data - */ - protected abstract void awtLock(); - protected abstract void awtUnlock(); - - /** - * Creates an input method event from the arguments given - * and posts it on the AWT event queue. For arguments, - * see InputMethodEvent. Called by input method. - * - * @see java.awt.event.InputMethodEvent#InputMethodEvent - */ - private void postInputMethodEvent(int id, - AttributedCharacterIterator text, - int committedCharacterCount, - TextHitInfo caret, - TextHitInfo visiblePosition, - long when) { - Component source = getClientComponent(); - if (source != null) { - InputMethodEvent event = new InputMethodEvent(source, - id, when, text, committedCharacterCount, caret, visiblePosition); - SunToolkit.postEvent(SunToolkit.targetToAppContext(source), (AWTEvent)event); - } - } - - private void postInputMethodEvent(int id, - AttributedCharacterIterator text, - int committedCharacterCount, - TextHitInfo caret, - TextHitInfo visiblePosition) { - postInputMethodEvent(id, text, committedCharacterCount, - caret, visiblePosition, EventQueue.getMostRecentEventTime()); - } - - /** - * Dispatches committed text from XIM to the awt event queue. This - * method is invoked from the event handler in canvas.c in the - * AWT Toolkit thread context and thus inside the AWT Lock. - * @param str committed text - * @param when when - */ - // NOTE: This method may be called by privileged threads. - // This functionality is implemented in a package-private method - // to insure that it cannot be overridden by client subclasses. - // DO NOT INVOKE CLIENT CODE ON THIS THREAD! - void dispatchCommittedText(String str, long when) { - if (str == null) - return; - - if (composedText == null) { - AttributedString attrstr = new AttributedString(str); - postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, - attrstr.getIterator(), - str.length(), - null, - null, - when); - } else { - // if there is composed text, wait until the preedit - // callback is invoked. - committedText = str; - } - } - - private void dispatchCommittedText(String str) { - dispatchCommittedText(str, EventQueue.getMostRecentEventTime()); } /** @@ -601,7 +197,7 @@ return; } - //Workaround for deadlock bug on solaris2.6_zh bug#4170760 + // Workaround for deadlock bug on solaris2.6_zh bug#4170760 if (chgText == null && chgStyles == null && chgOffset == 0 @@ -611,6 +207,41 @@ && committedText == null) return; + // Recalculate chgOffset and chgLength for supplementary char + if (composedText != null) { + int tmpChgOffset=chgOffset; + int tmpChgLength=chgLength; + int index = 0; + for (int i=0;i < tmpChgOffset; i++,index++){ + if (index < composedText.length() + && Character.charCount(composedText.codePointAt(index))==2){ + index++; + chgOffset++; + } + } + // The index keeps value + for (int i=0;i < tmpChgLength; i++,index++){ + if (index < composedText.length() + && Character.charCount(composedText.codePointAt(index))==2){ + index++; + chgLength++; + } + } + } + + // Replace control character with a square box + if (chgText != null) { + StringBuffer newChgText = new StringBuffer(); + for (int i=0; i < chgText.length(); i++){ + char c = chgText.charAt(i); + if (Character.isISOControl(c)){ + c = '\u25A1'; + } + newChgText.append(c); + } + chgText = new String(newChgText); + } + if (composedText == null) { // TODO: avoid reallocation of those buffers composedText = new StringBuffer(INITIAL_SIZE); @@ -645,8 +276,47 @@ } if (chgText != null) { composedText.insert(chgOffset, chgText); - if (chgStyles != null) + if (chgStyles != null) { + // Recalculate chgStyles for supplementary char + if (chgText.length() > chgStyles.length){ + int index=0; + int[] newStyles = new int[chgText.length()]; + for (int i=0; i < chgStyles.length; i++, index++){ + newStyles[index]=chgStyles[i]; + if (index < chgText.length() + && Character.charCount(chgText.codePointAt(index))==2){ + newStyles[++index]=chgStyles[i]; + } + } + chgStyles=newStyles; + } rawFeedbacks.insert(chgOffset, chgStyles); + } + + } + + else if (chgStyles != null) { + // Recalculate chgStyles to support supplementary char + int count=0; + for (int i=0; i < chgStyles.length; i++){ + if (composedText.length() > chgOffset+i+count + && Character.charCount(composedText.codePointAt(chgOffset+i+count))==2){ + count++; + } + } + if (count>0){ + int index=0; + int[] newStyles = new int[chgStyles.length+count]; + for (int i=0; i < chgStyles.length; i++, index++){ + newStyles[index]=chgStyles[i]; + if (composedText.length() > chgOffset+index + && Character.charCount(composedText.codePointAt(chgOffset+index))==2){ + newStyles[++index]=chgStyles[i]; + } + } + chgStyles=newStyles; + } + rawFeedbacks.replace(chgOffset, chgStyles); } if (composedText.length() == 0) { @@ -674,6 +344,15 @@ return; } + // Adjust caretPosition for supplementary char + for (int i=0; i< caretPosition; i++){ + if (i < composedText.length() + && Character.charCount(composedText.codePointAt(i))==2){ + caretPosition++; + i++; + } + } + // Now sending the composed text to the client int composedOffset; AttributedString inputText; @@ -739,31 +418,22 @@ when); } - /** - * Flushes composed and committed text held in this context. - * This method is invoked in the AWT Toolkit (X event loop) thread context - * and thus inside the AWT Lock. - */ - // NOTE: This method may be called by privileged threads. - // This functionality is implemented in a package-private method - // to insure that it cannot be overridden by client subclasses. - // DO NOT INVOKE CLIENT CODE ON THIS THREAD! - void flushText() { - String flush = (committedText != null ? committedText : ""); - if (composedText != null) { - flush += composedText.toString(); + /* Some IMs need forced Text clear */ + void clearComposedText(long when) { + composedText = null; + postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, + null, 0, null, null, + when); + if (committedText != null && committedText.length() > 0) { + dispatchCommittedText(committedText, when); } + committedText = null; + rawFeedbacks = null; + } - if (!flush.equals("")) { - AttributedString attrstr = new AttributedString(flush); - postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, - attrstr.getIterator(), - flush.length(), - null, - null, - EventQueue.getMostRecentEventTime()); - composedText = null; - committedText = null; + void clearComposedText() { + if (EventQueue.isDispatchThread()) { + clearComposedText(EventQueue.getMostRecentEventTime()); } } @@ -774,49 +444,17 @@ protected synchronized void disposeImpl() { disposeXIC(); awtLock(); - composedText = null; - committedText = null; - rawFeedbacks = null; - awtUnlock(); + try { + clearComposedText(); + } finally { + // Put awtUnlock into finally block in case an exception is thrown in clearComposedText. + awtUnlock(); + } awtFocussedComponent = null; lastXICFocussedComponent = null; - } - - /** - * Frees all X Window resources associated with this object. - * - * @see java.awt.im.spi.InputMethod#dispose - */ - public final void dispose() { - boolean call_disposeImpl = false; - - if (!disposed) { - synchronized (this) { - if (!disposed) { - disposed = call_disposeImpl = true; - } - } - } - - if (call_disposeImpl) { - disposeImpl(); - } - } - - /** - * Returns null. - * - * @see java.awt.im.spi.InputMethod#getControlObject - */ - public Object getControlObject() { - return null; - } - - /** - * @see java.awt.im.spi.InputMethod#removeNotify - */ - public synchronized void removeNotify() { - dispose(); + needResetXIC = false; + savedCompositionState = false; + compositionEnableSupported = true; } /** @@ -831,267 +469,22 @@ Use package private mthod 'resetCompositionState' if you want the exception to be caught. */ + boolean pre, post; + pre=getCompositionState(); + if (setCompositionEnabledNative(enable)) { savedCompositionState = enable; } - } - /** - * @see java.awt.im.spi.InputMethod#isCompositionEnabled - */ - public boolean isCompositionEnabled() { - /* isCompositionEnabledNative may throw UnsupportedOperationException. - Don't try to catch it since this method may be called by clients. - Use package private method 'getCompositionState' if you want the - exception to be caught. - */ - return isCompositionEnabledNative(); - } - - /** - * Ends any input composition that may currently be going on in this - * context. Depending on the platform and possibly user preferences, - * this may commit or delete uncommitted text. Any changes to the text - * are communicated to the active component using an input method event. - * - *

- * A text editing component may call this in a variety of situations, - * for example, when the user moves the insertion point within the text - * (but outside the composed text), or when the component's text is - * saved to a file or copied to the clipboard. - * - */ - public void endComposition() { - if (disposed) { - return; - } - - /* Before calling resetXIC, record the current composition mode - so that it can be restored later. */ - savedCompositionState = getCompositionState(); - boolean active = haveActiveClient(); - if (active && composedText == null && committedText == null){ - needResetXIC = true; - needResetXICClient = new WeakReference<>(getClientComponent()); - return; - } - - String text = resetXIC(); - /* needResetXIC is only set to true for active client. So passive - client should not reset the flag to false. */ - if (active) { - needResetXIC = false; - } - - // Remove any existing composed text by posting an InputMethodEvent - // with null composed text. It would be desirable to wait for a - // dispatchComposedText call from X input method engine, but some - // input method does not conform to the XIM specification and does - // not call the preedit callback to erase preedit text on calling - // XmbResetIC. To work around this problem, do it here by ourselves. - awtLock(); - composedText = null; - postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, - null, - 0, - null, - null); - - if (text != null && text.length() > 0) { - dispatchCommittedText(text); - } - awtUnlock(); - - // Restore the preedit state if it was enabled - if (savedCompositionState) { - resetCompositionState(); + post=getCompositionState(); + if (pre != post && post == enable){ + if (enable == false) flushText(); + if (awtFocussedComponent != null && isActive){ + setXICFocus(getPeer(awtFocussedComponent), + true, haveActiveClient()); + } } } - /** - * Returns a string with information about the current input method server, or null. - * On both Linux & SunOS, the value of environment variable XMODIFIERS is - * returned if set. Otherwise, on SunOS, $HOME/.dtprofile will be parsed - * to find out the language service engine (atok or wnn) since there is - * no API in Xlib which returns the information of native - * IM server or language service and we want to try our best to return as much - * information as possible. - * - * Note: This method could return null on Linux if XMODIFIERS is not set properly or - * if any IOException is thrown. - * See man page of XSetLocaleModifiers(3X11) for the usgae of XMODIFIERS, - * atok12setup(1) and wnn6setup(1) for the information written to - * $HOME/.dtprofile when you run these two commands. - * - */ - public String getNativeInputMethodInfo() { - String xmodifiers = System.getenv("XMODIFIERS"); - String imInfo = null; - - // If XMODIFIERS is set, return the value - if (xmodifiers != null) { - int imIndex = xmodifiers.indexOf("@im="); - if (imIndex != -1) { - imInfo = xmodifiers.substring(imIndex + 4); - } - } else if (System.getProperty("os.name").startsWith("SunOS")) { - File dtprofile = new File(System.getProperty("user.home") + - "/.dtprofile"); - String languageEngineInfo = null; - try { - BufferedReader br = new BufferedReader(new FileReader(dtprofile)); - String line = null; - - while ( languageEngineInfo == null && (line = br.readLine()) != null) { - if (line.contains("atok") || line.contains("wnn")) { - StringTokenizer tokens = new StringTokenizer(line); - while (tokens.hasMoreTokens()) { - String token = tokens.nextToken(); - if (Pattern.matches("atok.*setup", token) || - Pattern.matches("wnn.*setup", token)){ - languageEngineInfo = token.substring(0, token.indexOf("setup")); - break; - } - } - } - } - - br.close(); - } catch(IOException ioex) { - // Since this method is provided for internal testing only, - // we dump the stack trace for the ease of debugging. - ioex.printStackTrace(); - } - - imInfo = "htt " + languageEngineInfo; - } - - return imInfo; - } - - - /** - * Performs mapping from an XIM visible feedback value to Java IM highlight. - * @return Java input method highlight - */ - private InputMethodHighlight convertVisualFeedbackToHighlight(int feedback) { - InputMethodHighlight highlight; - - switch (feedback) { - case XIMUnderline: - highlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT; - break; - case XIMReverse: - highlight = InputMethodHighlight.SELECTED_CONVERTED_TEXT_HIGHLIGHT; - break; - case XIMHighlight: - highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT; - break; - case XIMPrimary: - highlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT; - break; - case XIMSecondary: - highlight = InputMethodHighlight.SELECTED_CONVERTED_TEXT_HIGHLIGHT; - break; - case XIMTertiary: - highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT; - break; - default: - highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT; - break; - } - return highlight; - } - - // initial capacity size for string buffer, etc. - private static final int INITIAL_SIZE = 64; - - /** - * IntBuffer is an inner class that manipulates an int array and - * provides UNIX file io stream-like programming interfaces to - * access it. (An alternative would be to use ArrayList which may - * be too expensive for the work.) - */ - private final class IntBuffer { - private int[] intArray; - private int size; - private int index; - - IntBuffer(int initialCapacity) { - intArray = new int[initialCapacity]; - size = 0; - index = 0; - } - - void insert(int offset, int[] values) { - int newSize = size + values.length; - if (intArray.length < newSize) { - int[] newIntArray = new int[newSize * 2]; - System.arraycopy(intArray, 0, newIntArray, 0, size); - intArray = newIntArray; - } - System.arraycopy(intArray, offset, intArray, offset+values.length, - size - offset); - System.arraycopy(values, 0, intArray, offset, values.length); - size += values.length; - if (index > offset) - index = offset; - } - - void remove(int offset, int length) { - if (offset + length != size) - System.arraycopy(intArray, offset+length, intArray, offset, - size - offset - length); - size -= length; - if (index > offset) - index = offset; - } - - void replace(int offset, int[] values) { - System.arraycopy(values, 0, intArray, offset, values.length); - } - - void removeAll() { - size = 0; - index = 0; - } - - void rewind() { - index = 0; - } - - int getNext() { - if (index == size) - return -1; - return intArray[index++]; - } - - void unget() { - if (index != 0) - index--; - } - - int getOffset() { - return index; - } - - public String toString() { - StringBuffer s = new StringBuffer(); - for (int i = 0; i < size;) { - s.append(intArray[i++]); - if (i < size) - s.append(","); - } - return s.toString(); - } - } - - /* - * Native methods - */ - private native String resetXIC(); - private native void disposeXIC(); - private native boolean setCompositionEnabledNative(boolean enable); - private native boolean isCompositionEnabledNative(); - private native void turnoffStatusWindow(); + private native void setStatusAreaVisible(boolean value, long data); } diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c b/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c copy from src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c copy to src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c +++ b/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -23,22 +23,27 @@ * questions. */ +#include "awt.h" +#include "awt_p.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + #ifdef HEADLESS #error This file should not be included in headless library #endif -#include -#include -#include -#include -#include - -#include "awt.h" -#include "awt_p.h" - -#include -#include - #define THROW_OUT_OF_MEMORY_ERROR() \ JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL) @@ -46,34 +51,37 @@ jfieldID pData; } x11InputMethodIDs; -static void PreeditStartCallback(XIC, XPointer, XPointer); +static int PreeditStartCallback(XIC, XPointer, XPointer); static void PreeditDoneCallback(XIC, XPointer, XPointer); static void PreeditDrawCallback(XIC, XPointer, XIMPreeditDrawCallbackStruct *); static void PreeditCaretCallback(XIC, XPointer, XIMPreeditCaretCallbackStruct *); -#if defined(__linux__) || defined(MACOSX) static void StatusStartCallback(XIC, XPointer, XPointer); static void StatusDoneCallback(XIC, XPointer, XPointer); static void StatusDrawCallback(XIC, XPointer, XIMStatusDrawCallbackStruct *); -#endif #define ROOT_WINDOW_STYLES (XIMPreeditNothing | XIMStatusNothing) #define NO_STYLES (XIMPreeditNone | XIMStatusNone) +/* added style to allow for in-place composition, such as "dead" keys for accents */ +#define IN_PLACE_STYLES (XIMPreeditNothing | XIMStatusNone) #define PreeditStartIndex 0 #define PreeditDoneIndex 1 #define PreeditDrawIndex 2 #define PreeditCaretIndex 3 -#if defined(__linux__) || defined(MACOSX) #define StatusStartIndex 4 #define StatusDoneIndex 5 #define StatusDrawIndex 6 #define NCALLBACKS 7 -#else -#define NCALLBACKS 4 -#endif + +#define STATUS_BORDER 2 /* Status Border width */ +#define CARET_OFFSET 1 /* Offset of caret position (pixel) */ +#define BORDER_MARGIN 3 /* BORDER MARGIN width */ +#define STATUS_MARGIN 7 /* Margin between the status window and its parent window */ +#define PREEDIT_ATTR_MASK (XIMReverse|XIMUnderline) + /* Preedit attribute which host adapter can handle */ /* * Callback function pointers: the order has to match the *Index @@ -84,19 +92,17 @@ (XIMProc)PreeditDoneCallback, (XIMProc)PreeditDrawCallback, (XIMProc)PreeditCaretCallback, -#if defined(__linux__) || defined(MACOSX) (XIMProc)StatusStartCallback, (XIMProc)StatusDoneCallback, (XIMProc)StatusDrawCallback, -#endif }; -#if defined(__linux__) || defined(MACOSX) #define MAX_STATUS_LEN 100 typedef struct { Window w; /*status window id */ Window root; /*the root window id */ Window parent; /*parent shell window */ + Window grandParent; /*window has WM frame */ int x, y; /*parent's upperleft position */ int width, height; /*parent's width, height */ GC lightGC; /*gc for light border */ @@ -106,12 +112,18 @@ int statusW, statusH; /*status window's w, h */ int rootW, rootH; /*root window's w, h */ int bWidth; /*border width */ - char status[MAX_STATUS_LEN]; /*status text */ + wchar_t status[MAX_STATUS_LEN + 1]; /*status text */ XFontSet fontset; /*fontset for drawing */ int off_x, off_y; Bool on; /*if the status window on*/ + int fOff; /* font base line(in pixel) from top */ + int fBot; /* font bottom line(in pixel) from top */ + int peTextW; /* Composition text width in pixel */ + wchar_t* peText; /* Composed string (wide char.) */ + XIMFeedback* peAttr; /* Composed text attribute */ + int peCaret; /* Caret position in number of character */ + Bool status_ready; /* Not draw Status at XCreateIC */ } StatusWindow; -#endif /* * X11InputMethodData keeps per X11InputMethod instance information. A pointer @@ -124,33 +136,12 @@ XIMCallback *callbacks; /* callback parameters */ jobject x11inputmethod; /* global ref to X11InputMethod instance */ /* associated with the XIC */ -#if defined(__linux__) || defined(MACOSX) StatusWindow *statusWindow; /* our own status window */ -#endif - char *lookup_buf; /* buffer used for XmbLookupString */ - int lookup_buf_len; /* lookup buffer size in bytes */ + Bool passiveStatusWindow;/* Passive Client uses StatusWindow */ + Bool isActiveClient; /* True:clinet is active */ + Bool forceReset; /* True: call resetXIC before UnsetICFocus */ } X11InputMethodData; -/* - * When XIC is created, a global reference is created for - * sun.awt.X11InputMethod object so that it could be used by the XIM callback - * functions. This could be a dangerous thing to do when the original - * X11InputMethod object is garbage collected and as a result, - * destroyX11InputMethodData is called to delete the global reference. - * If any XIM callback function still holds and uses the "already deleted" - * global reference, disaster is going to happen. So we have to maintain - * a list for these global references which is consulted first when the - * callback functions or any function tries to use "currentX11InputMethodObject" - * which always refers to the global reference try to use it. - * - */ -typedef struct _X11InputMethodGRefNode { - jobject inputMethodGRef; - struct _X11InputMethodGRefNode* next; -} X11InputMethodGRefNode; - -X11InputMethodGRefNode *x11InputMethodGRefListHead = NULL; - /* reference to the current X11InputMethod instance, it is always point to the global reference to the X11InputMethodObject since it could be referenced by different threads. */ @@ -165,25 +156,41 @@ #define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2) -static void DestroyXIMCallback(XIM, XPointer, XPointer); -static void OpenXIMCallback(Display *, XPointer, XPointer); -/* Solaris XIM Extention */ -#define XNCommitStringCallback "commitStringCallback" -static void CommitStringCallback(XIC, XPointer, XPointer); - static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject); static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *); static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *); static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *); -#ifdef __solaris__ -/* Prototype for this function is missing in Solaris X11R6 Xlib.h */ +/* Prototype for this function is missing in AIX Xlib.h */ extern char *XSetIMValues( #if NeedVarargsPrototypes XIM /* im */, ... #endif ); -#endif + +static int st_wcslen(wchar_t *string); +static Bool isPreeditStateActive(XIC ic); +static void * buf_insert(void * src, void * insert, int size, + int src_len, int ins_len, int offset); +static void * handle_buffer(void * source, void * insert, + int size, int src_len, int ins_len, + int del_len, int offset); +static void preedit_draw_passive(X11InputMethodData *pX11IMData, + XIMPreeditDrawCallbackStruct *pre_draw); +static void resetPassivePreeditText(StatusWindow *statusWindow); +static void draw_caret(StatusWindow *statusWindow, GC gc, int pos); +static int get_next_attr(int len, unsigned long *attr); +static void draw_preedit(StatusWindow *statusWindow); +static void align_status(StatusWindow *statusWindow); +static void shrink_status(StatusWindow *statusWindow); +static GC create_gc(Window win, Bool isReverse); +static XFontSet create_fontset(void); +static Bool is_text_available(XIMText * text); +static Bool isNativeIm(); +static Window getGrandParent(Window parent); +static void moveStatusWindow(StatusWindow *statusWindow); +static void arrange_window_stack(StatusWindow* statusWindow); +static Window get_current_focus(XIC ic); /* * This function is stolen from /src/solaris/hpi/src/system_md.c @@ -229,87 +236,6 @@ return mbs; } -/* - * Returns True if the global reference is still in the list, - * otherwise False. - */ -static Bool isX11InputMethodGRefInList(jobject imGRef) { - X11InputMethodGRefNode *pX11InputMethodGRef = x11InputMethodGRefListHead; - - if (imGRef == NULL) { - return False; - } - - while (pX11InputMethodGRef != NULL) { - if (pX11InputMethodGRef->inputMethodGRef == imGRef) { - return True; - } - pX11InputMethodGRef = pX11InputMethodGRef->next; - } - - return False; -} - -/* - * Add the new created global reference to the list. - */ -static void addToX11InputMethodGRefList(jobject newX11InputMethodGRef) { - X11InputMethodGRefNode *newNode = NULL; - - if (newX11InputMethodGRef == NULL || - isX11InputMethodGRefInList(newX11InputMethodGRef)) { - return; - } - - newNode = (X11InputMethodGRefNode *)malloc(sizeof(X11InputMethodGRefNode)); - - if (newNode == NULL) { - return; - } else { - newNode->inputMethodGRef = newX11InputMethodGRef; - newNode->next = x11InputMethodGRefListHead; - x11InputMethodGRefListHead = newNode; - } -} - -/* - * Remove the global reference from the list. - */ -static void removeX11InputMethodGRefFromList(jobject x11InputMethodGRef) { - X11InputMethodGRefNode *pX11InputMethodGRef = NULL; - X11InputMethodGRefNode *cX11InputMethodGRef = x11InputMethodGRefListHead; - - if (x11InputMethodGRefListHead == NULL || - x11InputMethodGRef == NULL) { - return; - } - - /* cX11InputMethodGRef always refers to the current node while - pX11InputMethodGRef refers to the previous node. - */ - while (cX11InputMethodGRef != NULL) { - if (cX11InputMethodGRef->inputMethodGRef == x11InputMethodGRef) { - break; - } - pX11InputMethodGRef = cX11InputMethodGRef; - cX11InputMethodGRef = cX11InputMethodGRef->next; - } - - if (cX11InputMethodGRef == NULL) { - return; /* Not found. */ - } - - if (cX11InputMethodGRef == x11InputMethodGRefListHead) { - x11InputMethodGRefListHead = x11InputMethodGRefListHead->next; - } else { - pX11InputMethodGRef->next = cX11InputMethodGRef->next; - } - free(cX11InputMethodGRef); - - return; -} - - static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) { X11InputMethodData *pX11IMData = (X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData); @@ -372,7 +298,6 @@ static void freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData) { -#if defined(__linux__) || defined(MACOSX) if (pX11IMData->statusWindow != NULL){ StatusWindow *sw = pX11IMData->statusWindow; XFreeGC(awt_display, sw->lightGC); @@ -383,25 +308,24 @@ XFreeFontSet(awt_display, sw->fontset); } XDestroyWindow(awt_display, sw->w); + if (pX11IMData->statusWindow->peText){ + free((void *)pX11IMData->statusWindow->peText); + pX11IMData->statusWindow->peText = NULL; + } + if (pX11IMData->statusWindow->peAttr){ + free((void *)pX11IMData->statusWindow->peAttr); + pX11IMData->statusWindow->peAttr = NULL; + } free((void*)sw); } -#endif if (pX11IMData->callbacks) free((void *)pX11IMData->callbacks); if (env) { - /* Remove the global reference from the list, so that - the callback function or whoever refers to it could know. - */ - removeX11InputMethodGRefFromList(pX11IMData->x11inputmethod); (*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod); } - if (pX11IMData->lookup_buf) { - free((void *)pX11IMData->lookup_buf); - } - free((void *)pX11IMData); } @@ -455,6 +379,9 @@ { JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; + int buf_len = INITIAL_LOOKUP_BUF_SIZE; + char mbbuf[INITIAL_LOOKUP_BUF_SIZE]; + char *buf; KeySym keysym = NoSymbol; Status status; int mblen; @@ -467,59 +394,34 @@ printf("lookupString: entering...\n"); */ - if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) { - currentX11InputMethodInstance = NULL; - return False; - } - pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance); if (pX11IMData == NULL) { -#if defined(__linux__) || defined(MACOSX) return False; -#else - return result; -#endif } if ((ic = pX11IMData->current_ic) == (XIC)0){ -#if defined(__linux__) || defined(MACOSX) return False; -#else - return result; -#endif } - /* allocate the lookup buffer at the first invocation */ - if (pX11IMData->lookup_buf_len == 0) { - pX11IMData->lookup_buf = (char *)malloc(INITIAL_LOOKUP_BUF_SIZE); - if (pX11IMData->lookup_buf == NULL) { - THROW_OUT_OF_MEMORY_ERROR(); - return result; - } - pX11IMData->lookup_buf_len = INITIAL_LOOKUP_BUF_SIZE; - } - - mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf, - pX11IMData->lookup_buf_len - 1, &keysym, &status); + buf = mbbuf; + mblen = XmbLookupString(ic, event, buf, + buf_len - 1, &keysym, &status); /* * In case of overflow, a buffer is allocated and it retries * XmbLookupString(). */ if (status == XBufferOverflow) { - free((void *)pX11IMData->lookup_buf); - pX11IMData->lookup_buf_len = 0; - pX11IMData->lookup_buf = (char *)malloc(mblen + 1); - if (pX11IMData->lookup_buf == NULL) { + buf_len = mblen + 1; + buf = (char *)malloc(buf_len); + if (buf == NULL) { THROW_OUT_OF_MEMORY_ERROR(); return result; } - pX11IMData->lookup_buf_len = mblen + 1; - mblen = XmbLookupString(ic, event, pX11IMData->lookup_buf, - pX11IMData->lookup_buf_len - 1, &keysym, &status); + mblen = XmbLookupString(ic, event, buf, buf_len, &keysym, &status); } - pX11IMData->lookup_buf[mblen] = 0; + buf[mblen] = 0; /* Get keysym without taking modifiers into account first to map * to AWT keyCode table. @@ -536,11 +438,11 @@ composing = False; /*FALLTHRU*/ case XLookupChars: - /* - printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n", - event->type, event->state, event->keycode, keysym); - */ - javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf); + /* + printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n", + event->type, event->state, event->keycode, keysym); + */ + javastr = JNU_NewStringPlatform(env, (const char *)buf); if (javastr != NULL) { JNU_CallMethodByName(env, NULL, currentX11InputMethodInstance, @@ -548,14 +450,18 @@ "(Ljava/lang/String;J)V", javastr, event->time); + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } } break; case XLookupKeySym: - /* - printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n", - event->type, event->state, event->keycode, keysym); - */ + /* + printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n", + event->type, event->state, event->keycode, keysym); + */ if (keysym == XK_Multi_key) composing = True; if (! composing) { @@ -565,19 +471,20 @@ break; case XLookupNone: - /* - printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n", - event->type, event->state, event->keycode, keysym); - */ + /* + printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n", + event->type, event->state, event->keycode, keysym); + */ break; } + if (buf != mbbuf) { + free(buf); + } return result; } -#if defined(__linux__) || defined(MACOSX) -static StatusWindow *createStatusWindow( - Window parent) { +static StatusWindow *createStatusWindow(Window parent) { StatusWindow *statusWindow; XSetWindowAttributes attrib; unsigned long attribmask; @@ -600,10 +507,18 @@ AwtGraphicsConfigDataPtr adata; extern int awt_numScreens; /*hardcode the size right now, should get the size base on font*/ - int width=80, height=22; + int width=80, height=22; Window rootWindow; Window *ignoreWindowPtr; unsigned int ignoreUnit; + Window grandParent; + Window target; + XFontSet fontset; + + fontset = create_fontset(); + if (NULL == fontset) { + return NULL; + } XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth); @@ -621,7 +536,9 @@ light = adata->AwtColorMatch(195, 195, 195, adata); dim = adata->AwtColorMatch(128, 128, 128, adata); - XGetWindowAttributes(dpy, parent, &xwa); + grandParent = getGrandParent(parent); + target = (grandParent == 0) ? parent : grandParent; + XGetWindowAttributes(dpy, target, &xwa); bw = 2; /*xwa.border_width does not have the correct value*/ /*compare the size difference between parent container @@ -629,21 +546,40 @@ and title bar height (?)*/ XQueryTree( dpy, - parent, + target, &rootWindow, &containerWindow, &ignoreWindowPtr, &ignoreUnit); XGetWindowAttributes(dpy, containerWindow, &xxwa); - off_x = (xxwa.width - xwa.width) / 2; - off_y = xxwa.height - xwa.height - off_x; /*it's magic:-) */ + XTranslateCoordinates(dpy, + target, xwa.root, + 0, 0, + &x, &y, &child); + + if (containerWindow == rootWindow) { + off_x = 0; off_y = STATUS_MARGIN; + } else { + XGetWindowAttributes(dpy, containerWindow, &xxwa); + off_x = (xxwa.width - xwa.width) / 2; + /* off_y = xxwa.height - xwa.height - off_x;*/ /*it's magic:-) */ + { + int cx, cy; + XTranslateCoordinates(dpy, + containerWindow, xxwa.root, + 0, 0, + &cx, &cy, + &child); + off_y = (xxwa.height + cy) - (xwa.height + y); + } + } /*get the size of root window*/ XGetWindowAttributes(dpy, rootWindow, &xxwa); XTranslateCoordinates(dpy, - parent, xwa.root, + target, xwa.root, xwa.x, xwa.y, &x, &y, &child); @@ -652,13 +588,21 @@ if (xx < 0 ){ xx = 0; } - if (xx + width > xxwa.width){ + if (xx + width > xxwa.width) { xx = xxwa.width - width; } - if (yy + height > xxwa.height){ + if (yy + height > xxwa.height) { yy = xxwa.height - height; } + if ((DefaultVisual(dpy,screen))->class != adata->awt_visInfo.visual->class && + adata->awt_visInfo.visual->class == TrueColor) { + attrib.colormap = XCreateColormap(dpy, xwa.root, + adata->awt_visInfo.visual, AllocNone ); + attrib.border_pixel = BlackPixel(dpy, screen) ; + attribmask |= CWColormap | CWBorderPixel; + } + status = XCreateWindow(dpy, xwa.root, xx, yy, @@ -671,21 +615,23 @@ XSelectInput(dpy, status, ExposureMask | StructureNotifyMask | EnterWindowMask | LeaveWindowMask | VisibilityChangeMask); + if (grandParent != 0){ + long mask; + XGetWindowAttributes(dpy, grandParent, &xwa); + mask = xwa.your_event_mask | StructureNotifyMask | + VisibilityChangeMask | PropertyChangeMask; + XSelectInput(dpy, grandParent,mask); + } + statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow)); if (statusWindow == NULL){ THROW_OUT_OF_MEMORY_ERROR(); return NULL; } statusWindow->w = status; - //12-point font - statusWindow->fontset = XCreateFontSet(dpy, - "-*-*-medium-r-normal-*-*-120-*-*-*-*", - &mclr, &mccr, &dsr); - /* In case we didn't find the font set, release the list of missing characters */ - if (mccr > 0) { - XFreeStringList(mclr); - } + statusWindow->fontset = fontset; statusWindow->parent = parent; + statusWindow->grandParent = grandParent; statusWindow->on = False; statusWindow->x = x; statusWindow->y = y; @@ -696,16 +642,19 @@ statusWindow->bWidth = bw; statusWindow->statusH = height; statusWindow->statusW = width; + statusWindow->peTextW = 0; statusWindow->rootH = xxwa.height; statusWindow->rootW = xxwa.width; statusWindow->lightGC = XCreateGC(dpy, status, valuemask, &values); XSetForeground(dpy, statusWindow->lightGC, light); statusWindow->dimGC = XCreateGC(dpy, status, valuemask, &values); XSetForeground(dpy, statusWindow->dimGC, dim); - statusWindow->fgGC = XCreateGC(dpy, status, valuemask, &values); + statusWindow->fgGC = create_gc(status, FALSE); XSetForeground(dpy, statusWindow->fgGC, fg); - statusWindow->bgGC = XCreateGC(dpy, status, valuemask, &values); + statusWindow->bgGC = create_gc(status, TRUE); XSetForeground(dpy, statusWindow->bgGC, bg); + statusWindow->status_ready = False; + wcscpy(statusWindow->status, L""); return statusWindow; } @@ -718,50 +667,36 @@ int x, y; StatusWindow *statusWindow = NULL; - if (NULL == currentX11InputMethodInstance || - NULL == pX11IMData || + if (NULL == pX11IMData || NULL == (statusWindow = pX11IMData->statusWindow)){ return; } - if (ON == False){ + if (ON == False) { XUnmapWindow(dpy, statusWindow->w); - statusWindow->on = False; + return; + } + if (NULL == currentX11InputMethodInstance){ return; } - parent = JNU_CallMethodByName(GetJNIEnv(), NULL, pX11IMData->x11inputmethod, - "getCurrentParentWindow", - "()J").j; - if (statusWindow->parent != parent){ + { + JNIEnv *env = GetJNIEnv(); + parent = JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, + "getCurrentParentWindow", + "()J").j; + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + } + if (statusWindow->parent != parent) { statusWindow->parent = parent; } - XGetWindowAttributes(dpy, parent, &xwa); - XTranslateCoordinates(dpy, - parent, xwa.root, - xwa.x, xwa.y, - &x, &y, - &child); - if (statusWindow->x != x - || statusWindow->y != y - || statusWindow->height != xwa.height){ - statusWindow->x = x; - statusWindow->y = y; - statusWindow->height = xwa.height; - x = statusWindow->x - statusWindow->off_x; - y = statusWindow->y + statusWindow->height - statusWindow->off_y; - if (x < 0 ){ - x = 0; - } - if (x + statusWindow->statusW > statusWindow->rootW){ - x = statusWindow->rootW - statusWindow->statusW; - } - if (y + statusWindow->statusH > statusWindow->rootH){ - y = statusWindow->rootH - statusWindow->statusH; - } - XMoveWindow(dpy, statusWindow->w, x, y); + if (st_wcslen(statusWindow->status) > 0 || + (statusWindow->peText != NULL && st_wcslen(statusWindow->peText) > 0 )) { + moveStatusWindow(statusWindow); + XMapRaised(dpy, statusWindow->w); } - statusWindow->on = True; - XMapWindow(dpy, statusWindow->w); } void paintStatusWindow(StatusWindow *statusWindow){ @@ -774,121 +709,118 @@ int width = statusWindow->statusW; int height = statusWindow->statusH; int bwidth = statusWindow->bWidth; - XFillRectangle(dpy, win, bggc, 0, 0, width, height); - /* draw border */ - XDrawLine(dpy, win, fggc, 0, 0, width, 0); - XDrawLine(dpy, win, fggc, 0, height-1, width-1, height-1); - XDrawLine(dpy, win, fggc, 0, 0, 0, height-1); - XDrawLine(dpy, win, fggc, width-1, 0, width-1, height-1); + int len; + XRectangle logical, ink; - XDrawLine(dpy, win, lightgc, 1, 1, width-bwidth, 1); - XDrawLine(dpy, win, lightgc, 1, 1, 1, height-2); - XDrawLine(dpy, win, lightgc, 1, height-2, width-bwidth, height-2); - XDrawLine(dpy, win, lightgc, width-bwidth-1, 1, width-bwidth-1, height-2); + if (NULL == statusWindow) return; + if ((len = st_wcslen(statusWindow->status)) == 0) { + return; + } + XwcTextExtents(statusWindow->fontset, statusWindow->status, + len, &ink, &logical); + width = logical.width; + height = logical.height; - XDrawLine(dpy, win, dimgc, 2, 2, 2, height-3); - XDrawLine(dpy, win, dimgc, 2, height-3, width-bwidth-1, height-3); - XDrawLine(dpy, win, dimgc, 2, 2, width-bwidth-2, 2); - XDrawLine(dpy, win, dimgc, width-bwidth, 2, width-bwidth, height-3); - if (statusWindow->fontset){ - XmbDrawString(dpy, win, statusWindow->fontset, fggc, - bwidth + 2, height - bwidth - 4, + XFillRectangle(dpy, win, bggc, 0, 0, width+2, height+2); + + XDrawLine(dpy, win, fggc, 0, 0, width+2, 0); + XDrawLine(dpy, win, fggc, 0, height+2, width+2, height+2); + XDrawLine(dpy, win, fggc, 0, 0, 0, height+2); + XDrawLine(dpy, win, fggc, width+2, 0, width+2, height+2); + + if (statusWindow->fontset) { + XwcDrawString(dpy, win, statusWindow->fontset, fggc, + -logical.x + 1, -logical.y + 1, statusWindow->status, - strlen(statusWindow->status)); - } - else{ + st_wcslen(statusWindow->status)); + } else { /*too bad we failed to create a fontset for this locale*/ XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4, "[InputMethod ON]", strlen("[InputMethod ON]")); } } -void statusWindowEventHandler(XEvent event){ +Bool statusWindowEventHandler(XEvent event) { JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; StatusWindow *statusWindow; - if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) { - currentX11InputMethodInstance = NULL; - return; - } - - if (NULL == currentX11InputMethodInstance - || NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance)) - || NULL == (statusWindow = pX11IMData->statusWindow) - || statusWindow->w != event.xany.window){ - return; + if (NULL == currentX11InputMethodInstance || + NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance)) || + NULL == (statusWindow = pX11IMData->statusWindow)) + { + return False; } - switch (event.type){ - case Expose: - paintStatusWindow(statusWindow); - break; - case MapNotify: - case ConfigureNotify: - { - /*need to reset the stackMode...*/ - XWindowChanges xwc; - int value_make = CWStackMode; - xwc.stack_mode = TopIf; - XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); + if (statusWindow->w == event.xany.window) { + switch (event.type) { + case Expose: + paintStatusWindow(statusWindow); + if (statusWindow->peText) + draw_preedit(statusWindow); + arrange_window_stack(statusWindow); + break; + case ConfigureNotify: + case VisibilityNotify: + arrange_window_stack(statusWindow); + break; + /* + case UnmapNotify: + case VisibilityNotify: + break; + */ + default: + break; } - break; - /* - case UnmapNotify: - case VisibilityNotify: - break; - */ - default: - break; - } + return True; + } else if ((statusWindow->parent == event.xany.window) || + (statusWindow->grandParent && statusWindow->grandParent == event.xany.window)) { + switch (event.type) { + case MapNotify: + if (statusWindow->on) { + onoffStatusWindow(pX11IMData, statusWindow->parent, True); + } + break; + case UnmapNotify: + onoffStatusWindow(pX11IMData, 0, False); + break; + case VisibilityNotify: + if (statusWindow->on) { + arrange_window_stack(statusWindow); + } + break; + case ConfigureNotify: + if (statusWindow->grandParent && statusWindow->on) { + moveStatusWindow(statusWindow); + } + case PropertyNotify: + if (statusWindow->on) { + arrange_window_stack(statusWindow); + } + break; + default: + break; + } + } + return False; } -static void adjustStatusWindow(Window shell){ +static void adjustStatusWindow(Window shell) { JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; StatusWindow *statusWindow; if (NULL == currentX11InputMethodInstance - || !isX11InputMethodGRefInList(currentX11InputMethodInstance) || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance)) || NULL == (statusWindow = pX11IMData->statusWindow) - || !statusWindow->on) { + || !statusWindow->on) + { return; } - { - XWindowAttributes xwa; - int x, y; - Window child; - XGetWindowAttributes(dpy, shell, &xwa); - XTranslateCoordinates(dpy, - shell, xwa.root, - xwa.x, xwa.y, - &x, &y, - &child); - if (statusWindow->x != x - || statusWindow->y != y - || statusWindow->height != xwa.height){ - statusWindow->x = x; - statusWindow->y = y; - statusWindow->height = xwa.height; - x = statusWindow->x - statusWindow->off_x; - y = statusWindow->y + statusWindow->height - statusWindow->off_y; - if (x < 0 ){ - x = 0; - } - if (x + statusWindow->statusW > statusWindow->rootW){ - x = statusWindow->rootW - statusWindow->statusW; - } - if (y + statusWindow->statusH > statusWindow->rootH){ - y = statusWindow->rootH - statusWindow->statusH; - } - XMoveWindow(dpy, statusWindow->w, x, y); - } - } + moveStatusWindow(statusWindow); } -#endif /* __linux__ || MACOSX */ + /* * Creates two XICs, one for active clients and the other for passive * clients. All information on those XICs are stored in the @@ -909,6 +841,7 @@ XVaNestedList preedit = NULL; XVaNestedList status = NULL; XIMStyle on_the_spot_styles = XIMPreeditCallbacks, + in_place_styles = 0, active_styles = 0, passive_styles = 0, no_styles = 0; @@ -916,6 +849,8 @@ unsigned short i; XIMStyles *im_styles; char *ret = NULL; + Bool passiveStatusWindow = False; + pX11IMData->statusWindow = NULL; if (X11im == NULL) { return False; @@ -924,6 +859,14 @@ return False; } + if (getenv("IBMJAVA_PASSIVE") == NULL) { + passiveStatusWindow = False; + } else { + passiveStatusWindow = True; + } + + if (isNativeIm()) { passiveStatusWindow = True; } + ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL); if (ret != NULL) { @@ -931,7 +874,6 @@ return FALSE ; } -#if defined(__linux__) || defined(MACOSX) on_the_spot_styles |= XIMStatusNothing; /*kinput does not support XIMPreeditCallbacks and XIMStatusArea @@ -944,14 +886,18 @@ break; } } -#else /*! __linux__ && !MACOSX */ - on_the_spot_styles |= XIMStatusNothing; -#endif /* __linux__ || MACOSX */ for (i = 0; i < im_styles->count_styles; i++) { - active_styles |= im_styles->supported_styles[i] & on_the_spot_styles; - passive_styles |= im_styles->supported_styles[i] & ROOT_WINDOW_STYLES; - no_styles |= im_styles->supported_styles[i] & NO_STYLES; + if (im_styles->supported_styles[i] == on_the_spot_styles) + active_styles = im_styles->supported_styles[i]; + if (im_styles->supported_styles[i] == ROOT_WINDOW_STYLES) + passive_styles = im_styles->supported_styles[i]; + if (im_styles->supported_styles[i] == IN_PLACE_STYLES) { + in_place_styles = im_styles->supported_styles[i]; + } + if (im_styles->supported_styles[i] == NO_STYLES) { + no_styles = im_styles->supported_styles[i]; + } } XFree(im_styles); @@ -960,27 +906,28 @@ if (passive_styles == ROOT_WINDOW_STYLES) active_styles = passive_styles; else { + if (in_place_styles == IN_PLACE_STYLES){ + active_styles = passive_styles = IN_PLACE_STYLES; + } else { if (no_styles == NO_STYLES) active_styles = passive_styles = NO_STYLES; else active_styles = passive_styles = 0; + } } } else { + if (!passiveStatusWindow) { if (passive_styles != ROOT_WINDOW_STYLES) { if (no_styles == NO_STYLES) active_styles = passive_styles = NO_STYLES; else active_styles = passive_styles = 0; } + } else + passive_styles = active_styles; } if (active_styles == on_the_spot_styles) { - pX11IMData->ic_passive = XCreateIC(X11im, - XNClientWindow, w, - XNFocusWindow, w, - XNInputStyle, passive_styles, - NULL); - callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS); if (callbacks == (XIMCallback *)NULL) return False; @@ -1000,9 +947,9 @@ NULL); if (preedit == (XVaNestedList)NULL) goto err; -#if defined(__linux__) || defined(MACOSX) /*always try XIMStatusCallbacks for active client...*/ { + if (on_the_spot_styles & XIMStatusCallbacks) { status = (XVaNestedList)XVaCreateNestedList(0, XNStatusStartCallback, &callbacks[StatusStartIndex], XNStatusDoneCallback, &callbacks[StatusDoneIndex], @@ -1011,6 +958,7 @@ if (status == NULL) goto err; + } pX11IMData->statusWindow = createStatusWindow(w); pX11IMData->ic_active = XCreateIC(X11im, XNClientWindow, w, @@ -1019,18 +967,21 @@ XNPreeditAttributes, preedit, XNStatusAttributes, status, NULL); + if (NULL != pX11IMData->statusWindow) { + pX11IMData->statusWindow->status_ready = True; + } XFree((void *)status); XFree((void *)preedit); } -#else /* !__linux__ && !MACOSX */ - pX11IMData->ic_active = XCreateIC(X11im, - XNClientWindow, w, - XNFocusWindow, w, - XNInputStyle, active_styles, - XNPreeditAttributes, preedit, - NULL); - XFree((void *)preedit); -#endif /* __linux__ || MACOSX */ + if (passiveStatusWindow) { + pX11IMData->ic_passive = pX11IMData->ic_active; + } else { + pX11IMData->ic_passive = XCreateIC(X11im, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, passive_styles, + NULL); + } } else { pX11IMData->ic_active = XCreateIC(X11im, XNClientWindow, w, @@ -1040,27 +991,29 @@ pX11IMData->ic_passive = pX11IMData->ic_active; } + // The code set the IC mode that the preedit state is not initialied + // at XmbResetIC. This attribute can be set at XCreateIC. I separately + // set the attribute to avoid the failure of XCreateIC at some platform + // which does not support the attribute. + if (pX11IMData->ic_active != 0) + XSetICValues(pX11IMData->ic_active, + XNResetState, XIMPreserveState, NULL); + if (pX11IMData->ic_passive != 0 && + pX11IMData->ic_active != pX11IMData->ic_passive) + XSetICValues(pX11IMData->ic_passive, + XNResetState, XIMInitialState, NULL); + + pX11IMData->passiveStatusWindow = passiveStatusWindow; + if (pX11IMData->ic_active == (XIC)0 || pX11IMData->ic_passive == (XIC)0) { return False; } - /* - * Use commit string call back if possible. - * This will ensure the correct order of preedit text and commit text - */ - { - XIMCallback cb; - cb.client_data = (XPointer) pX11IMData->x11inputmethod; - cb.callback = (XIMProc) CommitStringCallback; - XSetICValues (pX11IMData->ic_active, XNCommitStringCallback, &cb, NULL); - if (pX11IMData->ic_active != pX11IMData->ic_passive) { - XSetICValues (pX11IMData->ic_passive, XNCommitStringCallback, &cb, NULL); - } - } - - /* Add the global reference object to X11InputMethod to the list. */ - addToX11InputMethodGRefList(pX11IMData->x11inputmethod); + /* Unset focus to avoid unexpected IM on */ + setXICFocus(pX11IMData->ic_active, False); + if (pX11IMData->ic_active != pX11IMData->ic_passive) + setXICFocus(pX11IMData->ic_passive, False); return True; @@ -1071,18 +1024,46 @@ return False; } -static void +static int PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data) { - /*ARGSUSED*/ - /* printf("Native: PreeditCaretCallback\n"); */ + JNIEnv *env = GetJNIEnv(); + X11InputMethodData *pX11IMData; + + pX11IMData = getX11InputMethodData(env, (jobject)client_data); + if (pX11IMData == NULL || pX11IMData->statusWindow == NULL) { + return 0; + } + resetPassivePreeditText(pX11IMData->statusWindow); + + return -1; /* unlimited length for preedit text */ } static void PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data) { - /*ARGSUSED*/ - /* printf("Native: StatusStartCallback\n"); */ + JNIEnv *env = GetJNIEnv(); + X11InputMethodData *pX11IMData; + + pX11IMData = getX11InputMethodData(env, (jobject)client_data); + if (pX11IMData == NULL) { + return; + } + + if (!pX11IMData->isActiveClient) { + resetPassivePreeditText(pX11IMData->statusWindow); + shrink_status(pX11IMData->statusWindow); + } + else{ + JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, + "clearComposedText", + "(J)V", + awt_util_nowMillisUTC()); + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + } } /* @@ -1108,32 +1089,35 @@ return; } AWT_LOCK(); - if (!isX11InputMethodGRefInList((jobject)client_data)) { - if ((jobject)client_data == currentX11InputMethodInstance) { - currentX11InputMethodInstance = NULL; - } + if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) { goto finally; } - if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) { + + if (!pX11IMData->isActiveClient){ + if (ic == pX11IMData->ic_passive) { + preedit_draw_passive(pX11IMData, pre_draw); + } goto finally; } if ((text = pre_draw->text) != NULL) { - if (text->string.multi_byte != NULL) { - if (pre_draw->text->encoding_is_wchar == False) { - javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte); - if (javastr == NULL) { - goto finally; - } - } else { - char *mbstr = wcstombsdmp(text->string.wide_char, text->length); - if (mbstr == NULL) { - goto finally; - } - javastr = JNU_NewStringPlatform(env, (const char *)mbstr); - free(mbstr); - if (javastr == NULL) { - goto finally; + if (is_text_available(text)) { + if (text->string.multi_byte != NULL) { + if (pre_draw->text->encoding_is_wchar == False) { + javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte); + if (javastr == NULL) { + goto finally; + } + } else { + char *mbstr = wcstombsdmp(text->string.wide_char, text->length); + if (mbstr == NULL) { + goto finally; + } + javastr = JNU_NewStringPlatform(env, (const char *)mbstr); + free(mbstr); + if (javastr == NULL) { + goto finally; + } } } } @@ -1176,6 +1160,12 @@ (jint)pre_draw->chg_length, (jint)pre_draw->caret, awt_util_nowMillisUTC()); + + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + finally: AWT_UNLOCK(); return; @@ -1185,18 +1175,22 @@ PreeditCaretCallback(XIC ic, XPointer client_data, XIMPreeditCaretCallbackStruct *pre_caret) { - /*ARGSUSED*/ - /* printf("Native: PreeditCaretCallback\n"); */ + XIMPreeditDrawCallbackStruct pre_draw; + if (pre_caret != NULL && pre_caret->direction == XIMAbsolutePosition) { + pre_draw.caret = pre_caret->position; + pre_draw.chg_first = 0; + pre_draw.chg_length = 0; + pre_draw.text = NULL; + PreeditDrawCallback(ic, client_data, &pre_draw); + } } -#if defined(__linux__) || defined(MACOSX) static void StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data) { /*ARGSUSED*/ /*printf("StatusStartCallback:\n"); */ - } static void @@ -1204,52 +1198,71 @@ { /*ARGSUSED*/ /*printf("StatusDoneCallback:\n"); */ - } -static void -StatusDrawCallback(XIC ic, XPointer client_data, - XIMStatusDrawCallbackStruct *status_draw) +static void StatusDrawCallback + (XIC ic, XPointer client_data, XIMStatusDrawCallbackStruct *status_draw) { /*ARGSUSED*/ /*printf("StatusDrawCallback:\n"); */ JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; StatusWindow *statusWindow; + int value_make = CWX|CWWidth|CWHeight; + XRectangle logical, ink; + XWindowChanges xwc; + int len; AWT_LOCK(); - if (!isX11InputMethodGRefInList((jobject)client_data)) { - if ((jobject)client_data == currentX11InputMethodInstance) { - currentX11InputMethodInstance = NULL; - } - goto finally; - } - if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data)) || NULL == (statusWindow = pX11IMData->statusWindow)){ goto finally; } - currentX11InputMethodInstance = (jobject)client_data; - if (status_draw->type == XIMTextType){ + if (status_draw->type == XIMTextType) { XIMText *text = (status_draw->data).text; - if (text != NULL){ - if (text->string.multi_byte != NULL) { - strncpy(statusWindow->status, text->string.multi_byte, MAX_STATUS_LEN); - statusWindow->status[MAX_STATUS_LEN - 1] = '\0'; + if (text != NULL) { + if (text->string.multi_byte != NULL) { + if(!strcmp(text->string.multi_byte," ")){ + wcscpy(statusWindow->status, L""); + onoffStatusWindow(pX11IMData, 0, False); + goto finally; + } + mbstowcs(statusWindow->status, + (const char *)text->string.multi_byte, + (size_t)MAX_STATUS_LEN); + } else { + if (0 == st_wcslen(text->string.wide_char)){ + wcscpy(statusWindow->status, L""); + onoffStatusWindow(pX11IMData, 0, False); + goto finally; + } + wcsncpy(statusWindow->status, + text->string.wide_char, + MAX_STATUS_LEN); + } + XwcTextExtents(statusWindow->fontset, statusWindow->status, + st_wcslen(statusWindow->status), &ink, &logical); + statusWindow->statusW = logical.width + BORDER_MARGIN; + statusWindow->statusH = logical.height + BORDER_MARGIN; + xwc.x = statusWindow->x - statusWindow->off_x; + if (xwc.x < 0 ) xwc.x = 0; + xwc.width = statusWindow->statusW; + xwc.height = statusWindow->statusH; + if (xwc.x + xwc.width > statusWindow->rootW){ + xwc.x = statusWindow->rootW - xwc.width; + } + XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); + if (statusWindow->status_ready && statusWindow->on == True){ + onoffStatusWindow(pX11IMData, statusWindow->parent, True); } - else { - char *mbstr = wcstombsdmp(text->string.wide_char, text->length); - strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN); - statusWindow->status[MAX_STATUS_LEN - 1] = '\0'; - } - statusWindow->on = True; - onoffStatusWindow(pX11IMData, statusWindow->parent, True); - paintStatusWindow(statusWindow); + paintStatusWindow(statusWindow); + if (statusWindow->peText) + draw_preedit(statusWindow); } else { - statusWindow->on = False; + wcscpy(statusWindow->status, L""); /*just turnoff the status window paintStatusWindow(statusWindow); */ @@ -1260,93 +1273,628 @@ finally: AWT_UNLOCK(); } -#endif /* __linux__ || MACOSX */ -static void CommitStringCallback(XIC ic, XPointer client_data, XPointer call_data) { - JNIEnv *env = GetJNIEnv(); - XIMText * text = (XIMText *)call_data; - X11InputMethodData *pX11IMData = NULL; - jstring javastr; - - AWT_LOCK(); +/* return the string length without trailing spaces */ +/* work around code for Japanese AIXIM is implemented. */ +static int st_wcslen(wchar_t *string) +{ + int len = (int32_t)wcslen(string); + if (len == 0) + return 0; + for (len--;len >= 0; len--) { + if (!iswspace((wint_t) string[len])) break; + } + return len+1; +} - if (!isX11InputMethodGRefInList((jobject)client_data)) { - if ((jobject)client_data == currentX11InputMethodInstance) { - currentX11InputMethodInstance = NULL; - } - goto finally; +/* + * Checks whether given XIMText contains a string data. + */ +static Bool is_text_available(XIMText * text) +{ + if (text == NULL || text->length==0) + return False; + if (text->encoding_is_wchar) { + if(text->string.wide_char[0] == L'\0') + return False; + } else { + if (text->string.multi_byte[0] == '\0') + return False; } - - if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) { - goto finally; - } - currentX11InputMethodInstance = (jobject)client_data; + return True; +} - if (text->encoding_is_wchar == False) { - javastr = JNU_NewStringPlatform(env, (const char *)text->string.multi_byte); - } else { - char *mbstr = wcstombsdmp(text->string.wide_char, text->length); - if (mbstr == NULL) { - goto finally; - } - javastr = JNU_NewStringPlatform(env, (const char *)mbstr); - free(mbstr); - } +/* + * check if preedit status is active +*/ +static Bool isPreeditStateActive(XIC ic) +{ + XIMPreeditState state = XIMPreeditUnKnown; + XVaNestedList pr_atrb; + char* nosupportAttr; + + if (ic == NULL) return False; - if (javastr != NULL) { - JNU_CallMethodByName(env, NULL, - pX11IMData->x11inputmethod, - "dispatchCommittedText", - "(Ljava/lang/String;J)V", - javastr, - awt_util_nowMillisUTC()); + pr_atrb = XVaCreateNestedList(0,XNPreeditState,&state,NULL); + nosupportAttr=XGetICValues(ic,XNPreeditAttributes,pr_atrb,NULL); + XFree(pr_atrb); + if (nosupportAttr==NULL && state & XIMPreeditDisable) + return False; + else + return True; +} + +static void * buf_insert(void * src, void * insert, int size, + int src_len, int ins_len, int offset) +{ + char *temp; + + temp = realloc(src, size*(src_len+ins_len+1)); + if (temp == NULL) { + THROW_OUT_OF_MEMORY_ERROR(); + return src; } - finally: - AWT_UNLOCK(); + if (offset != src_len) { + memmove(&temp[size*(offset+ins_len)], + &((char *)temp)[size*offset], + size*(src_len-offset)); + } + memcpy(&temp[size*offset], insert, size*ins_len); + + return (void *)temp; } -static void OpenXIMCallback(Display *display, XPointer client_data, XPointer call_data) { - XIMCallback ximCallback; +static void * handle_buffer(void * source, void * insert, + int size,int src_len, int ins_len, + int del_len, int offset) +{ + void * temp = source; - X11im = XOpenIM(display, NULL, NULL, NULL); - if (X11im == NULL) { + if (del_len > 0) { + if (del_len == ins_len) { + memcpy(&((char *)source)[size*offset], insert, size*ins_len); + return source; + } + else if (src_len > offset+del_len) { + memmove(&((char *)source)[size*offset], + &((char *)source)[size*(offset+del_len)], + size*(src_len-offset-del_len)); + } + } + if (ins_len > 0) { + temp = buf_insert(source, insert, size, src_len, + ins_len, offset); + } + return temp; +} +/* + * Display the given preedit text to the root window which is ownd by + * myself. All of the character is converted to wide char. + * this function is used for the passive client. + */ +static void preedit_draw_passive(X11InputMethodData *pX11IMData, + XIMPreeditDrawCallbackStruct *pre_draw) +{ + XIMText *text; + wchar_t *tempbuf = NULL; + StatusWindow *statusWindow; + wchar_t *cur_text; + unsigned long *cur_attr; + int cur_len = 0; + int chg_len = pre_draw->chg_length; + int chg_1st = pre_draw->chg_first; + + if (NULL == (statusWindow = pX11IMData->statusWindow)) return; - } + cur_text = statusWindow->peText; + cur_attr = statusWindow->peAttr; + if (cur_text == NULL && pre_draw->text == NULL) + return; - ximCallback.callback = (XIMProc)DestroyXIMCallback; - ximCallback.client_data = NULL; - XSetIMValues(X11im, XNDestroyCallback, &ximCallback, NULL); -} + if (cur_text != NULL) + cur_len = (int32_t)wcslen(cur_text); + text = pre_draw->text; + if (text == NULL) { + /* delete only */ + if (cur_len > chg_1st+chg_len) { + memmove(&cur_text[chg_1st], + &cur_text[chg_1st+chg_len], + sizeof(wchar_t)*(cur_len-chg_1st-chg_len)); + memmove(&cur_attr[chg_1st], + &cur_attr[chg_1st+chg_len], + sizeof(long)*(cur_len-chg_1st-chg_len)); + } + if ((pre_draw->chg_length <= cur_len ) && (pre_draw->chg_length >0)) + cur_text[cur_len-pre_draw->chg_length] =L'\0'; + } else { + /* insert or replace */ + int ins_len = 0; + void * ins_text = NULL; -static void DestroyXIMCallback(XIM im, XPointer client_data, XPointer call_data) { - /* mark that XIM server was destroyed */ - X11im = NULL; - JNIEnv* env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); - /* free the old pX11IMData and set it to null. this also avoids crashing - * the jvm if the XIM server reappears */ - X11InputMethodData *pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance); + /* if invalid offset is specified, do nothing. */ + /* this fix is for aixim for eucTW */ + if (cur_len < chg_1st) + return; + if(is_text_available(text)) { + /* insert or replace the text */ + if (text->encoding_is_wchar == False) { + /* convert the text to wide chars. + allocate enough size buffer + */ + tempbuf = (wchar_t *)malloc(sizeof(wchar_t)*(text->length+1)); + if (tempbuf == NULL) { + THROW_OUT_OF_MEMORY_ERROR(); + return; + } + ins_len = (int32_t)mbstowcs(tempbuf, text->string.multi_byte, + text->length); + if (ins_len == -1) { + free(tempbuf); + return; + } + ins_text = (void *)tempbuf; + } + else { + ins_len = text->length; + ins_text = text->string.wide_char; + } + /* finish prepare the data to be inserted */ + + statusWindow->peText = + handle_buffer(cur_text, ins_text, sizeof(wchar_t), + cur_len, ins_len, chg_len, chg_1st); + statusWindow->peAttr = + handle_buffer(cur_attr, text->feedback, sizeof(long), + cur_len, ins_len, chg_len, chg_1st); + statusWindow->peText[cur_len-chg_len+ins_len] =L'\0'; + + if (tempbuf != NULL) + free(tempbuf); + } /* endof insert or replace text */ + else { + /* change attribute only */ + memcpy(&cur_attr[chg_1st], text->feedback, + sizeof(long)*text->length); + } + } + statusWindow->peCaret= pre_draw->caret; + draw_preedit(statusWindow); + if (statusWindow->on && wcslen(statusWindow->peText) > 0) + onoffStatusWindow(pX11IMData, statusWindow->parent, True); + else if (wcslen(statusWindow->status) == 0) + onoffStatusWindow(pX11IMData, 0, False); } /* - * Class: sun_awt_X11InputMethod - * Method: initIDs - * Signature: ()V + * reset predit test of passive mode */ +static void +resetPassivePreeditText(StatusWindow *statusWindow) +{ + if (NULL == statusWindow) return; + if(statusWindow->peText != NULL) { + free(statusWindow->peText); + statusWindow->peText = NULL; + } + if(statusWindow->peAttr != NULL) { + free(statusWindow->peAttr); + statusWindow->peAttr = NULL; + } + statusWindow->peCaret= 0; +} + +static void draw_caret(StatusWindow *statusWindow, GC gc, int pos) +{ + if (NULL == statusWindow) return; + XSetFunction(dpy, gc, GXinvert); + XDrawLine(dpy, statusWindow->w, + gc, pos, STATUS_BORDER/2, + pos, STATUS_BORDER/2+statusWindow->fOff); + XSetFunction(dpy, gc, GXcopy); +} + +static int get_next_attr(int len, unsigned long *attr) +{ + int count; + + for (count = 1; count < len; count++) { + if ((attr[count-1] & PREEDIT_ATTR_MASK) + != (attr[count] & PREEDIT_ATTR_MASK)) + break; + } + return count; +} + +static void draw_preedit(StatusWindow *statusWindow) +{ + unsigned long *attr; + int x_pos,x_caret; + unsigned int len; + int len_disp, pos; + wchar_t *str; + GC gc; + XRectangle ink, rect, rect_c; + Bool caret_done = False; + + if (NULL == statusWindow) return; + align_status(statusWindow); + XFillRectangle(dpy, statusWindow->w, + statusWindow->bgGC, + statusWindow->statusW,0, + statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, + statusWindow->fBot+2); + + + XDrawLine(dpy, statusWindow->w, statusWindow->fgGC, + statusWindow->statusW, 0, + statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0); + XDrawLine(dpy, statusWindow->w, statusWindow->fgGC, + statusWindow->statusW, statusWindow->fBot+2, + statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, + statusWindow->fBot+2); + XDrawLine(dpy, statusWindow->w, statusWindow->fgGC, + statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, 0, + statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN, + statusWindow->fBot+2); + if (0 == statusWindow->statusW) + XDrawLine(dpy, statusWindow->w, statusWindow->fgGC, + 0, 0, 0, statusWindow->fBot+2); + + str = statusWindow->peText; -/* This function gets called from the static initializer for - X11InputMethod.java - to initialize the fieldIDs for fields that may be accessed from C */ -JNIEXPORT void JNICALL -Java_sun_awt_X11InputMethod_initIDs(JNIEnv *env, jclass cls) + if (str != NULL && (len = (int32_t)wcslen(str)) != 0) { + pos = 0; + attr = statusWindow->peAttr; + x_pos = x_caret = statusWindow->statusW + STATUS_BORDER; + while((int)len-1 >= pos) { + len_disp = get_next_attr(len - pos, &attr[pos]); + if (attr[pos] & XIMReverse) { + gc = statusWindow->bgGC; + } + else { + gc = statusWindow->fgGC; + } + XwcTextExtents(statusWindow->fontset, + &str[pos], + len_disp, &ink, &rect); + XwcDrawImageString(dpy, statusWindow->w, + statusWindow->fontset, gc, + x_pos, statusWindow->fOff+1, &str[pos], len_disp); + if (attr[pos] & XIMUnderline) { + XDrawLine(dpy, statusWindow->w, + gc, x_pos, statusWindow->fBot, + x_pos+rect.width, statusWindow->fBot); + } + if (!caret_done) { + if( statusWindow->peCaret >= pos && + statusWindow->peCaret <= pos+len_disp) { + if (statusWindow->peCaret == 0) + x_caret = x_pos; + else if (statusWindow->peCaret == pos+len_disp) + x_caret = x_pos+rect.width; + else { + XwcTextExtents(statusWindow->fontset, + &str[pos], + statusWindow->peCaret-pos, + &ink, &rect_c); + x_caret = x_pos+ rect_c.width; + } + x_caret-=CARET_OFFSET; + caret_done = True; + } + } + pos += len_disp; + x_pos += rect.width; + } + if (caret_done) + draw_caret(statusWindow, statusWindow->fgGC, x_caret); + } +} + +/* calc required status window size and resize the window */ +static void align_status(StatusWindow *statusWindow) { - x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J"); + int len_st, len_pe = 0; + XRectangle rect_st, rect_pe, ink; + Dimension cur_w; + int value_make = CWX|CWWidth|CWHeight; + XWindowChanges xwc; + + if (NULL == statusWindow) return; + if ((len_st = st_wcslen(statusWindow->status)) == 0 + && (statusWindow->peText == NULL || st_wcslen(statusWindow->peText) == 0 )) + return; + + rect_pe.x = rect_pe.y = rect_pe.width = rect_pe.height = 0; + + XwcTextExtents(statusWindow->fontset, + statusWindow->status, + len_st, &ink, &rect_st); + if (statusWindow->peText != NULL + && (len_pe = (int32_t)wcslen(statusWindow->peText)) > 0) { + XwcTextExtents(statusWindow->fontset, + statusWindow->peText, + len_pe, &ink, &rect_pe); + } + statusWindow->fOff = max(-rect_st.y, -rect_pe.y); + statusWindow->fBot = max(rect_st.height, rect_pe.height); + statusWindow->statusW =rect_st.width; + if (rect_st.width > 0) statusWindow->statusW += BORDER_MARGIN; + statusWindow->peTextW = rect_pe.width; + + xwc.x = statusWindow->x - statusWindow->off_x; + if (xwc.x < 0 ) xwc.x = 0; + + if (len_pe > 0) { + xwc.width = statusWindow->statusW + + statusWindow->peTextW + BORDER_MARGIN + 1; + xwc.height = statusWindow->fBot + BORDER_MARGIN; + } else { + xwc.width = statusWindow->statusW; + xwc.height = statusWindow->fBot + BORDER_MARGIN; + } + if (xwc.x + xwc.width > statusWindow->rootW){ + xwc.x = statusWindow->rootW - xwc.width; + } + XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); +} + +static void shrink_status(StatusWindow *statusWindow) +{ + int value_make = CWX|CWWidth|CWHeight; + XWindowChanges xwc; + + if (NULL == statusWindow) return; + xwc.width = statusWindow->statusW; + xwc.height = statusWindow->statusH; + statusWindow->peTextW = 0; + xwc.x = statusWindow->x - statusWindow->off_x; + if (xwc.x < 0 ) xwc.x = 0; + if (xwc.x + xwc.width > statusWindow->rootW){ + xwc.x = statusWindow->rootW - xwc.width; + } + XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); +} + +static GC create_gc(Window win, Bool isReverse) +{ + XGCValues xgcv; + unsigned long mask; + AwtScreenDataPtr defaultScreen; + + defaultScreen = getScreenData(DefaultScreen(dpy)); + + mask = (GCForeground | GCBackground ); + if (isReverse) { + xgcv.foreground = defaultScreen->whitepixel; + xgcv.background = defaultScreen->blackpixel; + } else { + xgcv.foreground = defaultScreen->blackpixel; + xgcv.background = defaultScreen->whitepixel; + } + return XCreateGC(dpy, win, mask, &xgcv); } +static Bool isNativeIm() +{ +#define XIMMODIFIER "@im=" +#define XIM_SERVER_CATEGORY "@server=" + char *immodifiers; + char *imserver, *imserverPtr; + Atom imserverAtom; + + if (!(immodifiers = getenv("XMODIFIERS"))) return True; + if (!(imserver = calloc(1,strlen(immodifiers)+strlen(XIM_SERVER_CATEGORY)+1))) return True; + if (!(immodifiers = strstr(immodifiers,XIMMODIFIER))) return True; + immodifiers += strlen(XIMMODIFIER); + strcpy(imserver,XIM_SERVER_CATEGORY); + imserverPtr = imserver + strlen(imserver); + while(*immodifiers != '@' && *immodifiers != '\0') { + *imserverPtr = *immodifiers; + imserverPtr++; + immodifiers++; + } + imserverAtom = XInternAtom(awt_display, imserver, True); + free(imserver); + if (imserverAtom > 0) + return False; + else + return True; +} + +static Window getGrandParent(Window parent) +{ + Window containerWindow,rootWindow,tmp; + Window *ignoreWindowPtr; + unsigned int ignoreUnit; + Window grandParent=0; + XWindowAttributes xwa; + Atom WM_STATE; + Atom type = None; + int32_t format; + unsigned long nitems, after; + unsigned char * data; + + if (parent == 0) return grandParent; + WM_STATE = XInternAtom(dpy, "WM_STATE", True); + if (WM_STATE == None) return grandParent; + + tmp=parent; + while(XQueryTree(dpy, tmp, + &rootWindow, &containerWindow, + &ignoreWindowPtr, &ignoreUnit)){ + XFree(ignoreWindowPtr); + if (containerWindow == rootWindow) break; + if (XGetWindowProperty(dpy, containerWindow, WM_STATE, + 0, 0, False, AnyPropertyType, + &type, &format, &nitems, &after, &data) == Success) { + XFree(data); + if (type) { + XGetWindowAttributes(dpy, containerWindow, &xwa); + if (FALSE == xwa.override_redirect){ + grandParent=containerWindow; + } + } + } + tmp=containerWindow; + } + return grandParent; +} + +static void moveStatusWindow(StatusWindow *statusWindow) +{ + XWindowAttributes xwa; + Window child; + int x, y, width; + Window target; + + if (NULL == statusWindow) return; + if (statusWindow->grandParent) { + target = statusWindow->grandParent; + } else { + target = statusWindow->parent; + } + XGetWindowAttributes(dpy, target, &xwa); + XTranslateCoordinates(dpy, + target, xwa.root, + 0, 0, + &x, &y, + &child); + if (statusWindow->x != x + || statusWindow->y != y + || statusWindow->width != xwa.width + || statusWindow->height != xwa.height){ + statusWindow->x = x; + statusWindow->y = y; + statusWindow->height = xwa.height; + statusWindow->width = xwa.width; + x = statusWindow->x - statusWindow->off_x; + y = statusWindow->y + statusWindow->height + statusWindow->off_y; + if (x < 0 ){ + x = 0; + } + if (statusWindow->peTextW > 0) { + width = statusWindow->statusW + statusWindow->peTextW + BORDER_MARGIN + 1; + if (x + width > statusWindow->rootW){ + x = statusWindow->rootW - width; + } + } else { + if (x + statusWindow->statusW > statusWindow->rootW){ + x = statusWindow->rootW - statusWindow->statusW; + } + } + if (y + statusWindow->statusH > statusWindow->rootH){ + y = statusWindow->rootH - statusWindow->statusH; + } + XMoveWindow(dpy, statusWindow->w, x, y); + } +} + +static void arrange_window_stack(StatusWindow* statusWindow) +{ + XWindowChanges xwc; + int value_make = CWSibling|CWStackMode; + Window root, parent, *children; + unsigned int nchildren; + + if (NULL == statusWindow) return; + if (XQueryTree(dpy, statusWindow->parent, + &root, &parent, &children, &nchildren)){ + XFree(children); + xwc.sibling = parent; + while(XQueryTree(dpy, xwc.sibling, &root, &parent, &children, &nchildren)) { + XFree(children); + if (root != parent) { + xwc.sibling = parent; + } else { + break; + } + } + xwc.stack_mode = Above; + XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); + } +} + +static int count_missing_fonts(char **charset_list, int charset_count) +{ + int i,j; + if (charset_count > 0) { + j=charset_count; + for(i=0; i < charset_count; i++) { + if ((strstr(charset_list[i], "IBM-udc")) || + (strstr(charset_list[i], "IBM-sbd")) || + (strstr(charset_list[i], "IBM-ucdTW"))) + j--; + } + return j; + } + else + return 0; +} + +static XFontSet create_fontset_name(char * font_name, Bool force) +{ + XFontSet fontset = NULL; + char **charset_list; + int charset_count; + char *def_string; + int missing_fonts; + + fontset = XCreateFontSet(dpy, font_name, + &charset_list, &charset_count, &def_string); + if (charset_count > 0) { + missing_fonts = count_missing_fonts(charset_list, + charset_count); + XFreeStringList(charset_list); + if (fontset && (missing_fonts > 0)) { + if (!force) { + XFreeFontSet(dpy, fontset); + fontset = NULL; + } + } + } + return fontset; +} + +static XFontSet create_fontset() +{ + XFontSet fontset = NULL; + int i; + static char * fontlist[] = { + "-dt-interface user-medium-r-normal-S*-*-*-*-*-*-*-*-*", + "-*-*-medium-r-normal-*-14-*-*-*-c-*-*-*", + "-*-*-medium-r-normal-*-14-*-*-*-m-*-*-*", + "-*-*-medium-r-normal--14-0-0-0-m-*-*-*", + "-monotype-sansmonowt-medium-r-normal--14-*-*-*-m-*-*-*", + "-*--14-*", + "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*", + "-*--16-*", + "-*--17-*", + "-*--18-*", + "-*--19-*", + "-*--20-*", + "-*--24-*", + NULL}; + + for (i=0; fontlist[i] != NULL && fontset==NULL; i++) + fontset = create_fontset_name(fontlist[i], False); + + if (!fontset) + fprintf(stdout, "Cannot load fonts for IMF.\n"); + return fontset; +} + +static Window get_current_focus(XIC ic) { + Window w = 0; + if (ic != NULL) + XGetICValues(ic, XNFocusWindow, &w, NULL); + return w; +} JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env, - jobject this, - jlong display) + jobject this, + jlong display) { Bool registered; @@ -1354,19 +1902,9 @@ dpy = (Display *)jlong_to_ptr(display); -/* Use IMInstantiate call back only on Linux, as there is a bug in Solaris - (4768335) -*/ -#if defined(__linux__) || defined(MACOSX) - registered = XRegisterIMInstantiateCallback(dpy, NULL, NULL, - NULL, (XIDProc)OpenXIMCallback, NULL); - if (!registered) { - /* directly call openXIM callback */ -#endif - OpenXIMCallback(dpy, NULL, NULL); -#if defined(__linux__) || defined(MACOSX) + if (X11im == NULL) { + X11im = XOpenIM(dpy, NULL, NULL, NULL); } -#endif AWT_UNLOCK(); @@ -1375,8 +1913,8 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env, - jobject this, - jlong window) + jobject this, + jlong window) { X11InputMethodData *pX11IMData; jobject globalRef; @@ -1399,23 +1937,19 @@ globalRef = (*env)->NewGlobalRef(env, this); pX11IMData->x11inputmethod = globalRef; -#if defined(__linux__) || defined(MACOSX) pX11IMData->statusWindow = NULL; -#endif /* __linux__ || MACOSX */ - pX11IMData->lookup_buf = 0; - pX11IMData->lookup_buf_len = 0; + setX11InputMethodData(env, this, pX11IMData); if (createXIC(env, pX11IMData, (Window)window) == False) { destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData); pX11IMData = (X11InputMethodData *) NULL; + setX11InputMethodData(env, this, pX11IMData); if ((*env)->ExceptionCheck(env)) { goto finally; } } - setX11InputMethodData(env, this, pX11IMData); - finally: AWT_UNLOCK(); return (pX11IMData != NULL); @@ -1423,10 +1957,10 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env, - jobject this, - jlong w, - jboolean req, - jboolean active) + jobject this, + jlong w, + jboolean req, + jboolean active) { X11InputMethodData *pX11IMData; AWT_LOCK(); @@ -1441,27 +1975,30 @@ AWT_UNLOCK(); return; } + pX11IMData->isActiveClient = active; pX11IMData->current_ic = active ? pX11IMData->ic_active : pX11IMData->ic_passive; /* * On Solaris2.6, setXICWindowFocus() has to be invoked * before setting focus. */ - setXICWindowFocus(pX11IMData->current_ic, w); - setXICFocus(pX11IMData->current_ic, req); - currentX11InputMethodInstance = pX11IMData->x11inputmethod; - currentFocusWindow = w; -#if defined(__linux__) || defined(MACOSX) - if (active && pX11IMData->statusWindow && pX11IMData->statusWindow->on) + get_current_focus(pX11IMData->current_ic); /* workaround for kinput2 and SCIM */ + if (currentFocusWindow != w) { + setXICWindowFocus(pX11IMData->current_ic, w); + setXICFocus(pX11IMData->current_ic, req); + currentX11InputMethodInstance = pX11IMData->x11inputmethod; + currentFocusWindow = w; + } else { + setXICFocus(pX11IMData->current_ic, req); + } + if ((active || pX11IMData->passiveStatusWindow) + && (pX11IMData->statusWindow && pX11IMData->statusWindow->on)) onoffStatusWindow(pX11IMData, w, True); -#endif } else { currentX11InputMethodInstance = NULL; currentFocusWindow = 0; -#if defined(__linux__) || defined(MACOSX) onoffStatusWindow(pX11IMData, 0, False); if (pX11IMData->current_ic != NULL) -#endif setXICFocus(pX11IMData->current_ic, req); pX11IMData->current_ic = (XIC)0; @@ -1471,18 +2008,34 @@ AWT_UNLOCK(); } -JNIEXPORT void JNICALL -Java_sun_awt_X11InputMethod_turnoffStatusWindow(JNIEnv *env, - jobject this) +/* + * Class: sun_awt_X11InputMethodBase + * Method: initIDs + * Signature: ()V + * This function gets called from the static initializer for + * X11InputMethod.java to initialize the fieldIDs for fields + * that may be accessed from C + */ +JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_initIDs + (JNIEnv *env, jclass cls) { -#if defined(__linux__) || defined(MACOSX) + x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J"); +} + +/* + * Class: sun_awt_X11InputMethodBase + * Method: turnoffStatusWindow + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_turnoffStatusWindow + (JNIEnv *env, jobject this) +{ X11InputMethodData *pX11IMData; StatusWindow *statusWindow; AWT_LOCK(); if (NULL == currentX11InputMethodInstance - || !isX11InputMethodGRefInList(currentX11InputMethodInstance) || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance)) || NULL == (statusWindow = pX11IMData->statusWindow) || !statusWindow->on ){ @@ -1490,14 +2043,18 @@ return; } onoffStatusWindow(pX11IMData, 0, False); + statusWindow->on = False; AWT_UNLOCK(); -#endif } -JNIEXPORT void JNICALL -Java_sun_awt_X11InputMethod_disposeXIC(JNIEnv *env, - jobject this) +/* + * Class: sun_awt_X11InputMethodBase + * Method: disposeXIC + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_disposeXIC + (JNIEnv *env, jobject this) { X11InputMethodData *pX11IMData = NULL; @@ -1518,9 +2075,13 @@ AWT_UNLOCK(); } -JNIEXPORT jstring JNICALL -Java_sun_awt_X11InputMethod_resetXIC(JNIEnv *env, - jobject this) +/* + * Class: sun_awt_X11InputMethodBase + * Method: resetXIC + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_sun_awt_X11InputMethodBase_resetXIC + (JNIEnv *env, jobject this) { X11InputMethodData *pX11IMData; char *xText = NULL; @@ -1533,12 +2094,23 @@ return jText; } - if (pX11IMData->current_ic) - xText = XmbResetIC(pX11IMData->current_ic); - else { + if (pX11IMData->current_ic) { + if (!isPreeditStateActive(pX11IMData->current_ic)) { + xText = NULL; + } else { + if (!(pX11IMData->forceReset)) + setXICFocus(pX11IMData->current_ic, FALSE); + xText = XmbResetIC(pX11IMData->current_ic); + if (!(pX11IMData->forceReset)) + setXICFocus(pX11IMData->current_ic, TRUE); + } + } else { /* * If there is no reference to the current XIC, try to reset both XICs. */ + if (!isPreeditStateActive(pX11IMData->ic_active)) + xText = NULL; + else xText = XmbResetIC(pX11IMData->ic_active); /*it may also means that the real client component does not have focus -- has been deactivated... its xic should @@ -1547,26 +2119,46 @@ */ setXICFocus(pX11IMData->ic_active, FALSE); if (pX11IMData->ic_active != pX11IMData->ic_passive) { - char *tmpText = XmbResetIC(pX11IMData->ic_passive); + char *tmpText; + if (!isPreeditStateActive(pX11IMData->ic_passive)) + tmpText = NULL; + else + tmpText = XmbResetIC(pX11IMData->ic_passive); setXICFocus(pX11IMData->ic_passive, FALSE); if (xText == (char *)NULL && tmpText) xText = tmpText; } - } if (xText != NULL) { jText = JNU_NewStringPlatform(env, (const char *)xText); XFree((void *)xText); } + /* workaround + * Some IME do not call PreeditDoneCallback routine even + * when XmbResetIC is called. I force to reset the preedit string. + */ + if (!pX11IMData->isActiveClient) { + resetPassivePreeditText(pX11IMData->statusWindow); + shrink_status(pX11IMData->statusWindow); + } else { + JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, + "clearComposedText", + "()V"); + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + } + AWT_UNLOCK(); return jText; } /* - * Class: sun_awt_X11InputMethod + * Class: sun_awt_X11InputMethodBase * Method: setCompositionEnabledNative - * Signature: (ZJ)V + * Signature: (Z)Z * * This method tries to set the XNPreeditState attribute associated with the current * XIC to the passed in 'enable' state. @@ -1575,13 +2167,13 @@ * 'enable' state; Otherwise, if XSetICValues fails to set this attribute, * java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this * method fails due to other reasons. - * */ -JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_setCompositionEnabledNative +JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative (JNIEnv *env, jobject this, jboolean enable) { X11InputMethodData *pX11IMData; char * ret = NULL; + XVaNestedList pr_atrb; AWT_LOCK(); pX11IMData = getX11InputMethodData(env, this); @@ -1591,11 +2183,15 @@ return JNI_FALSE; } - ret = XSetICValues(pX11IMData->current_ic, XNPreeditState, - (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL); + pr_atrb = XVaCreateNestedList(0, XNPreeditState, + (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL); + ret = XSetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL); + XFree((void *)pr_atrb); AWT_UNLOCK(); - if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) { + if ((ret != 0) && + ((strcmp(ret, XNPreeditAttributes) == 0) + || (strcmp(ret, XNPreeditState) == 0))) { JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ""); } @@ -1603,23 +2199,23 @@ } /* - * Class: sun_awt_X11InputMethod + * Class: sun_awt_X11InputMethodBase * Method: isCompositionEnabledNative - * Signature: (J)Z + * Signature: ()Z * * This method tries to get the XNPreeditState attribute associated with the current XIC. * * Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if * XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException * will be thrown. JNI_FALSE is returned if this method fails due to other reasons. - * */ -JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_isCompositionEnabledNative +JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_isCompositionEnabledNative (JNIEnv *env, jobject this) { X11InputMethodData *pX11IMData = NULL; char * ret = NULL; - XIMPreeditState state; + XIMPreeditState state = XIMPreeditUnKnown; + XVaNestedList pr_atrb; AWT_LOCK(); pX11IMData = getX11InputMethodData(env, this); @@ -1629,10 +2225,14 @@ return JNI_FALSE; } - ret = XGetICValues(pX11IMData->current_ic, XNPreeditState, &state, NULL); + pr_atrb = XVaCreateNestedList(0, XNPreeditState, &state, NULL); + ret = XGetICValues(pX11IMData->current_ic, XNPreeditAttributes, pr_atrb, NULL); + XFree((void *)pr_atrb); AWT_UNLOCK(); - if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) { + if ((ret != 0) && + ((strcmp(ret, XNPreeditAttributes) == 0) + || (strcmp(ret, XNPreeditState) == 0))) { JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ""); return JNI_FALSE; } @@ -1643,9 +2243,27 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_adjustStatusWindow (JNIEnv *env, jobject this, jlong window) { -#if defined(__linux__) || defined(MACOSX) - AWT_LOCK(); - adjustStatusWindow(window); - AWT_UNLOCK(); -#endif + } + +/* + * Class: sun_awt_X11InputMethod + * Method: setStatusAreaVisible + * Signature: (ZJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11InputMethod_setStatusAreaVisible + (JNIEnv *env, jobject this, jboolean value, jlong data) +{ + X11InputMethodData *pX11IMData; + + pX11IMData = getX11InputMethodData(env, this); + if (NULL == pX11IMData) return; + if (NULL == pX11IMData->statusWindow) return; + + if ((int)value){ + pX11IMData->statusWindow->on = True; + }else{ + pX11IMData->statusWindow->on = False; + } + return; +} diff --git a/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java b/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java --- a/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java +++ b/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -25,147 +25,21 @@ package sun.awt; -import java.util.Collections; -import java.util.Locale; -import java.util.Map; -import java.util.HashMap; -import java.awt.AWTEvent; import java.awt.AWTException; -import java.awt.Component; -import java.awt.Container; -import java.awt.EventQueue; -import java.awt.Window; -import java.awt.im.InputMethodHighlight; -import java.awt.im.spi.InputMethodContext; -import sun.awt.im.InputMethodAdapter; import java.awt.event.InputMethodEvent; import java.awt.font.TextAttribute; import java.awt.font.TextHitInfo; import java.awt.peer.ComponentPeer; -import java.lang.Character.Subset; import java.text.AttributedString; -import java.text.AttributedCharacterIterator; -import java.io.File; -import java.io.FileReader; -import java.io.BufferedReader; -import java.io.IOException; -import java.lang.ref.WeakReference; import sun.util.logging.PlatformLogger; -import java.util.StringTokenizer; -import java.util.regex.Pattern; - /** * Input Method Adapter for XIM * * @author JavaSoft International */ -public abstract class X11InputMethod extends InputMethodAdapter { - private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11InputMethod"); - /* - * The following XIM* values must be the same as those defined in - * Xlib.h - */ - private static final int XIMReverse = (1<<0); - private static final int XIMUnderline = (1<<1); - private static final int XIMHighlight = (1<<2); - private static final int XIMPrimary = (1<<5); - private static final int XIMSecondary = (1<<6); - private static final int XIMTertiary = (1<<7); - - /* - * visible position values - */ - private static final int XIMVisibleToForward = (1<<8); - private static final int XIMVisibleToBackward = (1<<9); - private static final int XIMVisibleCenter = (1<<10); - private static final int XIMVisibleMask = (XIMVisibleToForward| - XIMVisibleToBackward| - XIMVisibleCenter); - - private Locale locale; - private static boolean isXIMOpened = false; - protected Container clientComponentWindow = null; - private Component awtFocussedComponent = null; - private Component lastXICFocussedComponent = null; - private boolean isLastXICActive = false; - private boolean isLastTemporary = false; - private boolean isActive = false; - private boolean isActiveClient = false; - private static Map[] highlightStyles; - private boolean disposed = false; - - //reset the XIC if necessary - private boolean needResetXIC = false; - private WeakReference needResetXICClient = new WeakReference<>(null); - - // The use of compositionEnableSupported is to reduce unnecessary - // native calls if set/isCompositionEnabled - // throws UnsupportedOperationException. - // It is set to false if that exception is thrown first time - // either of the two methods are called. - private boolean compositionEnableSupported = true; - // The savedCompositionState indicates the composition mode when - // endComposition or setCompositionEnabled is called. It doesn't always - // reflect the actual composition state because it doesn't get updated - // when the user changes the composition state through direct interaction - // with the input method. It is used to save the composition mode when - // focus is traversed across different client components sharing the - // same java input context. Also if set/isCompositionEnabled are not - // supported, it remains false. - private boolean savedCompositionState = false; - - // variables to keep track of preedit context. - // these variables need to be accessed within AWT_LOCK/UNLOCK - private String committedText = null; - private StringBuffer composedText = null; - private IntBuffer rawFeedbacks; - - // private data (X11InputMethodData structure defined in - // awt_InputMethod.c) for native methods - // this structure needs to be accessed within AWT_LOCK/UNLOCK - private transient long pData = 0; // accessed by native - - // Initialize highlight mapping table - static { - @SuppressWarnings({"unchecked", "rawtypes"}) - Map styles[] = new Map[4]; - HashMap map; - - // UNSELECTED_RAW_TEXT_HIGHLIGHT - map = new HashMap<>(1); - map.put(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD); - styles[0] = Collections.unmodifiableMap(map); - - // SELECTED_RAW_TEXT_HIGHLIGHT - map = new HashMap<>(1); - map.put(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON); - styles[1] = Collections.unmodifiableMap(map); - - // UNSELECTED_CONVERTED_TEXT_HIGHLIGHT - map = new HashMap<>(1); - map.put(TextAttribute.INPUT_METHOD_UNDERLINE, - TextAttribute.UNDERLINE_LOW_ONE_PIXEL); - styles[2] = Collections.unmodifiableMap(map); - - // SELECTED_CONVERTED_TEXT_HIGHLIGHT - map = new HashMap<>(1); - map.put(TextAttribute.SWAP_COLORS, TextAttribute.SWAP_COLORS_ON); - styles[3] = Collections.unmodifiableMap(map); - - highlightStyles = styles; - } - - static { - initIDs(); - } - - /** - * Initialize JNI field and method IDs for fields that may be - accessed from C. - */ - private static native void initIDs(); +public abstract class X11InputMethod extends X11InputMethodBase { /** * Constructs an X11InputMethod instance. It initializes the XIM @@ -174,113 +48,13 @@ * @exception AWTException if XOpenIM() failed. */ public X11InputMethod() throws AWTException { - // supports only the locale in which the VM is started - locale = X11InputMethodDescriptor.getSupportedLocale(); - if (initXIM() == false) { - throw new AWTException("Cannot open X Input Method"); - } - } - - @SuppressWarnings("deprecation") - protected void finalize() throws Throwable { - dispose(); - super.finalize(); - } - - /** - * Invokes openIM() that invokes XOpenIM() if it's not opened yet. - * @return true if openXIM() is successful or it's already been opened. - */ - private synchronized boolean initXIM() { - if (isXIMOpened == false) - isXIMOpened = openXIM(); - return isXIMOpened; - } - - protected abstract boolean openXIM(); - - protected boolean isDisposed() { - return disposed; - } - - protected abstract void setXICFocus(ComponentPeer peer, - boolean value, boolean active); - - /** - * Does nothing - this adapter doesn't use the input method context. - * - * @see java.awt.im.spi.InputMethod#setInputMethodContext - */ - public void setInputMethodContext(InputMethodContext context) { - } - - /** - * Set locale to input. If input method doesn't support specified locale, - * false will be returned and its behavior is not changed. - * - * @param lang locale to input - * @return the true is returned when specified locale is supported. - */ - public boolean setLocale(Locale lang) { - if (lang.equals(locale)) { - return true; - } - // special compatibility rule for Japanese and Korean - if (locale.equals(Locale.JAPAN) && lang.equals(Locale.JAPANESE) || - locale.equals(Locale.KOREA) && lang.equals(Locale.KOREAN)) { - return true; - } - return false; - } - - /** - * Returns current input locale. - */ - public Locale getLocale() { - return locale; - } - - /** - * Does nothing - XIM doesn't let you specify which characters you expect. - * - * @see java.awt.im.spi.InputMethod#setCharacterSubsets - */ - public void setCharacterSubsets(Subset[] subsets) { - } - - /** - * Dispatch event to input method. InputContext dispatch event with this - * method. Input method set consume flag if event is consumed in - * input method. - * - * @param e event - */ - public void dispatchEvent(AWTEvent e) { - } - - - protected final void resetXICifneeded(){ - /* needResetXIC is used to indicate whether to call - resetXIC on the active client. resetXIC will always be - called on the passive client when endComposition is called. - */ - if (needResetXIC && haveActiveClient() && - getClientComponent() != needResetXICClient.get()){ - resetXIC(); - - // needs to reset the last xic focussed component. - lastXICFocussedComponent = null; - isLastXICActive = false; - - needResetXICClient.clear(); - needResetXIC = false; - } + super(); } /** * Reset the composition state to the current composition state. */ - private void resetCompositionState() { + protected void resetCompositionState() { if (compositionEnableSupported) { try { /* Restore the composition mode to the last saved composition @@ -293,23 +67,6 @@ } /** - * Query and then return the current composition state. - * @return the composition state if isCompositionEnabled call - * is successful. Otherwise, it returns false. - */ - private boolean getCompositionState() { - boolean compositionState = false; - if (compositionEnableSupported) { - try { - compositionState = isCompositionEnabled(); - } catch (UnsupportedOperationException e) { - compositionEnableSupported = false; - } - } - return compositionState; - } - - /** * Activate input method. */ public synchronized void activate() { @@ -317,7 +74,7 @@ if (clientComponentWindow == null) return; - if (lastXICFocussedComponent != null){ + if (lastXICFocussedComponent != null) { if (log.isLoggable(PlatformLogger.Level.FINE)) { log.fine("XICFocused {0}, AWTFocused {1}", lastXICFocussedComponent, awtFocussedComponent); @@ -360,8 +117,6 @@ isActive = true; } - protected abstract boolean createXIC(); - /** * Deactivate input method. */ @@ -387,198 +142,26 @@ */ savedCompositionState = getCompositionState(); - if (isTemporary){ + if (isTemporary) { //turn the status window off... turnoffStatusWindow(); } /* Delay resetting the XIC focus until activate is called and the newly - focussed component has a different peer as the last focussed component. - */ + * Focused component has a different peer as the last focused component. + */ lastXICFocussedComponent = awtFocussedComponent; isLastXICActive = isAc; isLastTemporary = isTemporary; isActive = false; } - /** - * Explicitly disable the native IME. Native IME is not disabled when - * deactivate is called. - */ - public void disableInputMethod() { - if (lastXICFocussedComponent != null) { - setXICFocus(getPeer(lastXICFocussedComponent), false, isLastXICActive); - lastXICFocussedComponent = null; - isLastXICActive = false; - - resetXIC(); - needResetXICClient.clear(); - needResetXIC = false; - } - } - // implements java.awt.im.spi.InputMethod.hideWindows public void hideWindows() { // ??? need real implementation } /** - * @see java.awt.Toolkit#mapInputMethodHighlight - */ - public static Map mapInputMethodHighlight(InputMethodHighlight highlight) { - int index; - int state = highlight.getState(); - if (state == InputMethodHighlight.RAW_TEXT) { - index = 0; - } else if (state == InputMethodHighlight.CONVERTED_TEXT) { - index = 2; - } else { - return null; - } - if (highlight.isSelected()) { - index += 1; - } - return highlightStyles[index]; - } - - /** - * @see sun.awt.im.InputMethodAdapter#setAWTFocussedComponent - */ - protected void setAWTFocussedComponent(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(); - setXICFocus(getPeer(awtFocussedComponent), false, ac); - setXICFocus(getPeer(component), true, ac); - } - awtFocussedComponent = component; - } - - /** - * @see sun.awt.im.InputMethodAdapter#stopListening - */ - protected void stopListening() { - // It is desirable to disable XIM by calling XSetICValues with - // XNPreeditState == XIMPreeditDisable. But Solaris 2.6 and - // Solaris 7 do not implement this correctly without a patch, - // so just call resetXIC here. Prior endComposition call commits - // the existing composed text. - endComposition(); - // disable the native input method so that the other input - // method could get the input focus. - disableInputMethod(); - if (needResetXIC) { - resetXIC(); - needResetXICClient.clear(); - needResetXIC = false; - } - } - - /** - * Returns the Window instance in which the client component is - * contained. If not found, null is returned. (IS THIS POSSIBLE?) - */ - // NOTE: This method may be called by privileged threads. - // DO NOT INVOKE CLIENT CODE ON THIS THREAD! - private Window getClientComponentWindow() { - Component client = getClientComponent(); - Container container; - - if (client instanceof Container) { - container = (Container) client; - } else { - container = getParent(client); - } - - while (container != null && !(container instanceof java.awt.Window)) { - container = getParent(container); - } - return (Window) container; - } - - protected abstract Container getParent(Component client); - - /** - * Returns peer of the given client component. If the given client component - * doesn't have peer, peer of the native container of the client is returned. - */ - protected abstract ComponentPeer getPeer(Component client); - - /** - * Used to protect preedit data - */ - protected abstract void awtLock(); - protected abstract void awtUnlock(); - - /** - * Creates an input method event from the arguments given - * and posts it on the AWT event queue. For arguments, - * see InputMethodEvent. Called by input method. - * - * @see java.awt.event.InputMethodEvent#InputMethodEvent - */ - private void postInputMethodEvent(int id, - AttributedCharacterIterator text, - int committedCharacterCount, - TextHitInfo caret, - TextHitInfo visiblePosition, - long when) { - Component source = getClientComponent(); - if (source != null) { - InputMethodEvent event = new InputMethodEvent(source, - id, when, text, committedCharacterCount, caret, visiblePosition); - SunToolkit.postEvent(SunToolkit.targetToAppContext(source), (AWTEvent)event); - } - } - - private void postInputMethodEvent(int id, - AttributedCharacterIterator text, - int committedCharacterCount, - TextHitInfo caret, - TextHitInfo visiblePosition) { - postInputMethodEvent(id, text, committedCharacterCount, - caret, visiblePosition, EventQueue.getMostRecentEventTime()); - } - - /** - * Dispatches committed text from XIM to the awt event queue. This - * method is invoked from the event handler in canvas.c in the - * AWT Toolkit thread context and thus inside the AWT Lock. - * @param str committed text - * @param when when - */ - // NOTE: This method may be called by privileged threads. - // This functionality is implemented in a package-private method - // to insure that it cannot be overridden by client subclasses. - // DO NOT INVOKE CLIENT CODE ON THIS THREAD! - void dispatchCommittedText(String str, long when) { - if (str == null) - return; - - if (composedText == null) { - AttributedString attrstr = new AttributedString(str); - postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, - attrstr.getIterator(), - str.length(), - null, - null, - when); - } else { - // if there is composed text, wait until the preedit - // callback is invoked. - committedText = str; - } - } - - private void dispatchCommittedText(String str) { - dispatchCommittedText(str, EventQueue.getMostRecentEventTime()); - } - - /** * Updates composed text with XIM preedit information and * posts composed text to the awt event queue. The args of * this method correspond to the XIM preedit callback @@ -601,7 +184,7 @@ return; } - //Workaround for deadlock bug on solaris2.6_zh bug#4170760 + // Workaround for deadlock bug on solaris2.6_zh bug#4170760 if (chgText == null && chgStyles == null && chgOffset == 0 @@ -739,34 +322,6 @@ when); } - /** - * Flushes composed and committed text held in this context. - * This method is invoked in the AWT Toolkit (X event loop) thread context - * and thus inside the AWT Lock. - */ - // NOTE: This method may be called by privileged threads. - // This functionality is implemented in a package-private method - // to insure that it cannot be overridden by client subclasses. - // DO NOT INVOKE CLIENT CODE ON THIS THREAD! - void flushText() { - String flush = (committedText != null ? committedText : ""); - if (composedText != null) { - flush += composedText.toString(); - } - - if (!flush.equals("")) { - AttributedString attrstr = new AttributedString(flush); - postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, - attrstr.getIterator(), - flush.length(), - null, - null, - EventQueue.getMostRecentEventTime()); - composedText = null; - committedText = null; - } - } - /* * Subclasses should override disposeImpl() instead of dispose(). Client * code should always invoke dispose(), never disposeImpl(). @@ -783,43 +338,6 @@ } /** - * Frees all X Window resources associated with this object. - * - * @see java.awt.im.spi.InputMethod#dispose - */ - public final void dispose() { - boolean call_disposeImpl = false; - - if (!disposed) { - synchronized (this) { - if (!disposed) { - disposed = call_disposeImpl = true; - } - } - } - - if (call_disposeImpl) { - disposeImpl(); - } - } - - /** - * Returns null. - * - * @see java.awt.im.spi.InputMethod#getControlObject - */ - public Object getControlObject() { - return null; - } - - /** - * @see java.awt.im.spi.InputMethod#removeNotify - */ - public synchronized void removeNotify() { - dispose(); - } - - /** * @see java.awt.im.spi.InputMethod#setCompositionEnabled(boolean) */ public void setCompositionEnabled(boolean enable) { @@ -835,263 +353,4 @@ savedCompositionState = enable; } } - - /** - * @see java.awt.im.spi.InputMethod#isCompositionEnabled - */ - public boolean isCompositionEnabled() { - /* isCompositionEnabledNative may throw UnsupportedOperationException. - Don't try to catch it since this method may be called by clients. - Use package private method 'getCompositionState' if you want the - exception to be caught. - */ - return isCompositionEnabledNative(); - } - - /** - * Ends any input composition that may currently be going on in this - * context. Depending on the platform and possibly user preferences, - * this may commit or delete uncommitted text. Any changes to the text - * are communicated to the active component using an input method event. - * - *

- * A text editing component may call this in a variety of situations, - * for example, when the user moves the insertion point within the text - * (but outside the composed text), or when the component's text is - * saved to a file or copied to the clipboard. - * - */ - public void endComposition() { - if (disposed) { - return; - } - - /* Before calling resetXIC, record the current composition mode - so that it can be restored later. */ - savedCompositionState = getCompositionState(); - boolean active = haveActiveClient(); - if (active && composedText == null && committedText == null){ - needResetXIC = true; - needResetXICClient = new WeakReference<>(getClientComponent()); - return; - } - - String text = resetXIC(); - /* needResetXIC is only set to true for active client. So passive - client should not reset the flag to false. */ - if (active) { - needResetXIC = false; - } - - // Remove any existing composed text by posting an InputMethodEvent - // with null composed text. It would be desirable to wait for a - // dispatchComposedText call from X input method engine, but some - // input method does not conform to the XIM specification and does - // not call the preedit callback to erase preedit text on calling - // XmbResetIC. To work around this problem, do it here by ourselves. - awtLock(); - composedText = null; - postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, - null, - 0, - null, - null); - - if (text != null && text.length() > 0) { - dispatchCommittedText(text); - } - awtUnlock(); - - // Restore the preedit state if it was enabled - if (savedCompositionState) { - resetCompositionState(); - } - } - - /** - * Returns a string with information about the current input method server, or null. - * On both Linux & SunOS, the value of environment variable XMODIFIERS is - * returned if set. Otherwise, on SunOS, $HOME/.dtprofile will be parsed - * to find out the language service engine (atok or wnn) since there is - * no API in Xlib which returns the information of native - * IM server or language service and we want to try our best to return as much - * information as possible. - * - * Note: This method could return null on Linux if XMODIFIERS is not set properly or - * if any IOException is thrown. - * See man page of XSetLocaleModifiers(3X11) for the usgae of XMODIFIERS, - * atok12setup(1) and wnn6setup(1) for the information written to - * $HOME/.dtprofile when you run these two commands. - * - */ - public String getNativeInputMethodInfo() { - String xmodifiers = System.getenv("XMODIFIERS"); - String imInfo = null; - - // If XMODIFIERS is set, return the value - if (xmodifiers != null) { - int imIndex = xmodifiers.indexOf("@im="); - if (imIndex != -1) { - imInfo = xmodifiers.substring(imIndex + 4); - } - } else if (System.getProperty("os.name").startsWith("SunOS")) { - File dtprofile = new File(System.getProperty("user.home") + - "/.dtprofile"); - String languageEngineInfo = null; - try { - BufferedReader br = new BufferedReader(new FileReader(dtprofile)); - String line = null; - - while ( languageEngineInfo == null && (line = br.readLine()) != null) { - if (line.contains("atok") || line.contains("wnn")) { - StringTokenizer tokens = new StringTokenizer(line); - while (tokens.hasMoreTokens()) { - String token = tokens.nextToken(); - if (Pattern.matches("atok.*setup", token) || - Pattern.matches("wnn.*setup", token)){ - languageEngineInfo = token.substring(0, token.indexOf("setup")); - break; - } - } - } - } - - br.close(); - } catch(IOException ioex) { - // Since this method is provided for internal testing only, - // we dump the stack trace for the ease of debugging. - ioex.printStackTrace(); - } - - imInfo = "htt " + languageEngineInfo; - } - - return imInfo; - } - - - /** - * Performs mapping from an XIM visible feedback value to Java IM highlight. - * @return Java input method highlight - */ - private InputMethodHighlight convertVisualFeedbackToHighlight(int feedback) { - InputMethodHighlight highlight; - - switch (feedback) { - case XIMUnderline: - highlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT; - break; - case XIMReverse: - highlight = InputMethodHighlight.SELECTED_CONVERTED_TEXT_HIGHLIGHT; - break; - case XIMHighlight: - highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT; - break; - case XIMPrimary: - highlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT; - break; - case XIMSecondary: - highlight = InputMethodHighlight.SELECTED_CONVERTED_TEXT_HIGHLIGHT; - break; - case XIMTertiary: - highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT; - break; - default: - highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT; - break; - } - return highlight; - } - - // initial capacity size for string buffer, etc. - private static final int INITIAL_SIZE = 64; - - /** - * IntBuffer is an inner class that manipulates an int array and - * provides UNIX file io stream-like programming interfaces to - * access it. (An alternative would be to use ArrayList which may - * be too expensive for the work.) - */ - private final class IntBuffer { - private int[] intArray; - private int size; - private int index; - - IntBuffer(int initialCapacity) { - intArray = new int[initialCapacity]; - size = 0; - index = 0; - } - - void insert(int offset, int[] values) { - int newSize = size + values.length; - if (intArray.length < newSize) { - int[] newIntArray = new int[newSize * 2]; - System.arraycopy(intArray, 0, newIntArray, 0, size); - intArray = newIntArray; - } - System.arraycopy(intArray, offset, intArray, offset+values.length, - size - offset); - System.arraycopy(values, 0, intArray, offset, values.length); - size += values.length; - if (index > offset) - index = offset; - } - - void remove(int offset, int length) { - if (offset + length != size) - System.arraycopy(intArray, offset+length, intArray, offset, - size - offset - length); - size -= length; - if (index > offset) - index = offset; - } - - void replace(int offset, int[] values) { - System.arraycopy(values, 0, intArray, offset, values.length); - } - - void removeAll() { - size = 0; - index = 0; - } - - void rewind() { - index = 0; - } - - int getNext() { - if (index == size) - return -1; - return intArray[index++]; - } - - void unget() { - if (index != 0) - index--; - } - - int getOffset() { - return index; - } - - public String toString() { - StringBuffer s = new StringBuffer(); - for (int i = 0; i < size;) { - s.append(intArray[i++]); - if (i < size) - s.append(","); - } - return s.toString(); - } - } - - /* - * Native methods - */ - private native String resetXIC(); - private native void disposeXIC(); - private native boolean setCompositionEnabledNative(boolean enable); - private native boolean isCompositionEnabledNative(); - private native void turnoffStatusWindow(); } diff --git a/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java b/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java copy from src/java.desktop/unix/classes/sun/awt/X11InputMethod.java copy to src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java --- a/src/java.desktop/unix/classes/sun/awt/X11InputMethod.java +++ b/src/java.desktop/unix/classes/sun/awt/X11InputMethodBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -25,44 +25,43 @@ package sun.awt; -import java.util.Collections; -import java.util.Locale; -import java.util.Map; -import java.util.HashMap; import java.awt.AWTEvent; import java.awt.AWTException; import java.awt.Component; import java.awt.Container; import java.awt.EventQueue; import java.awt.Window; -import java.awt.im.InputMethodHighlight; -import java.awt.im.spi.InputMethodContext; -import sun.awt.im.InputMethodAdapter; import java.awt.event.InputMethodEvent; import java.awt.font.TextAttribute; import java.awt.font.TextHitInfo; +import java.awt.im.InputMethodHighlight; +import java.awt.im.spi.InputMethodContext; import java.awt.peer.ComponentPeer; -import java.lang.Character.Subset; -import java.text.AttributedString; -import java.text.AttributedCharacterIterator; - +import java.io.BufferedReader; import java.io.File; import java.io.FileReader; -import java.io.BufferedReader; import java.io.IOException; +import java.lang.Character.Subset; import java.lang.ref.WeakReference; -import sun.util.logging.PlatformLogger; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; import java.util.StringTokenizer; import java.util.regex.Pattern; +import sun.awt.im.InputMethodAdapter; +import sun.util.logging.PlatformLogger; /** * Input Method Adapter for XIM * * @author JavaSoft International */ -public abstract class X11InputMethod extends InputMethodAdapter { - private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11InputMethod"); +public abstract class X11InputMethodBase extends InputMethodAdapter { + protected static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11InputMethod"); /* * The following XIM* values must be the same as those defined in * Xlib.h @@ -77,27 +76,25 @@ /* * visible position values */ - private static final int XIMVisibleToForward = (1<<8); - private static final int XIMVisibleToBackward = (1<<9); - private static final int XIMVisibleCenter = (1<<10); - private static final int XIMVisibleMask = (XIMVisibleToForward| - XIMVisibleToBackward| - XIMVisibleCenter); + protected static final int XIMVisibleToForward = (1<<8); + protected static final int XIMVisibleToBackward = (1<<9); + protected static final int XIMVisibleCenter = (1<<10); + protected static final int XIMVisibleMask = + (XIMVisibleToForward | XIMVisibleToBackward | XIMVisibleCenter); private Locale locale; private static boolean isXIMOpened = false; protected Container clientComponentWindow = null; - private Component awtFocussedComponent = null; - private Component lastXICFocussedComponent = null; - private boolean isLastXICActive = false; - private boolean isLastTemporary = false; - private boolean isActive = false; - private boolean isActiveClient = false; + protected Component awtFocussedComponent = null; + protected Component lastXICFocussedComponent = null; + protected boolean isLastXICActive = false; + protected boolean isLastTemporary = false; + protected boolean isActive = false; private static Map[] highlightStyles; - private boolean disposed = false; + protected boolean disposed = false; //reset the XIC if necessary - private boolean needResetXIC = false; + protected boolean needResetXIC = false; private WeakReference needResetXICClient = new WeakReference<>(null); // The use of compositionEnableSupported is to reduce unnecessary @@ -105,7 +102,7 @@ // throws UnsupportedOperationException. // It is set to false if that exception is thrown first time // either of the two methods are called. - private boolean compositionEnableSupported = true; + protected boolean compositionEnableSupported = true; // The savedCompositionState indicates the composition mode when // endComposition or setCompositionEnabled is called. It doesn't always // reflect the actual composition state because it doesn't get updated @@ -114,18 +111,18 @@ // focus is traversed across different client components sharing the // same java input context. Also if set/isCompositionEnabled are not // supported, it remains false. - private boolean savedCompositionState = false; + protected boolean savedCompositionState = false; // variables to keep track of preedit context. // these variables need to be accessed within AWT_LOCK/UNLOCK - private String committedText = null; - private StringBuffer composedText = null; - private IntBuffer rawFeedbacks; + protected String committedText = null; + protected StringBuffer composedText = null; + protected IntBuffer rawFeedbacks; // private data (X11InputMethodData structure defined in // awt_InputMethod.c) for native methods // this structure needs to be accessed within AWT_LOCK/UNLOCK - private transient long pData = 0; // accessed by native + protected transient long pData = 0; // accessed by native // Initialize highlight mapping table static { @@ -162,18 +159,12 @@ } /** - * Initialize JNI field and method IDs for fields that may be - accessed from C. - */ - private static native void initIDs(); - - /** * Constructs an X11InputMethod instance. It initializes the XIM * environment if it's not done yet. * * @exception AWTException if XOpenIM() failed. */ - public X11InputMethod() throws AWTException { + public X11InputMethodBase() throws AWTException { // supports only the locale in which the VM is started locale = X11InputMethodDescriptor.getSupportedLocale(); if (initXIM() == false) { @@ -258,7 +249,6 @@ public void dispatchEvent(AWTEvent e) { } - protected final void resetXICifneeded(){ /* needResetXIC is used to indicate whether to call resetXIC on the active client. resetXIC will always be @@ -280,24 +270,14 @@ /** * Reset the composition state to the current composition state. */ - private void resetCompositionState() { - if (compositionEnableSupported) { - try { - /* Restore the composition mode to the last saved composition - mode. */ - setCompositionEnabled(savedCompositionState); - } catch (UnsupportedOperationException e) { - compositionEnableSupported = false; - } - } - } + protected abstract void resetCompositionState(); /** * Query and then return the current composition state. * @return the composition state if isCompositionEnabled call * is successful. Otherwise, it returns false. */ - private boolean getCompositionState() { + protected boolean getCompositionState() { boolean compositionState = false; if (compositionEnableSupported) { try { @@ -312,94 +292,14 @@ /** * Activate input method. */ - public synchronized void activate() { - clientComponentWindow = getClientComponentWindow(); - if (clientComponentWindow == null) - return; - - if (lastXICFocussedComponent != null){ - if (log.isLoggable(PlatformLogger.Level.FINE)) { - log.fine("XICFocused {0}, AWTFocused {1}", - lastXICFocussedComponent, awtFocussedComponent); - } - } - - if (pData == 0) { - if (!createXIC()) { - return; - } - disposed = false; - } - - /* reset input context if necessary and set the XIC focus - */ - resetXICifneeded(); - ComponentPeer lastXICFocussedComponentPeer = null; - ComponentPeer awtFocussedComponentPeer = getPeer(awtFocussedComponent); - - if (lastXICFocussedComponent != null) { - lastXICFocussedComponentPeer = getPeer(lastXICFocussedComponent); - } - - /* If the last XIC focussed component has a different peer as the - current focussed component, change the XIC focus to the newly - focussed component. - */ - if (isLastTemporary || lastXICFocussedComponentPeer != awtFocussedComponentPeer || - isLastXICActive != haveActiveClient()) { - if (lastXICFocussedComponentPeer != null) { - setXICFocus(lastXICFocussedComponentPeer, false, isLastXICActive); - } - if (awtFocussedComponentPeer != null) { - setXICFocus(awtFocussedComponentPeer, true, haveActiveClient()); - } - lastXICFocussedComponent = awtFocussedComponent; - isLastXICActive = haveActiveClient(); - } - resetCompositionState(); - isActive = true; - } + public abstract void activate(); protected abstract boolean createXIC(); /** * Deactivate input method. */ - public synchronized void deactivate(boolean isTemporary) { - boolean isAc = haveActiveClient(); - /* Usually as the client component, let's call it component A, - loses the focus, this method is called. Then when another client - component, let's call it component B, gets the focus, activate is first called on - the previous focused compoent which is A, then endComposition is called on A, - deactivate is called on A again. And finally activate is called on the newly - focused component B. Here is the call sequence. - - A loses focus B gains focus - -------------> deactivate A -------------> activate A -> endComposition A -> - deactivate A -> activate B ----.... - - So in order to carry the composition mode across the components sharing the same - input context, we save it when deactivate is called so that when activate is - called, it can be restored correctly till activate is called on the newly focused - component. (See also sun/awt/im/InputContext and bug 6184471). - Last note, getCompositionState should be called before setXICFocus since - setXICFocus here sets the XIC to 0. - */ - savedCompositionState = getCompositionState(); - - if (isTemporary){ - //turn the status window off... - turnoffStatusWindow(); - } - - /* Delay resetting the XIC focus until activate is called and the newly - focussed component has a different peer as the last focussed component. - */ - lastXICFocussedComponent = awtFocussedComponent; - isLastXICActive = isAc; - isLastTemporary = isTemporary; - isActive = false; - } + public abstract void deactivate(boolean isTemporary); /** * Explicitly disable the native IME. Native IME is not disabled when @@ -418,9 +318,7 @@ } // implements java.awt.im.spi.InputMethod.hideWindows - public void hideWindows() { - // ??? need real implementation - } + public abstract void hideWindows(); /** * @see java.awt.Toolkit#mapInputMethodHighlight @@ -484,7 +382,7 @@ */ // NOTE: This method may be called by privileged threads. // DO NOT INVOKE CLIENT CODE ON THIS THREAD! - private Window getClientComponentWindow() { + protected Window getClientComponentWindow() { Component client = getClientComponent(); Container container; @@ -521,7 +419,7 @@ * * @see java.awt.event.InputMethodEvent#InputMethodEvent */ - private void postInputMethodEvent(int id, + protected void postInputMethodEvent(int id, AttributedCharacterIterator text, int committedCharacterCount, TextHitInfo caret, @@ -591,153 +489,12 @@ // This functionality is implemented in a package-private method // to insure that it cannot be overridden by client subclasses. // DO NOT INVOKE CLIENT CODE ON THIS THREAD! - void dispatchComposedText(String chgText, + abstract void dispatchComposedText(String chgText, int chgStyles[], int chgOffset, int chgLength, int caretPosition, - long when) { - if (disposed) { - return; - } - - //Workaround for deadlock bug on solaris2.6_zh bug#4170760 - if (chgText == null - && chgStyles == null - && chgOffset == 0 - && chgLength == 0 - && caretPosition == 0 - && composedText == null - && committedText == null) - return; - - if (composedText == null) { - // TODO: avoid reallocation of those buffers - composedText = new StringBuffer(INITIAL_SIZE); - rawFeedbacks = new IntBuffer(INITIAL_SIZE); - } - if (chgLength > 0) { - if (chgText == null && chgStyles != null) { - rawFeedbacks.replace(chgOffset, chgStyles); - } else { - if (chgLength == composedText.length()) { - // optimization for the special case to replace the - // entire previous text - composedText = new StringBuffer(INITIAL_SIZE); - rawFeedbacks = new IntBuffer(INITIAL_SIZE); - } else { - if (composedText.length() > 0) { - if (chgOffset+chgLength < composedText.length()) { - String text; - text = composedText.toString().substring(chgOffset+chgLength, - composedText.length()); - composedText.setLength(chgOffset); - composedText.append(text); - } else { - // in case to remove substring from chgOffset - // to the end - composedText.setLength(chgOffset); - } - rawFeedbacks.remove(chgOffset, chgLength); - } - } - } - } - if (chgText != null) { - composedText.insert(chgOffset, chgText); - if (chgStyles != null) - rawFeedbacks.insert(chgOffset, chgStyles); - } - - if (composedText.length() == 0) { - composedText = null; - rawFeedbacks = null; - - // if there is any outstanding committed text stored by - // dispatchCommittedText(), it has to be sent to the - // client component. - if (committedText != null) { - dispatchCommittedText(committedText, when); - committedText = null; - return; - } - - // otherwise, send null text to delete client's composed - // text. - postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, - null, - 0, - null, - null, - when); - - return; - } - - // Now sending the composed text to the client - int composedOffset; - AttributedString inputText; - - // if there is any partially committed text, concatenate it to - // the composed text. - if (committedText != null) { - composedOffset = committedText.length(); - inputText = new AttributedString(committedText + composedText); - committedText = null; - } else { - composedOffset = 0; - inputText = new AttributedString(composedText.toString()); - } - - int currentFeedback; - int nextFeedback; - int startOffset = 0; - int currentOffset; - int visiblePosition = 0; - TextHitInfo visiblePositionInfo = null; - - rawFeedbacks.rewind(); - currentFeedback = rawFeedbacks.getNext(); - rawFeedbacks.unget(); - while ((nextFeedback = rawFeedbacks.getNext()) != -1) { - if (visiblePosition == 0) { - visiblePosition = nextFeedback & XIMVisibleMask; - if (visiblePosition != 0) { - int index = rawFeedbacks.getOffset() - 1; - - if (visiblePosition == XIMVisibleToBackward) - visiblePositionInfo = TextHitInfo.leading(index); - else - visiblePositionInfo = TextHitInfo.trailing(index); - } - } - nextFeedback &= ~XIMVisibleMask; - if (currentFeedback != nextFeedback) { - rawFeedbacks.unget(); - currentOffset = rawFeedbacks.getOffset(); - inputText.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT, - convertVisualFeedbackToHighlight(currentFeedback), - composedOffset + startOffset, - composedOffset + currentOffset); - startOffset = currentOffset; - currentFeedback = nextFeedback; - } - } - currentOffset = rawFeedbacks.getOffset(); - if (currentOffset >= 0) { - inputText.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT, - convertVisualFeedbackToHighlight(currentFeedback), - composedOffset + startOffset, - composedOffset + currentOffset); - } - - postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, - inputText.getIterator(), - composedOffset, - TextHitInfo.leading(caretPosition), - visiblePositionInfo, - when); - } + long when); /** * Flushes composed and committed text held in this context. @@ -771,16 +528,7 @@ * Subclasses should override disposeImpl() instead of dispose(). Client * code should always invoke dispose(), never disposeImpl(). */ - protected synchronized void disposeImpl() { - disposeXIC(); - awtLock(); - composedText = null; - committedText = null; - rawFeedbacks = null; - awtUnlock(); - awtFocussedComponent = null; - lastXICFocussedComponent = null; - } + protected abstract void disposeImpl(); /** * Frees all X Window resources associated with this object. @@ -822,19 +570,7 @@ /** * @see java.awt.im.spi.InputMethod#setCompositionEnabled(boolean) */ - public void setCompositionEnabled(boolean enable) { - /* If the composition state is successfully changed, set - the savedCompositionState to 'enable'. Otherwise, simply - return. - setCompositionEnabledNative may throw UnsupportedOperationException. - Don't try to catch it since the method may be called by clients. - Use package private mthod 'resetCompositionState' if you want the - exception to be caught. - */ - if (setCompositionEnabledNative(enable)) { - savedCompositionState = enable; - } - } + public abstract void setCompositionEnabled(boolean enable); /** * @see java.awt.im.spi.InputMethod#isCompositionEnabled @@ -890,17 +626,21 @@ // not call the preedit callback to erase preedit text on calling // XmbResetIC. To work around this problem, do it here by ourselves. awtLock(); - composedText = null; - postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, - null, - 0, - null, - null); + try { + composedText = null; + postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, + null, + 0, + null, + null); - if (text != null && text.length() > 0) { - dispatchCommittedText(text); + if (text != null && text.length() > 0) { + dispatchCommittedText(text); + } + } finally { + // Put awtUnlock into finally block in case an exception is thrown. + awtUnlock(); } - awtUnlock(); // Restore the preedit state if it was enabled if (savedCompositionState) { @@ -974,7 +714,7 @@ * Performs mapping from an XIM visible feedback value to Java IM highlight. * @return Java input method highlight */ - private InputMethodHighlight convertVisualFeedbackToHighlight(int feedback) { + protected InputMethodHighlight convertVisualFeedbackToHighlight(int feedback) { InputMethodHighlight highlight; switch (feedback) { @@ -987,6 +727,7 @@ case XIMHighlight: highlight = InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT; break; + case 0: //None of the value is set by Wnn case XIMPrimary: highlight = InputMethodHighlight.UNSELECTED_CONVERTED_TEXT_HIGHLIGHT; break; @@ -1004,7 +745,7 @@ } // initial capacity size for string buffer, etc. - private static final int INITIAL_SIZE = 64; + protected static final int INITIAL_SIZE = 64; /** * IntBuffer is an inner class that manipulates an int array and @@ -1012,7 +753,7 @@ * access it. (An alternative would be to use ArrayList which may * be too expensive for the work.) */ - private final class IntBuffer { + protected final class IntBuffer { private int[] intArray; private int size; private int index; @@ -1089,9 +830,20 @@ /* * Native methods */ + + /** + * Initialize JNI field and method IDs for fields that may be + * accessed from C. + */ + private static native void initIDs(); + + protected native void turnoffStatusWindow(); + + protected native void disposeXIC(); + private native String resetXIC(); - private native void disposeXIC(); - private native boolean setCompositionEnabledNative(boolean enable); + + protected native boolean setCompositionEnabledNative(boolean enable); + private native boolean isCompositionEnabledNative(); - private native void turnoffStatusWindow(); } 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 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_InputMethod.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2018, 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 @@ -23,21 +23,21 @@ * questions. */ -#ifdef HEADLESS - #error This file should not be included in headless library -#endif +#include "awt.h" +#include "awt_p.h" + +#include +#include #include #include -#include +#include #include -#include +#include -#include "awt.h" -#include "awt_p.h" - -#include -#include +#ifdef HEADLESS + #error This file should not be included in headless library +#endif #define THROW_OUT_OF_MEMORY_ERROR() \ JNU_ThrowOutOfMemoryError((JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2), NULL) @@ -536,10 +536,10 @@ composing = False; /*FALLTHRU*/ case XLookupChars: - /* - printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n", - event->type, event->state, event->keycode, keysym); - */ + /* + printf("lookupString: status=XLookupChars, type=%d, state=%x, keycode=%x, keysym=%x\n", + event->type, event->state, event->keycode, keysym); + */ javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf); if (javastr != NULL) { JNU_CallMethodByName(env, NULL, @@ -552,10 +552,10 @@ break; case XLookupKeySym: - /* - printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n", - event->type, event->state, event->keycode, keysym); - */ + /* + printf("lookupString: status=XLookupKeySym, type=%d, state=%x, keycode=%x, keysym=%x\n", + event->type, event->state, event->keycode, keysym); + */ if (keysym == XK_Multi_key) composing = True; if (! composing) { @@ -565,10 +565,10 @@ break; case XLookupNone: - /* - printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n", - event->type, event->state, event->keycode, keysym); - */ + /* + printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n", + event->type, event->state, event->keycode, keysym); + */ break; } @@ -576,8 +576,7 @@ } #if defined(__linux__) || defined(MACOSX) -static StatusWindow *createStatusWindow( - Window parent) { +static StatusWindow *createStatusWindow(Window parent) { StatusWindow *statusWindow; XSetWindowAttributes attrib; unsigned long attribmask; @@ -600,7 +599,7 @@ AwtGraphicsConfigDataPtr adata; extern int awt_numScreens; /*hardcode the size right now, should get the size base on font*/ - int width=80, height=22; + int width=80, height=22; Window rootWindow; Window *ignoreWindowPtr; unsigned int ignoreUnit; @@ -652,10 +651,10 @@ if (xx < 0 ){ xx = 0; } - if (xx + width > xxwa.width){ + if (xx + width > xxwa.width) { xx = xxwa.width - width; } - if (yy + height > xxwa.height){ + if (yy + height > xxwa.height) { yy = xxwa.height - height; } @@ -724,7 +723,7 @@ return; } - if (ON == False){ + if (ON == False) { XUnmapWindow(dpy, statusWindow->w); statusWindow->on = False; return; @@ -732,7 +731,7 @@ parent = JNU_CallMethodByName(GetJNIEnv(), NULL, pX11IMData->x11inputmethod, "getCurrentParentWindow", "()J").j; - if (statusWindow->parent != parent){ + if (statusWindow->parent != parent) { statusWindow->parent = parent; } XGetWindowAttributes(dpy, parent, &xwa); @@ -741,21 +740,22 @@ xwa.x, xwa.y, &x, &y, &child); - if (statusWindow->x != x - || statusWindow->y != y - || statusWindow->height != xwa.height){ + if (statusWindow->x != x || + statusWindow->y != y || + statusWindow->height != xwa.height) + { statusWindow->x = x; statusWindow->y = y; statusWindow->height = xwa.height; x = statusWindow->x - statusWindow->off_x; y = statusWindow->y + statusWindow->height - statusWindow->off_y; - if (x < 0 ){ + if (x < 0 ) { x = 0; } - if (x + statusWindow->statusW > statusWindow->rootW){ + if (x + statusWindow->statusW > statusWindow->rootW) { x = statusWindow->rootW - statusWindow->statusW; } - if (y + statusWindow->statusH > statusWindow->rootH){ + if (y + statusWindow->statusH > statusWindow->rootH) { y = statusWindow->rootH - statusWindow->statusH; } XMoveWindow(dpy, statusWindow->w, x, y); @@ -790,61 +790,19 @@ XDrawLine(dpy, win, dimgc, 2, height-3, width-bwidth-1, height-3); XDrawLine(dpy, win, dimgc, 2, 2, width-bwidth-2, 2); XDrawLine(dpy, win, dimgc, width-bwidth, 2, width-bwidth, height-3); - if (statusWindow->fontset){ + if (statusWindow->fontset) { XmbDrawString(dpy, win, statusWindow->fontset, fggc, bwidth + 2, height - bwidth - 4, statusWindow->status, strlen(statusWindow->status)); - } - else{ + } else { /*too bad we failed to create a fontset for this locale*/ XDrawString(dpy, win, fggc, bwidth + 2, height - bwidth - 4, "[InputMethod ON]", strlen("[InputMethod ON]")); } } -void statusWindowEventHandler(XEvent event){ - JNIEnv *env = GetJNIEnv(); - X11InputMethodData *pX11IMData = NULL; - StatusWindow *statusWindow; - - if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) { - currentX11InputMethodInstance = NULL; - return; - } - - if (NULL == currentX11InputMethodInstance - || NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance)) - || NULL == (statusWindow = pX11IMData->statusWindow) - || statusWindow->w != event.xany.window){ - return; - } - - switch (event.type){ - case Expose: - paintStatusWindow(statusWindow); - break; - case MapNotify: - case ConfigureNotify: - { - /*need to reset the stackMode...*/ - XWindowChanges xwc; - int value_make = CWStackMode; - xwc.stack_mode = TopIf; - XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); - } - break; - /* - case UnmapNotify: - case VisibilityNotify: - break; - */ - default: - break; - } -} - -static void adjustStatusWindow(Window shell){ +static void adjustStatusWindow(Window shell) { JNIEnv *env = GetJNIEnv(); X11InputMethodData *pX11IMData = NULL; StatusWindow *statusWindow; @@ -853,9 +811,11 @@ || !isX11InputMethodGRefInList(currentX11InputMethodInstance) || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance)) || NULL == (statusWindow = pX11IMData->statusWindow) - || !statusWindow->on) { + || !statusWindow->on) + { return; } + { XWindowAttributes xwa; int x, y; @@ -875,7 +835,7 @@ x = statusWindow->x - statusWindow->off_x; y = statusWindow->y + statusWindow->height - statusWindow->off_y; - if (x < 0 ){ + if (x < 0 ) { x = 0; } if (x + statusWindow->statusW > statusWindow->rootW){ @@ -889,6 +849,7 @@ } } #endif /* __linux__ || MACOSX */ + /* * Creates two XICs, one for active clients and the other for passive * clients. All information on those XICs are stored in the @@ -931,9 +892,9 @@ return FALSE ; } -#if defined(__linux__) || defined(MACOSX) on_the_spot_styles |= XIMStatusNothing; +#if defined(__linux__) || defined(MACOSX) /*kinput does not support XIMPreeditCallbacks and XIMStatusArea at the same time, so use StatusCallback to draw the status ourself @@ -944,8 +905,6 @@ break; } } -#else /*! __linux__ && !MACOSX */ - on_the_spot_styles |= XIMStatusNothing; #endif /* __linux__ || MACOSX */ for (i = 0; i < im_styles->count_styles; i++) { @@ -1023,12 +982,12 @@ XFree((void *)preedit); } #else /* !__linux__ && !MACOSX */ - pX11IMData->ic_active = XCreateIC(X11im, - XNClientWindow, w, - XNFocusWindow, w, - XNInputStyle, active_styles, - XNPreeditAttributes, preedit, - NULL); + pX11IMData->ic_active = XCreateIC(X11im, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, active_styles, + XNPreeditAttributes, preedit, + NULL); XFree((void *)preedit); #endif /* __linux__ || MACOSX */ } else { @@ -1075,14 +1034,14 @@ PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data) { /*ARGSUSED*/ - /* printf("Native: PreeditCaretCallback\n"); */ + /* printf("Native: PreeditStartCallback\n"); */ } static void PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data) { /*ARGSUSED*/ - /* printf("Native: StatusStartCallback\n"); */ + /* printf("Native: PreeditDoneCallback\n"); */ } /* @@ -1187,7 +1146,6 @@ { /*ARGSUSED*/ /* printf("Native: PreeditCaretCallback\n"); */ - } #if defined(__linux__) || defined(MACOSX) @@ -1196,7 +1154,6 @@ { /*ARGSUSED*/ /*printf("StatusStartCallback:\n"); */ - } static void @@ -1204,7 +1161,6 @@ { /*ARGSUSED*/ /*printf("StatusDoneCallback:\n"); */ - } static void @@ -1230,25 +1186,23 @@ || NULL == (statusWindow = pX11IMData->statusWindow)){ goto finally; } - currentX11InputMethodInstance = (jobject)client_data; + currentX11InputMethodInstance = (jobject)client_data; - if (status_draw->type == XIMTextType){ + if (status_draw->type == XIMTextType) { XIMText *text = (status_draw->data).text; - if (text != NULL){ - if (text->string.multi_byte != NULL) { - strncpy(statusWindow->status, text->string.multi_byte, MAX_STATUS_LEN); - statusWindow->status[MAX_STATUS_LEN - 1] = '\0'; - } - else { - char *mbstr = wcstombsdmp(text->string.wide_char, text->length); - strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN); - statusWindow->status[MAX_STATUS_LEN - 1] = '\0'; - } - statusWindow->on = True; - onoffStatusWindow(pX11IMData, statusWindow->parent, True); - paintStatusWindow(statusWindow); - } - else { + if (text != NULL) { + if (text->string.multi_byte != NULL) { + strncpy(statusWindow->status, text->string.multi_byte, MAX_STATUS_LEN); + statusWindow->status[MAX_STATUS_LEN - 1] = '\0'; + } else { + char *mbstr = wcstombsdmp(text->string.wide_char, text->length); + strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN); + statusWindow->status[MAX_STATUS_LEN - 1] = '\0'; + } + statusWindow->on = True; + onoffStatusWindow(pX11IMData, statusWindow->parent, True); + paintStatusWindow(statusWindow); + } else { statusWindow->on = False; /*just turnoff the status window paintStatusWindow(statusWindow); @@ -1327,26 +1281,10 @@ X11InputMethodData *pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance); } -/* - * Class: sun_awt_X11InputMethod - * Method: initIDs - * Signature: ()V - */ - -/* This function gets called from the static initializer for - X11InputMethod.java - to initialize the fieldIDs for fields that may be accessed from C */ -JNIEXPORT void JNICALL -Java_sun_awt_X11InputMethod_initIDs(JNIEnv *env, jclass cls) -{ - x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J"); -} - - JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XInputMethod_openXIMNative(JNIEnv *env, - jobject this, - jlong display) + jobject this, + jlong display) { Bool registered; @@ -1375,8 +1313,8 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env, - jobject this, - jlong window) + jobject this, + jlong window) { X11InputMethodData *pX11IMData; jobject globalRef; @@ -1423,10 +1361,10 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env, - jobject this, - jlong w, - jboolean req, - jboolean active) + jobject this, + jlong w, + jboolean req, + jboolean active) { X11InputMethodData *pX11IMData; AWT_LOCK(); @@ -1471,9 +1409,27 @@ AWT_UNLOCK(); } -JNIEXPORT void JNICALL -Java_sun_awt_X11InputMethod_turnoffStatusWindow(JNIEnv *env, - jobject this) +/* + * Class: sun_awt_X11InputMethodBase + * Method: initIDs + * Signature: ()V + * This function gets called from the static initializer for + * X11InputMethod.java to initialize the fieldIDs for fields + * that may be accessed from C + */ +JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_initIDs + (JNIEnv *env, jclass cls) +{ + x11InputMethodIDs.pData = (*env)->GetFieldID(env, cls, "pData", "J"); +} + +/* + * Class: sun_awt_X11InputMethodBase + * Method: turnoffStatusWindow + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_turnoffStatusWindow + (JNIEnv *env, jobject this) { #if defined(__linux__) || defined(MACOSX) X11InputMethodData *pX11IMData; @@ -1495,9 +1451,13 @@ #endif } -JNIEXPORT void JNICALL -Java_sun_awt_X11InputMethod_disposeXIC(JNIEnv *env, - jobject this) +/* + * Class: sun_awt_X11InputMethodBase + * Method: disposeXIC + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11InputMethodBase_disposeXIC + (JNIEnv *env, jobject this) { X11InputMethodData *pX11IMData = NULL; @@ -1518,9 +1478,13 @@ AWT_UNLOCK(); } -JNIEXPORT jstring JNICALL -Java_sun_awt_X11InputMethod_resetXIC(JNIEnv *env, - jobject this) +/* + * Class: sun_awt_X11InputMethodBase + * Method: resetXIC + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_sun_awt_X11InputMethodBase_resetXIC + (JNIEnv *env, jobject this) { X11InputMethodData *pX11IMData; char *xText = NULL; @@ -1564,9 +1528,9 @@ } /* - * Class: sun_awt_X11InputMethod + * Class: sun_awt_X11InputMethodBase * Method: setCompositionEnabledNative - * Signature: (ZJ)V + * Signature: (Z)Z * * This method tries to set the XNPreeditState attribute associated with the current * XIC to the passed in 'enable' state. @@ -1575,9 +1539,8 @@ * 'enable' state; Otherwise, if XSetICValues fails to set this attribute, * java.lang.UnsupportedOperationException will be thrown. JNI_FALSE is returned if this * method fails due to other reasons. - * */ -JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_setCompositionEnabledNative +JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_setCompositionEnabledNative (JNIEnv *env, jobject this, jboolean enable) { X11InputMethodData *pX11IMData; @@ -1603,18 +1566,17 @@ } /* - * Class: sun_awt_X11InputMethod + * Class: sun_awt_X11InputMethodBase * Method: isCompositionEnabledNative - * Signature: (J)Z + * Signature: ()Z * * This method tries to get the XNPreeditState attribute associated with the current XIC. * * Return JNI_TRUE if the XNPreeditState is successfully retrieved. Otherwise, if * XGetICValues fails to get this attribute, java.lang.UnsupportedOperationException * will be thrown. JNI_FALSE is returned if this method fails due to other reasons. - * */ -JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethod_isCompositionEnabledNative +JNIEXPORT jboolean JNICALL Java_sun_awt_X11InputMethodBase_isCompositionEnabledNative (JNIEnv *env, jobject this) { X11InputMethodData *pX11IMData = NULL; diff --git a/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c b/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c --- a/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c +++ b/src/java.desktop/unix/native/libawt_xawt/xawt/XlibWrapper.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2018, 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 @@ -23,31 +23,32 @@ * questions. */ +#include "awt.h" +#include "awt_util.h" +#include "jni.h" +#include "jlong.h" +#include "Region.h" +#include "sizecalc.h" +#include "utility/rect.h" + #include "sun_awt_X11_XlibWrapper.h" -#include -#include -#include -#include -#include + +#include +#include #include #include -#include -#include +#include #include - -#include -#include -#include -#include +#include +#include +#include +#include +#include -#include -#include -#include - -#include -#include "utility/rect.h" - -#include +#if defined(AIX) +#undef X_HAVE_UTF8_STRING +extern Bool statusWindowEventHandler(XEvent event); +#endif // From XWindow.c extern KeySym keycodeToKeysym(Display *display, KeyCode keycode, int index); @@ -288,7 +289,6 @@ return ScreenCount((Display *) jlong_to_ptr(display)); } - /* * Class: XlibWrapper * Method: XCreateWindow @@ -303,7 +303,6 @@ return XCreateWindow((Display *) jlong_to_ptr(display),(Window) window, x, y, w, h, border_width, depth, wclass, (Visual *) jlong_to_ptr(visual), valuemask, (XSetWindowAttributes *) jlong_to_ptr(attributes)); - } /* @@ -320,7 +319,6 @@ (jlong_to_ptr(keysym_uppercase))); } - /* * Class: XlibWrapper * Method: XMapWindow @@ -331,7 +329,6 @@ { AWT_CHECK_HAVE_LOCK(); XMapWindow( (Display *)jlong_to_ptr(display),(Window) window); - } /* @@ -344,7 +341,6 @@ { AWT_CHECK_HAVE_LOCK(); XMapRaised( (Display *)jlong_to_ptr(display),(Window) window); - } /* @@ -355,10 +351,8 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XRaiseWindow (JNIEnv *env, jclass clazz, jlong display, jlong window) { - AWT_CHECK_HAVE_LOCK(); XRaiseWindow( (Display *)jlong_to_ptr(display),(Window) window); - } /* @@ -369,10 +363,8 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XLowerWindow (JNIEnv *env, jclass clazz, jlong display, jlong window) { - AWT_CHECK_HAVE_LOCK(); XLowerWindow( (Display *)jlong_to_ptr(display),(Window) window); - } /* @@ -383,10 +375,8 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XRestackWindows (JNIEnv *env, jclass clazz, jlong display, jlong windows, jint length) { - AWT_CHECK_HAVE_LOCK(); XRestackWindows( (Display *) jlong_to_ptr(display), (Window *) jlong_to_ptr(windows), length); - } /* @@ -411,11 +401,10 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSetInputFocus (JNIEnv *env, jclass clazz, jlong display, jlong window) { - AWT_CHECK_HAVE_LOCK(); XSetInputFocus( (Display *)jlong_to_ptr(display),(Window) window, RevertToPointerRoot, CurrentTime); +} -} /* * Class: XlibWrapper * Method: XSetInputFocus2 @@ -424,10 +413,8 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSetInputFocus2 (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong time) { - AWT_CHECK_HAVE_LOCK(); XSetInputFocus( (Display *)jlong_to_ptr(display),(Window) window, RevertToPointerRoot, time); - } /* @@ -438,7 +425,6 @@ JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XGetInputFocus (JNIEnv *env, jclass clazz, jlong display) { - Window focusOwner; int revert_to; AWT_CHECK_HAVE_LOCK_RETURN(0); @@ -446,7 +432,6 @@ return focusOwner; } - /* * Class: XlibWrapper * Method: XDestroyWindow @@ -525,8 +510,6 @@ } - - JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSelectInput (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong mask) { @@ -543,6 +526,7 @@ (unsigned long)bits_to_change, (unsigned long)values_for_bits); } + JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XkbSelectEventDetails (JNIEnv *env, jclass clazz, jlong display, jlong device, jlong event_type, jlong bits_to_change, jlong values_for_bits) @@ -553,6 +537,7 @@ (unsigned long)bits_to_change, (unsigned long)values_for_bits); } + JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XkbQueryExtension (JNIEnv *env, jclass clazz, jlong display, jlong opcode_rtrn, jlong event_rtrn, jlong error_rtrn, jlong major_in_out, jlong minor_in_out) @@ -567,6 +552,7 @@ (int *) jlong_to_ptr(minor_in_out)); return status ? JNI_TRUE : JNI_FALSE; } + JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XkbLibraryVersion (JNIEnv *env, jclass clazz, jlong lib_major_in_out, jlong lib_minor_in_out) { @@ -587,6 +573,7 @@ (unsigned int) which, (unsigned int) device_spec); } + JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XkbGetUpdatedMap (JNIEnv *env, jclass clazz, jlong display, jlong which, jlong xkb) { @@ -626,8 +613,6 @@ * Method: XNextEvent * Signature: (JJ)V */ - - JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XNextEvent (JNIEnv *env, jclass clazz, jlong display, jlong ptr) { @@ -640,7 +625,6 @@ * Method: XMaskEvent * Signature: (JJJ)V */ - JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XMaskEvent (JNIEnv *env, jclass clazz, jlong display, jlong event_mask, jlong event_return) { @@ -653,7 +637,6 @@ * Method: XWindowEvent * Signature: (JJJJ)V */ - JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XWindowEvent (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong event_mask, jlong event_return) { @@ -670,6 +653,11 @@ (JNIEnv *env, jclass clazz, jlong ptr, jlong window) { AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); +#if defined(AIX) + if (True == statusWindowEventHandler(*((XEvent *)(uintptr_t)ptr))) { + return (jboolean)True; + } +#endif return (jboolean) XFilterEvent((XEvent *) jlong_to_ptr(ptr), (Window) window); } @@ -727,19 +715,15 @@ XPeekEvent((Display *) jlong_to_ptr(display),jlong_to_ptr(ptr)); } - /* * Class: sun_awt_X11_XlibWrapper * Method: XMoveResizeWindow * Signature: (JJIIII)V */ - JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XMoveResizeWindow (JNIEnv *env, jclass clazz, jlong display, jlong window, jint x , jint y , jint width, jint height) { - AWT_CHECK_HAVE_LOCK(); XMoveResizeWindow( (Display *) jlong_to_ptr(display), (Window) window, x, y, width, height); - } /* @@ -747,10 +731,8 @@ * Method: XResizeWindow * Signature: (JJII)V */ - JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XResizeWindow -(JNIEnv *env, jclass clazz, jlong display, jlong window, jint width, jint height) -{ +(JNIEnv *env, jclass clazz, jlong display, jlong window, jint width, jint height) { AWT_CHECK_HAVE_LOCK(); XResizeWindow( (Display *) jlong_to_ptr(display),(Window) window,width,height); } @@ -760,10 +742,8 @@ * Method: XMoveWindow * Signature: (JJII)V */ - JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XMoveWindow -(JNIEnv *env, jclass clazz, jlong display, jlong window, jint width, jint height) -{ +(JNIEnv *env, jclass clazz, jlong display, jlong window, jint width, jint height) { AWT_CHECK_HAVE_LOCK(); XMoveWindow( (Display *) jlong_to_ptr(display),(Window) window,width,height); } @@ -774,13 +754,10 @@ * Method: XSetWindowBackground * Signature: (JJJ)V */ - JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSetWindowBackground (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong background_pixel) { - AWT_CHECK_HAVE_LOCK(); XSetWindowBackground((Display *) jlong_to_ptr(display),window,background_pixel); - } @@ -803,10 +780,8 @@ */ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSync (JNIEnv *env, jclass clazz, jlong display, jint discard) { - AWT_CHECK_HAVE_LOCK(); XSync((Display *) jlong_to_ptr(display), discard); - } JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XTranslateCoordinates @@ -855,7 +830,6 @@ cname = ""; } - AWT_CHECK_HAVE_LOCK(); #ifdef X_HAVE_UTF8_STRING @@ -866,7 +840,6 @@ XStdICCTextStyle, &tp); #endif - if (status == Success || status > 0) { XChangeProperty((Display *)jlong_to_ptr(display), window, atom, tp.encoding, tp.format, PropModeReplace, tp.value, tp.nitems); if (tp.value != NULL) { @@ -1005,7 +978,6 @@ return XCreateFontCursor((Display *) jlong_to_ptr(display), (int) shape); } - /* * Class: sun_awt_X11_XlibWrapper * Method: XCreatePixmapCursor @@ -1019,7 +991,6 @@ (XColor *) jlong_to_ptr(fore), (XColor *) jlong_to_ptr(back), x, y); } - /* * Class: sun_awt_X11_XlibWrapper * Method: XQueryBestCursor @@ -1038,7 +1009,6 @@ else return JNI_TRUE; } - /* * Class: sun_awt_X11_XlibWrapper * Method: XFreeCursor @@ -1084,7 +1054,6 @@ (XSetWindowAttributes *) jlong_to_ptr(attributes)); } - /* * Class: sun_awt_X11_XlibWrapper * Method: XSetTransientFor @@ -1181,7 +1150,6 @@ } } - /* * Class: sun_awt_X11_XlibWrapper * Method: getScreenOfWindow @@ -1253,7 +1221,6 @@ return res; } - /* * Class: sun_awt_X11_XlibWrapper * Method: ServerVendor @@ -1265,6 +1232,7 @@ AWT_CHECK_HAVE_LOCK_RETURN(NULL); return JNU_NewStringPlatform(env, ServerVendor((Display*)jlong_to_ptr(display))); } + /* * Class: sun_awt_X11_XlibWrapper * Method: VendorRelease @@ -1276,6 +1244,7 @@ AWT_CHECK_HAVE_LOCK_RETURN(0); return VendorRelease((Display*)jlong_to_ptr(display)); } + /* * Class: sun_awt_X11_XlibWrapper * Method: IsXsunKPBehavior @@ -1309,7 +1278,6 @@ } } - JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_IsSunKeyboard (JNIEnv *env, jclass clazz, jlong display) { @@ -1407,7 +1375,6 @@ return (*(XErrorHandler)jlong_to_ptr(handler))((Display*) jlong_to_ptr(display), (XErrorEvent*) jlong_to_ptr(event_ptr)); } - /* * Class: sun_awt_X11_XlibWrapper * Method: PrintXErrorEvent @@ -1431,7 +1398,6 @@ } } - /* * Class: sun_awt_X11_XlibWrapper * Method: XInternAtoms @@ -1451,8 +1417,6 @@ return status; } - - /* * Class: sun_awt_X11_XlibWrapper * Method: XGetWindowAttributes @@ -1468,7 +1432,6 @@ return status; } - /* * Class: sun_awt_X11_XlibWrapper * Method: XGetGeometry @@ -1490,7 +1453,6 @@ return status; } - /* * Class: sun_awt_X11_XlibWrapper * Method: XGetWMNormalHints @@ -1546,7 +1508,6 @@ (XEvent*) jlong_to_ptr(event)); } - /* * Class: sun_awt_X11_XlibWrapper * Method: XQueryTree @@ -1564,7 +1525,6 @@ (unsigned int*) jlong_to_ptr(nchildren_return)); } - /* * Class: sun_awt_X11_XlibWrapper * Method: memcpy @@ -1576,7 +1536,6 @@ memcpy(jlong_to_ptr(dest_ptr), jlong_to_ptr(src_ptr), length); } - JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSetMinMaxHints (JNIEnv *env, jclass clazz, jlong display, jlong window, jint x, jint y, jint width, jint height, jlong flags) { XSizeHints * hints; @@ -1595,7 +1554,6 @@ XFree(hints); } - JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XGetVisualInfo (JNIEnv *env, jclass clazz, jlong display, jlong vinfo_mask, jlong vinfo_template, jlong nitems_return) @@ -1626,7 +1584,6 @@ XBell((Display*)jlong_to_ptr(display), percent); } - /* * Class: sun_awt_X11_XlibWrapper * Method: XAllocColor @@ -1643,7 +1600,6 @@ else return JNI_TRUE; } - /* * Class: sun_awt_X11_XlibWrapper * Method: XCreateBitmapFromData @@ -1657,7 +1613,6 @@ (char *) jlong_to_ptr(data), width, height); } - /* * Class: sun_awt_X11_XlibWrapper * Method: XFreePixmap @@ -1772,6 +1727,7 @@ AWT_CHECK_HAVE_LOCK_RETURN(0); return XCreatePixmap((Display*)jlong_to_ptr(display), (Drawable)drawable, width, height, depth); } + JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XCreateImage (JNIEnv *env, jclass clazz, jlong display, jlong visual_ptr, @@ -1783,6 +1739,7 @@ depth, format, offset, (char*) jlong_to_ptr(data), width, height, bitmap_pad, bytes_per_line)); } + JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XCreateGC (JNIEnv *env, jclass clazz, jlong display, jlong drawable, @@ -1806,6 +1763,7 @@ img->data = NULL; XDestroyImage(img); } + JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XPutImage(JNIEnv *env, jclass clazz, jlong display, jlong drawable, jlong gc, jlong image, jint src_x, jint src_y, jint dest_x, jint dest_y, jint width, jint height) { @@ -1813,18 +1771,21 @@ XPutImage((Display*)jlong_to_ptr(display), (Drawable)drawable, (GC) jlong_to_ptr(gc), (XImage*) jlong_to_ptr(image), src_x, src_y, dest_x, dest_y, width, height); } + JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XFreeGC(JNIEnv *env, jclass clazz, jlong display, jlong gc) { AWT_CHECK_HAVE_LOCK(); XFreeGC((Display*) jlong_to_ptr(display), (GC) jlong_to_ptr(gc)); } + JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSetWindowBackgroundPixmap(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong pixmap) { AWT_CHECK_HAVE_LOCK(); XSetWindowBackgroundPixmap((Display*) jlong_to_ptr(display), (Window)window, (Pixmap)pixmap); } + JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XClearWindow(JNIEnv *env, jclass clazz, jlong display, jlong window) { @@ -1922,7 +1883,6 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XQueryKeymap (JNIEnv *env, jclass clazz, jlong display, jlong vector) { - AWT_CHECK_HAVE_LOCK(); XQueryKeymap( (Display *) jlong_to_ptr(display), (char *) jlong_to_ptr(vector)); } @@ -1961,6 +1921,7 @@ // printf("-------------------------------------^^^^\n"); return (jint)(sr.group); } + JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XkbKeycodeToKeysym(JNIEnv *env, jclass clazz, jlong display, jint keycode, @@ -1989,6 +1950,7 @@ AWT_CHECK_HAVE_LOCK(); XFreeModifiermap((XModifierKeymap*) jlong_to_ptr(keymap)); } + /* * Class: sun_awt_X11_XlibWrapper * Method: XRefreshKeyboardMapping @@ -2034,7 +1996,6 @@ ) ? True : False; } - JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XNextSecondaryLoopEvent(JNIEnv *env, jclass clazz, jlong display, jlong ptr) { @@ -2062,7 +2023,6 @@ exitSecondaryLoop = True; AWT_NOTIFY_ALL(); } -/*******************************************************************************/ JNIEXPORT jobjectArray JNICALL Java_sun_awt_X11_XlibWrapper_XTextPropertyToStringList(JNIEnv *env, @@ -2181,7 +2141,6 @@ return ret; } - JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XPutBackEvent(JNIEnv *env, jclass clazz,