blob: 1612009354589e756325d98d16a779160e76347e [file] [log] [blame]
/*
* Copyright 1996-2005 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package sun.awt.motif;
import java.awt.Toolkit;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.FlavorMap;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.SystemFlavorMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.Vector;
import sun.awt.AppContext;
import sun.awt.SunToolkit;
import sun.awt.datatransfer.DataTransferer;
/*
* Implements a general interface to the X11 selection mechanism.
*
* @author Amy Fowler
* @author Roger Brinkley
* @author Danila Sinopalnikov
* @author Alexander Gerasimov
*
* @since JDK1.1
*/
public class X11Selection {
static FlavorMap flavorMap = SystemFlavorMap.getDefaultFlavorMap();
static Vector selections;
long atom;
private X11Clipboard clipboard;
private X11SelectionHolder holder;
private Transferable contents;
private boolean disposed = false;
private byte[] data = null;
private boolean dataAvailable = false;
private static final Object source = new Object();
static {
// 4154170: Need to ensure the the toolkit is initialized prior
// to executing this initializer
Toolkit toolkit = Toolkit.getDefaultToolkit();
selections = new Vector();
initIDs();
init();
}
private static native void initIDs();
static native void init();
public X11Selection(String name, X11Clipboard clipboard) {
atom = ((MDataTransferer)DataTransferer.getInstance()).getAtomForTarget(name);
selections.addElement(this);
this.clipboard = clipboard;
}
private static Object[] getSelectionsArray() {
return selections.toArray();
}
/*
* methods for acting as selection provider
*/
native boolean pGetSelectionOwnership(Object source,
Transferable transferable,
long[] formats,
Map formatMap,
X11SelectionHolder holder);
boolean getSelectionOwnership(Transferable contents,
X11SelectionHolder holder) {
SortedMap formatMap =
DataTransferer.getInstance().getFormatsForTransferable
(contents, DataTransferer.adaptFlavorMap(flavorMap));
long[] formats =
DataTransferer.getInstance().keysToLongArray(formatMap);
SunToolkit.insertTargetMapping(source, AppContext.getAppContext());
/*
* Update 'contents' and 'holder' fields in the native code under
* AWTLock protection to prevent race with lostSelectionOwnership().
*/
SunToolkit.awtLock();
try {
boolean isOwnerSet = pGetSelectionOwnership(source, contents, formats, formatMap,
holder);
if (isOwnerSet) {
clipboard.checkChangeHere(contents);
}
return isOwnerSet;
} finally {
SunToolkit.awtUnlock();
}
}
// To be MT-safe this method should be called under awtLock.
boolean isOwner() {
return holder != null;
}
// NOTE: This method may be called by privileged threads.
// DO NOT INVOKE CLIENT CODE ON THIS THREAD!
private void lostSelectionOwnership() {
if (holder != null) {
holder.lostSelectionOwnership();
holder = null;
}
contents = null;
}
native void clearNativeContext();
/*
* Subclasses should override disposeImpl() instead of dispose(). Client
* code should always invoke dispose(), never disposeImpl().
*/
protected void disposeImpl() {
selections.removeElement(this);
}
public final void dispose() {
boolean call_disposeImpl = false;
if (!disposed) {
synchronized (this) {
if (!disposed) {
disposed = call_disposeImpl = true;
}
}
}
if (call_disposeImpl) {
disposeImpl();
}
}
/**
* Finds out all selections that have flavor listeners registered
* and returns their atoms.
* Upcall from native code.
*
* @return an array of selection atoms
*/
private static long[] getSelectionAtomsToCheckChange() {
Object[] sels = getSelectionsArray();
long[] idArray = new long[sels.length];
int count = 0;
for (int i = 0; i < sels.length; i++) {
X11Clipboard clipboard = ((X11Selection)sels[i]).clipboard;
if (clipboard.areFlavorListenersRegistered()) {
idArray[count++] = clipboard.getID();
}
}
long[] atomArray = new long[count];
System.arraycopy(idArray, 0, atomArray, 0, atomArray.length);
return atomArray;
}
/**
* Upcall from native code.
*/
private void checkChange(long[] formats) {
clipboard.checkChange(formats);
}
}