1 /* 2 * Copyright 2006-2008 Sun Microsystems, Inc. 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. Sun designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 22 * CA 95054 USA or visit www.sun.com if you need additional information or 23 * have any questions. 24 */ 25 26 package sun.awt.X11; 27 28 import java.awt.Dimension; 29 import java.awt.GraphicsEnvironment; 30 import java.awt.Point; 31 import java.awt.Rectangle; 32 33 import java.util.Collections; 34 import java.util.HashSet; 35 import java.util.Set; 36 37 import sun.awt.X11GraphicsConfig; 38 import sun.awt.X11GraphicsDevice; 39 import sun.awt.X11GraphicsEnvironment; 40 41 /* 42 * This class is a collection of utility methods that operate 43 * with native windows. 44 */ 45 public class XlibUtil 46 { 47 /** 48 * The constructor is made private to eliminate any 49 * instances of this class 50 */ 51 private XlibUtil() 52 { 53 } 54 55 /** 56 * Xinerama-aware version of XlibWrapper.RootWindow method. 57 */ 58 public static long getRootWindow(int screenNumber) 59 { 60 XToolkit.awtLock(); 61 try 62 { 63 X11GraphicsEnvironment x11ge = (X11GraphicsEnvironment) 64 GraphicsEnvironment.getLocalGraphicsEnvironment(); 65 if (x11ge.runningXinerama()) 66 { 67 // all the Xinerama windows share the same root window 68 return XlibWrapper.RootWindow(XToolkit.getDisplay(), 0); 69 } 70 else 71 { 72 return XlibWrapper.RootWindow(XToolkit.getDisplay(), screenNumber); 73 } 74 } 75 finally 76 { 77 XToolkit.awtUnlock(); 78 } 79 } 80 81 /** 82 * Checks if the given window is a root window for the given screen 83 */ 84 static boolean isRoot(long rootCandidate, long screenNumber) 85 { 86 long root; 87 88 XToolkit.awtLock(); 89 try 90 { 91 root = XlibWrapper.RootWindow(XToolkit.getDisplay(), 92 screenNumber); 93 } 94 finally 95 { 96 XToolkit.awtUnlock(); 97 } 98 99 return root == rootCandidate; 100 } 101 102 /** 103 * Returns the bounds of the given window relative to its parent. 104 */ 105 public static Rectangle getWindowGeometry(long window) { 106 XToolkit.awtLock(); 107 try { 108 return getWindowGeometry(window, XlibWrapper.larg1); 109 } finally { 110 XToolkit.awtUnlock(); 111 } 112 } 113 114 /** 115 * Returns the bounds of the given window relative to its parent. 116 * The unsafe memory pointed to by the rootWindowBuffer will 117 * contain the root window of the given window. 118 * WARNING: DO NOT USE XlibWrapper.larg[2..7] as the rootWindowBuffer! 119 * Only larg1 or larg8 can be used, or some other allocated memory block. 120 * 121 * @throws IllegalArgumentException if the rootWindowBuffer refers to 122 * unsupported values. 123 */ 124 public static Rectangle getWindowGeometry(long window, long rootWindowBuffer) 125 { 126 if (rootWindowBuffer == XlibWrapper.larg2 || 127 rootWindowBuffer == XlibWrapper.larg3 || 128 rootWindowBuffer == XlibWrapper.larg4 || 129 rootWindowBuffer == XlibWrapper.larg5 || 130 rootWindowBuffer == XlibWrapper.larg6 || 131 rootWindowBuffer == XlibWrapper.larg7) 132 { 133 throw new IllegalArgumentException( 134 "The rootWindowBuffer should not refer to XlibWrapper.larg[2..7]"); 135 } 136 XToolkit.awtLock(); 137 try 138 { 139 int res = XlibWrapper.XGetGeometry(XToolkit.getDisplay(), 140 window, 141 rootWindowBuffer, // root_return 142 XlibWrapper.larg2, // x_return 143 XlibWrapper.larg3, // y_return 144 XlibWrapper.larg4, // width_return 145 XlibWrapper.larg5, // height_return 146 XlibWrapper.larg6, // border_width_return 147 XlibWrapper.larg7); // depth_return 148 if (res == 0) 149 { 150 return null; 151 } 152 153 int x = Native.getInt(XlibWrapper.larg2); 154 int y = Native.getInt(XlibWrapper.larg3); 155 long width = Native.getUInt(XlibWrapper.larg4); 156 long height = Native.getUInt(XlibWrapper.larg5); 157 158 return new Rectangle(x, y, (int)width, (int)height); 159 } 160 finally 161 { 162 XToolkit.awtUnlock(); 163 } 164 } 165 166 /** 167 * Translates the given point from one window to another. Returns 168 * null if the translation is failed 169 */ 170 static Point translateCoordinates(long src, long dst, Point p) 171 { 172 Point translated = null; 173 174 XToolkit.awtLock(); 175 try 176 { 177 XTranslateCoordinates xtc = 178 new XTranslateCoordinates(src, dst, p.x, p.y); 179 try 180 { 181 int status = xtc.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 182 if ((status != 0) && 183 ((XToolkit.saved_error == null) || 184 (XToolkit.saved_error.get_error_code() == XConstants.Success))) 185 { 186 translated = new Point(xtc.get_dest_x(), xtc.get_dest_y()); 187 } 188 } 189 finally 190 { 191 xtc.dispose(); 192 } 193 } 194 finally 195 { 196 XToolkit.awtUnlock(); 197 } 198 199 return translated; 200 } 201 202 /** 203 * Translates the given rectangle from one window to another. 204 * Returns null if the translation is failed 205 */ 206 static Rectangle translateCoordinates(long src, long dst, Rectangle r) 207 { 208 Point translatedLoc = translateCoordinates(src, dst, r.getLocation()); 209 if (translatedLoc == null) 210 { 211 return null; 212 } 213 else 214 { 215 return new Rectangle(translatedLoc, r.getSize()); 216 } 217 } 218 219 /** 220 * Returns the parent for the given window 221 */ 222 static long getParentWindow(long window) 223 { 224 XToolkit.awtLock(); 225 try 226 { 227 XBaseWindow bw = XToolkit.windowToXWindow(window); 228 if (bw != null) 229 { 230 XBaseWindow pbw = bw.getParentWindow(); 231 if (pbw != null) 232 { 233 return pbw.getWindow(); 234 } 235 } 236 237 XQueryTree qt = new XQueryTree(window); 238 try 239 { 240 if (qt.execute() == 0) 241 { 242 return XConstants.None; 243 } 244 else 245 { 246 return qt.get_parent(); 247 } 248 } 249 finally 250 { 251 qt.dispose(); 252 } 253 } 254 finally 255 { 256 XToolkit.awtUnlock(); 257 } 258 } 259 260 /** 261 * Returns all the children for the given window 262 */ 263 static Set<Long> getChildWindows(long window) 264 { 265 XToolkit.awtLock(); 266 try 267 { 268 XBaseWindow bw = XToolkit.windowToXWindow(window); 269 if (bw != null) 270 { 271 return bw.getChildren(); 272 } 273 274 XQueryTree xqt = new XQueryTree(window); 275 try 276 { 277 int status = xqt.execute(); 278 if (status == 0) 279 { 280 return Collections.emptySet(); 281 } 282 283 long children = xqt.get_children(); 284 285 if (children == 0) 286 { 287 return Collections.emptySet(); 288 } 289 290 int childrenCount = xqt.get_nchildren(); 291 292 Set<Long> childrenSet = new HashSet<Long>(childrenCount); 293 for (int i = 0; i < childrenCount; i++) 294 { 295 childrenSet.add(Native.getWindow(children, i)); 296 } 297 298 return childrenSet; 299 } 300 finally 301 { 302 xqt.dispose(); 303 } 304 } 305 finally 306 { 307 XToolkit.awtUnlock(); 308 } 309 } 310 311 /** 312 * Checks if the given window is a Java window and is an 313 * instance of XWindowPeer 314 */ 315 static boolean isXAWTToplevelWindow(long window) 316 { 317 return XToolkit.windowToXWindow(window) instanceof XWindowPeer; 318 } 319 320 /** 321 * NOTICE: Right now returns only decorated top-levels (not Window) 322 */ 323 static boolean isToplevelWindow(long window) 324 { 325 if (XToolkit.windowToXWindow(window) instanceof XDecoratedPeer) 326 { 327 return true; 328 } 329 330 XToolkit.awtLock(); 331 try 332 { 333 WindowPropertyGetter wpg = 334 new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false, 335 XWM.XA_WM_STATE); 336 try 337 { 338 wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 339 if (wpg.getActualType() == XWM.XA_WM_STATE.getAtom()) 340 { 341 return true; 342 } 343 } 344 finally 345 { 346 wpg.dispose(); 347 } 348 349 return false; 350 } 351 finally 352 { 353 XToolkit.awtUnlock(); 354 } 355 } 356 357 /** 358 * The same as isToplevelWindow(window), but doesn't treat 359 * XEmbeddedFramePeer as toplevel. 360 */ 361 static boolean isTrueToplevelWindow(long window) 362 { 363 if (XToolkit.windowToXWindow(window) instanceof XEmbeddedFramePeer) 364 { 365 return false; 366 } 367 368 return isToplevelWindow(window); 369 } 370 371 static int getWindowMapState(long window) 372 { 373 XToolkit.awtLock(); 374 XWindowAttributes wattr = new XWindowAttributes(); 375 try 376 { 377 XToolkit.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 378 int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), 379 window, wattr.pData); 380 XToolkit.RESTORE_XERROR_HANDLER(); 381 if ((status != 0) && 382 ((XToolkit.saved_error == null) || 383 (XToolkit.saved_error.get_error_code() == XConstants.Success))) 384 { 385 return wattr.get_map_state(); 386 } 387 } 388 finally 389 { 390 wattr.dispose(); 391 XToolkit.awtUnlock(); 392 } 393 394 return XConstants.IsUnmapped; 395 } 396 397 /** 398 * XSHAPE extension support. 399 */ 400 401 // The variable is declared static as the XSHAPE extension cannot 402 // be disabled at run-time, and thus is available all the time 403 // once the check is passed. 404 static Boolean isShapingSupported = null; 405 406 /** 407 * Returns whether the XSHAPE extension available 408 * @since 1.7 409 */ 410 static synchronized boolean isShapingSupported() { 411 412 if (isShapingSupported == null) { 413 XToolkit.awtLock(); 414 try { 415 isShapingSupported = 416 XlibWrapper.XShapeQueryExtension( 417 XToolkit.getDisplay(), 418 XlibWrapper.larg1, 419 XlibWrapper.larg2); 420 } finally { 421 XToolkit.awtUnlock(); 422 } 423 } 424 425 return isShapingSupported.booleanValue(); 426 } 427 428 }