001: /*
002: * Copyright 2003-2007 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.X11;
027:
028: import java.awt.datatransfer.Transferable;
029:
030: import java.util.SortedMap;
031: import java.util.Set;
032: import java.util.Iterator;
033: import java.util.HashSet;
034:
035: import java.io.IOException;
036:
037: import java.security.AccessController;
038:
039: import sun.awt.datatransfer.DataTransferer;
040: import sun.awt.datatransfer.SunClipboard;
041: import sun.awt.datatransfer.ClipboardTransferable;
042:
043: import sun.security.action.GetIntegerAction;
044:
045: /**
046: * A class which interfaces with the X11 selection service in order to support
047: * data transfer via Clipboard operations.
048: */
049: public class XClipboard extends SunClipboard implements Runnable {
050: private final XSelection selection;
051:
052: private static final Object classLock = new Object();
053:
054: private static final int defaultPollInterval = 200;
055:
056: private static int pollInterval;
057:
058: private static Set listenedClipboards;
059:
060: /**
061: * Creates a system clipboard object.
062: */
063: public XClipboard(String name, String selectionName) {
064: super (name);
065: selection = new XSelection(XAtom.get(selectionName), this );
066: }
067:
068: /**
069: * The action to be run when we lose ownership
070: * NOTE: This method may be called by privileged threads.
071: * DO NOT INVOKE CLIENT CODE ON THIS THREAD!
072: */
073: public void run() {
074: lostOwnershipImpl();
075: }
076:
077: protected synchronized void setContentsNative(Transferable contents) {
078: SortedMap formatMap = DataTransferer.getInstance()
079: .getFormatsForTransferable(contents,
080: DataTransferer.adaptFlavorMap(flavorMap));
081: long[] formats = DataTransferer.getInstance().keysToLongArray(
082: formatMap);
083:
084: if (!selection.setOwner(contents, formatMap, formats, XToolkit
085: .getCurrentServerTime())) {
086: this .owner = null;
087: this .contents = null;
088: }
089: }
090:
091: public long getID() {
092: return selection.getSelectionAtom().getAtom();
093: }
094:
095: public synchronized Transferable getContents(Object requestor) {
096: if (contents != null) {
097: return contents;
098: }
099: return new ClipboardTransferable(this );
100: }
101:
102: /* Caller is synchronized on this. */
103: protected void clearNativeContext() {
104: selection.reset();
105: }
106:
107: protected long[] getClipboardFormats() {
108: return selection.getTargets(XToolkit.getCurrentServerTime());
109: }
110:
111: protected byte[] getClipboardData(long format) throws IOException {
112: return selection.getData(format, XToolkit
113: .getCurrentServerTime());
114: }
115:
116: // Called on the toolkit thread under awtLock.
117: public void checkChange(long[] formats) {
118: if (!selection.isOwner()) {
119: super .checkChange(formats);
120: }
121: }
122:
123: void checkChangeHere(Transferable contents) {
124: if (areFlavorListenersRegistered()) {
125: super .checkChange(DataTransferer.getInstance()
126: .getFormatsForTransferableAsArray(contents,
127: flavorMap));
128: }
129: }
130:
131: protected void registerClipboardViewerChecked() {
132: if (pollInterval <= 0) {
133: pollInterval = ((Integer) AccessController
134: .doPrivileged(new GetIntegerAction(
135: "awt.datatransfer.clipboard.poll.interval",
136: defaultPollInterval))).intValue();
137: if (pollInterval <= 0) {
138: pollInterval = defaultPollInterval;
139: }
140: }
141: selection.initializeSelectionForTrackingChanges();
142: boolean mustSchedule = false;
143: synchronized (XClipboard.classLock) {
144: if (listenedClipboards == null) {
145: listenedClipboards = new HashSet(2);
146: }
147: mustSchedule = listenedClipboards.isEmpty();
148: listenedClipboards.add(this );
149: }
150: if (mustSchedule) {
151: XToolkit.schedule(new CheckChangeTimerTask(), pollInterval);
152: }
153: }
154:
155: private static class CheckChangeTimerTask implements Runnable {
156: public void run() {
157: for (Iterator iter = listenedClipboards.iterator(); iter
158: .hasNext();) {
159: XClipboard clpbrd = (XClipboard) iter.next();
160: clpbrd.selection.getTargetsDelayed();
161: }
162: synchronized (XClipboard.classLock) {
163: if (listenedClipboards != null
164: && !listenedClipboards.isEmpty()) {
165: XToolkit.schedule(this , pollInterval);
166: }
167: }
168: }
169: }
170:
171: protected void unregisterClipboardViewerChecked() {
172: selection.deinitializeSelectionForTrackingChanges();
173: synchronized (XClipboard.classLock) {
174: listenedClipboards.remove(this);
175: }
176: }
177:
178: }
|