1 /*
2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.awt.X11;
27
28 import java.awt.datatransfer.Transferable;
29 import java.awt.datatransfer.DataFlavor;
30
31 import java.awt.dnd.DnDConstants;
32 import java.awt.dnd.InvalidDnDOperationException;
33
34 import java.util.Map;
35
36 /**
37 * An abstract class for drag protocols on X11 systems.
38 * Contains protocol-independent drag source code.
39 *
40 * @since 1.5
41 */
42 abstract class XDragSourceProtocol {
43 private final XDragSourceProtocolListener listener;
44
45 private boolean initialized = false;
46
47 private long targetWindow = 0;
48 private long targetProxyWindow = 0;
49 private int targetProtocolVersion = 0;
50 private long targetWindowMask = 0;
51
52 // Always use the XAWT root window as the drag source window.
53 static long getDragSourceWindow() {
54 return XWindow.getXAWTRootWindow().getWindow();
55 }
56
57 protected XDragSourceProtocol(XDragSourceProtocolListener listener) {
58 if (listener == null) {
59 throw new NullPointerException("Null XDragSourceProtocolListener");
60 }
61 this.listener = listener;
62 }
63
64 protected final XDragSourceProtocolListener getProtocolListener() {
65 return listener;
66 }
67
68 /**
69 * Returns the protocol name. The protocol name cannot be null.
70 */
71 public abstract String getProtocolName();
72
73 /**
74 * Initializes a drag operation with the specified supported drop actions,
75 * contents and data formats.
76 *
77 * @param actions a bitwise mask of {@code DnDConstants} that represent
78 * the supported drop actions.
79 * @param contents the contents for the drag operation.
80 * @param formats an array of Atoms that represent the supported data formats.
81 * @param formats an array of Atoms that represent the supported data formats.
82 * @throws InvalidDnDOperationException if a drag operation is already
83 * initialized.
84 * @throws IllegalArgumentException if some argument has invalid value.
85 * @throws XException if some X call failed.
86 */
87 public final void initializeDrag(int actions, Transferable contents,
88 Map<Long, DataFlavor> formatMap, long[] formats)
89 throws InvalidDnDOperationException,
90 IllegalArgumentException, XException {
91 XToolkit.awtLock();
92 try {
93 try {
94 if (initialized) {
95 throw new InvalidDnDOperationException("Already initialized");
96 }
97
98 initializeDragImpl(actions, contents, formatMap, formats);
99
100 initialized = true;
101 } finally {
102 if (!initialized) {
103 cleanup();
104 }
105 }
106 } finally {
107 XToolkit.awtUnlock();
108 }
109 }
110
111 /* The caller must hold AWT_LOCK. */
112 protected abstract void initializeDragImpl(int actions,
113 Transferable contents,
114 Map<Long, DataFlavor> formatMap,
115 long[] formats)
116 throws InvalidDnDOperationException, IllegalArgumentException, XException;
117
118 /**
119 * Terminates the current drag operation (if any) and resets the internal
120 * state of this object.
121 *
122 * @throws XException if some X call failed.
123 */
124 public void cleanup() {
125 initialized = false;
126 cleanupTargetInfo();
127 }
128
129 /**
130 * Clears the information on the current drop target.
131 *
132 * @throws XException if some X call failed.
133 */
134 public void cleanupTargetInfo() {
135 targetWindow = 0;
136 targetProxyWindow = 0;
137 targetProtocolVersion = 0;
138 }
139
140 /**
141 * Processes the specified client message event.
142 *
143 * @return true if the event was successfully processed.
144 */
145 public abstract boolean processClientMessage(XClientMessageEvent xclient)
146 throws XException;
147
148 /* The caller must hold AWT_LOCK. */
149 public final boolean attachTargetWindow(long window, long time) {
150 assert XToolkit.isAWTLockHeldByCurrentThread();
151
152 TargetWindowInfo info = getTargetWindowInfo(window);
153 if (info == null) {
154 return false;
155 } else {
156 targetWindow = window;
157 targetProxyWindow = info.getProxyWindow();
158 targetProtocolVersion = info.getProtocolVersion();
159 return true;
160 }
161 }
162
163 /* The caller must hold AWT_LOCK. */
164 public abstract TargetWindowInfo getTargetWindowInfo(long window);
165
166 /* The caller must hold AWT_LOCK. */
167 public abstract void sendEnterMessage(long[] formats, int sourceAction,
168 int sourceActions, long time);
169 /* The caller must hold AWT_LOCK. */
170 public abstract void sendMoveMessage(int xRoot, int yRoot,
171 int sourceAction, int sourceActions,
172 long time);
173 /* The caller must hold AWT_LOCK. */
174 public abstract void sendLeaveMessage(long time);
175
176 /* The caller must hold AWT_LOCK. */
177 protected abstract void sendDropMessage(int xRoot, int yRoot,
178 int sourceAction, int sourceActions,
179 long time);
180
181 public final void initiateDrop(int xRoot, int yRoot,
182 int sourceAction, int sourceActions,
183 long time) {
184 XWindowAttributes wattr = new XWindowAttributes();
185 try {
186 XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
187 int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
188 targetWindow, wattr.pData);
189
190 XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
191
192 if ((status == 0) ||
193 ((XErrorHandlerUtil.saved_error != null) &&
194 (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success))) {
195 throw new XException("XGetWindowAttributes failed");
196 }
197
198 targetWindowMask = wattr.get_your_event_mask();
199 } finally {
200 wattr.dispose();
201 }
202
203 XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
204 XlibWrapper.XSelectInput(XToolkit.getDisplay(), targetWindow,
205 targetWindowMask |
206 XConstants.StructureNotifyMask);
207
208 XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
209
210 if ((XErrorHandlerUtil.saved_error != null) &&
211 (XErrorHandlerUtil.saved_error.get_error_code() != XConstants.Success)) {
212 throw new XException("XSelectInput failed");
213 }
214
215 sendDropMessage(xRoot, yRoot, sourceAction, sourceActions, time);
216 }
217
218 protected final void finalizeDrop() {
219 XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance());
220 XlibWrapper.XSelectInput(XToolkit.getDisplay(), targetWindow,
221 targetWindowMask);
222 XErrorHandlerUtil.RESTORE_XERROR_HANDLER();
223 }
224
225 public abstract boolean processProxyModeEvent(XClientMessageEvent xclient,
226 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 public TargetWindowInfo(long proxy, int version) {
248 proxyWindow = proxy;
249 protocolVersion = version;
250 }
251 public long getProxyWindow() {
252 return proxyWindow;
253 }
254 public int getProtocolVersion() {
255 return protocolVersion;
256 }
257 }
258 }
--- EOF ---