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