1 /* 2 * Copyright (c) 1996, 2020, 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.windows; 27 28 import java.awt.datatransfer.DataFlavor; 29 import java.awt.datatransfer.Transferable; 30 import java.awt.datatransfer.UnsupportedFlavorException; 31 import java.io.IOException; 32 import java.util.Map; 33 34 import sun.awt.datatransfer.DataTransferer; 35 import sun.awt.datatransfer.SunClipboard; 36 import sun.util.logging.PlatformLogger; 37 38 /** 39 * A class which interfaces with the Windows clipboard in order to support 40 * data transfer via Clipboard operations. Most of the work is provided by 41 * sun.awt.datatransfer.DataTransferer. 42 * 43 * @author Tom Ball 44 * @author David Mendenhall 45 * @author Danila Sinopalnikov 46 * @author Alexander Gerasimov 47 * 48 * @since 1.1 49 */ 50 final class WClipboard extends SunClipboard { 51 52 private boolean isClipboardViewerRegistered; 53 54 private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.windows.WClipboard"); 55 56 WClipboard() { 57 super("System"); 58 } 59 60 @Override 61 public long getID() { 62 return 0; 63 } 64 65 @Override 66 protected void setContentsNative(Transferable contents) { 67 // Don't use delayed Clipboard rendering for the Transferable's data. 68 // If we did that, we would call Transferable.getTransferData on 69 // the Toolkit thread, which is a security hole. 70 // 71 // Get all of the target formats into which the Transferable can be 72 // translated. Then, for each format, translate the data and post 73 // it to the Clipboard. 74 Map <Long, DataFlavor> formatMap = WDataTransferer.getInstance(). 75 getFormatsForTransferable(contents, getDefaultFlavorTable()); 76 77 openClipboard(this); 78 79 try { 80 for (Long format : formatMap.keySet()) { 81 DataFlavor flavor = formatMap.get(format); 82 try { 83 byte[] bytes = WDataTransferer.getInstance(). 84 translateTransferable(contents, flavor, format); 85 publishClipboardData(format, bytes); 86 } catch (IOException e) { 87 if (log.isLoggable(PlatformLogger.Level.WARNING)) { 88 log.warning("Registered service providers failed to encode ", e); 89 } 90 } 91 } 92 } finally { 93 closeClipboard(); 94 } 95 } 96 97 private void lostSelectionOwnershipImpl() { 98 lostOwnershipImpl(); 99 } 100 101 /** 102 * Currently delayed data rendering is not used for the Windows clipboard, 103 * so there is no native context to clear. 104 */ 105 @Override 106 protected void clearNativeContext() {} 107 108 /** 109 * Call the Win32 OpenClipboard function. If newOwner is non-null, 110 * we also call EmptyClipboard and take ownership. 111 * 112 * @throws IllegalStateException if the clipboard has not been opened 113 */ 114 @Override 115 public native void openClipboard(SunClipboard newOwner) throws IllegalStateException; 116 /** 117 * Call the Win32 CloseClipboard function if we have clipboard ownership, 118 * does nothing if we have not ownership. 119 */ 120 @Override 121 public native void closeClipboard(); 122 /** 123 * Call the Win32 SetClipboardData function. 124 */ 125 private native void publishClipboardData(long format, byte[] bytes); 126 127 private static native void init(); 128 static { 129 init(); 130 } 131 132 @Override 133 protected native long[] getClipboardFormats(); 134 @Override 135 protected native byte[] getClipboardData(long format) throws IOException; 136 137 @Override 138 protected void registerClipboardViewerChecked() { 139 if (!isClipboardViewerRegistered) { 140 registerClipboardViewer(); 141 isClipboardViewerRegistered = true; 142 } 143 } 144 145 private native void registerClipboardViewer(); 146 147 /** 148 * The clipboard viewer (it's the toolkit window) is not unregistered 149 * until the toolkit window disposing since MSDN suggests removing 150 * the window from the clipboard viewer chain just before it is destroyed. 151 */ 152 @Override 153 protected void unregisterClipboardViewerChecked() {} 154 155 /** 156 * Upcall from native code. 157 */ 158 private void handleContentsChanged() { 159 if (!areFlavorListenersRegistered()) { 160 return; 161 } 162 163 long[] formats = null; 164 try { 165 openClipboard(null); 166 formats = getClipboardFormats(); 167 } catch (IllegalStateException exc) { 168 // do nothing to handle the exception, call checkChange(null) 169 } finally { 170 closeClipboard(); 171 } 172 checkChange(formats); 173 } 174 175 /** 176 * The clipboard must be opened. 177 * 178 * @since 1.5 179 */ 180 @Override 181 protected Transferable createLocaleTransferable(long[] formats) throws IOException { 182 boolean found = false; 183 for (int i = 0; i < formats.length; i++) { 184 if (formats[i] == WDataTransferer.CF_LOCALE) { 185 found = true; 186 break; 187 } 188 } 189 if (!found) { 190 return null; 191 } 192 193 byte[] localeData = null; 194 try { 195 localeData = getClipboardData(WDataTransferer.CF_LOCALE); 196 } catch (IOException ioexc) { 197 return null; 198 } 199 200 final byte[] localeDataFinal = localeData; 201 202 return new Transferable() { 203 @Override 204 public DataFlavor[] getTransferDataFlavors() { 205 return new DataFlavor[] { DataTransferer.javaTextEncodingFlavor }; 206 } 207 @Override 208 public boolean isDataFlavorSupported(DataFlavor flavor) { 209 return flavor.equals(DataTransferer.javaTextEncodingFlavor); 210 } 211 @Override 212 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { 213 if (isDataFlavorSupported(flavor)) { 214 return localeDataFinal; 215 } 216 throw new UnsupportedFlavorException(flavor); 217 } 218 }; 219 } 220 }