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</code> 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 * @returns 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 }