--- old/make/lib/Awt2dLibraries.gmk 2018-04-13 18:47:00.000000000 +0900 +++ new/make/lib/Awt2dLibraries.gmk 2018-04-13 18:46:59.000000000 +0900 @@ -335,10 +335,16 @@ BUILD_LIBAWT_XAWT_debug_mem.c_CFLAGS := -w endif + ifeq ($(OPENJDK_TARGET_OS), aix) + LIBAWT_XAWT_DIRS += $(TOPDIR)/src/java.desktop/aix/native/libawt_xawt $(TOPDIR)/src/java.desktop/aix/native/libawt_xawt/xawt + LIBAWT_XAWT_EXCLUDE_FILES += unix/native/libawt_xawt/awt/awt_InputMethod.c unix/native/libawt_xawt/xawt/XlibWrapper.c + endif + $(eval $(call SetupJdkLibrary, BUILD_LIBAWT_XAWT, \ NAME := awt_xawt, \ SRC := $(LIBAWT_XAWT_DIRS), \ EXCLUDES := $(LIBAWT_XAWT_EXCLUDES), \ + EXCLUDE_FILES := $(LIBAWT_XAWT_EXCLUDE_FILES), \ OPTIMIZATION := LOW, \ CFLAGS := $(CFLAGS_JDKLIB) $(LIBAWT_XAWT_CFLAGS) \ $(X_CFLAGS), \ --- /dev/null 2018-02-05 10:17:31.364998584 +0900 +++ new/src/java.desktop/aix/classes/sun/awt/X11InputMethod.java 2018-04-13 18:47:00.000000000 +0900 @@ -0,0 +1,1239 @@ +/* + * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.awt; + +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 + + // to keep the instance of activating if IM resumed + static protected X11InputMethod activatedInstance = null; + + // 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(); + + /** + * Constructs an X11InputMethod instance. It initializes the XIM + * environment if it's not done yet. + * + * @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; + } + } + + /** + * Reset the composition state to the current composition state. + */ + private void resetCompositionState() { + if (compositionEnableSupported && haveActiveClient()) { + try { + /* Restore the composition mode to the last saved composition + mode. */ + setCompositionEnabled(savedCompositionState); + } catch (UnsupportedOperationException e) { + compositionEnableSupported = false; + } + } + } + + /** + * 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 (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) { + if (!createXIC()) { + return; + } + disposed = false; + } + + /* reset input context if necessary and set the XIC focus + */ + resetXICifneeded(); + ComponentPeer lastXICFocussedComponentPeer = null; + ComponentPeer awtFocussedComponentPeer = getPeer(awtFocussedComponent); + setStatusAreaVisible(true, pData); + + if (awtFocussedComponentPeer != null) { + setXICFocus(awtFocussedComponentPeer, true, haveActiveClient()); + } + lastXICFocussedComponent = awtFocussedComponent; + isLastXICActive = haveActiveClient(); + isActive = true; + if (savedCompositionState) { + resetCompositionState(); + } + } + + 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. + */ + activatedInstance = null; + savedCompositionState = getCompositionState(); + + if (isTemporary){ + //turn the status window off... + turnoffStatusWindow(); + } + + if (!isTemporary){ + if (awtFocussedComponent != null ){ + ComponentPeer awtFocussedComponentPeer = getPeer(awtFocussedComponent); + if (awtFocussedComponentPeer != null){ + setXICFocus(awtFocussedComponentPeer, false, isAc); + } + } + lastXICFocussedComponent = null; + } else { + /* 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; + setStatusAreaVisible(false, pData); + } + + /** + * 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 + if (pData != 0) { + setStatusAreaVisible(false, pData); + turnoffStatusWindow(); + } + } + + /** + * @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 + * information. The XIM highlight attributes are translated via + * fixed mapping (i.e., independent from any underlying input + * method engine). 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 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; + + // 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); + 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) { + // 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) { + 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; + } + + // 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; + + // 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); + } + + /** + * 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; + } + } + + /* 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; + } + + void clearComposedText() { + if (EventQueue.isDispatchThread()) { + clearComposedText(EventQueue.getMostRecentEventTime()); + } + } + + /* + * Subclasses should override disposeImpl() instead of dispose(). Client + * code should always invoke dispose(), never disposeImpl(). + */ + protected synchronized void disposeImpl() { + disposeXIC(); + awtLock(); + try { + clearComposedText(); + } finally { + // Put awtUnlock into finally block in case an exception is thrown in clearComposedText. + awtUnlock(); + } + awtFocussedComponent = null; + lastXICFocussedComponent = null; + needResetXIC = false; + savedCompositionState = false; + compositionEnableSupported = true; + } + + /** + * 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) { + /* 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. + */ + boolean pre, post; + pre=getCompositionState(); + + if (setCompositionEnabledNative(enable)) { + savedCompositionState = enable; + } + + post=getCompositionState(); + if (pre != post && post == enable){ + if (enable == false) flushText(); + if (awtFocussedComponent != null && isActive){ + setXICFocus(getPeer(awtFocussedComponent), + true, haveActiveClient()); + } + } + } + + /** + * @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(); + try { + composedText = null; + postInputMethodEvent(InputMethodEvent.INPUT_METHOD_TEXT_CHANGED, + null, + 0, + null, + null); + + if (text != null && text.length() > 0) { + dispatchCommittedText(text); + } + } finally { + // Put awtUnlock into finally block in case an exception is thrown. + 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 0: //None of the value is set by Wnn + 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); +} --- /dev/null 2018-02-05 10:17:31.364998584 +0900 +++ new/src/java.desktop/aix/native/libawt_xawt/awt/awt_InputMethod.c 2018-04-13 18:47:02.000000000 +0900 @@ -0,0 +1,3032 @@ +/* + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifdef HEADLESS + #error This file should not be included in headless library +#endif + +#include +#include +#include +#include +#include + +#if defined(AIX) +#include + +#include +#include +#include +#endif + +#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) + +#if !defined(AIX) +#define RESUME_ENABLE 1 +#endif + +struct X11InputMethodIDs { + jfieldID pData; +} x11InputMethodIDs; + +#if !defined(AIX) +static void PreeditStartCallback(XIC, XPointer, XPointer); +#else +static int PreeditStartCallback(XIC, XPointer, XPointer); +#endif +static void PreeditDoneCallback(XIC, XPointer, XPointer); +static void PreeditDrawCallback(XIC, XPointer, + XIMPreeditDrawCallbackStruct *); +static void PreeditCaretCallback(XIC, XPointer, + XIMPreeditCaretCallbackStruct *); +#if defined(__linux__) || defined(MACOSX) || defined(AIX) +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) +#if defined(AIX) +/* added style to allow for in-place composition, such as "dead" keys for accents */ +#define IN_PLACE_STYLES (XIMPreeditNothing | XIMStatusNone) +#endif + +#define PreeditStartIndex 0 +#define PreeditDoneIndex 1 +#define PreeditDrawIndex 2 +#define PreeditCaretIndex 3 +#if defined(__linux__) || defined(MACOSX) || defined(AIX) +#define StatusStartIndex 4 +#define StatusDoneIndex 5 +#define StatusDrawIndex 6 +#define NCALLBACKS 7 +#else +#define NCALLBACKS 4 +#endif + +#if defined(AIX) +#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 */ +#endif + +/* + * Callback function pointers: the order has to match the *Index + * values above. + */ +static XIMProc callback_funcs[NCALLBACKS] = { + (XIMProc)PreeditStartCallback, + (XIMProc)PreeditDoneCallback, + (XIMProc)PreeditDrawCallback, + (XIMProc)PreeditCaretCallback, +#if defined(__linux__) || defined(MACOSX) || defined(AIX) + (XIMProc)StatusStartCallback, + (XIMProc)StatusDoneCallback, + (XIMProc)StatusDrawCallback, +#endif +}; + +#if defined(__linux__) || defined(MACOSX) || defined(AIX) +#define MAX_STATUS_LEN 100 +typedef struct { + Window w; /*status window id */ + Window root; /*the root window id */ + Window parent; /*parent shell window */ +#if defined(AIX) + Window grandParent; /*window has WM frame */ +#endif + int x, y; /*parent's upperleft position */ + int width, height; /*parent's width, height */ + GC lightGC; /*gc for light border */ + GC dimGC; /*gc for dim border */ + GC bgGC; /*normal painting */ + GC fgGC; /*normal painting */ + int statusW, statusH; /*status window's w, h */ + int rootW, rootH; /*root window's w, h */ + int bWidth; /*border width */ +#if !defined(AIX) + char status[MAX_STATUS_LEN]; /*status text */ +#else + wchar_t status[MAX_STATUS_LEN+1]; /*status text */ +#endif + XFontSet fontset; /*fontset for drawing */ + int off_x, off_y; + Bool on; /*if the status window on*/ +#if defined(AIX) + 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 */ +#endif +} StatusWindow; +#endif + +/* + * X11InputMethodData keeps per X11InputMethod instance information. A pointer + * to this data structure is kept in an X11InputMethod object (pData). + */ +typedef struct _X11InputMethodData { + XIC current_ic; /* current X Input Context */ + XIC ic_active; /* X Input Context for active clients */ + XIC ic_passive; /* X Input Context for passive clients */ + XIMCallback *callbacks; /* callback parameters */ + jobject x11inputmethod; /* global ref to X11InputMethod instance */ + /* associated with the XIC */ +#if defined(__linux__) || defined(MACOSX) || defined(AIX) + StatusWindow *statusWindow; /* our own status window */ +#endif +#if !defined(AIX) + char *lookup_buf; /* buffer used for XmbLookupString */ + int lookup_buf_len; /* lookup buffer size in bytes */ +#else + Bool passiveStatusWindow;/* Passive Client uses StatusWindow */ + Bool isActiveClient; /* True:clinet is active */ + Bool forceReset; /* True: call resetXIC before UnsetICFocus */ +#endif +} X11InputMethodData; + +#if defined(RESUME_ENABLE) +/* + * 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; +#endif + +/* 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. */ +jobject currentX11InputMethodInstance = NULL; + +Window currentFocusWindow = 0; /* current window that has focus for input + method. (the best place to put this + information should be + currentX11InputMethodInstance's pData) */ +static XIM X11im = NULL; +Display * dpy = NULL; + +#define GetJNIEnv() (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2) + +#if defined(RESUME_ENABLE) +static void DestroyXIMCallback(XIM, XPointer, XPointer); +static void OpenXIMCallback(Display *, XPointer, XPointer); +#endif + +#if !defined(AIX) +/* Solaris XIM Extention */ +#define XNCommitStringCallback "commitStringCallback" +static void CommitStringCallback(XIC, XPointer, XPointer); +#endif + +static X11InputMethodData * getX11InputMethodData(JNIEnv *, jobject); +static void setX11InputMethodData(JNIEnv *, jobject, X11InputMethodData *); +static void destroyX11InputMethodData(JNIEnv *, X11InputMethodData *); +static void freeX11InputMethodData(JNIEnv *, X11InputMethodData *); + +#if defined(__solaris__) || defined(AIX) +/* Prototype for this function is missing in Solaris X11R6 Xlib.h */ +extern char *XSetIMValues( +#if NeedVarargsPrototypes + XIM /* im */, ... +#endif +); +#endif + +#if defined(AIX) +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); +#endif + +/* + * This function is stolen from /src/solaris/hpi/src/system_md.c + * It is used in setting the time in Java-level InputEvents + */ +jlong +awt_util_nowMillisUTC() +{ + struct timeval t; + gettimeofday(&t, NULL); + return ((jlong)t.tv_sec) * 1000 + (jlong)(t.tv_usec/1000); +} + +/* + * Converts the wchar_t string to a multi-byte string calling wcstombs(). A + * buffer is allocated by malloc() to store the multi-byte string. NULL is + * returned if the given wchar_t string pointer is NULL or buffer allocation is + * failed. + */ +static char * +wcstombsdmp(wchar_t *wcs, int len) +{ + size_t n; + char *mbs; + + if (wcs == NULL) + return NULL; + + n = len*MB_CUR_MAX + 1; + + mbs = (char *) malloc(n * sizeof(char)); + if (mbs == NULL) { + THROW_OUT_OF_MEMORY_ERROR(); + return NULL; + } + + /* TODO: check return values... Handle invalid characters properly... */ + if (wcstombs(mbs, wcs, n) == (size_t)-1) { + free(mbs); + return NULL; + } + + return mbs; +} + +#if defined(RESUME_ENABLE) +/* + * 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; +} +#endif /* RESUME_ENABLE */ + + +static X11InputMethodData * getX11InputMethodData(JNIEnv * env, jobject imInstance) { + X11InputMethodData *pX11IMData = + (X11InputMethodData *)JNU_GetLongFieldAsPtr(env, imInstance, x11InputMethodIDs.pData); + + /* + * In case the XIM server was killed somehow, reset X11InputMethodData. + */ + if (X11im == NULL && pX11IMData != NULL) { + JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, + "flushText", + "()V"); + JNU_CHECK_EXCEPTION_RETURN(env, NULL); +#if defined(AIX) + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } +#endif + /* IMPORTANT: + The order of the following calls is critical since "imInstance" may + point to the global reference itself, if "freeX11InputMethodData" is called + first, the global reference will be destroyed and "setX11InputMethodData" + will in fact fail silently. So pX11IMData will not be set to NULL. + This could make the original java object refers to a deleted pX11IMData + object. + */ + setX11InputMethodData(env, imInstance, NULL); + freeX11InputMethodData(env, pX11IMData); + pX11IMData = NULL; + } + + return pX11IMData; +} + +static void setX11InputMethodData(JNIEnv * env, jobject imInstance, X11InputMethodData *pX11IMData) { + JNU_SetLongFieldFromPtr(env, imInstance, x11InputMethodIDs.pData, pX11IMData); +} + +/* this function should be called within AWT_LOCK() */ +static void +destroyX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData) +{ + /* + * Destroy XICs + */ + if (pX11IMData == NULL) { + return; + } + + if (pX11IMData->ic_active != (XIC)0) { + XUnsetICFocus(pX11IMData->ic_active); + XDestroyIC(pX11IMData->ic_active); + if (pX11IMData->ic_active != pX11IMData->ic_passive) { + if (pX11IMData->ic_passive != (XIC)0) { + XUnsetICFocus(pX11IMData->ic_passive); + XDestroyIC(pX11IMData->ic_passive); + } + pX11IMData->ic_passive = (XIC)0; + pX11IMData->current_ic = (XIC)0; + } + } + + freeX11InputMethodData(env, pX11IMData); +} + +static void +freeX11InputMethodData(JNIEnv *env, X11InputMethodData *pX11IMData) +{ +#if defined(__linux__) || defined(MACOSX) || defined(AIX) + if (pX11IMData->statusWindow != NULL){ + StatusWindow *sw = pX11IMData->statusWindow; + XFreeGC(awt_display, sw->lightGC); + XFreeGC(awt_display, sw->dimGC); + XFreeGC(awt_display, sw->bgGC); + XFreeGC(awt_display, sw->fgGC); + if (sw->fontset != NULL) { + XFreeFontSet(awt_display, sw->fontset); + } + XDestroyWindow(awt_display, sw->w); +#if defined(AIX) + 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; + } +#endif + free((void*)sw); + } +#endif + + if (pX11IMData->callbacks) + free((void *)pX11IMData->callbacks); + + if (env) { +#if defined(RESUME_ENABLE) + /* Remove the global reference from the list, so that + the callback function or whoever refers to it could know. + */ + removeX11InputMethodGRefFromList(pX11IMData->x11inputmethod); +#endif + (*env)->DeleteGlobalRef(env, pX11IMData->x11inputmethod); + } + +#if !defined(AIX) + if (pX11IMData->lookup_buf) { + free((void *)pX11IMData->lookup_buf); + } +#endif + + free((void *)pX11IMData); +} + +/* + * Sets or unsets the focus to the given XIC. + */ +static void +setXICFocus(XIC ic, unsigned short req) +{ + if (ic == NULL) { + (void)fprintf(stderr, "Couldn't find X Input Context\n"); + return; + } + if (req == 1) + XSetICFocus(ic); + else + XUnsetICFocus(ic); +} + +/* + * Sets the focus window to the given XIC. + */ +static void +setXICWindowFocus(XIC ic, Window w) +{ + if (ic == NULL) { + (void)fprintf(stderr, "Couldn't find X Input Context\n"); + return; + } + (void) XSetICValues(ic, XNFocusWindow, w, NULL); +} + +/* + * Invokes XmbLookupString() to get something from the XIM. It invokes + * X11InputMethod.dispatchCommittedText() if XmbLookupString() returns + * committed text. This function is called from handleKeyEvent in canvas.c and + * it's under the Motif event loop thread context. + * + * Buffer usage: There is a bug in XFree86-4.3.0 XmbLookupString implementation, + * where it never returns XBufferOverflow. We need to allocate the initial lookup buffer + * big enough, so that the possibility that user encounters this problem is relatively + * small. When this bug gets fixed, we can make the initial buffer size smaller. + * Note that XmbLookupString() sometimes produces a non-null-terminated string. + * + * Returns True when there is a keysym value to be handled. + */ +#define INITIAL_LOOKUP_BUF_SIZE 512 + +Boolean +awt_x11inputmethod_lookupString(XKeyPressedEvent *event, KeySym *keysymp) +{ + JNIEnv *env = GetJNIEnv(); + X11InputMethodData *pX11IMData = NULL; +#if defined(AIX) + int buf_len = INITIAL_LOOKUP_BUF_SIZE; + char mbbuf[INITIAL_LOOKUP_BUF_SIZE]; + char *buf; +#endif + KeySym keysym = NoSymbol; + Status status; + int mblen; + jstring javastr; + XIC ic; + Boolean result = True; + static Boolean composing = False; + + /* + printf("lookupString: entering...\n"); + */ + +#if defined(RESUME_ENABLE) + if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) { + currentX11InputMethodInstance = NULL; + return False; + } +#endif + + pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance); + + if (pX11IMData == NULL) { +#if defined(__linux__) || defined(MACOSX) || defined(AIX) + return False; +#else + return result; +#endif + } + + if ((ic = pX11IMData->current_ic) == (XIC)0){ +#if defined(__linux__) || defined(MACOSX) || defined(AIX) + return False; +#else + return result; +#endif + } + +#if !defined(AIX) + /* 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); +#else + buf = mbbuf; + mblen = XmbLookupString(ic, event, buf, + buf_len - 1, &keysym, &status); +#endif + + /* + * In case of overflow, a buffer is allocated and it retries + * XmbLookupString(). + */ + if (status == XBufferOverflow) { +#if !defined(AIX) + free((void *)pX11IMData->lookup_buf); + pX11IMData->lookup_buf_len = 0; + pX11IMData->lookup_buf = (char *)malloc(mblen + 1); + if (pX11IMData->lookup_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); +#else + buf_len = mblen + 1; + buf = (char *)malloc(buf_len); + if (buf == NULL) { + THROW_OUT_OF_MEMORY_ERROR(); + return result; + } + mblen = XmbLookupString(ic, event, buf, buf_len, &keysym, &status); +#endif + } +#if !defined(AIX) + pX11IMData->lookup_buf[mblen] = 0; +#else + buf[mblen] = 0; +#endif + + /* Get keysym without taking modifiers into account first to map + * to AWT keyCode table. + */ + switch (status) { + case XLookupBoth: + if (!composing) { + if (event->keycode != 0) { + *keysymp = keysym; + result = False; + break; + } + } + 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); + */ +#if !defined(AIX) + javastr = JNU_NewStringPlatform(env, (const char *)pX11IMData->lookup_buf); +#else + javastr = JNU_NewStringPlatform(env, (const char *)buf); +#endif + if (javastr != NULL) { + JNU_CallMethodByName(env, NULL, + currentX11InputMethodInstance, + "dispatchCommittedText", + "(Ljava/lang/String;J)V", + javastr, + event->time); +#if defined(AIX) + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } +#endif + } + break; + + case XLookupKeySym: + /* + 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) { + *keysymp = keysym; + result = False; + } + break; + + case XLookupNone: + /* + printf("lookupString: status=XLookupNone, type=%d, state=%x, keycode=%x, keysym=%x\n", + event->type, event->state, event->keycode, keysym); + */ + break; + } + +#if defined(AIX) + if (buf != mbbuf) free(buf); +#endif + return result; +} + +#if defined(__linux__) || defined(MACOSX) || defined(AIX) +static StatusWindow *createStatusWindow( + Window parent) { + StatusWindow *statusWindow; + XSetWindowAttributes attrib; + unsigned long attribmask; + Window containerWindow; + Window status; + Window child; + XWindowAttributes xwa; + XWindowAttributes xxwa; + /* Variable for XCreateFontSet()*/ + char **mclr; + int mccr = 0; + char *dsr; + unsigned long bg, fg, light, dim; + int x, y, off_x, off_y, xx, yy; + unsigned int w, h, bw, depth; + XGCValues values; + unsigned long valuemask = 0; /*ignore XGCvalue and use defaults*/ + int screen = 0; + int i; + AwtGraphicsConfigDataPtr adata; + extern int awt_numScreens; + /*hardcode the size right now, should get the size base on font*/ + int width=80, height=22; + Window rootWindow; + Window *ignoreWindowPtr; + unsigned int ignoreUnit; +#if defined(AIX) + Window grandParent; + Window target; + XFontSet fontset; + + fontset = create_fontset(); + if (NULL == fontset) return NULL; +#endif + + XGetGeometry(dpy, parent, &rootWindow, &x, &y, &w, &h, &bw, &depth); + + attrib.override_redirect = True; + attribmask = CWOverrideRedirect; + for (i = 0; i < awt_numScreens; i++) { + if (RootWindow(dpy, i) == rootWindow) { + screen = i; + break; + } + } + adata = getDefaultConfig(screen); + bg = adata->AwtColorMatch(255, 255, 255, adata); + fg = adata->AwtColorMatch(0, 0, 0, adata); + light = adata->AwtColorMatch(195, 195, 195, adata); + dim = adata->AwtColorMatch(128, 128, 128, adata); + +#if !defined(AIX) + XGetWindowAttributes(dpy, parent, &xwa); +#else + grandParent=getGrandParent(parent); + if (grandParent == 0){ + target = parent; + }else{ + target = grandParent; + } + XGetWindowAttributes(dpy, target, &xwa); +#endif + bw = 2; /*xwa.border_width does not have the correct value*/ + + /*compare the size difference between parent container + and shell widget, the diff should be the border frame + and title bar height (?)*/ + + XQueryTree( dpy, +#if !defined(AIX) + parent, +#else + target, +#endif + &rootWindow, + &containerWindow, + &ignoreWindowPtr, + &ignoreUnit); + XGetWindowAttributes(dpy, containerWindow, &xxwa); + +#if !defined(AIX) + off_x = (xxwa.width - xwa.width) / 2; + off_y = xxwa.height - xwa.height - off_x; /*it's magic:-) */ +#else + 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) ; + } + } +#endif + + /*get the size of root window*/ + XGetWindowAttributes(dpy, rootWindow, &xxwa); + + XTranslateCoordinates(dpy, +#if !defined(AIX) + parent, xwa.root, +#else + target, xwa.root, +#endif + xwa.x, xwa.y, + &x, &y, + &child); + xx = x - off_x; + yy = y + xwa.height - off_y; + if (xx < 0 ){ + xx = 0; + } + if (xx + width > xxwa.width){ + xx = xxwa.width - width; + } + if (yy + height > xxwa.height){ + yy = xxwa.height - height; + } + +#if defined(AIX) + 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; + } +#endif + + status = XCreateWindow(dpy, + xwa.root, + xx, yy, + width, height, + 0, + xwa.depth, + InputOutput, + adata->awt_visInfo.visual, + attribmask, &attrib); + XSelectInput(dpy, status, + ExposureMask | StructureNotifyMask | EnterWindowMask | + LeaveWindowMask | VisibilityChangeMask); +#if defined(AIX) + if (grandParent != 0){ + long mask; + XGetWindowAttributes(dpy, grandParent, &xwa); + mask = xwa.your_event_mask | StructureNotifyMask | + VisibilityChangeMask | PropertyChangeMask; + XSelectInput(dpy, grandParent,mask); + } +#endif + + statusWindow = (StatusWindow*) calloc(1, sizeof(StatusWindow)); + if (statusWindow == NULL){ + THROW_OUT_OF_MEMORY_ERROR(); + return NULL; + } + statusWindow->w = status; +#if !defined(AIX) + //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); + } +#else + statusWindow->fontset = fontset; +#endif + statusWindow->parent = parent; +#if defined(AIX) + statusWindow->grandParent = grandParent; +#endif + statusWindow->on = False; + statusWindow->x = x; + statusWindow->y = y; + statusWindow->width = xwa.width; + statusWindow->height = xwa.height; + statusWindow->off_x = off_x; + statusWindow->off_y = off_y; + statusWindow->bWidth = bw; + statusWindow->statusH = height; + statusWindow->statusW = width; +#if defined(AIX) + statusWindow->peTextW = 0; +#endif + 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); +#if !defined(AIX) + statusWindow->fgGC = XCreateGC(dpy, status, valuemask, &values); +#else + statusWindow->fgGC = create_gc(status, FALSE); +#endif + XSetForeground(dpy, statusWindow->fgGC, fg); +#if !defined(AIX) + statusWindow->bgGC = XCreateGC(dpy, status, valuemask, &values); +#else + statusWindow->bgGC = create_gc(status, TRUE); +#endif + XSetForeground(dpy, statusWindow->bgGC, bg); +#if defined(AIX) + statusWindow->status_ready = False; + wcscpy(statusWindow->status, L""); +#endif + return statusWindow; +} + +/* This method is to turn off or turn on the status window. */ +static void onoffStatusWindow(X11InputMethodData* pX11IMData, + Window parent, + Bool ON){ + XWindowAttributes xwa; + Window child; + int x, y; + StatusWindow *statusWindow = NULL; + +#if !defined(AIX) + if (NULL == currentX11InputMethodInstance || + NULL == pX11IMData || +#else + if (NULL == pX11IMData || +#endif + NULL == (statusWindow = pX11IMData->statusWindow)){ + return; + } + + if (ON == False){ + XUnmapWindow(dpy, statusWindow->w); +#if !defined(AIX) + statusWindow->on = False; +#endif + return; + } +#if !defined(AIX) + parent = JNU_CallMethodByName(GetJNIEnv(), NULL, pX11IMData->x11inputmethod, +#else + if (NULL == currentX11InputMethodInstance){ + return; + } + { + JNIEnv *env = GetJNIEnv(); + parent = JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, +#endif + "getCurrentParentWindow", + "()J").j; +#if defined(AIX) + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } + } +#endif + if (statusWindow->parent != parent){ + statusWindow->parent = parent; + } +#if !defined(AIX) + 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); + } + statusWindow->on = True; + XMapWindow(dpy, statusWindow->w); +#else + if (st_wcslen(statusWindow->status) > 0 + || (statusWindow->peText != NULL && st_wcslen(statusWindow->peText) > 0 )){ + moveStatusWindow(statusWindow); + XMapRaised(dpy, statusWindow->w); + } +#endif +} + +void paintStatusWindow(StatusWindow *statusWindow){ + Window win = statusWindow->w; + GC lightgc = statusWindow->lightGC; + GC dimgc = statusWindow->dimGC; + GC bggc = statusWindow->bgGC; + GC fggc = statusWindow->fgGC; + + int width = statusWindow->statusW; + int height = statusWindow->statusH; + int bwidth = statusWindow->bWidth; +#if defined(AIX) + int len; + XRectangle logical, ink; + + 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; + + XFillRectangle(dpy, win, bggc, 0, 0, width+2, height+2); +#endif + +#if !defined(AIX) + 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); + + 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); + + 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); +#else + 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); +#endif + + if (statusWindow->fontset){ +#if !defined(AIX) + XmbDrawString(dpy, win, statusWindow->fontset, fggc, + bwidth + 2, height - bwidth - 4, +#else + XwcDrawString(dpy, win, statusWindow->fontset, fggc, + -logical.x + 1, -logical.y + 1, +#endif + statusWindow->status, +#if !defined(AIX) + strlen(statusWindow->status)); +#else + st_wcslen(statusWindow->status)); +#endif + } + 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]")); + } +} + +#if !defined(AIX) +void statusWindowEventHandler(XEvent event){ +#else +Bool statusWindowEventHandler(XEvent event){ +#endif + JNIEnv *env = GetJNIEnv(); + X11InputMethodData *pX11IMData = NULL; + StatusWindow *statusWindow; + +#if defined(RESUME_ENABLE) + if (!isX11InputMethodGRefInList(currentX11InputMethodInstance)) { + currentX11InputMethodInstance = NULL; +#if !defined(AIX) + return; +#else + return False; +#endif + } +#endif + + if (NULL == currentX11InputMethodInstance + || NULL == (pX11IMData = getX11InputMethodData(env, currentX11InputMethodInstance)) +#if !defined(AIX) + || NULL == (statusWindow = pX11IMData->statusWindow) + || statusWindow->w != event.xany.window){ + return; +#else + || NULL == (statusWindow = pX11IMData->statusWindow)){ + return False; +#endif + } + +#if defined(AIX) + if (statusWindow->w == event.xany.window){ +#endif + switch (event.type){ + case Expose: + paintStatusWindow(statusWindow); +#if defined(AIX) + if (statusWindow->peText) + draw_preedit(statusWindow); + arrange_window_stack(statusWindow); +#endif + break; +#if !defined(AIX) + case MapNotify: +#endif + case ConfigureNotify: +#if defined(AIX) + case VisibilityNotify: + arrange_window_stack(statusWindow); +#endif +#if !defined(AIX) + { + /*need to reset the stackMode...*/ + XWindowChanges xwc; + int value_make = CWStackMode; + xwc.stack_mode = TopIf; + XConfigureWindow(dpy, statusWindow->w, value_make, &xwc); + } +#endif + break; + /* + case UnmapNotify: + case VisibilityNotify: + break; + */ + default: + break; + } +#if defined(AIX) + 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; +#endif +} + +static void adjustStatusWindow(Window shell){ + JNIEnv *env = GetJNIEnv(); + X11InputMethodData *pX11IMData = NULL; + StatusWindow *statusWindow; + + if (NULL == currentX11InputMethodInstance +#if defined(RESUME_ENABLE) + || !isX11InputMethodGRefInList(currentX11InputMethodInstance) +#endif + || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance)) + || NULL == (statusWindow = pX11IMData->statusWindow) + || !statusWindow->on) { + return; + } +#if defined(AIX) + moveStatusWindow(statusWindow); +#endif +#if !defined(AIX) + { + 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); + } + } +#endif +} +#endif /* __linux__ || MACOSX || AIX */ +/* + * Creates two XICs, one for active clients and the other for passive + * clients. All information on those XICs are stored in the + * X11InputMethodData given by the pX11IMData parameter. + * + * For active clients: Try to use preedit callback to support + * on-the-spot. If tc is not null, the XIC to be created will + * share the Status Area with Motif widgets (TextComponents). If the + * preferable styles can't be used, fallback to root-window styles. If + * root-window styles failed, fallback to None styles. + * + * For passive clients: Try to use root-window styles. If failed, + * fallback to None styles. + */ +static Bool +createXIC(JNIEnv * env, X11InputMethodData *pX11IMData, Window w) +{ + XVaNestedList preedit = NULL; + XVaNestedList status = NULL; + XIMStyle on_the_spot_styles = XIMPreeditCallbacks, +#if defined(AIX) + in_place_styles = 0, +#endif + active_styles = 0, + passive_styles = 0, + no_styles = 0; + XIMCallback *callbacks; + unsigned short i; + XIMStyles *im_styles; + char *ret = NULL; +#if defined(AIX) + Bool passiveStatusWindow = False; + + pX11IMData->statusWindow = NULL; +#endif + + if (X11im == NULL) { + return False; + } + if (!w) { + return False; + } + +#if defined(AIX) + if (getenv("IBMJAVA_PASSIVE") == NULL) { + passiveStatusWindow = False; + } else { + passiveStatusWindow = True; + } + + if (isNativeIm()) { passiveStatusWindow = True; } +#endif + + ret = XGetIMValues(X11im, XNQueryInputStyle, &im_styles, NULL); + + if (ret != NULL) { + jio_fprintf(stderr,"XGetIMValues: %s\n",ret); + return FALSE ; + } + +#if defined(__linux__) || defined(MACOSX) || defined(AIX) + on_the_spot_styles |= XIMStatusNothing; + + /*kinput does not support XIMPreeditCallbacks and XIMStatusArea + at the same time, so use StatusCallback to draw the status + ourself + */ + for (i = 0; i < im_styles->count_styles; i++) { + if (im_styles->supported_styles[i] == (XIMPreeditCallbacks | XIMStatusCallbacks)) { + on_the_spot_styles = (XIMPreeditCallbacks | XIMStatusCallbacks); + break; + } + } +#else /*! __linux__ && !MACOSX && !AIX */ + on_the_spot_styles |= XIMStatusNothing; +#endif /* __linux__ || MACOSX || AIX */ + +#if !defined(AIX) + 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; + } +#else + for (i = 0; i < im_styles->count_styles; i++) { + 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]; + } +#endif + + XFree(im_styles); + + if (active_styles != on_the_spot_styles) { + if (passive_styles == ROOT_WINDOW_STYLES) + active_styles = passive_styles; + else { +#if defined(AIX) + if (in_place_styles == IN_PLACE_STYLES){ + active_styles = passive_styles = IN_PLACE_STYLES; + } else { +#endif + if (no_styles == NO_STYLES) + active_styles = passive_styles = NO_STYLES; + else + active_styles = passive_styles = 0; +#if defined(AIX) + } +#endif + } + } else { +#if defined(AIX) + if (!passiveStatusWindow) { +#endif + if (passive_styles != ROOT_WINDOW_STYLES) { + if (no_styles == NO_STYLES) + active_styles = passive_styles = NO_STYLES; + else + active_styles = passive_styles = 0; + } +#if defined(AIX) + } else + passive_styles = active_styles; +#endif + } + + if (active_styles == on_the_spot_styles) { +#if !defined(AIX) + pX11IMData->ic_passive = XCreateIC(X11im, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, passive_styles, + NULL); + +#endif + callbacks = (XIMCallback *)malloc(sizeof(XIMCallback) * NCALLBACKS); + if (callbacks == (XIMCallback *)NULL) + return False; + pX11IMData->callbacks = callbacks; + + for (i = 0; i < NCALLBACKS; i++, callbacks++) { + callbacks->client_data = (XPointer) pX11IMData->x11inputmethod; + callbacks->callback = callback_funcs[i]; + } + + callbacks = pX11IMData->callbacks; + preedit = (XVaNestedList)XVaCreateNestedList(0, + XNPreeditStartCallback, &callbacks[PreeditStartIndex], + XNPreeditDoneCallback, &callbacks[PreeditDoneIndex], + XNPreeditDrawCallback, &callbacks[PreeditDrawIndex], + XNPreeditCaretCallback, &callbacks[PreeditCaretIndex], + NULL); + if (preedit == (XVaNestedList)NULL) + goto err; +#if defined(__linux__) || defined(MACOSX) || defined(AIX) + /*always try XIMStatusCallbacks for active client...*/ + { +#if defined(AIX) + if (on_the_spot_styles & XIMStatusCallbacks) { +#endif + status = (XVaNestedList)XVaCreateNestedList(0, + XNStatusStartCallback, &callbacks[StatusStartIndex], + XNStatusDoneCallback, &callbacks[StatusDoneIndex], + XNStatusDrawCallback, &callbacks[StatusDrawIndex], + NULL); + + if (status == NULL) + goto err; +#if defined(AIX) + } +#endif + pX11IMData->statusWindow = createStatusWindow(w); + pX11IMData->ic_active = XCreateIC(X11im, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, active_styles, + XNPreeditAttributes, preedit, + XNStatusAttributes, status, + NULL); +#if defined(AIX) + if (NULL != pX11IMData->statusWindow) { + pX11IMData->statusWindow->status_ready = True; + } +#endif + XFree((void *)status); + XFree((void *)preedit); + } +#else /* !__linux__ && !MACOSX && !AIX */ + pX11IMData->ic_active = XCreateIC(X11im, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, active_styles, + XNPreeditAttributes, preedit, + NULL); + XFree((void *)preedit); +#endif /* __linux__ || MACOSX || AIX */ +#if defined(AIX) + if (passiveStatusWindow) { + pX11IMData->ic_passive = pX11IMData->ic_active; + } else { + pX11IMData->ic_passive = XCreateIC(X11im, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, passive_styles, + NULL); + } +#endif + } else { + pX11IMData->ic_active = XCreateIC(X11im, + XNClientWindow, w, + XNFocusWindow, w, + XNInputStyle, active_styles, + NULL); + pX11IMData->ic_passive = pX11IMData->ic_active; + } + +#if defined(AIX) + // 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; +#endif + + if (pX11IMData->ic_active == (XIC)0 + || pX11IMData->ic_passive == (XIC)0) { + return False; + } +#if !defined(AIX) + /* + * 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); + } + } +#endif + +#if defined(RESUME_ENABLE) + /* Add the global reference object to X11InputMethod to the list. */ + addToX11InputMethodGRefList(pX11IMData->x11inputmethod); +#endif + +#if defined(AIX) + /* Unset focus to avoid unexpected IM on */ + setXICFocus(pX11IMData->ic_active, False); + if (pX11IMData->ic_active != pX11IMData->ic_passive) + setXICFocus(pX11IMData->ic_passive, False); +#endif + + return True; + + err: + if (preedit) + XFree((void *)preedit); + THROW_OUT_OF_MEMORY_ERROR(); + return False; +} + +#if !defined(AIX) +static void +#else +static int +#endif +PreeditStartCallback(XIC ic, XPointer client_data, XPointer call_data) +{ +#if defined(AIX) + JNIEnv *env = GetJNIEnv(); + X11InputMethodData *pX11IMData; +#endif + + /*ARGSUSED*/ +#if !defined(AIX) + /* printf("Native: PreeditCaretCallback\n"); */ +#else + /* printf("Native: PreeditStartCallback\n"); */ + + pX11IMData = getX11InputMethodData(env, (jobject)client_data); + if (pX11IMData == NULL || pX11IMData->statusWindow == NULL) { + return 0; + } + resetPassivePreeditText(pX11IMData->statusWindow); + + return -1; /* unlimited length for preedit text */ +#endif +} + +static void +PreeditDoneCallback(XIC ic, XPointer client_data, XPointer call_data) +{ +#if defined(AIX) + JNIEnv *env = GetJNIEnv(); + X11InputMethodData *pX11IMData; +#endif + + /*ARGSUSED*/ +#if !defined(AIX) + /* printf("Native: StatusStartCallback\n"); */ +#else + /* printf("Native: PreeditDoneCallback\n"); */ + 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); + } + } +#endif +} + +/* + * Translate the preedit draw callback items to Java values and invoke + * X11InputMethod.dispatchComposedText(). + * + * client_data: X11InputMethod object + */ +static void +PreeditDrawCallback(XIC ic, XPointer client_data, + XIMPreeditDrawCallbackStruct *pre_draw) +{ + JNIEnv *env = GetJNIEnv(); + X11InputMethodData *pX11IMData = NULL; + jmethodID x11imMethodID; + + XIMText *text; + jstring javastr = NULL; + jintArray style = NULL; + + /* printf("Native: PreeditDrawCallback() \n"); */ + if (pre_draw == NULL) { + return; + } + AWT_LOCK(); +#if defined(RESUME_ENABLE) + if (!isX11InputMethodGRefInList((jobject)client_data)) { + if ((jobject)client_data == currentX11InputMethodInstance) { + currentX11InputMethodInstance = NULL; + } + goto finally; + } +#endif + if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) { + goto finally; + } + +#if defined(AIX) + if (!pX11IMData->isActiveClient){ + if (ic == pX11IMData->ic_passive) { + preedit_draw_passive(pX11IMData, pre_draw); + } + goto finally; + } +#endif + + if ((text = pre_draw->text) != NULL) { +#if defined(AIX) + if (is_text_available(text)) { +#endif + 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 defined(AIX) + } +#endif + if (text->feedback != NULL) { + int cnt; + jint *tmpstyle; + + style = (*env)->NewIntArray(env, text->length); + if (JNU_IsNull(env, style)) { + (*env)->ExceptionClear(env); + THROW_OUT_OF_MEMORY_ERROR(); + goto finally; + } + + if (sizeof(XIMFeedback) == sizeof(jint)) { + /* + * Optimization to avoid copying the array + */ + (*env)->SetIntArrayRegion(env, style, 0, + text->length, (jint *)text->feedback); + } else { + tmpstyle = (jint *)malloc(sizeof(jint)*(text->length)); + if (tmpstyle == (jint *) NULL) { + THROW_OUT_OF_MEMORY_ERROR(); + goto finally; + } + for (cnt = 0; cnt < (int)text->length; cnt++) + tmpstyle[cnt] = text->feedback[cnt]; + (*env)->SetIntArrayRegion(env, style, 0, + text->length, (jint *)tmpstyle); + } + } + } + JNU_CallMethodByName(env, NULL, pX11IMData->x11inputmethod, + "dispatchComposedText", + "(Ljava/lang/String;[IIIIJ)V", + javastr, + style, + (jint)pre_draw->chg_first, + (jint)pre_draw->chg_length, + (jint)pre_draw->caret, + awt_util_nowMillisUTC()); +#if defined(AIX) + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + } +#endif +finally: + AWT_UNLOCK(); + return; +} + +static void +PreeditCaretCallback(XIC ic, XPointer client_data, + XIMPreeditCaretCallbackStruct *pre_caret) +{ +#if defined(AIX) + XIMPreeditDrawCallbackStruct pre_draw; +#endif + + /*ARGSUSED*/ + /* printf("Native: PreeditCaretCallback\n"); */ + +#if defined(AIX) + 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); + } +#endif +} + +#if defined(__linux__) || defined(MACOSX) || defined(AIX) +static void +StatusStartCallback(XIC ic, XPointer client_data, XPointer call_data) +{ + /*ARGSUSED*/ + /*printf("StatusStartCallback:\n"); */ + +} + +static void +StatusDoneCallback(XIC ic, XPointer client_data, XPointer call_data) +{ + /*ARGSUSED*/ + /*printf("StatusDoneCallback:\n"); */ + +} + +static void +StatusDrawCallback(XIC ic, XPointer client_data, + XIMStatusDrawCallbackStruct *status_draw) +{ + /*ARGSUSED*/ + /*printf("StatusDrawCallback:\n"); */ + JNIEnv *env = GetJNIEnv(); + X11InputMethodData *pX11IMData = NULL; + StatusWindow *statusWindow; +#if defined(AIX) + int value_make = CWX|CWWidth|CWHeight; + XRectangle logical, ink; + XWindowChanges xwc; + int len; +#endif + + AWT_LOCK(); + +#if defined(RESUME_ENABLE) + if (!isX11InputMethodGRefInList((jobject)client_data)) { + if ((jobject)client_data == currentX11InputMethodInstance) { + currentX11InputMethodInstance = NULL; + } + goto finally; + } +#endif + + if (NULL == (pX11IMData = getX11InputMethodData(env, (jobject)client_data)) + || NULL == (statusWindow = pX11IMData->statusWindow)){ + goto finally; + } +#if !defined(AIX) + currentX11InputMethodInstance = (jobject)client_data; +#endif + + if (status_draw->type == XIMTextType){ + XIMText *text = (status_draw->data).text; + if (text != NULL){ + if (text->string.multi_byte != NULL) { +#if !defined(AIX) + strncpy(statusWindow->status, text->string.multi_byte, MAX_STATUS_LEN); + statusWindow->status[MAX_STATUS_LEN - 1] = '\0'; +#else + 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); +#endif + } + else { +#if !defined(AIX) + char *mbstr = wcstombsdmp(text->string.wide_char, text->length); + strncpy(statusWindow->status, mbstr, MAX_STATUS_LEN); + statusWindow->status[MAX_STATUS_LEN - 1] = '\0'; +#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); +#endif + } +#if !defined(AIX) + statusWindow->on = True; + onoffStatusWindow(pX11IMData, statusWindow->parent, True); + paintStatusWindow(statusWindow); +#else + 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); + } + paintStatusWindow(statusWindow); + if (statusWindow->peText) + draw_preedit(statusWindow); +#endif + } + else { +#if !defined(AIX) + statusWindow->on = False; +#else + wcscpy(statusWindow->status, L""); +#endif + /*just turnoff the status window + paintStatusWindow(statusWindow); + */ + onoffStatusWindow(pX11IMData, 0, False); + } + } + + finally: + AWT_UNLOCK(); +} +#endif /* __linux__ || MACOSX */ + +#if !defined(AIX) +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(); + + if (!isX11InputMethodGRefInList((jobject)client_data)) { + if ((jobject)client_data == currentX11InputMethodInstance) { + currentX11InputMethodInstance = NULL; + } + goto finally; + } + + if ((pX11IMData = getX11InputMethodData(env, (jobject)client_data)) == NULL) { + goto finally; + } + currentX11InputMethodInstance = (jobject)client_data; + + 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); + } + + if (javastr != NULL) { + JNU_CallMethodByName(env, NULL, + pX11IMData->x11inputmethod, + "dispatchCommittedText", + "(Ljava/lang/String;J)V", + javastr, + awt_util_nowMillisUTC()); + } + finally: + AWT_UNLOCK(); +} +#endif + +#if defined(RESUME_ENABLE) +static void OpenXIMCallback(Display *display, XPointer client_data, XPointer call_data) { + XIMCallback ximCallback; + + X11im = XOpenIM(display, NULL, NULL, NULL); + if (X11im == NULL) { + return; + } + + ximCallback.callback = (XIMProc)DestroyXIMCallback; + ximCallback.client_data = NULL; + XSetIMValues(X11im, XNDestroyCallback, &ximCallback, 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); +} +#endif /* RESUME_ENABLE */ + +/* + * 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) +{ + Bool registered; + + AWT_LOCK(); + + dpy = (Display *)jlong_to_ptr(display); + +#ifndef RESUME_ENABLE + if (X11im == NULL) { + X11im = XOpenIM(dpy, NULL, NULL, NULL); + } +#else /* !RESUME_ENABLE */ +/* 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) + } +#endif +#endif /* RESUME_ENABLE */ + + AWT_UNLOCK(); + + return JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL +Java_sun_awt_X11_XInputMethod_createXICNative(JNIEnv *env, + jobject this, + jlong window) +{ + X11InputMethodData *pX11IMData; + jobject globalRef; + XIC ic; + + AWT_LOCK(); + + if (!window) { + JNU_ThrowNullPointerException(env, "NullPointerException"); + AWT_UNLOCK(); + return JNI_FALSE; + } + + pX11IMData = (X11InputMethodData *) calloc(1, sizeof(X11InputMethodData)); + if (pX11IMData == NULL) { + THROW_OUT_OF_MEMORY_ERROR(); + AWT_UNLOCK(); + return JNI_FALSE; + } + + globalRef = (*env)->NewGlobalRef(env, this); + pX11IMData->x11inputmethod = globalRef; +#if defined(__linux__) || defined(MACOSX) || defined(AIX) + pX11IMData->statusWindow = NULL; +#endif /* __linux__ || MACOSX || AIX */ + +#if !defined(AIX) + pX11IMData->lookup_buf = 0; + pX11IMData->lookup_buf_len = 0; + +#else + setX11InputMethodData(env, this, pX11IMData); + +#endif + + if (createXIC(env, pX11IMData, (Window)window) == False) { + destroyX11InputMethodData((JNIEnv *) NULL, pX11IMData); + pX11IMData = (X11InputMethodData *) NULL; +#if defined(AIX) + setX11InputMethodData(env, this, pX11IMData); +#endif + if ((*env)->ExceptionCheck(env)) { + goto finally; + } + } + +#if !defined(AIX) + setX11InputMethodData(env, this, pX11IMData); +#endif + +finally: + AWT_UNLOCK(); + return (pX11IMData != NULL); +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XInputMethod_setXICFocusNative(JNIEnv *env, + jobject this, + jlong w, + jboolean req, + jboolean active) +{ + X11InputMethodData *pX11IMData; + AWT_LOCK(); + pX11IMData = getX11InputMethodData(env, this); + if (pX11IMData == NULL) { + AWT_UNLOCK(); + return; + } + + if (req) { + if (!w) { + AWT_UNLOCK(); + return; + } +#if defined(AIX) + pX11IMData->isActiveClient = active; +#endif + pX11IMData->current_ic = active ? + pX11IMData->ic_active : pX11IMData->ic_passive; + /* + * On Solaris2.6, setXICWindowFocus() has to be invoked + * before setting focus. + */ +#if defined(AIX) + get_current_focus(pX11IMData->current_ic); /* workaround for kinput2 and SCIM */ + if (currentFocusWindow != w) { +#endif + setXICWindowFocus(pX11IMData->current_ic, w); + setXICFocus(pX11IMData->current_ic, req); + currentX11InputMethodInstance = pX11IMData->x11inputmethod; + currentFocusWindow = w; +#if defined(AIX) + } else { +#endif +#if defined(__linux__) || defined(MACOSX) + if (active && pX11IMData->statusWindow && pX11IMData->statusWindow->on) +#endif +#if defined(AIX) + setXICFocus(pX11IMData->current_ic, req); + } + if ((active || pX11IMData->passiveStatusWindow) + && (pX11IMData->statusWindow && pX11IMData->statusWindow->on)) +#endif +#if defined(__linux__) || defined(MACOSX) || defined(AIX) + onoffStatusWindow(pX11IMData, w, True); +#endif + } else { + currentX11InputMethodInstance = NULL; + currentFocusWindow = 0; +#if defined(__linux__) || defined(MACOSX) || defined(AIX) + onoffStatusWindow(pX11IMData, 0, False); + if (pX11IMData->current_ic != NULL) +#endif + setXICFocus(pX11IMData->current_ic, req); + + pX11IMData->current_ic = (XIC)0; + } + + XFlush(dpy); + AWT_UNLOCK(); +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11InputMethod_turnoffStatusWindow(JNIEnv *env, + jobject this) +{ +#if defined(__linux__) || defined(MACOSX) || defined(AIX) + X11InputMethodData *pX11IMData; + StatusWindow *statusWindow; + + AWT_LOCK(); + + if (NULL == currentX11InputMethodInstance +#if defined(RESUME_ENABLE) + || !isX11InputMethodGRefInList(currentX11InputMethodInstance) +#endif + || NULL == (pX11IMData = getX11InputMethodData(env,currentX11InputMethodInstance)) + || NULL == (statusWindow = pX11IMData->statusWindow) + || !statusWindow->on ){ + AWT_UNLOCK(); + return; + } + onoffStatusWindow(pX11IMData, 0, False); +#if defined(AIX) + statusWindow->on = False; +#endif + + AWT_UNLOCK(); +#endif +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11InputMethod_disposeXIC(JNIEnv *env, + jobject this) +{ + X11InputMethodData *pX11IMData = NULL; + + AWT_LOCK(); + pX11IMData = getX11InputMethodData(env, this); + if (pX11IMData == NULL) { + AWT_UNLOCK(); + return; + } + + setX11InputMethodData(env, this, NULL); + + if (pX11IMData->x11inputmethod == currentX11InputMethodInstance) { + currentX11InputMethodInstance = NULL; + currentFocusWindow = 0; + } + destroyX11InputMethodData(env, pX11IMData); + AWT_UNLOCK(); +} + +JNIEXPORT jstring JNICALL +Java_sun_awt_X11InputMethod_resetXIC(JNIEnv *env, + jobject this) +{ + X11InputMethodData *pX11IMData; + char *xText = NULL; + jstring jText = (jstring)0; + + AWT_LOCK(); + pX11IMData = getX11InputMethodData(env, this); + if (pX11IMData == NULL) { + AWT_UNLOCK(); + return jText; + } + + if (pX11IMData->current_ic) +#if defined(AIX) + { + if (!isPreeditStateActive(pX11IMData->current_ic)) { + xText = NULL; + } else { + if (!(pX11IMData->forceReset)) + setXICFocus(pX11IMData->current_ic, FALSE); +#endif + xText = XmbResetIC(pX11IMData->current_ic); +#if defined(AIX) + if (!(pX11IMData->forceReset)) + setXICFocus(pX11IMData->current_ic, TRUE); + } + } +#endif + else { + /* + * If there is no reference to the current XIC, try to reset both XICs. + */ +#if defined(AIX) + if (!isPreeditStateActive(pX11IMData->ic_active)) + xText = NULL; + else +#endif + xText = XmbResetIC(pX11IMData->ic_active); + /*it may also means that the real client component does + not have focus -- has been deactivated... its xic should + not have the focus, bug#4284651 showes reset XIC for htt + may bring the focus back, so de-focus it again. + */ + setXICFocus(pX11IMData->ic_active, FALSE); + if (pX11IMData->ic_active != pX11IMData->ic_passive) { +#if !defined(AIX) + char *tmpText = XmbResetIC(pX11IMData->ic_passive); +#else + char *tmpText; + if (!isPreeditStateActive(pX11IMData->ic_passive)) + tmpText = NULL; + else + tmpText = XmbResetIC(pX11IMData->ic_passive); +#endif + 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); + } + +#if defined(AIX) + /* 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); + } + } +#endif + + AWT_UNLOCK(); + return jText; +} + +/* + * Class: sun_awt_X11InputMethod + * Method: setCompositionEnabledNative + * Signature: (ZJ)V + * + * This method tries to set the XNPreeditState attribute associated with the current + * XIC to the passed in 'enable' state. + * + * Return JNI_TRUE if XNPreeditState attribute is successfully changed to the + * '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 + (JNIEnv *env, jobject this, jboolean enable) +{ + X11InputMethodData *pX11IMData; + char * ret = NULL; +#if defined(AIX) + XVaNestedList pr_atrb; +#endif + + AWT_LOCK(); + pX11IMData = getX11InputMethodData(env, this); + + if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) { + AWT_UNLOCK(); + return JNI_FALSE; + } + +#if !defined(AIX) + ret = XSetICValues(pX11IMData->current_ic, XNPreeditState, + (enable ? XIMPreeditEnable : XIMPreeditDisable), NULL); + AWT_UNLOCK(); + + if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ""); + } +#else + 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, XNPreeditAttributes) == 0) + || (strcmp(ret, XNPreeditState) == 0))) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ""); + } +#endif + + return (jboolean)(ret == 0); +} + +/* + * Class: sun_awt_X11InputMethod + * Method: isCompositionEnabledNative + * Signature: (J)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 + (JNIEnv *env, jobject this) +{ + X11InputMethodData *pX11IMData = NULL; + char * ret = NULL; +#if !defined(AIX) + XIMPreeditState state; +#else + XIMPreeditState state = XIMPreeditUnKnown; + XVaNestedList pr_atrb; +#endif + + AWT_LOCK(); + pX11IMData = getX11InputMethodData(env, this); + + if ((pX11IMData == NULL) || (pX11IMData->current_ic == NULL)) { + AWT_UNLOCK(); + return JNI_FALSE; + } + +#if !defined(AIX) + ret = XGetICValues(pX11IMData->current_ic, XNPreeditState, &state, NULL); + AWT_UNLOCK(); + + if ((ret != 0) && (strcmp(ret, XNPreeditState) == 0)) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ""); + return JNI_FALSE; + } +#else + 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, XNPreeditAttributes) == 0) + || (strcmp(ret, XNPreeditState) == 0))) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", ""); + return JNI_FALSE; + } +#endif + + return (jboolean)(state == XIMPreeditEnable); +} + +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 +} +#if defined(AIX) +/* + * The following functions are IBM's enhancement. + */ + +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; +} + +/* 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; +} + +/* + * 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; + } + return True; +} + +/* + * check if preedit status is active +*/ +static Bool isPreeditStateActive(XIC ic) +{ + XIMPreeditState state = XIMPreeditUnKnown; + XVaNestedList pr_atrb; + char* nosupportAttr; + + if (ic == NULL) return False; + + 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; + } + 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 * handle_buffer(void * source, void * insert, + int size,int src_len, int ins_len, + int del_len, int offset) +{ + void * temp = source; + + 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; + + 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; + + /* 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); +} + +/* + * 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; + + 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 requied status window size and resize the window */ +static void align_status(StatusWindow *statusWindow) +{ + 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; +} +#endif --- /dev/null 2018-02-05 10:17:31.364998584 +0900 +++ new/src/java.desktop/aix/native/libawt_xawt/xawt/XlibWrapper.c 2018-04-13 18:47:05.000000000 +0900 @@ -0,0 +1,2371 @@ +/* + * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#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 "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); + +#if defined(DEBUG) +static jmethodID lockIsHeldMID = NULL; + +static void +CheckHaveAWTLock(JNIEnv *env) +{ + if (lockIsHeldMID == NULL) { + if (tkClass == NULL) return; + lockIsHeldMID = + (*env)->GetStaticMethodID(env, tkClass, + "isAWTLockHeldByCurrentThread", "()Z"); + if (lockIsHeldMID == NULL) return; + } + if (!(*env)->CallStaticBooleanMethod(env, tkClass, lockIsHeldMID)) { + JNU_ThrowInternalError(env, "Current thread does not hold AWT_LOCK!"); + } +} + +#define AWT_CHECK_HAVE_LOCK() \ + do { \ + CheckHaveAWTLock(env); \ + if ((*env)->ExceptionCheck(env)) { \ + return; \ + } \ + } while (0); \ + +#define AWT_CHECK_HAVE_LOCK_RETURN(ret) \ + do { \ + CheckHaveAWTLock(env); \ + if ((*env)->ExceptionCheck(env)) { \ + return (ret); \ + } \ + } while (0); \ + +#else +#define AWT_CHECK_HAVE_LOCK() +#define AWT_CHECK_HAVE_LOCK_RETURN(ret) +#endif + +void freeNativeStringArray(char **array, jsize length) { + int i; + if (array == NULL) { + return; + } + for (i = 0; i < length; i++) { + free(array[i]); + } + free(array); +} + +char** stringArrayToNative(JNIEnv *env, jobjectArray array, jsize * ret_length) { + Bool err = FALSE; + char ** strings; + int index, str_index = 0; + jsize length = (*env)->GetArrayLength(env, array); + + if (length == 0) { + return NULL; + } + + strings = (char**) calloc(length, sizeof (char*)); + + if (strings == NULL) { + JNU_ThrowOutOfMemoryError(env, ""); + return NULL; + } + + for (index = 0; index < length; index++) { + jstring str = (*env)->GetObjectArrayElement(env, array, index); + if (str != NULL) { + const char * str_char = JNU_GetStringPlatformChars(env, str, NULL); + if (str_char != NULL) { + char * dup_str = strdup(str_char); + if (dup_str != NULL) { + strings[str_index++] = dup_str; + } else { + JNU_ThrowOutOfMemoryError(env, ""); + err = TRUE; + } + JNU_ReleaseStringPlatformChars(env, str, str_char); + } else { + err = TRUE; + } + (*env)->DeleteLocalRef(env, str); + if (err) { + break; + } + } + } + + if (err) { + freeNativeStringArray(strings, str_index); + strings = NULL; + str_index = -1; + } + *ret_length = str_index; + + return strings; +} + +/* + * Class: XlibWrapper + * Method: XOpenDisplay + * Signature: (J)J + */ + +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XOpenDisplay +(JNIEnv *env, jclass clazz, jlong display_name) +{ + Display *dp; + AWT_CHECK_HAVE_LOCK_RETURN(0); + dp = XOpenDisplay((char *) jlong_to_ptr(display_name)); + + return ptr_to_jlong(dp); +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_XCloseDisplay(JNIEnv *env, jclass clazz, + jlong display) { + AWT_CHECK_HAVE_LOCK(); + XCloseDisplay((Display*) jlong_to_ptr(display)); +} + +JNIEXPORT jlong JNICALL +Java_sun_awt_X11_XlibWrapper_XDisplayString(JNIEnv *env, jclass clazz, + jlong display) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return ptr_to_jlong(XDisplayString((Display*) jlong_to_ptr(display))); +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_XSetCloseDownMode(JNIEnv *env, jclass clazz, + jlong display, jint mode) { + AWT_CHECK_HAVE_LOCK(); + XSetCloseDownMode((Display*) jlong_to_ptr(display), (int)mode); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: DefaultScreen + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_DefaultScreen (JNIEnv *env, jclass clazz, jlong display) { + + AWT_CHECK_HAVE_LOCK_RETURN(0); + return (jlong) DefaultScreen((Display *) jlong_to_ptr(display)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: ScreenOfDisplay + * Signature: (JJ)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_ScreenOfDisplay(JNIEnv *env, jclass clazz, jlong display, jlong screen_number) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return ptr_to_jlong(ScreenOfDisplay((Display *) jlong_to_ptr(display), + screen_number)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: DoesBackingStore + * Signature: (J)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_DoesBackingStore(JNIEnv *env, jclass clazz, jlong screen) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return (jint) DoesBackingStore((Screen*) jlong_to_ptr(screen)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: DisplayWidth + * Signature: (JJ)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_DisplayWidth +(JNIEnv *env, jclass clazz, jlong display, jlong screen) { + + AWT_CHECK_HAVE_LOCK_RETURN(0); + return (jlong) DisplayWidth((Display *) jlong_to_ptr(display),screen); + +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: DisplayWidthMM + * Signature: (JJ)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_DisplayWidthMM +(JNIEnv *env, jclass clazz, jlong display, jlong screen) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return (jlong) DisplayWidthMM((Display *) jlong_to_ptr(display),screen); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: DisplayHeight + * Signature: (JJ)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_DisplayHeight +(JNIEnv *env, jclass clazz, jlong display, jlong screen) { + + AWT_CHECK_HAVE_LOCK_RETURN(0); + return (jlong) DisplayHeight((Display *) jlong_to_ptr(display),screen); +} +/* + * Class: sun_awt_X11_XlibWrapper + * Method: DisplayHeightMM + * Signature: (JJ)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_DisplayHeightMM +(JNIEnv *env, jclass clazz, jlong display, jlong screen) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return (jlong) DisplayHeightMM((Display *) jlong_to_ptr(display),screen); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: RootWindow + * Signature: (JJ)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_RootWindow +(JNIEnv *env , jclass clazz, jlong display, jlong screen_number) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return (jlong) RootWindow((Display *) jlong_to_ptr(display), screen_number); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: ScreenCount + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_ScreenCount +(JNIEnv *env , jclass clazz, jlong display) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return ScreenCount((Display *) jlong_to_ptr(display)); +} + + +/* + * Class: XlibWrapper + * Method: XCreateWindow + * Signature: (JJIIIIIIJJJJ)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XCreateWindow + (JNIEnv *env, jclass clazz, jlong display, jlong window, + jint x, jint y, jint w, jint h , jint border_width, jint depth, + jlong wclass, jlong visual, jlong valuemask, jlong attributes) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + 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)); + +} + +/* + * Class: XlibWrapper + * Method: XConvertCase + * Signature: (JJJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XConvertCase + (JNIEnv *env, jclass clazz, jlong keysym, + jlong keysym_lowercase, jlong keysym_uppercase) +{ + AWT_CHECK_HAVE_LOCK(); + XConvertCase(keysym, (jlong_to_ptr(keysym_lowercase)), + (jlong_to_ptr(keysym_uppercase))); +} + + +/* + * Class: XlibWrapper + * Method: XMapWindow + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XMapWindow +(JNIEnv *env, jclass clazz, jlong display, jlong window) +{ + AWT_CHECK_HAVE_LOCK(); + XMapWindow( (Display *)jlong_to_ptr(display),(Window) window); + +} + +/* + * Class: XlibWrapper + * Method: XMapRaised + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XMapRaised +(JNIEnv *env, jclass clazz, jlong display, jlong window) +{ + AWT_CHECK_HAVE_LOCK(); + XMapRaised( (Display *)jlong_to_ptr(display),(Window) window); + +} + +/* + * Class: XlibWrapper + * Method: XRaiseWindow + * Signature: (JJ)V + */ +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); + +} + +/* + * Class: XlibWrapper + * Method: XLowerWindow + * Signature: (JJ)V + */ +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); + +} + +/* + * Class: XlibWrapper + * Method: XRestackWindows + * Signature: (JJI)V + */ +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); + +} + +/* + * Class: XlibWrapper + * Method: XConfigureWindow + * Signature: (JJJJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XConfigureWindow +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong value_mask, + jlong values) +{ + AWT_CHECK_HAVE_LOCK(); + XConfigureWindow((Display*)jlong_to_ptr(display), (Window)window, + (unsigned int)value_mask, (XWindowChanges*)jlong_to_ptr(values)); +} + +/* + * Class: XlibWrapper + * Method: XSetInputFocus + * Signature: (JJ)V + */ +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 + * Signature: (JJJ)V + */ +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); + +} + +/* + * Class: XlibWrapper + * Method: XGetInputFocus + * Signature: (JJ)V + */ +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); + XGetInputFocus( (Display *)jlong_to_ptr(display), &focusOwner, &revert_to); + return focusOwner; +} + + +/* + * Class: XlibWrapper + * Method: XDestroyWindow + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XDestroyWindow +(JNIEnv *env, jclass clazz, jlong display, jlong window) +{ + AWT_CHECK_HAVE_LOCK(); + XDestroyWindow( (Display *)jlong_to_ptr(display),(Window) window); +} + +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XGrabPointer +(JNIEnv *env, jclass clazz, jlong display, jlong window, + jint owner_events, jint event_mask, jint pointer_mode, + jint keyboard_mode, jlong confine_to, jlong cursor, jlong time) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XGrabPointer( (Display *)jlong_to_ptr(display), (Window) window, + (Bool) owner_events, (unsigned int) event_mask, (int) pointer_mode, + (int) keyboard_mode, (Window) confine_to, (Cursor) cursor, (Time) time); +} + +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XUngrabPointer +(JNIEnv *env, jclass clazz, jlong display, jlong time) +{ + AWT_CHECK_HAVE_LOCK(); + XUngrabPointer( (Display *)jlong_to_ptr(display), (Time) time); +} + +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XGrabKeyboard +(JNIEnv *env, jclass clazz, jlong display, jlong window, + jint owner_events, jint pointer_mode, + jint keyboard_mode, jlong time) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XGrabKeyboard( (Display *)jlong_to_ptr(display), (Window) window, + (Bool) owner_events, (int) pointer_mode, + (int) keyboard_mode, (Time) time); +} + +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XUngrabKeyboard +(JNIEnv *env, jclass clazz, jlong display, jlong time) +{ + AWT_CHECK_HAVE_LOCK(); + XUngrabKeyboard( (Display *)jlong_to_ptr(display), (Time) time); +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_XGrabServer(JNIEnv *env, jclass clazz, + jlong display) { + AWT_CHECK_HAVE_LOCK(); + XGrabServer((Display*)jlong_to_ptr(display)); +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_XUngrabServer(JNIEnv *env, jclass clazz, + jlong display) { + AWT_CHECK_HAVE_LOCK(); + XUngrabServer((Display*)jlong_to_ptr(display)); + /* Workaround for bug 5039226 */ + XSync((Display*)jlong_to_ptr(display), False); +} + +/* + * Class: XlibWrapper + * Method: XUnmapWindow + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XUnmapWindow +(JNIEnv *env, jclass clazz, jlong display, jlong window) +{ + + AWT_CHECK_HAVE_LOCK(); + XUnmapWindow( (Display *)jlong_to_ptr(display),(Window) window); + +} + + + +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSelectInput +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong mask) +{ + AWT_CHECK_HAVE_LOCK(); + XSelectInput((Display *) jlong_to_ptr(display), (Window) window, mask); +} + +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XkbSelectEvents +(JNIEnv *env, jclass clazz, jlong display, jlong device, jlong bits_to_change, + jlong values_for_bits) +{ + AWT_CHECK_HAVE_LOCK(); + XkbSelectEvents((Display *) jlong_to_ptr(display), (unsigned int)device, + (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) +{ + AWT_CHECK_HAVE_LOCK(); + XkbSelectEventDetails((Display *) jlong_to_ptr(display), (unsigned int)device, + (unsigned int) event_type, + (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) +{ + Bool status; + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + status = XkbQueryExtension((Display *) jlong_to_ptr(display), + (int *) jlong_to_ptr(opcode_rtrn), + (int *) jlong_to_ptr(event_rtrn), + (int *) jlong_to_ptr(error_rtrn), + (int *) jlong_to_ptr(major_in_out), + (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) +{ + Bool status; + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + *((int *)jlong_to_ptr(lib_major_in_out)) = XkbMajorVersion; + *((int *)jlong_to_ptr(lib_minor_in_out)) = XkbMinorVersion; + status = XkbLibraryVersion((int *)jlong_to_ptr(lib_major_in_out), + (int *)jlong_to_ptr(lib_minor_in_out)); + return status ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XkbGetMap +(JNIEnv *env, jclass clazz, jlong display, jlong which, jlong device_spec) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return (jlong) XkbGetMap( (Display *) jlong_to_ptr(display), + (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) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return (jlong) XkbGetUpdatedMap( (Display *) jlong_to_ptr(display), + (unsigned int) which, + (XkbDescPtr) jlong_to_ptr(xkb)); +} +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XkbFreeKeyboard +(JNIEnv *env, jclass clazz, jlong xkb, jlong which, jboolean free_all) +{ + AWT_CHECK_HAVE_LOCK(); + XkbFreeKeyboard(jlong_to_ptr(xkb), (unsigned int)which, free_all); +} +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XkbTranslateKeyCode +(JNIEnv *env, jclass clazz, jlong xkb, jint keycode, jlong mods, jlong mods_rtrn, jlong keysym_rtrn) +{ + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + Bool b; + b = XkbTranslateKeyCode((XkbDescPtr)xkb, (unsigned int)keycode, (unsigned int)mods, + (unsigned int *)jlong_to_ptr(mods_rtrn), + (KeySym *)jlong_to_ptr(keysym_rtrn)); + //printf("native, input: keycode:0x%0X; mods:0x%0X\n", keycode, mods); + //printf("native, output: keysym:0x%0X; mods:0x%0X\n", + // *(unsigned int *)jlong_to_ptr(keysym_rtrn), + // *(unsigned int *)jlong_to_ptr(mods_rtrn)); + return b ? JNI_TRUE : JNI_FALSE; +} +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XkbSetDetectableAutoRepeat +(JNIEnv *env, jclass clazz, jlong display, jboolean detectable) +{ + AWT_CHECK_HAVE_LOCK(); + XkbSetDetectableAutoRepeat((Display *) jlong_to_ptr(display), detectable, NULL); +} +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XNextEvent + * Signature: (JJ)V + */ + + +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XNextEvent +(JNIEnv *env, jclass clazz, jlong display, jlong ptr) +{ + AWT_CHECK_HAVE_LOCK(); + XNextEvent( (Display *) jlong_to_ptr(display), jlong_to_ptr(ptr)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * 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) +{ + AWT_CHECK_HAVE_LOCK(); + XMaskEvent( (Display *) jlong_to_ptr(display), event_mask, (XEvent *) jlong_to_ptr(event_return)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * 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) +{ + AWT_CHECK_HAVE_LOCK(); + XWindowEvent( (Display *) jlong_to_ptr(display), (Window)window, event_mask, (XEvent *) jlong_to_ptr(event_return)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XFilterEvent + * Signature: (JJ)Z + */ +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XFilterEvent +(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); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XSupportsLocale + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XSupportsLocale +(JNIEnv *env, jclass clazz) +{ + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + return (jboolean)XSupportsLocale(); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XSetLocaleModifiers + * Signature: (Ljava/lang/String;)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_sun_awt_X11_XlibWrapper_XSetLocaleModifiers +(JNIEnv *env, jclass clazz, jstring jstr) +{ + char * modifier_list = NULL; + char * ret = NULL; + + if (!JNU_IsNull(env, jstr)) { + modifier_list = (char *)JNU_GetStringPlatformChars(env, jstr, NULL); + CHECK_NULL_RETURN(modifier_list, NULL); + } + + AWT_CHECK_HAVE_LOCK_RETURN(NULL); + if (modifier_list) { + ret = XSetLocaleModifiers(modifier_list); + JNU_ReleaseStringPlatformChars(env, jstr, (const char *) modifier_list); + } else { + ret = XSetLocaleModifiers(""); + } + + return (ret != NULL ? JNU_NewStringPlatform(env, ret): NULL); +} + + +/* + * Class: sun_awt_X11_wrappers_XlibWrapper + * Method: XPeekEvent + * Signature: (JJ)V + */ + + +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XPeekEvent +(JNIEnv *env, jclass clazz, jlong display, jlong ptr) +{ + AWT_CHECK_HAVE_LOCK(); + 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); + +} + +/* + * Class: sun_awt_X11_XlibWrapper + * 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) +{ + AWT_CHECK_HAVE_LOCK(); + XResizeWindow( (Display *) jlong_to_ptr(display),(Window) window,width,height); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * 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) +{ + AWT_CHECK_HAVE_LOCK(); + XMoveWindow( (Display *) jlong_to_ptr(display),(Window) window,width,height); +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * 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); + +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XFlush + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XFlush +(JNIEnv *env, jclass clazz, jlong display) { + + AWT_CHECK_HAVE_LOCK(); + XFlush((Display *)jlong_to_ptr(display)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XSync + * Signature: (JI)V + */ +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 +(JNIEnv *env, jclass clazz, jlong display, jlong src_w, jlong dest_w, + jlong src_x, jlong src_y, jlong dest_x_return, jlong dest_y_return, + jlong child_return) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XTranslateCoordinates( (Display *) jlong_to_ptr(display), src_w, dest_w, + src_x, src_y, + (int *) jlong_to_ptr(dest_x_return), + (int *) jlong_to_ptr(dest_y_return), + (Window *) jlong_to_ptr(child_return)); +} + +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XEventsQueued +(JNIEnv *env, jclass clazz, jlong display, jint mode) { + + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XEventsQueued((Display *) jlong_to_ptr(display), mode); + +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: SetProperty + * Signature: (JJJLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_SetProperty +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong atom, jstring jstr) { + char *cname; + XTextProperty tp; + int32_t status; + + /* + In case there are direct support of UTF-8 declared, use UTF-8 strings. + */ + if (!JNU_IsNull(env, jstr)) { +#ifdef X_HAVE_UTF8_STRING + cname = (char *) (*env)->GetStringUTFChars(env, jstr, JNI_FALSE); +#else + cname = (char *) JNU_GetStringPlatformChars(env, jstr, NULL); +#endif + CHECK_NULL(cname); + } else { + cname = ""; + } + + + AWT_CHECK_HAVE_LOCK(); + +#ifdef X_HAVE_UTF8_STRING + status = Xutf8TextListToTextProperty((Display *)jlong_to_ptr(display), &cname, 1, + XStdICCTextStyle, &tp); +#else + status = XmbTextListToTextProperty((Display *)jlong_to_ptr(display), &cname, 1, + 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) { + XFree(tp.value); + } + } + + if (!JNU_IsNull(env, jstr)) { +#ifdef X_HAVE_UTF8_STRING + (*env)->ReleaseStringUTFChars(env, jstr, (const char *) cname); +#else + JNU_ReleaseStringPlatformChars(env, jstr, (const char *) cname); +#endif + } +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XChangeProperty + * Signature: (JJJJJJJJJJJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XChangePropertyImpl( + JNIEnv *env, jclass clazz, jlong display, jlong window, jlong property, + jlong type, jint format, jint mode, jlong data, jint nelements) +{ + AWT_CHECK_HAVE_LOCK(); + XChangeProperty((Display*) jlong_to_ptr(display), (Window) window, (Atom) property, + (Atom) type, format, mode, (unsigned char*) jlong_to_ptr(data), + nelements); +} +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XChangePropertyS + * Signature: (JJJJJJJJJLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XChangePropertyS( + JNIEnv *env, jclass clazz, jlong display, jlong window, jlong property, + jlong type, jint format, jint mode, jstring value) +{ + jboolean iscopy; + AWT_CHECK_HAVE_LOCK(); + const char * chars = JNU_GetStringPlatformChars(env, value, &iscopy); + CHECK_NULL(chars); + XChangeProperty((Display*)jlong_to_ptr(display), window, (Atom)property, + (Atom)type, format, mode, (unsigned char*)chars, strlen(chars)); + if (iscopy) { + JNU_ReleaseStringPlatformChars(env, value, chars); + } +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XGetWindowProperty + * Signature: (JJJJJJJJJJJ)J; + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XGetWindowProperty +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong property, jlong long_offset, + jlong long_length, jlong delete, jlong req_type, jlong actual_type, + jlong actual_format, jlong nitems_ptr, jlong bytes_after, jlong data_ptr) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XGetWindowProperty((Display*) jlong_to_ptr(display), window, property, long_offset, long_length, + delete, (Atom) req_type, (Atom*) jlong_to_ptr(actual_type), + (int *) jlong_to_ptr(actual_format), (unsigned long *) jlong_to_ptr(nitems_ptr), + (unsigned long*) jlong_to_ptr(bytes_after), (unsigned char**) jlong_to_ptr(data_ptr)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: GetProperty + * Signature: (JJJ)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_sun_awt_X11_XlibWrapper_GetProperty +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong atom) +{ + /* Request status */ + int status; + + /* Returns of XGetWindowProperty */ + Atom actual_type; + int actual_format; + unsigned long nitems; + unsigned long bytes_after; + unsigned char * string; + jstring res = NULL; + AWT_CHECK_HAVE_LOCK_RETURN(NULL); + status = XGetWindowProperty((Display*)jlong_to_ptr(display), window, + atom, 0, 0xFFFF, False, XA_STRING, + &actual_type, &actual_format, &nitems, &bytes_after, + &string); + + if (status != Success || string == NULL) { + return NULL; + } + + if (actual_type == XA_STRING && actual_format == 8) { + res = JNU_NewStringPlatform(env,(char*) string); + } + XFree(string); + return res; +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: InternAtom + * Signature: (JLjava/lang/String;I)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_InternAtom +(JNIEnv *env, jclass clazz, jlong display, jstring jstr, jint ife) { + + char *cname; + unsigned long atom; + + AWT_CHECK_HAVE_LOCK_RETURN(0); + + if (!JNU_IsNull(env, jstr)) { + cname = (char *)JNU_GetStringPlatformChars(env, jstr, NULL); + CHECK_NULL_RETURN(cname, 0); + } else { + cname = ""; + } + + atom = XInternAtom((Display *) jlong_to_ptr(display), cname, ife); + + if (!JNU_IsNull(env, jstr)) { + JNU_ReleaseStringPlatformChars(env, jstr, (const char *) cname); + } + + return (jlong) atom; + +} + +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XCreateFontCursor +(JNIEnv *env, jclass clazz, jlong display, jint shape) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XCreateFontCursor((Display *) jlong_to_ptr(display), (int) shape); +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XCreatePixmapCursor + * Signature: (JJJJJII)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XCreatePixmapCursor +(JNIEnv *env , jclass clazz, jlong display, jlong source, jlong mask, jlong fore, jlong back, jint x , jint y) { + + AWT_CHECK_HAVE_LOCK_RETURN(0); + return (jlong) XCreatePixmapCursor((Display *) jlong_to_ptr(display), (Pixmap) source, (Pixmap) mask, + (XColor *) jlong_to_ptr(fore), (XColor *) jlong_to_ptr(back), x, y); +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XQueryBestCursor + * Signature: (JJIIJJ)Z + */ +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XQueryBestCursor +(JNIEnv *env, jclass clazz, jlong display, jlong drawable, jint width, jint height, jlong width_return, jlong height_return) { + + Status status; + + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + status = XQueryBestCursor((Display *) jlong_to_ptr(display), (Drawable) drawable, width,height, + (unsigned int *) jlong_to_ptr(width_return), (unsigned int *) jlong_to_ptr(height_return)); + + if (status == 0) return JNI_FALSE; + else return JNI_TRUE; +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XFreeCursor + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XFreeCursor +(JNIEnv *env, jclass clazz, jlong display, jlong cursor) { + + AWT_CHECK_HAVE_LOCK(); + XFreeCursor( (Display *) jlong_to_ptr(display), (Cursor) cursor); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XQueryPointer + * Signature: (JJJJJJJJJ)Z + */ +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XQueryPointer +(JNIEnv *env, jclass clazz, jlong display, jlong w, jlong root_return, jlong child_return, jlong root_x_return , jlong root_y_return, jlong win_x_return, jlong win_y_return, jlong mask_return) { + + Bool b; + + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + b = XQueryPointer((Display *) jlong_to_ptr(display), + (Window) w, (Window *) jlong_to_ptr(root_return), (Window *) jlong_to_ptr(child_return), + (int *) jlong_to_ptr(root_x_return), (int *) jlong_to_ptr(root_y_return), + (int *) jlong_to_ptr(win_x_return), (int *) jlong_to_ptr(win_y_return), + (unsigned int *) jlong_to_ptr(mask_return)); + + return b ? JNI_TRUE : JNI_FALSE; +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XChangeWindowAttributes + * Signature: (JJJJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XChangeWindowAttributes +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong valuemask, jlong attributes) { + + AWT_CHECK_HAVE_LOCK(); + XChangeWindowAttributes((Display *) jlong_to_ptr(display), (Window) window, (unsigned long) valuemask, + (XSetWindowAttributes *) jlong_to_ptr(attributes)); +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XSetTransientFor + * Signature: (JJJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSetTransientFor +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong transient_for_window) +{ + AWT_CHECK_HAVE_LOCK(); + XSetTransientForHint((Display *) jlong_to_ptr(display), window, transient_for_window); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XSetWMHints + * Signature: (JJJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSetWMHints +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong hints) +{ + AWT_CHECK_HAVE_LOCK(); + XSetWMHints((Display *) jlong_to_ptr(display), window, (XWMHints *) jlong_to_ptr(hints)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XGetWMHints + * Signature: (JJJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XGetWMHints +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong hints) +{ + XWMHints * get_hints; + AWT_CHECK_HAVE_LOCK(); + get_hints = XGetWMHints((Display*)jlong_to_ptr(display), window); + if (get_hints != NULL) { + memcpy(jlong_to_ptr(hints), get_hints, sizeof(XWMHints)); + XFree(get_hints); + } else { + memset(jlong_to_ptr(hints), 0, sizeof(XWMHints)); + } +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XGetPointerMapping + * Signature: (JJI)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XGetPointerMapping +(JNIEnv *env, jclass clazz, jlong display, jlong map, jint buttonNumber) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XGetPointerMapping((Display*)jlong_to_ptr(display), (unsigned char*) jlong_to_ptr(map), buttonNumber); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XGetDefault + * Signature: (JJI)I + */ +JNIEXPORT jstring JNICALL Java_sun_awt_X11_XlibWrapper_XGetDefault +(JNIEnv *env, jclass clazz, jlong display, jstring program, jstring option) +{ + char * c_program = NULL; + char * c_option = NULL; + char * c_res = NULL; + + if (!JNU_IsNull(env, program)) { + c_program = (char *)JNU_GetStringPlatformChars(env, program, NULL); + } + CHECK_NULL_RETURN(c_program, NULL); + + if (!JNU_IsNull(env, option)) { + c_option = (char *)JNU_GetStringPlatformChars(env, option, NULL); + } + + if (c_option == NULL) { + JNU_ReleaseStringPlatformChars(env, program, (const char *) c_program); + return NULL; + } + + AWT_CHECK_HAVE_LOCK_RETURN(NULL); + c_res = XGetDefault((Display*)jlong_to_ptr(display), c_program, c_option); + // The strings returned by XGetDefault() are owned by Xlib and + // should not be modified or freed by the client. + + JNU_ReleaseStringPlatformChars(env, program, (const char *) c_program); + JNU_ReleaseStringPlatformChars(env, option, (const char *) c_option); + + if (c_res != NULL) { + return JNU_NewStringPlatform(env, c_res); + } else { + return NULL; + } +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: getScreenOfWindow + * Signature: (JJ)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_getScreenOfWindow +(JNIEnv *env, jclass clazz, jlong display, jlong window) +{ + XWindowAttributes attrs; + memset(&attrs, 0, sizeof(attrs)); + AWT_CHECK_HAVE_LOCK_RETURN(0); + XGetWindowAttributes((Display *) jlong_to_ptr(display), window, &attrs); + return ptr_to_jlong(attrs.screen); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XScreenNumberOfScreen + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XScreenNumberOfScreen +(JNIEnv *env, jclass clazz, jlong screen) +{ + AWT_CHECK_HAVE_LOCK_RETURN(-1); + if(jlong_to_ptr(screen) == NULL) { + return -1; + } + return XScreenNumberOfScreen((Screen*) jlong_to_ptr(screen)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XIconifyWindow + * Signature: (JJJ)V + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XIconifyWindow +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong screenNumber) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XIconifyWindow((Display*) jlong_to_ptr(display), window, screenNumber); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XFree + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XFree +(JNIEnv *env, jclass clazz, jlong ptr) +{ + AWT_CHECK_HAVE_LOCK(); + XFree(jlong_to_ptr(ptr)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XFree + * Signature: (J)V + */ +JNIEXPORT jbyteArray JNICALL Java_sun_awt_X11_XlibWrapper_getStringBytes +(JNIEnv *env, jclass clazz, jlong str_ptr) +{ + unsigned char * str = (unsigned char*) jlong_to_ptr(str_ptr); + long length = strlen((char*)str); + jbyteArray res = (*env)->NewByteArray(env, length); + CHECK_NULL_RETURN(res, NULL); + (*env)->SetByteArrayRegion(env, res, 0, length, + (const signed char*) str); + return res; +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: ServerVendor + * Signature: (J)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_sun_awt_X11_XlibWrapper_ServerVendor +(JNIEnv *env, jclass clazz, jlong display) +{ + AWT_CHECK_HAVE_LOCK_RETURN(NULL); + return JNU_NewStringPlatform(env, ServerVendor((Display*)jlong_to_ptr(display))); +} +/* + * Class: sun_awt_X11_XlibWrapper + * Method: VendorRelease + * Signature: (J)I; + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_VendorRelease +(JNIEnv *env, jclass clazz, jlong display) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return VendorRelease((Display*)jlong_to_ptr(display)); +} +/* + * Class: sun_awt_X11_XlibWrapper + * Method: IsXsunKPBehavior + * Signature: (J)Z; + */ +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_IsXsunKPBehavior +(JNIEnv *env, jclass clazz, jlong display) +{ + // Xsun without XKB uses keysymarray[2] keysym to determine if it is KP event. + // Otherwise, it is [1] or sometimes [0]. + // This sniffer first tries to determine what is a keycode for XK_KP_7 + // using XKeysymToKeycode; + // second, in which place in the keysymarray is XK_KP_7 + // using XKeycodeToKeysym. + int kc7; + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + kc7 = XKeysymToKeycode((Display*)jlong_to_ptr(display), XK_KP_7); + if( !kc7 ) { + // keycode is not defined. Why, it's a reduced keyboard perhaps: + // report arbitrarily false. + return JNI_FALSE; + } else { + long ks2 = keycodeToKeysym((Display*)jlong_to_ptr(display), kc7, 2); + if( ks2 == XK_KP_7 ) { + //XXX If some Xorg server would put XK_KP_7 in keysymarray[2] as well, + //XXX for yet unknown to me reason, the sniffer would lie. + return JNI_TRUE; + }else{ + return JNI_FALSE; + } + } +} + + +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_IsSunKeyboard +(JNIEnv *env, jclass clazz, jlong display) +{ + int xx; + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + xx = XKeysymToKeycode((Display*)jlong_to_ptr(display), SunXK_F37); + return (!xx) ? JNI_FALSE : JNI_TRUE; +} + +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_IsKanaKeyboard +(JNIEnv *env, jclass clazz, jlong display) +{ + int xx; + static jboolean result = JNI_FALSE; + + int32_t minKeyCode, maxKeyCode, keySymsPerKeyCode; + KeySym *keySyms, *keySymsStart, keySym; + int32_t i; + int32_t kanaCount = 0; + + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + + // There's no direct way to determine whether the keyboard has + // a kana lock key. From available keyboard mapping tables, it looks + // like only keyboards with the kana lock key can produce keysyms + // for kana characters. So, as an indirect test, we check for those. + XDisplayKeycodes((Display*)jlong_to_ptr(display), &minKeyCode, &maxKeyCode); + keySyms = XGetKeyboardMapping((Display*)jlong_to_ptr(display), minKeyCode, maxKeyCode - minKeyCode + 1, &keySymsPerKeyCode); + keySymsStart = keySyms; + for (i = 0; i < (maxKeyCode - minKeyCode + 1) * keySymsPerKeyCode; i++) { + keySym = *keySyms++; + if ((keySym & 0xff00) == 0x0400) { + kanaCount++; + } + } + XFree(keySymsStart); + + // use a (somewhat arbitrary) minimum so we don't get confused by a stray function key + result = kanaCount > 10; + return result ? JNI_TRUE : JNI_FALSE; +} + +JavaVM* jvm = NULL; +static int ToolkitErrorHandler(Display * dpy, XErrorEvent * event) { + JNIEnv * env; + // First call the native synthetic error handler declared in "awt_util.h" file. + if (current_native_xerror_handler != NULL) { + current_native_xerror_handler(dpy, event); + } + if (jvm != NULL) { + env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); + if (env) { + return JNU_CallStaticMethodByName(env, NULL, "sun/awt/X11/XErrorHandlerUtil", + "globalErrorHandler", "(JJ)I", ptr_to_jlong(dpy), ptr_to_jlong(event)).i; + } + } + return 0; +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: SetToolkitErrorHandler + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_SetToolkitErrorHandler +(JNIEnv *env, jclass clazz) +{ + if ((*env)->GetJavaVM(env, &jvm) < 0) { + return 0; + } + AWT_CHECK_HAVE_LOCK_RETURN(0); + return ptr_to_jlong(XSetErrorHandler(ToolkitErrorHandler)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XSetErrorHandler + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSetErrorHandler +(JNIEnv *env, jclass clazz, jlong handler) +{ + AWT_CHECK_HAVE_LOCK(); + XSetErrorHandler((XErrorHandler) jlong_to_ptr(handler)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: CallErrorHandler + * Signature: (JJJ)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_CallErrorHandler +(JNIEnv *env, jclass clazz, jlong handler, jlong display, jlong event_ptr) +{ + return (*(XErrorHandler)jlong_to_ptr(handler))((Display*) jlong_to_ptr(display), (XErrorEvent*) jlong_to_ptr(event_ptr)); +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: PrintXErrorEvent + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_PrintXErrorEvent +(JNIEnv *env, jclass clazz, jlong display, jlong event_ptr) +{ + char msg[128]; + char buf[128]; + + XErrorEvent* err = (XErrorEvent *)jlong_to_ptr(event_ptr); + + XGetErrorText((Display *)jlong_to_ptr(display), err->error_code, msg, sizeof(msg)); + jio_fprintf(stderr, "Xerror %s, XID %x, ser# %d\n", msg, err->resourceid, err->serial); + jio_snprintf(buf, sizeof(buf), "%d", err->request_code); + XGetErrorDatabaseText((Display *)jlong_to_ptr(display), "XRequest", buf, "Unknown", msg, sizeof(msg)); + jio_fprintf(stderr, "Major opcode %d (%s)\n", err->request_code, msg); + if (err->request_code > 128) { + jio_fprintf(stderr, "Minor opcode %d\n", err->minor_code); + } +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XInternAtoms + * Signature: (J[Ljava/lang/String;ZJ)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XInternAtoms +(JNIEnv *env, jclass clazz, jlong display, jobjectArray names_arr, jboolean only_if_exists, jlong atoms) +{ + int status = 0; + AWT_CHECK_HAVE_LOCK_RETURN(0); + jsize length; + char** names = stringArrayToNative(env, names_arr, &length); + if (names) { + status = XInternAtoms((Display*)jlong_to_ptr(display), names, length, only_if_exists, (Atom*) jlong_to_ptr(atoms)); + freeNativeStringArray(names, length); + } + return status; +} + + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XGetWindowAttributes + * Signature: (JJJ)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XGetWindowAttributes +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong attr_ptr) +{ + jint status; + AWT_CHECK_HAVE_LOCK_RETURN(0); + memset((XWindowAttributes*) jlong_to_ptr(attr_ptr), 0, sizeof(XWindowAttributes)); + status = XGetWindowAttributes((Display*)jlong_to_ptr(display), window, (XWindowAttributes*) jlong_to_ptr(attr_ptr)); + return status; +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XGetGeometry + * Signature: (JJJJJJJJJ)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XGetGeometry +(JNIEnv *env, jclass clazz, jlong display, jlong drawable, jlong root_return, + jlong x_return, jlong y_return, jlong width_return, jlong height_return, + jlong border_width_return, jlong depth_return) +{ + jint status; + AWT_CHECK_HAVE_LOCK_RETURN(0); + status = XGetGeometry((Display *)jlong_to_ptr(display), + (Drawable)drawable, (Window *)jlong_to_ptr(root_return), + (int *)jlong_to_ptr(x_return), (int *)jlong_to_ptr(y_return), + (unsigned int *)jlong_to_ptr(width_return), (unsigned int *)jlong_to_ptr(height_return), + (unsigned int *)jlong_to_ptr(border_width_return), + (unsigned int *)jlong_to_ptr(depth_return)); + return status; +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XGetWMNormalHints + * Signature: (JJJJ)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XGetWMNormalHints +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong hints, jlong supplied_return) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XGetWMNormalHints((Display*) jlong_to_ptr(display), + window, + (XSizeHints*) jlong_to_ptr(hints), + (long*) jlong_to_ptr(supplied_return)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XSetWMNormalHints + * Signature: (JJJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSetWMNormalHints +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong hints) +{ + AWT_CHECK_HAVE_LOCK(); + XSetWMNormalHints((Display*) jlong_to_ptr(display), window, (XSizeHints*) jlong_to_ptr(hints)); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XDeleteProperty + * Signature: (JJJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XDeleteProperty +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong atom) +{ + AWT_CHECK_HAVE_LOCK(); + XDeleteProperty((Display*) jlong_to_ptr(display), window, (Atom)atom); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XSendEvent + * Signature: (JJZJJ)V + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XSendEvent +(JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean propagate, jlong event_mask, jlong event) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XSendEvent((Display*) jlong_to_ptr(display), + window, + propagate==JNI_TRUE?True:False, + (long) event_mask, + (XEvent*) jlong_to_ptr(event)); +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XQueryTree + * Signature: (JJJJJJ)I + */ +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XQueryTree +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong root_return, jlong parent_return, jlong children_return, jlong nchildren_return) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XQueryTree((Display*) jlong_to_ptr(display), + window, + (Window *) jlong_to_ptr(root_return), + (Window*) jlong_to_ptr(parent_return), + (Window**) jlong_to_ptr(children_return), + (unsigned int*) jlong_to_ptr(nchildren_return)); +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: memcpy + * Signature: (JJJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_memcpy +(JNIEnv *env, jclass clazz, jlong dest_ptr, jlong src_ptr, jlong length) +{ + 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; + AWT_CHECK_HAVE_LOCK(); + hints = XAllocSizeHints(); + hints->flags = flags; + hints->width = width; + hints->min_width = width; + hints->max_width = width; + hints->height = height; + hints->min_height = height; + hints->max_height = height; + hints->x = x; + hints->y = y; + XSetWMNormalHints((Display*) jlong_to_ptr(display), window, hints); + 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) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return ptr_to_jlong(XGetVisualInfo((Display*) jlong_to_ptr(display), + (long) vinfo_mask, + (XVisualInfo*) jlong_to_ptr(vinfo_template), + (int*) jlong_to_ptr(nitems_return))); +} + +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XAllocSizeHints + (JNIEnv *env, jclass clazz) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return ptr_to_jlong(XAllocSizeHints()); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XIconifyWindow + * Signature: (JJJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XBell +(JNIEnv *env, jclass clazz, jlong display, jint percent) +{ + AWT_CHECK_HAVE_LOCK(); + XBell((Display*)jlong_to_ptr(display), percent); +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XAllocColor + * Signature: (JJJ)Z + */ +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XAllocColor +(JNIEnv *env, jclass clazz, jlong display , jlong colormap, jlong xcolor) { + + Status status; + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + status = XAllocColor((Display *) jlong_to_ptr(display), (Colormap) colormap, (XColor *) jlong_to_ptr(xcolor)); + + if (status == 0) return JNI_FALSE; + else return JNI_TRUE; +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XCreateBitmapFromData + * Signature: (JJJII)J + */ +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XCreateBitmapFromData +(JNIEnv *env, jclass clazz, jlong display, jlong drawable, jlong data, jint width, jint height) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + + return (jlong) XCreateBitmapFromData((Display *) jlong_to_ptr(display), (Drawable) drawable, + (char *) jlong_to_ptr(data), width, height); +} + + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XFreePixmap + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XFreePixmap +(JNIEnv *env, jclass clazz, jlong display, jlong pixmap) { + AWT_CHECK_HAVE_LOCK(); + XFreePixmap((Display *)jlong_to_ptr(display), (Pixmap) pixmap); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XReparentWindow + * Signature: (JJJII)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XReparentWindow +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong parent, jint x, jint y) { + AWT_CHECK_HAVE_LOCK(); + XReparentWindow((Display*)jlong_to_ptr(display), window, parent, x, y); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XConvertSelection + * Signature: (JJJJJJ)V + */ +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_XConvertSelection(JNIEnv *env, jclass clazz, + jlong display, jlong selection, + jlong target, jlong property, + jlong requestor, jlong time) { + AWT_CHECK_HAVE_LOCK(); + XConvertSelection((Display*)jlong_to_ptr(display), selection, target, property, requestor, + time); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XSetSelectionOwner + * Signature: (JJJJ)V + */ +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_XSetSelectionOwner(JNIEnv *env, jclass clazz, + jlong display, jlong selection, + jlong owner, jlong time) { + AWT_CHECK_HAVE_LOCK(); + XSetSelectionOwner((Display*)jlong_to_ptr(display), selection, owner, time); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XGetSelectionOwner + * Signature: (JJ)J + */ +JNIEXPORT jlong JNICALL +Java_sun_awt_X11_XlibWrapper_XGetSelectionOwner(JNIEnv *env, jclass clazz, + jlong display, jlong selection) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return (jlong)XGetSelectionOwner((Display*)jlong_to_ptr(display), selection); +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XGetAtomName + * Signature: (JJ)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_sun_awt_X11_XlibWrapper_XGetAtomName(JNIEnv *env, jclass clazz, + jlong display, jlong atom) +{ + jstring string = NULL; + char* name; + AWT_CHECK_HAVE_LOCK_RETURN(NULL); + name = (char*) XGetAtomName((Display*)jlong_to_ptr(display), atom); + + if (name == NULL) { + fprintf(stderr, "Atom was %d\n", (int)atom); + JNU_ThrowNullPointerException(env, "Failed to retrieve atom name."); + return NULL; + } + + string = (*env)->NewStringUTF(env, (const char *)name); + + XFree(name); + + return string; +} + +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XMaxRequestSize + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL +Java_sun_awt_X11_XlibWrapper_XMaxRequestSize(JNIEnv *env, jclass clazz, + jlong display) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XMaxRequestSize((Display*) jlong_to_ptr(display)); +} + +JNIEXPORT jlong JNICALL +Java_sun_awt_X11_XlibWrapper_XAllocWMHints(JNIEnv *env, jclass clazz) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return ptr_to_jlong(XAllocWMHints()); +} + +JNIEXPORT jlong JNICALL +Java_sun_awt_X11_XlibWrapper_XCreatePixmap(JNIEnv *env, jclass clazz, jlong display, jlong drawable, jint width, jint height, jint depth) +{ + 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, + jint depth, jint format, jint offset, jlong data, jint width, + jint height, jint bitmap_pad, jint bytes_per_line) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return ptr_to_jlong(XCreateImage((Display*) jlong_to_ptr(display), (Visual*) jlong_to_ptr(visual_ptr), + 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, + jlong valuemask, jlong values) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return ptr_to_jlong(XCreateGC((Display*) jlong_to_ptr(display), (Drawable)drawable, valuemask, (XGCValues*) jlong_to_ptr(values))); +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_XDestroyImage(JNIEnv *env, jclass clazz, jlong image) +{ + XImage *img = (XImage*) jlong_to_ptr(image); + AWT_CHECK_HAVE_LOCK(); + + // Fix for bug 4903671 : + // We should be careful to not double free the memory pointed to data + // Since we use unsafe to allocate it, we should use unsafe to free it. + // So we should NULL the data pointer before calling XDestroyImage so + // that X does not free the pointer for us. + 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) +{ + AWT_CHECK_HAVE_LOCK(); + 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) +{ + AWT_CHECK_HAVE_LOCK(); + XClearWindow((Display*) jlong_to_ptr(display), (Window)window); +} + +JNIEXPORT jint JNICALL +Java_sun_awt_X11_XlibWrapper_XGetIconSizes(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong ret_sizes, jlong ret_count) +{ + XIconSize** psize = (XIconSize**) jlong_to_ptr(ret_sizes); + int * pcount = (int *) jlong_to_ptr(ret_count); + Status res; + AWT_CHECK_HAVE_LOCK_RETURN(0); + res = XGetIconSizes((Display*) jlong_to_ptr(display), (Window)window, psize, pcount); + return res; +} + +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XdbeQueryExtension + (JNIEnv *env, jclass clazz, jlong display, jlong major_version_return, + jlong minor_version_return) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XdbeQueryExtension((Display*) jlong_to_ptr(display), (int *) jlong_to_ptr(major_version_return), + (int *) jlong_to_ptr(minor_version_return)); +} + +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_XQueryExtension + (JNIEnv *env, jclass clazz, jlong display, jstring jstr, jlong mop_return, + jlong feve_return, jlong err_return) +{ + char *cname; + Boolean bu; + if (!JNU_IsNull(env, jstr)) { + cname = (char *)JNU_GetStringPlatformChars(env, jstr, NULL); + CHECK_NULL_RETURN(cname, JNI_FALSE); + } else { + cname = ""; + } + + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + bu = XQueryExtension((Display*) jlong_to_ptr(display), cname, (int *) jlong_to_ptr(mop_return), + (int *) jlong_to_ptr(feve_return), (int *) jlong_to_ptr(err_return)); + if (!JNU_IsNull(env, jstr)) { + JNU_ReleaseStringPlatformChars(env, jstr, (const char *) cname); + } + return bu ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL Java_sun_awt_X11_XlibWrapper_IsKeypadKey + (JNIEnv *env, jclass clazz, jlong keysym) +{ + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + if(IsKeypadKey(keysym)) { + return JNI_TRUE; + } + return JNI_FALSE; +} + +JNIEXPORT jlong JNICALL Java_sun_awt_X11_XlibWrapper_XdbeAllocateBackBufferName + (JNIEnv *env, jclass clazz, jlong display, jlong window, jint swap_action) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XdbeAllocateBackBufferName((Display*) jlong_to_ptr(display), (Window) window, + (XdbeSwapAction) swap_action); +} + +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XdbeDeallocateBackBufferName + (JNIEnv *env, jclass clazz, jlong display, jlong buffer) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XdbeDeallocateBackBufferName((Display*) jlong_to_ptr(display), (XdbeBackBuffer) buffer); +} + +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XdbeBeginIdiom + (JNIEnv *env, jclass clazz, jlong display) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XdbeBeginIdiom((Display*) jlong_to_ptr(display)); +} + +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XdbeEndIdiom + (JNIEnv *env, jclass clazz, jlong display) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XdbeEndIdiom((Display*) jlong_to_ptr(display)); +} + +JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XdbeSwapBuffers + (JNIEnv *env, jclass clazz, jlong display, jlong swap_info, jint num_windows) +{ + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XdbeSwapBuffers((Display*) jlong_to_ptr(display), (XdbeSwapInfo *) jlong_to_ptr(swap_info), num_windows); +} +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)); +} + +// XKeycodeToKeysym is deprecated but for compatibility we keep the API. +JNIEXPORT jlong JNICALL +Java_sun_awt_X11_XlibWrapper_XKeycodeToKeysym(JNIEnv *env, jclass clazz, + jlong display, jint keycode, + jint index) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return keycodeToKeysym((Display*)jlong_to_ptr(display), (unsigned int)keycode, (int)index); +} + +JNIEXPORT jint JNICALL +Java_sun_awt_X11_XlibWrapper_XkbGetEffectiveGroup(JNIEnv *env, jclass clazz, + jlong display) { + XkbStateRec sr; + AWT_CHECK_HAVE_LOCK_RETURN(0); + memset(&sr, 0, sizeof(XkbStateRec)); + XkbGetState((Display*) jlong_to_ptr(display), XkbUseCoreKbd, &sr); +// printf("-------------------------------------VVVV\n"); +// printf(" group:0x%0X\n",sr.group); +// printf(" base_group:0x%0X\n",sr.base_group); +// printf(" latched_group:0x%0X\n",sr.latched_group); +// printf(" locked_group:0x%0X\n",sr.locked_group); +// printf(" mods:0x%0X\n",sr.mods); +// printf(" base_mods:0x%0X\n",sr.base_mods); +// printf(" latched_mods:0x%0X\n",sr.latched_mods); +// printf(" locked_mods:0x%0X\n",sr.locked_mods); +// printf(" compat_state:0x%0X\n",sr.compat_state); +// printf(" grab_mods:0x%0X\n",sr.grab_mods); +// printf(" compat_grab_mods:0x%0X\n",sr.compat_grab_mods); +// printf(" lookup_mods:0x%0X\n",sr.lookup_mods); +// printf(" compat_lookup_mods:0x%0X\n",sr.compat_lookup_mods); +// printf(" ptr_buttons:0x%0X\n",sr.ptr_buttons); +// printf("-------------------------------------^^^^\n"); + return (jint)(sr.group); +} +JNIEXPORT jlong JNICALL +Java_sun_awt_X11_XlibWrapper_XkbKeycodeToKeysym(JNIEnv *env, jclass clazz, + jlong display, jint keycode, + jint group, jint level) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XkbKeycodeToKeysym((Display*) jlong_to_ptr(display), (unsigned int)keycode, (unsigned int)group, (unsigned int)level); +} + +JNIEXPORT jint JNICALL +Java_sun_awt_X11_XlibWrapper_XKeysymToKeycode(JNIEnv *env, jclass clazz, + jlong display, jlong keysym) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return XKeysymToKeycode((Display*) jlong_to_ptr(display), (KeySym)keysym); +} + +JNIEXPORT jlong JNICALL +Java_sun_awt_X11_XlibWrapper_XGetModifierMapping(JNIEnv *env, jclass clazz, + jlong display) { + AWT_CHECK_HAVE_LOCK_RETURN(0); + return ptr_to_jlong(XGetModifierMapping((Display*) jlong_to_ptr(display))); +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_XFreeModifiermap(JNIEnv *env, jclass clazz, + jlong keymap) { + AWT_CHECK_HAVE_LOCK(); + XFreeModifiermap((XModifierKeymap*) jlong_to_ptr(keymap)); +} +/* + * Class: sun_awt_X11_XlibWrapper + * Method: XRefreshKeyboardMapping + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XRefreshKeyboardMapping +(JNIEnv *env, jclass clazz, jlong event_ptr) +{ + AWT_CHECK_HAVE_LOCK(); + XRefreshKeyboardMapping((XMappingEvent*) jlong_to_ptr(event_ptr)); +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_XChangeActivePointerGrab(JNIEnv *env, jclass clazz, + jlong display, jint mask, + jlong cursor, jlong time) { + AWT_CHECK_HAVE_LOCK(); + XChangeActivePointerGrab((Display*)jlong_to_ptr(display), (unsigned int)mask, + (Cursor)cursor, (Time)time); +} + +/******************* Secondary loop support ************************************/ +#define AWT_SECONDARY_LOOP_TIMEOUT 250 + +static Bool exitSecondaryLoop = True; + +/* + * This predicate procedure allows the Toolkit thread to process specific events + * while it is blocked waiting for the event dispatch thread to process + * a SunDropTargetEvent. We need this to prevent deadlock when the client code + * processing SunDropTargetEvent sets or gets the contents of the system + * clipboard/selection. In this case the event dispatch thread waits for the + * Toolkit thread to process PropertyNotify or SelectionNotify events. + */ +static Bool +secondary_loop_event(Display* dpy, XEvent* event, XPointer xawt_root_window) { + return ( + event->type == SelectionNotify || + event->type == SelectionClear || + event->type == PropertyNotify || + (event->type == ConfigureNotify + && event->xany.window == *(Window*) xawt_root_window) + ) ? True : False; +} + + +JNIEXPORT jboolean JNICALL +Java_sun_awt_X11_XlibWrapper_XNextSecondaryLoopEvent(JNIEnv *env, jclass clazz, + jlong display, jlong ptr) { + uint32_t timeout = 1; + + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + exitSecondaryLoop = False; + Window xawt_root_window = get_xawt_root_shell(env); + + while (!exitSecondaryLoop) { + if (XCheckIfEvent((Display*) jlong_to_ptr(display), + (XEvent*) jlong_to_ptr(ptr), secondary_loop_event, (XPointer) &xawt_root_window)) { + return JNI_TRUE; + } + timeout = (timeout < AWT_SECONDARY_LOOP_TIMEOUT) ? (timeout << 1) : AWT_SECONDARY_LOOP_TIMEOUT; + AWT_WAIT(timeout); + } + return JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_ExitSecondaryLoop(JNIEnv *env, jclass clazz) { + DASSERT(!exitSecondaryLoop); + AWT_CHECK_HAVE_LOCK(); + exitSecondaryLoop = True; + AWT_NOTIFY_ALL(); +} +/*******************************************************************************/ + +JNIEXPORT jobjectArray JNICALL +Java_sun_awt_X11_XlibWrapper_XTextPropertyToStringList(JNIEnv *env, + jclass clazz, + jbyteArray bytes, + jlong encodingAtom) { + XTextProperty tp; + jbyte *value; + + char** strings = (char **)NULL; + int32_t nstrings = 0; + jobjectArray ret = NULL; + int32_t i; + jsize len; + jboolean isCopy = JNI_FALSE; + static jclass stringClass = NULL; + jclass stringClassLocal = NULL; + + AWT_CHECK_HAVE_LOCK_RETURN(NULL); + + if (JNU_IsNull(env, stringClass)) { + stringClassLocal = (*env)->FindClass(env, "java/lang/String"); + + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + DASSERT(False); + } + + if (JNU_IsNull(env, stringClassLocal)) { + return NULL; + } + + stringClass = (*env)->NewGlobalRef(env, stringClassLocal); /* never freed! */ + (*env)->DeleteLocalRef(env, stringClassLocal); + + if (JNU_IsNull(env, stringClass)) { + JNU_ThrowOutOfMemoryError(env, ""); + return NULL; + } + } + + /* + * If the length of the byte array is 0 just return a null + */ + len = (*env)->GetArrayLength(env, bytes); + if (len == 0) { + return (*env)->NewObjectArray(env, 0, stringClass, NULL); + } + + value = (*env)->GetByteArrayElements(env, bytes, &isCopy); + if (JNU_IsNull(env, value)) { + return NULL; + } + + tp.encoding = encodingAtom; + tp.value = (unsigned char *)value; + tp.nitems = len; + tp.format = 8; + + /* + * Convert the byte stream into a list of X11 strings + */ + if (XTextPropertyToStringList(&tp, &strings, &nstrings) == 0) { + (*env)->ReleaseByteArrayElements(env, bytes, value, JNI_ABORT); + return NULL; + } + + (*env)->ReleaseByteArrayElements(env, bytes, value, JNI_ABORT); + + if (nstrings == 0) { + return (*env)->NewObjectArray(env, 0, stringClass, NULL); + } + + ret = (*env)->NewObjectArray(env, nstrings, stringClass, NULL); + + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + goto wayout; + } + + if (JNU_IsNull(env, ret)) { + goto wayout; + } + + for (i = 0; i < nstrings; i++) { + jstring string = (*env)->NewStringUTF(env, + (const char *)strings[i]); + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + goto wayout; + } + + if (JNU_IsNull(env, string)) { + goto wayout; + } + + (*env)->SetObjectArrayElement(env, ret, i, string); + + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionDescribe(env); + (*env)->ExceptionClear(env); + goto wayout; + } + + (*env)->DeleteLocalRef(env, string); + } + + wayout: + /* + * Clean up and return + */ + XFreeStringList(strings); + return ret; +} + + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_XPutBackEvent(JNIEnv *env, + jclass clazz, + jlong display, + jlong event) { + XPutBackEvent((Display*)jlong_to_ptr(display), (XEvent*) jlong_to_ptr(event)); +} + +JNIEXPORT jlong JNICALL +Java_sun_awt_X11_XlibWrapper_getAddress(JNIEnv *env, + jclass clazz, + jobject o) { + return ptr_to_jlong(o); +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_copyIntArray(JNIEnv *env, + jclass clazz, + jlong dest, jobject array, jint size) { + jboolean isCopy = JNI_FALSE; + jint * ints = (*env)->GetIntArrayElements(env, array, &isCopy); + memcpy(jlong_to_ptr(dest), ints, size); + if (isCopy) { + (*env)->ReleaseIntArrayElements(env, array, ints, JNI_ABORT); + } +} + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_copyLongArray(JNIEnv *env, + jclass clazz, + jlong dest, jobject array, jint size) { + jboolean isCopy = JNI_FALSE; + jlong * longs = (*env)->GetLongArrayElements(env, array, &isCopy); + memcpy(jlong_to_ptr(dest), longs, size); + if (isCopy) { + (*env)->ReleaseLongArrayElements(env, array, longs, JNI_ABORT); + } +} + +JNIEXPORT jint JNICALL +Java_sun_awt_X11_XlibWrapper_XSynchronize(JNIEnv *env, jclass clazz, jlong display, jboolean onoff) +{ + return (jint) XSynchronize((Display*)jlong_to_ptr(display), (onoff == JNI_TRUE ? True : False)); +} + +JNIEXPORT jboolean JNICALL +Java_sun_awt_X11_XlibWrapper_XShapeQueryExtension +(JNIEnv *env, jclass clazz, jlong display, jlong event_base_return, jlong error_base_return) +{ + Bool status; + + AWT_CHECK_HAVE_LOCK_RETURN(JNI_FALSE); + + status = XShapeQueryExtension((Display *)jlong_to_ptr(display), + (int *)jlong_to_ptr(event_base_return), (int *)jlong_to_ptr(error_base_return)); + return status ? JNI_TRUE : JNI_FALSE; +} + +/* + * Class: XlibWrapper + * Method: SetRectangularShape + */ + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_SetRectangularShape +(JNIEnv *env, jclass clazz, jlong display, jlong window, + jint x1, jint y1, jint x2, jint y2, + jobject region) +{ + AWT_CHECK_HAVE_LOCK(); + + // If all the params are zeros, the shape must be simply reset. + // Otherwise, the shape may be not rectangular. + if (region || x1 || x2 || y1 || y2) { + XRectangle rects[256]; + XRectangle *pRect = rects; + + int numrects = RegionToYXBandedRectangles(env, x1, y1, x2, y2, region, + &pRect, 256); + + XShapeCombineRectangles((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window), + ShapeClip, 0, 0, pRect, numrects, ShapeSet, YXBanded); + XShapeCombineRectangles((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window), + ShapeBounding, 0, 0, pRect, numrects, ShapeSet, YXBanded); + + if (pRect != rects) { + free(pRect); + } + } else { + // Reset the shape to a rectangular form. + XShapeCombineMask((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window), + ShapeClip, 0, 0, None, ShapeSet); + XShapeCombineMask((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window), + ShapeBounding, 0, 0, None, ShapeSet); + } +} + +/* + * Class: XlibWrapper + * Method: SetZOrder + */ + +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_SetZOrder +(JNIEnv *env, jclass clazz, jlong display, jlong window, jlong above) +{ + unsigned int value_mask = CWStackMode; + + XWindowChanges wc; + wc.sibling = (Window)jlong_to_ptr(above); + + AWT_CHECK_HAVE_LOCK(); + + if (above == 0) { + wc.stack_mode = Above; + } else { + wc.stack_mode = Below; + value_mask |= CWSibling; + } + + XConfigureWindow((Display *)jlong_to_ptr(display), + (Window)jlong_to_ptr(window), + value_mask, &wc ); +} + +/* + * Class: XlibWrapper + * Method: SetBitmapShape + */ +JNIEXPORT void JNICALL +Java_sun_awt_X11_XlibWrapper_SetBitmapShape +(JNIEnv *env, jclass clazz, jlong display, jlong window, + jint width, jint height, jintArray bitmap) +{ + jsize len; + jint *values; + jboolean isCopy = JNI_FALSE; + size_t worstBufferSize = (size_t)((width / 2 + 1) * height); + RECT_T * pRect; + int numrects; + + if (!IS_SAFE_SIZE_MUL(width / 2 + 1, height)) { + return; + } + + AWT_CHECK_HAVE_LOCK(); + + len = (*env)->GetArrayLength(env, bitmap); + if (len == 0 || len < width * height) { + return; + } + + values = (*env)->GetIntArrayElements(env, bitmap, &isCopy); + if (JNU_IsNull(env, values)) { + return; + } + + pRect = (RECT_T *)SAFE_SIZE_ARRAY_ALLOC(malloc, worstBufferSize, sizeof(RECT_T)); + if (!pRect) { + return; + } + + /* Note: the values[0] and values[1] are supposed to contain the width + * and height (see XIconInfo.getIntData() for details). So, we do +2. + */ + numrects = BitmapToYXBandedRectangles(32, (int)width, (int)height, + (unsigned char *)(values + 2), pRect); + + XShapeCombineRectangles((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window), + ShapeClip, 0, 0, pRect, numrects, ShapeSet, YXBanded); + XShapeCombineRectangles((Display *)jlong_to_ptr(display), (Window)jlong_to_ptr(window), + ShapeBounding, 0, 0, pRect, numrects, ShapeSet, YXBanded); + + free(pRect); + + (*env)->ReleaseIntArrayElements(env, bitmap, values, JNI_ABORT); +}