001: /*
002: * Copyright 2003-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.X11;
027:
028: import java.awt.datatransfer.Transferable;
029:
030: import java.awt.dnd.DnDConstants;
031: import java.awt.dnd.InvalidDnDOperationException;
032:
033: import java.util.Map;
034:
035: /**
036: * An abstract class for drag protocols on X11 systems.
037: * Contains protocol-independent drag source code.
038: *
039: * @since 1.5
040: */
041: abstract class XDragSourceProtocol {
042: private final XDragSourceProtocolListener listener;
043:
044: private boolean initialized = false;
045:
046: private long targetWindow = 0;
047: private long targetProxyWindow = 0;
048: private int targetProtocolVersion = 0;
049: private long targetWindowMask = 0;
050:
051: // Always use the XAWT root window as the drag source window.
052: static long getDragSourceWindow() {
053: return XWindow.getXAWTRootWindow().getWindow();
054: }
055:
056: protected XDragSourceProtocol(XDragSourceProtocolListener listener) {
057: if (listener == null) {
058: throw new NullPointerException(
059: "Null XDragSourceProtocolListener");
060: }
061: this .listener = listener;
062: }
063:
064: protected final XDragSourceProtocolListener getProtocolListener() {
065: return listener;
066: }
067:
068: /**
069: * Returns the protocol name. The protocol name cannot be null.
070: */
071: public abstract String getProtocolName();
072:
073: /**
074: * Initalizes a drag operation with the specified supported drop actions,
075: * contents and data formats.
076: *
077: * @param actions a bitwise mask of <code>DnDConstants</code> that represent
078: * the supported drop actions.
079: * @param contents the contents for the drag operation.
080: * @param formats an array of Atoms that represent the supported data formats.
081: * @param formats an array of Atoms that represent the supported data formats.
082: * @throws InvalidDnDOperationException if a drag operation is already
083: * initialized.
084: * @throws IllegalArgumentException if some argument has invalid value.
085: * @throws XException if some X call failed.
086: */
087: public final void initializeDrag(int actions,
088: Transferable contents, Map formatMap, long[] formats)
089: throws InvalidDnDOperationException,
090: IllegalArgumentException, XException {
091: XToolkit.awtLock();
092: try {
093: try {
094: if (initialized) {
095: throw new InvalidDnDOperationException(
096: "Already initialized");
097: }
098:
099: initializeDragImpl(actions, contents, formatMap,
100: formats);
101:
102: initialized = true;
103: } finally {
104: if (!initialized) {
105: cleanup();
106: }
107: }
108: } finally {
109: XToolkit.awtUnlock();
110: }
111: }
112:
113: /* The caller must hold AWT_LOCK. */
114: protected abstract void initializeDragImpl(int actions,
115: Transferable contents, Map formatMap, long[] formats)
116: throws InvalidDnDOperationException,
117: IllegalArgumentException, XException;
118:
119: /**
120: * Terminates the current drag operation (if any) and resets the internal
121: * state of this object.
122: *
123: * @throws XException if some X call failed.
124: */
125: public void cleanup() {
126: initialized = false;
127: cleanupTargetInfo();
128: }
129:
130: /**
131: * Clears the information on the current drop target.
132: *
133: * @throws XException if some X call failed.
134: */
135: public void cleanupTargetInfo() {
136: targetWindow = 0;
137: targetProxyWindow = 0;
138: targetProtocolVersion = 0;
139: }
140:
141: /**
142: * Processes the specified client message event.
143: *
144: * @returns true if the event was successfully processed.
145: */
146: public abstract boolean processClientMessage(
147: XClientMessageEvent xclient) throws XException;
148:
149: /* The caller must hold AWT_LOCK. */
150: public final boolean attachTargetWindow(long window, long time) {
151: assert XToolkit.isAWTLockHeldByCurrentThread();
152:
153: TargetWindowInfo info = getTargetWindowInfo(window);
154: if (info == null) {
155: return false;
156: } else {
157: targetWindow = window;
158: targetProxyWindow = info.getProxyWindow();
159: targetProtocolVersion = info.getProtocolVersion();
160: return true;
161: }
162: }
163:
164: /* The caller must hold AWT_LOCK. */
165: public abstract TargetWindowInfo getTargetWindowInfo(long window);
166:
167: /* The caller must hold AWT_LOCK. */
168: public abstract void sendEnterMessage(long[] formats,
169: int sourceAction, int sourceActions, long time);
170:
171: /* The caller must hold AWT_LOCK. */
172: public abstract void sendMoveMessage(int xRoot, int yRoot,
173: int sourceAction, int sourceActions, long time);
174:
175: /* The caller must hold AWT_LOCK. */
176: public abstract void sendLeaveMessage(long time);
177:
178: /* The caller must hold AWT_LOCK. */
179: protected abstract void sendDropMessage(int xRoot, int yRoot,
180: int sourceAction, int sourceActions, long time);
181:
182: public final void initiateDrop(int xRoot, int yRoot,
183: int sourceAction, int sourceActions, long time) {
184: XWindowAttributes wattr = new XWindowAttributes();
185: try {
186: XToolkit
187: .WITH_XERROR_HANDLER(XToolkit.IgnoreBadWindowHandler);
188: int status = XlibWrapper.XGetWindowAttributes(XToolkit
189: .getDisplay(), targetWindow, wattr.pData);
190:
191: XToolkit.RESTORE_XERROR_HANDLER();
192:
193: if (status == 0
194: || (XToolkit.saved_error != null && XToolkit.saved_error
195: .get_error_code() != XlibWrapper.Success)) {
196: throw new XException("XGetWindowAttributes failed");
197: }
198:
199: targetWindowMask = wattr.get_your_event_mask();
200: } finally {
201: wattr.dispose();
202: }
203:
204: XToolkit.WITH_XERROR_HANDLER(XToolkit.IgnoreBadWindowHandler);
205: XlibWrapper.XSelectInput(XToolkit.getDisplay(), targetWindow,
206: targetWindowMask | XlibWrapper.StructureNotifyMask);
207:
208: XToolkit.RESTORE_XERROR_HANDLER();
209:
210: if (XToolkit.saved_error != null
211: && XToolkit.saved_error.get_error_code() != XlibWrapper.Success) {
212: throw new XException("XSelectInput failed");
213: }
214:
215: sendDropMessage(xRoot, yRoot, sourceAction, sourceActions, time);
216: }
217:
218: protected final void finalizeDrop() {
219: XToolkit.WITH_XERROR_HANDLER(XToolkit.IgnoreBadWindowHandler);
220: XlibWrapper.XSelectInput(XToolkit.getDisplay(), targetWindow,
221: targetWindowMask);
222: XToolkit.RESTORE_XERROR_HANDLER();
223: }
224:
225: public abstract boolean processProxyModeEvent(
226: XClientMessageEvent xclient, long sourceWindow);
227:
228: protected final long getTargetWindow() {
229: return targetWindow;
230: }
231:
232: protected final long getTargetProxyWindow() {
233: if (targetProxyWindow != 0) {
234: return targetProxyWindow;
235: } else {
236: return targetWindow;
237: }
238: }
239:
240: protected final int getTargetProtocolVersion() {
241: return targetProtocolVersion;
242: }
243:
244: public static class TargetWindowInfo {
245: private final long proxyWindow;
246: private final int protocolVersion;
247:
248: public TargetWindowInfo(long proxy, int version) {
249: proxyWindow = proxy;
250: protocolVersion = version;
251: }
252:
253: public long getProxyWindow() {
254: return proxyWindow;
255: }
256:
257: public int getProtocolVersion() {
258: return protocolVersion;
259: }
260: }
261: }
|