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.util.*; 29 import jdk.internal.misc.Unsafe; 30 31 public class WindowPropertyGetter { 32 private static Unsafe unsafe = XlibWrapper.unsafe; 33 private final long actual_type = unsafe.allocateMemory(8); 34 private final long actual_format = unsafe.allocateMemory(4); 35 private final long nitems_ptr = unsafe.allocateMemory(8); 36 private final long bytes_after = unsafe.allocateMemory(8); 37 private final long data = unsafe.allocateMemory(8); 38 private final long window; 39 private final XAtom property; 40 private final long offset; 41 private final long length; 42 private final boolean auto_delete; 43 private final long type; 44 private boolean executed = false; 45 public WindowPropertyGetter(long window, XAtom property, long offset, 46 long length, boolean auto_delete, long type) 47 { 48 if (property.getAtom() == 0) { 49 throw new IllegalArgumentException("Property ATOM should be initialized first:" + property); 50 } 51 // Zero is AnyPropertyType. 52 // if (type == 0) { 53 // throw new IllegalArgumentException("Type ATOM shouldn't be zero"); 54 // } 55 if (window == 0) { 56 throw new IllegalArgumentException("Window must not be zero"); 57 } 58 this.window = window; 59 this.property = property; 60 this.offset = offset; 61 this.length = length; 62 this.auto_delete = auto_delete; 63 this.type = type; 64 65 Native.putLong(data, 0); 66 sun.java2d.Disposer.addRecord(this, disposer = new UnsafeXDisposerRecord("WindowPropertyGetter", new long[] {actual_type, 67 actual_format, nitems_ptr, bytes_after}, new long[] {data})); 68 } 69 UnsafeXDisposerRecord disposer; 70 public WindowPropertyGetter(long window, XAtom property, long offset, 71 long length, boolean auto_delete, XAtom type) 72 { 73 this(window, property, offset, length, auto_delete, type.getAtom()); 74 } 75 public int execute() { 76 return execute(null); 77 } 78 public int execute(XErrorHandler errorHandler) { 79 80 XToolkit.awtLock(); 81 try { 82 if (isDisposed()) { 83 throw new IllegalStateException("Disposed"); 84 } 85 if (executed) { 86 throw new IllegalStateException("Already executed"); 87 } 88 executed = true; 89 90 if (isCachingSupported() && isCached()) { 91 readFromCache(); 92 return XConstants.Success; 93 } 94 95 // Fix for performance problem - IgnodeBadWindowHandler is 96 // used too much without reason, just ignore it 97 if (errorHandler instanceof XErrorHandler.IgnoreBadWindowHandler) { 98 errorHandler = null; 99 } 100 101 if (errorHandler != null) { 102 XErrorHandlerUtil.WITH_XERROR_HANDLER(errorHandler); 103 } 104 Native.putLong(data, 0); 105 int status = XlibWrapper.XGetWindowProperty(XToolkit.getDisplay(), window, property.getAtom(), 106 offset, length, (auto_delete?1:0), type, 107 actual_type, actual_format, nitems_ptr, 108 bytes_after, data); 109 if (isCachingSupported() && status == XConstants.Success && getData() != 0 && isCacheableProperty(property)) { 110 // Property has some data, we cache them 111 cacheProperty(); 112 } 113 114 if (errorHandler != null) { 115 XErrorHandlerUtil.RESTORE_XERROR_HANDLER(); 116 } 117 return status; 118 } finally { 119 XToolkit.awtUnlock(); 120 } 121 } 122 123 public boolean isExecuted() { 124 return executed; 125 } 126 127 public boolean isDisposed() { 128 return disposer.disposed; 129 } 130 131 public int getActualFormat() { 132 if (isDisposed()) { 133 throw new IllegalStateException("Disposed"); 134 } 135 if (!executed) { 136 throw new IllegalStateException("Not executed"); 137 } 138 return unsafe.getInt(actual_format); 139 } 140 public long getActualType() { 141 if (isDisposed()) { 142 throw new IllegalStateException("Disposed"); 143 } 144 if (!executed) { 145 throw new IllegalStateException("Not executed"); 146 } 147 return XAtom.getAtom(actual_type); 148 } 149 public int getNumberOfItems() { 150 if (isDisposed()) { 151 throw new IllegalStateException("Disposed"); 152 } 153 if (!executed) { 154 throw new IllegalStateException("Not executed"); 155 } 156 return (int)Native.getLong(nitems_ptr); 157 } 158 public long getData() { 159 if (isDisposed()) { 160 throw new IllegalStateException("Disposed"); 161 } 162 return Native.getLong(data); 163 } 164 public long getBytesAfter() { 165 if (isDisposed()) { 166 throw new IllegalStateException("Disposed"); 167 } 168 if (!executed) { 169 throw new IllegalStateException("Not executed"); 170 } 171 return Native.getLong(bytes_after); 172 } 173 public void dispose() { 174 XToolkit.awtLock(); 175 try { 176 if (isDisposed()) { 177 return; 178 } 179 disposer.dispose(); 180 } finally { 181 XToolkit.awtUnlock(); 182 } 183 } 184 185 static boolean isCachingSupported() { 186 return XPropertyCache.isCachingSupported(); 187 } 188 189 static Set<XAtom> cacheableProperties = new HashSet<XAtom>(Arrays.asList(new XAtom[] { 190 XAtom.get("_NET_WM_STATE"), XAtom.get("WM_STATE"), XAtom.get("_MOTIF_WM_HINTS")})); 191 192 static boolean isCacheableProperty(XAtom property) { 193 return cacheableProperties.contains(property); 194 } 195 196 boolean isCached() { 197 return XPropertyCache.isCached(window, property); 198 } 199 200 int getDataLength() { 201 return getActualFormat() / 8 * getNumberOfItems(); 202 } 203 204 void readFromCache() { 205 property.putAtom(actual_type); 206 XPropertyCache.PropertyCacheEntry entry = XPropertyCache.getCacheEntry(window, property); 207 Native.putInt(actual_format, entry.getFormat()); 208 Native.putLong(nitems_ptr, entry.getNumberOfItems()); 209 Native.putLong(bytes_after, entry.getBytesAfter()); 210 Native.putLong(data, unsafe.allocateMemory(getDataLength())); 211 XlibWrapper.memcpy(getData(), entry.getData(), getDataLength()); 212 } 213 214 void cacheProperty() { 215 XPropertyCache.storeCache( 216 new XPropertyCache.PropertyCacheEntry(getActualFormat(), 217 getNumberOfItems(), 218 getBytesAfter(), 219 getData(), 220 getDataLength()), 221 window, 222 property); 223 } 224 225 }