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