001: /*
002: * Copyright 1996-2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.awt.motif;
027:
028: import java.awt.Toolkit;
029:
030: import java.awt.datatransfer.Transferable;
031: import java.awt.datatransfer.FlavorMap;
032: import java.awt.datatransfer.DataFlavor;
033: import java.awt.datatransfer.SystemFlavorMap;
034:
035: import java.util.Map;
036: import java.util.SortedMap;
037: import java.util.Vector;
038:
039: import sun.awt.AppContext;
040: import sun.awt.SunToolkit;
041:
042: import sun.awt.datatransfer.DataTransferer;
043:
044: /*
045: * Implements a general interface to the X11 selection mechanism.
046: *
047: * @author Amy Fowler
048: * @author Roger Brinkley
049: * @author Danila Sinopalnikov
050: * @author Alexander Gerasimov
051: * @version 1.41, 05/05/07
052: *
053: * @since JDK1.1
054: */
055: public class X11Selection {
056:
057: static FlavorMap flavorMap = SystemFlavorMap.getDefaultFlavorMap();
058:
059: static Vector selections;
060:
061: long atom;
062:
063: private X11Clipboard clipboard;
064: private X11SelectionHolder holder;
065: private Transferable contents;
066:
067: private boolean disposed = false;
068: private byte[] data = null;
069: private boolean dataAvailable = false;
070: private static final Object source = new Object();
071:
072: static {
073: // 4154170: Need to ensure the the toolkit is initialized prior
074: // to executing this initializer
075: Toolkit toolkit = Toolkit.getDefaultToolkit();
076:
077: selections = new Vector();
078:
079: initIDs();
080: init();
081:
082: }
083:
084: private static native void initIDs();
085:
086: static native void init();
087:
088: public X11Selection(String name, X11Clipboard clipboard) {
089: atom = ((MDataTransferer) DataTransferer.getInstance())
090: .getAtomForTarget(name);
091: selections.addElement(this );
092: this .clipboard = clipboard;
093: }
094:
095: private static Object[] getSelectionsArray() {
096: return selections.toArray();
097: }
098:
099: /*
100: * methods for acting as selection provider
101: */
102: native boolean pGetSelectionOwnership(Object source,
103: Transferable transferable, long[] formats, Map formatMap,
104: X11SelectionHolder holder);
105:
106: boolean getSelectionOwnership(Transferable contents,
107: X11SelectionHolder holder) {
108: SortedMap formatMap = DataTransferer.getInstance()
109: .getFormatsForTransferable(contents,
110: DataTransferer.adaptFlavorMap(flavorMap));
111: long[] formats = DataTransferer.getInstance().keysToLongArray(
112: formatMap);
113: SunToolkit.insertTargetMapping(source, AppContext
114: .getAppContext());
115:
116: /*
117: * Update 'contents' and 'holder' fields in the native code under
118: * AWTLock protection to prevent race with lostSelectionOwnership().
119: */
120: SunToolkit.awtLock();
121: try {
122: boolean isOwnerSet = pGetSelectionOwnership(source,
123: contents, formats, formatMap, holder);
124: if (isOwnerSet) {
125: clipboard.checkChangeHere(contents);
126: }
127: return isOwnerSet;
128: } finally {
129: SunToolkit.awtUnlock();
130: }
131: }
132:
133: // To be MT-safe this method should be called under awtLock.
134: boolean isOwner() {
135: return holder != null;
136: }
137:
138: // NOTE: This method may be called by privileged threads.
139: // DO NOT INVOKE CLIENT CODE ON THIS THREAD!
140: private void lostSelectionOwnership() {
141: if (holder != null) {
142: holder.lostSelectionOwnership();
143: holder = null;
144: }
145: contents = null;
146: }
147:
148: native void clearNativeContext();
149:
150: /*
151: * Subclasses should override disposeImpl() instead of dispose(). Client
152: * code should always invoke dispose(), never disposeImpl().
153: */
154: protected void disposeImpl() {
155: selections.removeElement(this );
156: }
157:
158: public final void dispose() {
159: boolean call_disposeImpl = false;
160:
161: if (!disposed) {
162: synchronized (this ) {
163: if (!disposed) {
164: disposed = call_disposeImpl = true;
165: }
166: }
167: }
168:
169: if (call_disposeImpl) {
170: disposeImpl();
171: }
172: }
173:
174: /**
175: * Finds out all selections that have flavor listeners registered
176: * and returns their atoms.
177: * Upcall from native code.
178: *
179: * @return an array of selection atoms
180: */
181: private static long[] getSelectionAtomsToCheckChange() {
182: Object[] sels = getSelectionsArray();
183: long[] idArray = new long[sels.length];
184: int count = 0;
185:
186: for (int i = 0; i < sels.length; i++) {
187: X11Clipboard clipboard = ((X11Selection) sels[i]).clipboard;
188: if (clipboard.areFlavorListenersRegistered()) {
189: idArray[count++] = clipboard.getID();
190: }
191: }
192:
193: long[] atomArray = new long[count];
194: System.arraycopy(idArray, 0, atomArray, 0, atomArray.length);
195:
196: return atomArray;
197: }
198:
199: /**
200: * Upcall from native code.
201: */
202: private void checkChange(long[] formats) {
203: clipboard.checkChange(formats);
204: }
205: }
|