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