1 /* 2 * Copyright (c) 2006, 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.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, in absolute coordinates 104 */ 105 static Rectangle getWindowGeometry(long window, int scale) 106 { 107 XToolkit.awtLock(); 108 try 109 { 110 int res = XlibWrapper.XGetGeometry(XToolkit.getDisplay(), 111 window, 112 XlibWrapper.larg1, // root_return 113 XlibWrapper.larg2, // x_return 114 XlibWrapper.larg3, // y_return 115 XlibWrapper.larg4, // width_return 116 XlibWrapper.larg5, // height_return 117 XlibWrapper.larg6, // border_width_return 118 XlibWrapper.larg7); // depth_return 119 if (res == 0) 120 { 121 return null; 122 } 123 124 int x = Native.getInt(XlibWrapper.larg2); 125 int y = Native.getInt(XlibWrapper.larg3); 126 long width = Native.getUInt(XlibWrapper.larg4); 127 long height = Native.getUInt(XlibWrapper.larg5); 128 129 return new Rectangle(x / scale, y / scale, 130 (int) (width / scale), 131 (int) (height / scale)); 132 } 133 finally 134 { 135 XToolkit.awtUnlock(); 136 } 137 } 138 139 /** 140 * Translates the given point from one window to another. Returns 141 * null if the translation is failed 142 */ 143 static Point translateCoordinates(long src, long dst, Point p, int scale) 144 { 145 Point translated = null; 146 147 XToolkit.awtLock(); 148 try 149 { 150 XTranslateCoordinates xtc = 151 new XTranslateCoordinates(src, dst, p.x * scale, p.y * scale); 152 try 153 { 154 int status = xtc.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 155 if ((status != 0) && 156 ((XErrorHandlerUtil.saved_error == null) || 157 (XErrorHandlerUtil.saved_error.get_error_code() == XConstants.Success))) 158 { 159 translated = new Point(xtc.get_dest_x() / scale, xtc.get_dest_y() / scale); 160 } 161 } 162 finally 163 { 164 xtc.dispose(); 165 } 166 } 167 finally 168 { 169 XToolkit.awtUnlock(); 170 } 171 172 return translated; 173 } 174 175 /** 176 * Translates the given rectangle from one window to another. 177 * Returns null if the translation is failed 178 */ 179 static Rectangle translateCoordinates(long src, long dst, Rectangle r, 180 int scale) 181 { 182 Point translatedLoc = translateCoordinates(src, dst, r.getLocation(), 183 scale); 184 185 if (translatedLoc == null) 186 { 187 return null; 188 } 189 else 190 { 191 return new Rectangle(translatedLoc, r.getSize()); 192 } 193 } 194 195 /** 196 * Returns the parent for the given window 197 */ 198 static long getParentWindow(long window) 199 { 200 XToolkit.awtLock(); 201 try 202 { 203 XBaseWindow bw = XToolkit.windowToXWindow(window); 204 if (bw != null) 205 { 206 XBaseWindow pbw = bw.getParentWindow(); 207 if (pbw != null) 208 { 209 return pbw.getWindow(); 210 } 211 } 212 213 XQueryTree qt = new XQueryTree(window); 214 try 215 { 216 if (qt.execute() == 0) 217 { 218 return 0; 219 } 220 else 221 { 222 return qt.get_parent(); 223 } 224 } 225 finally 226 { 227 qt.dispose(); 228 } 229 } 230 finally 231 { 232 XToolkit.awtUnlock(); 233 } 234 } 235 236 /** 237 * Returns all the children for the given window 238 */ 239 static Set<Long> getChildWindows(long window) 240 { 241 XToolkit.awtLock(); 242 try 243 { 244 XBaseWindow bw = XToolkit.windowToXWindow(window); 245 if (bw != null) 246 { 247 return bw.getChildren(); 248 } 249 250 XQueryTree xqt = new XQueryTree(window); 251 try 252 { 253 int status = xqt.execute(); 254 if (status == 0) 255 { 256 return Collections.emptySet(); 257 } 258 259 long children = xqt.get_children(); 260 261 if (children == 0) 262 { 263 return Collections.emptySet(); 264 } 265 266 int childrenCount = xqt.get_nchildren(); 267 268 Set<Long> childrenSet = new HashSet<Long>(childrenCount); 269 for (int i = 0; i < childrenCount; i++) 270 { 271 childrenSet.add(Native.getWindow(children, i)); 272 } 273 274 return childrenSet; 275 } 276 finally 277 { 278 xqt.dispose(); 279 } 280 } 281 finally 282 { 283 XToolkit.awtUnlock(); 284 } 285 } 286 287 /** 288 * Checks if the given window is a Java window and is an 289 * instance of XWindowPeer 290 */ 291 static boolean isXAWTToplevelWindow(long window) 292 { 293 return XToolkit.windowToXWindow(window) instanceof XWindowPeer; 294 } 295 296 /** 297 * NOTICE: Right now returns only decorated top-levels (not Window) 298 */ 299 static boolean isToplevelWindow(long window) 300 { 301 if (XToolkit.windowToXWindow(window) instanceof XDecoratedPeer) 302 { 303 return true; 304 } 305 306 XToolkit.awtLock(); 307 try 308 { 309 WindowPropertyGetter wpg = 310 new WindowPropertyGetter(window, XWM.XA_WM_STATE, 0, 1, false, 311 XWM.XA_WM_STATE); 312 try 313 { 314 wpg.execute(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 315 if (wpg.getActualType() == XWM.XA_WM_STATE.getAtom()) 316 { 317 return true; 318 } 319 } 320 finally 321 { 322 wpg.dispose(); 323 } 324 325 return false; 326 } 327 finally 328 { 329 XToolkit.awtUnlock(); 330 } 331 } 332 333 /** 334 * The same as isToplevelWindow(window), but doesn't treat 335 * XEmbeddedFramePeer as toplevel. 336 */ 337 static boolean isTrueToplevelWindow(long window) 338 { 339 if (XToolkit.windowToXWindow(window) instanceof XEmbeddedFramePeer) 340 { 341 return false; 342 } 343 344 return isToplevelWindow(window); 345 } 346 347 static int getWindowMapState(long window) 348 { 349 XToolkit.awtLock(); 350 XWindowAttributes wattr = new XWindowAttributes(); 351 try 352 { 353 XErrorHandlerUtil.WITH_XERROR_HANDLER(XErrorHandler.IgnoreBadWindowHandler.getInstance()); 354 int status = XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(), 355 window, wattr.pData); 356 XErrorHandlerUtil.RESTORE_XERROR_HANDLER(); 357 if ((status != 0) && 358 ((XErrorHandlerUtil.saved_error == null) || 359 (XErrorHandlerUtil.saved_error.get_error_code() == XConstants.Success))) 360 { 361 return wattr.get_map_state(); 362 } 363 } 364 finally 365 { 366 wattr.dispose(); 367 XToolkit.awtUnlock(); 368 } 369 370 return XConstants.IsUnmapped; 371 } 372 373 /** 374 * XSHAPE extension support. 375 */ 376 377 // The variable is declared static as the XSHAPE extension cannot 378 // be disabled at run-time, and thus is available all the time 379 // once the check is passed. 380 static Boolean isShapingSupported = null; 381 382 /** 383 * Returns whether the XSHAPE extension available 384 * @since 1.7 385 */ 386 static synchronized boolean isShapingSupported() { 387 388 if (isShapingSupported == null) { 389 XToolkit.awtLock(); 390 try { 391 isShapingSupported = 392 XlibWrapper.XShapeQueryExtension( 393 XToolkit.getDisplay(), 394 XlibWrapper.larg1, 395 XlibWrapper.larg2); 396 } finally { 397 XToolkit.awtUnlock(); 398 } 399 } 400 401 return isShapingSupported.booleanValue(); 402 } 403 404 static int getButtonMask(int button) { 405 // Button indices start with 1. The first bit in the button mask is the 8th. 406 // The state mask does not support button indicies > 5, so we need to 407 // cut there. 408 if (button <= 0 || button > XConstants.MAX_BUTTONS) { 409 return 0; 410 } else { 411 return 1 << (7 + button); 412 } 413 } 414 }