1 /*
   2  * Copyright (c) 2003, 2010, 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.*;
  29 import sun.awt.*;
  30 import java.util.*;
  31 import sun.util.logging.PlatformLogger;
  32 
  33 public class XBaseWindow {
  34     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XBaseWindow");
  35     private static final PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XBaseWindow");
  36     private static final PlatformLogger eventLog = PlatformLogger.getLogger("sun.awt.X11.event.XBaseWindow");
  37     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XBaseWindow");
  38     private static final PlatformLogger grabLog = PlatformLogger.getLogger("sun.awt.X11.grab.XBaseWindow");
  39 
  40     public static final String
  41         PARENT_WINDOW = "parent window", // parent window, Long
  42         BOUNDS = "bounds", // bounds of the window, Rectangle
  43         OVERRIDE_REDIRECT = "overrideRedirect", // override_redirect setting, Boolean
  44         EVENT_MASK = "event mask", // event mask, Integer
  45         VALUE_MASK = "value mask", // value mask, Long
  46         BORDER_PIXEL = "border pixel", // border pixel value, Integer
  47         COLORMAP = "color map", // color map, Long
  48         DEPTH = "visual depth", // depth, Integer
  49         VISUAL_CLASS = "visual class", // visual class, Integer
  50         VISUAL = "visual", // visual, Long
  51         EMBEDDED = "embedded", // is embedded?, Boolean
  52         DELAYED = "delayed", // is creation delayed?, Boolean
  53         PARENT = "parent", // parent peer
  54         BACKGROUND_PIXMAP = "pixmap", // background pixmap
  55         VISIBLE = "visible", // whether it is visible by default
  56         SAVE_UNDER = "save under", // save content under this window
  57         BACKING_STORE = "backing store", // enables double buffering
  58         BIT_GRAVITY = "bit gravity"; // copy old content on geometry change
  59     private XCreateWindowParams delayedParams;
  60 
  61     Set<Long> children = new HashSet<Long>();
  62     long window;
  63     boolean visible;
  64     boolean mapped;
  65     boolean embedded;
  66     Rectangle maxBounds;
  67     volatile XBaseWindow parentWindow;
  68 
  69     private boolean disposed;
  70 
  71     private long screen;
  72     private XSizeHints hints;
  73     private XWMHints wmHints;
  74 
  75     final static int MIN_SIZE = 1;
  76     final static int DEF_LOCATION = 1;
  77 
  78     private static XAtom wm_client_leader;
  79 
  80     static enum InitialiseState {
  81         INITIALISING,
  82         NOT_INITIALISED,
  83         INITIALISED,
  84         FAILED_INITIALISATION
  85     };
  86 
  87     private InitialiseState initialising;
  88 
  89     int x;
  90     int y;
  91     int width;
  92     int height;
  93 
  94     void awtLock() {
  95         XToolkit.awtLock();
  96     }
  97 
  98     void awtUnlock() {
  99         XToolkit.awtUnlock();
 100     }
 101 
 102     void awtLockNotifyAll() {
 103         XToolkit.awtLockNotifyAll();
 104     }
 105 
 106     void awtLockWait() throws InterruptedException {
 107         XToolkit.awtLockWait();
 108     }
 109 
 110     // To prevent errors from overriding obsolete methods
 111     protected final void init(long parentWindow, Rectangle bounds) {}
 112     protected final void preInit() {}
 113     protected final void postInit() {}
 114 
 115     // internal lock for synchronizing state changes and paint calls, initialized in preInit.
 116     // the order with other locks: AWTLock -> stateLock
 117     static class StateLock extends Object { }
 118     protected StateLock state_lock;
 119 
 120     /**
 121      * Called for delayed inits during construction
 122      */
 123     void instantPreInit(XCreateWindowParams params) {
 124         state_lock = new StateLock();
 125         initialising = InitialiseState.NOT_INITIALISED;
 126     }
 127 
 128     /**
 129      * Called before window creation, descendants should override to initialize the data,
 130      * initialize params.
 131      */
 132     void preInit(XCreateWindowParams params) {
 133         state_lock = new StateLock();
 134         initialising = InitialiseState.NOT_INITIALISED;
 135         embedded = Boolean.TRUE.equals(params.get(EMBEDDED));
 136         visible = Boolean.TRUE.equals(params.get(VISIBLE));
 137 
 138         Object parent = params.get(PARENT);
 139         if (parent instanceof XBaseWindow) {
 140             parentWindow = (XBaseWindow)parent;
 141         } else {
 142             Long parentWindowID = (Long)params.get(PARENT_WINDOW);
 143             if (parentWindowID != null) {
 144                 parentWindow = XToolkit.windowToXWindow(parentWindowID);
 145             }
 146         }
 147 
 148         Long eventMask = (Long)params.get(EVENT_MASK);
 149         if (eventMask != null) {
 150             long mask = eventMask.longValue();
 151             mask |= XConstants.SubstructureNotifyMask;
 152             params.put(EVENT_MASK, mask);
 153         }
 154 
 155         screen = -1;
 156     }
 157 
 158     /**
 159      * Called after window creation, descendants should override to initialize Window
 160      * with class-specific values and perform post-initialization actions.
 161      */
 162     void postInit(XCreateWindowParams params) {
 163         if (log.isLoggable(PlatformLogger.FINE)) log.fine("WM name is " + getWMName());
 164         updateWMName();
 165 
 166         // Set WM_CLIENT_LEADER property
 167         initClientLeader();
 168     }
 169 
 170     /**
 171      * Creates window using parameters <code>params</code>
 172      * If params contain flag DELAYED doesn't do anything.
 173      * Note: Descendants can call this method to create the window
 174      * at the time different to instance construction.
 175      */
 176     protected final void init(XCreateWindowParams params) {
 177         awtLock();
 178         initialising = InitialiseState.INITIALISING;
 179         awtUnlock();
 180 
 181         try {
 182             if (!Boolean.TRUE.equals(params.get(DELAYED))) {
 183                 preInit(params);
 184                 create(params);
 185                 postInit(params);
 186             } else {
 187                 instantPreInit(params);
 188                 delayedParams = params;
 189             }
 190             awtLock();
 191             initialising = InitialiseState.INITIALISED;
 192             awtLockNotifyAll();
 193             awtUnlock();
 194         } catch (RuntimeException re) {
 195             awtLock();
 196             initialising = InitialiseState.FAILED_INITIALISATION;
 197             awtLockNotifyAll();
 198             awtUnlock();
 199             throw re;
 200         } catch (Throwable t) {
 201             log.warning("Exception during peer initialization", t);
 202             awtLock();
 203             initialising = InitialiseState.FAILED_INITIALISATION;
 204             awtLockNotifyAll();
 205             awtUnlock();
 206         }
 207     }
 208 
 209     public boolean checkInitialised() {
 210         awtLock();
 211         try {
 212             switch (initialising) {
 213               case INITIALISED:
 214                   return true;
 215               case INITIALISING:
 216                   try {
 217                       while (initialising != InitialiseState.INITIALISED) {
 218                           awtLockWait();
 219                       }
 220                   } catch (InterruptedException ie) {
 221                       return false;
 222                   }
 223                   return true;
 224               case NOT_INITIALISED:
 225               case FAILED_INITIALISATION:
 226                   return false;
 227               default:
 228                   return false;
 229             }
 230         } finally {
 231             awtUnlock();
 232         }
 233     }
 234 
 235     /*
 236      * Creates an invisible InputOnly window without an associated Component.
 237      */
 238     XBaseWindow() {
 239         this(new XCreateWindowParams());
 240     }
 241 
 242     /**
 243      * Creates normal child window
 244      */
 245     XBaseWindow(long parentWindow, Rectangle bounds) {
 246         this(new XCreateWindowParams(new Object[] {
 247             BOUNDS, bounds,
 248             PARENT_WINDOW, Long.valueOf(parentWindow)}));
 249     }
 250 
 251     /**
 252      * Creates top-level window
 253      */
 254     XBaseWindow(Rectangle bounds) {
 255         this(new XCreateWindowParams(new Object[] {
 256             BOUNDS, bounds
 257         }));
 258     }
 259 
 260     public XBaseWindow (XCreateWindowParams params) {
 261         init(params);
 262     }
 263 
 264     /* This create is used by the XEmbeddedFramePeer since it has to create the window
 265        as a child of the netscape window. This netscape window is passed in as wid */
 266     XBaseWindow(long parentWindow) {
 267         this(new XCreateWindowParams(new Object[] {
 268             PARENT_WINDOW, Long.valueOf(parentWindow),
 269             EMBEDDED, Boolean.TRUE
 270         }));
 271     }
 272 
 273     /**
 274      * Verifies that all required parameters are set. If not, sets them to default values.
 275      * Verifies values of critical parameters, adjust their values when needed.
 276      * @throws IllegalArgumentException if params is null
 277      */
 278     protected void checkParams(XCreateWindowParams params) {
 279         if (params == null) {
 280             throw new IllegalArgumentException("Window creation parameters are null");
 281         }
 282         params.putIfNull(PARENT_WINDOW, Long.valueOf(XToolkit.getDefaultRootWindow()));
 283         params.putIfNull(BOUNDS, new Rectangle(DEF_LOCATION, DEF_LOCATION, MIN_SIZE, MIN_SIZE));
 284         params.putIfNull(DEPTH, Integer.valueOf((int)XConstants.CopyFromParent));
 285         params.putIfNull(VISUAL, Long.valueOf(XConstants.CopyFromParent));
 286         params.putIfNull(VISUAL_CLASS, Integer.valueOf((int)XConstants.InputOnly));
 287         params.putIfNull(VALUE_MASK, Long.valueOf(XConstants.CWEventMask));
 288         Rectangle bounds = (Rectangle)params.get(BOUNDS);
 289         bounds.width = Math.max(MIN_SIZE, bounds.width);
 290         bounds.height = Math.max(MIN_SIZE, bounds.height);
 291 
 292         Long eventMaskObj = (Long)params.get(EVENT_MASK);
 293         long eventMask = eventMaskObj != null ? eventMaskObj.longValue() : 0;
 294         // We use our own synthetic grab see XAwtState.getGrabWindow()
 295         // (see X vol. 1, 8.3.3.2)
 296         eventMask |= XConstants.PropertyChangeMask | XConstants.OwnerGrabButtonMask;
 297         params.put(EVENT_MASK, Long.valueOf(eventMask));
 298     }
 299 
 300     /**
 301      * Creates window with parameters specified by <code>params</code>
 302      * @see #init
 303      */
 304     private final void create(XCreateWindowParams params) {
 305         XToolkit.awtLock();
 306         try {
 307             XSetWindowAttributes xattr = new XSetWindowAttributes();
 308             try {
 309                 checkParams(params);
 310 
 311                 long value_mask = ((Long)params.get(VALUE_MASK)).longValue();
 312 
 313                 Long eventMask = (Long)params.get(EVENT_MASK);
 314                 xattr.set_event_mask(eventMask.longValue());
 315                 value_mask |= XConstants.CWEventMask;
 316 
 317                 Long border_pixel = (Long)params.get(BORDER_PIXEL);
 318                 if (border_pixel != null) {
 319                     xattr.set_border_pixel(border_pixel.longValue());
 320                     value_mask |= XConstants.CWBorderPixel;
 321                 }
 322 
 323                 Long colormap = (Long)params.get(COLORMAP);
 324                 if (colormap != null) {
 325                     xattr.set_colormap(colormap.longValue());
 326                     value_mask |= XConstants.CWColormap;
 327                 }
 328                 Long background_pixmap = (Long)params.get(BACKGROUND_PIXMAP);
 329                 if (background_pixmap != null) {
 330                     xattr.set_background_pixmap(background_pixmap.longValue());
 331                     value_mask |= XConstants.CWBackPixmap;
 332                 }
 333 
 334                 Long parentWindow = (Long)params.get(PARENT_WINDOW);
 335                 Rectangle bounds = (Rectangle)params.get(BOUNDS);
 336                 Integer depth = (Integer)params.get(DEPTH);
 337                 Integer visual_class = (Integer)params.get(VISUAL_CLASS);
 338                 Long visual = (Long)params.get(VISUAL);
 339                 Boolean overrideRedirect = (Boolean)params.get(OVERRIDE_REDIRECT);
 340                 if (overrideRedirect != null) {
 341                     xattr.set_override_redirect(overrideRedirect.booleanValue());
 342                     value_mask |= XConstants.CWOverrideRedirect;
 343                 }
 344 
 345                 Boolean saveUnder = (Boolean)params.get(SAVE_UNDER);
 346                 if (saveUnder != null) {
 347                     xattr.set_save_under(saveUnder.booleanValue());
 348                     value_mask |= XConstants.CWSaveUnder;
 349                 }
 350 
 351                 Integer backingStore = (Integer)params.get(BACKING_STORE);
 352                 if (backingStore != null) {
 353                     xattr.set_backing_store(backingStore.intValue());
 354                     value_mask |= XConstants.CWBackingStore;
 355                 }
 356 
 357                 Integer bitGravity = (Integer)params.get(BIT_GRAVITY);
 358                 if (bitGravity != null) {
 359                     xattr.set_bit_gravity(bitGravity.intValue());
 360                     value_mask |= XConstants.CWBitGravity;
 361                 }
 362 
 363                 if (log.isLoggable(PlatformLogger.FINE)) {
 364                     log.fine("Creating window for " + this + " with the following attributes: \n" + params);
 365                 }
 366                 window = XlibWrapper.XCreateWindow(XToolkit.getDisplay(),
 367                                    parentWindow.longValue(),
 368                                    bounds.x, bounds.y, // location
 369                                    bounds.width, bounds.height, // size
 370                                    0, // border
 371                                    depth.intValue(), // depth
 372                                    visual_class.intValue(), // class
 373                                    visual.longValue(), // visual
 374                                    value_mask,  // value mask
 375                                    xattr.pData); // attributes
 376 
 377                 if (window == 0) {
 378                     throw new IllegalStateException("Couldn't create window because of wrong parameters. Run with NOISY_AWT to see details");
 379                 }
 380                 XToolkit.addToWinMap(window, this);
 381             } finally {
 382                 xattr.dispose();
 383             }
 384         } finally {
 385             XToolkit.awtUnlock();
 386         }
 387     }
 388 
 389     public XCreateWindowParams getDelayedParams() {
 390         return delayedParams;
 391     }
 392 
 393     protected String getWMName() {
 394         return XToolkit.getCorrectXIDString(getClass().getName());
 395     }
 396 
 397     protected void initClientLeader() {
 398         XToolkit.awtLock();
 399         try {
 400             if (wm_client_leader == null) {
 401                 wm_client_leader = XAtom.get("WM_CLIENT_LEADER");
 402             }
 403             wm_client_leader.setWindowProperty(this, getXAWTRootWindow());
 404         } finally {
 405             XToolkit.awtUnlock();
 406         }
 407     }
 408 
 409     static XRootWindow getXAWTRootWindow() {
 410         return XRootWindow.getInstance();
 411     }
 412 
 413     void destroy() {
 414         XToolkit.awtLock();
 415         try {
 416             if (hints != null) {
 417                 XlibWrapper.XFree(hints.pData);
 418                 hints = null;
 419             }
 420             XToolkit.removeFromWinMap(getWindow(), this);
 421             XlibWrapper.XDestroyWindow(XToolkit.getDisplay(), getWindow());
 422             if (XPropertyCache.isCachingSupported()) {
 423                 XPropertyCache.clearCache(window);
 424             }
 425             window = -1;
 426             if( !isDisposed() ) {
 427                 setDisposed( true );
 428             }
 429 
 430             XAwtState.getGrabWindow(); // Magic - getGrabWindow clear state if grabbing window is disposed of.
 431         } finally {
 432             XToolkit.awtUnlock();
 433         }
 434     }
 435 
 436     void flush() {
 437         XToolkit.awtLock();
 438         try {
 439             XlibWrapper.XFlush(XToolkit.getDisplay());
 440         } finally {
 441             XToolkit.awtUnlock();
 442         }
 443     }
 444 
 445     /**
 446      * Helper function to set W
 447      */
 448     public final void setWMHints(XWMHints hints) {
 449         XToolkit.awtLock();
 450         try {
 451             XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
 452         } finally {
 453             XToolkit.awtUnlock();
 454         }
 455     }
 456 
 457     public XWMHints getWMHints() {
 458         if (wmHints == null) {
 459             wmHints = new XWMHints(XlibWrapper.XAllocWMHints());
 460 //              XlibWrapper.XGetWMHints(XToolkit.getDisplay(),
 461 //                                      getWindow(),
 462 //                                      wmHints.pData);
 463         }
 464         return wmHints;
 465     }
 466 
 467 
 468     /*
 469      * Call this method under AWTLock.
 470      * The lock should be acquired untill all operations with XSizeHints are completed.
 471      */
 472     public XSizeHints getHints() {
 473         if (hints == null) {
 474             long p_hints = XlibWrapper.XAllocSizeHints();
 475             hints = new XSizeHints(p_hints);
 476 //              XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), getWindow(), p_hints, XlibWrapper.larg1);
 477             // TODO: Shouldn't we listen for WM updates on this property?
 478         }
 479         return hints;
 480     }
 481 
 482     public void setSizeHints(long flags, int x, int y, int width, int height) {
 483         if (insLog.isLoggable(PlatformLogger.FINER)) insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(flags));
 484         XToolkit.awtLock();
 485         try {
 486             XSizeHints hints = getHints();
 487             // Note: if PPosition is not set in flags this means that
 488             // we want to reset PPosition in hints.  This is necessary
 489             // for locationByPlatform functionality
 490             if ((flags & XUtilConstants.PPosition) != 0) {
 491                 hints.set_x(x);
 492                 hints.set_y(y);
 493             }
 494             if ((flags & XUtilConstants.PSize) != 0) {
 495                 hints.set_width(width);
 496                 hints.set_height(height);
 497             } else if ((hints.get_flags() & XUtilConstants.PSize) != 0) {
 498                 flags |= XUtilConstants.PSize;
 499             }
 500             if ((flags & XUtilConstants.PMinSize) != 0) {
 501                 hints.set_min_width(width);
 502                 hints.set_min_height(height);
 503             } else if ((hints.get_flags() & XUtilConstants.PMinSize) != 0) {
 504                 flags |= XUtilConstants.PMinSize;
 505                 //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
 506                 //We don't need to reset minimum size if it's already set
 507             }
 508             if ((flags & XUtilConstants.PMaxSize) != 0) {
 509                 if (maxBounds != null) {
 510                     if (maxBounds.width != Integer.MAX_VALUE) {
 511                         hints.set_max_width(maxBounds.width);
 512                     } else {
 513                         hints.set_max_width(XToolkit.getDefaultScreenWidth());
 514                     }
 515                     if (maxBounds.height != Integer.MAX_VALUE) {
 516                         hints.set_max_height(maxBounds.height);
 517                     } else {
 518                         hints.set_max_height(XToolkit.getDefaultScreenHeight());
 519                     }
 520                 } else {
 521                     hints.set_max_width(width);
 522                     hints.set_max_height(height);
 523                 }
 524             } else if ((hints.get_flags() & XUtilConstants.PMaxSize) != 0) {
 525                 flags |= XUtilConstants.PMaxSize;
 526                 if (maxBounds != null) {
 527                     if (maxBounds.width != Integer.MAX_VALUE) {
 528                         hints.set_max_width(maxBounds.width);
 529                     } else {
 530                         hints.set_max_width(XToolkit.getDefaultScreenWidth());
 531                     }
 532                     if (maxBounds.height != Integer.MAX_VALUE) {
 533                         hints.set_max_height(maxBounds.height);
 534                     } else {
 535                         hints.set_max_height(XToolkit.getDefaultScreenHeight());
 536                     }
 537                 } else {
 538                     // Leave intact
 539                 }
 540             }
 541             flags |= XUtilConstants.PWinGravity;
 542             hints.set_flags(flags);
 543             hints.set_win_gravity((int)XConstants.NorthWestGravity);
 544             if (insLog.isLoggable(PlatformLogger.FINER)) insLog.finer("Setting hints, resulted flags " + XlibWrapper.hintsToString(flags) +
 545                                                              ", values " + hints);
 546             XlibWrapper.XSetWMNormalHints(XToolkit.getDisplay(), getWindow(), hints.pData);
 547         } finally {
 548             XToolkit.awtUnlock();
 549         }
 550     }
 551 
 552     public boolean isMinSizeSet() {
 553         XSizeHints hints = getHints();
 554         long flags = hints.get_flags();
 555         return ((flags & XUtilConstants.PMinSize) == XUtilConstants.PMinSize);
 556     }
 557 
 558     /**
 559      * This lock object can be used to protect instance data from concurrent access
 560      * by two threads. If both state lock and AWT lock are taken, AWT Lock should be taken first.
 561      */
 562     Object getStateLock() {
 563         return state_lock;
 564     }
 565 
 566     public long getWindow() {
 567         return window;
 568     }
 569     public long getContentWindow() {
 570         return window;
 571     }
 572 
 573     public XBaseWindow getContentXWindow() {
 574         return XToolkit.windowToXWindow(getContentWindow());
 575     }
 576 
 577     public Rectangle getBounds() {
 578         return new Rectangle(x, y, width, height);
 579     }
 580     public Dimension getSize() {
 581         return new Dimension(width, height);
 582     }
 583 
 584 
 585     public void toFront() {
 586         XToolkit.awtLock();
 587         try {
 588             XlibWrapper.XRaiseWindow(XToolkit.getDisplay(), getWindow());
 589         } finally {
 590             XToolkit.awtUnlock();
 591         }
 592     }
 593     public void xRequestFocus(long time) {
 594         XToolkit.awtLock();
 595         try {
 596             if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer("XSetInputFocus on " + Long.toHexString(getWindow()) + " with time " + time);
 597             XlibWrapper.XSetInputFocus2(XToolkit.getDisplay(), getWindow(), time);
 598         } finally {
 599             XToolkit.awtUnlock();
 600         }
 601     }
 602     public void xRequestFocus() {
 603         XToolkit.awtLock();
 604         try {
 605             if (focusLog.isLoggable(PlatformLogger.FINER)) focusLog.finer("XSetInputFocus on " + Long.toHexString(getWindow()));
 606              XlibWrapper.XSetInputFocus(XToolkit.getDisplay(), getWindow());
 607         } finally {
 608             XToolkit.awtUnlock();
 609         }
 610     }
 611 
 612     public static long xGetInputFocus() {
 613         XToolkit.awtLock();
 614         try {
 615             return XlibWrapper.XGetInputFocus(XToolkit.getDisplay());
 616         } finally {
 617             XToolkit.awtUnlock();
 618         }
 619     }
 620 
 621     public void xSetVisible(boolean visible) {
 622         if (log.isLoggable(PlatformLogger.FINE)) log.fine("Setting visible on " + this + " to " + visible);
 623         XToolkit.awtLock();
 624         try {
 625             this.visible = visible;
 626             if (visible) {
 627                 XlibWrapper.XMapWindow(XToolkit.getDisplay(), getWindow());
 628             }
 629             else {
 630                 XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), getWindow());
 631             }
 632             XlibWrapper.XFlush(XToolkit.getDisplay());
 633         } finally {
 634             XToolkit.awtUnlock();
 635         }
 636     }
 637 
 638     boolean isMapped() {
 639         return mapped;
 640     }
 641 
 642     void updateWMName() {
 643         String name = getWMName();
 644         XToolkit.awtLock();
 645         try {
 646             if (name == null) {
 647                 name = " ";
 648             }
 649             XAtom nameAtom = XAtom.get(XAtom.XA_WM_NAME);
 650             nameAtom.setProperty(getWindow(), name);
 651             XAtom netNameAtom = XAtom.get("_NET_WM_NAME");
 652             netNameAtom.setPropertyUTF8(getWindow(), name);
 653         } finally {
 654             XToolkit.awtUnlock();
 655         }
 656     }
 657     void setWMClass(String[] cl) {
 658         if (cl.length != 2) {
 659             throw new IllegalArgumentException("WM_CLASS_NAME consists of exactly two strings");
 660         }
 661         XToolkit.awtLock();
 662         try {
 663             XAtom xa = XAtom.get(XAtom.XA_WM_CLASS);
 664             xa.setProperty8(getWindow(), cl[0] + '\0' + cl[1]);
 665         } finally {
 666             XToolkit.awtUnlock();
 667         }
 668     }
 669 
 670     boolean isVisible() {
 671         return visible;
 672     }
 673 
 674     static long getScreenOfWindow(long window) {
 675         XToolkit.awtLock();
 676         try {
 677             return XlibWrapper.getScreenOfWindow(XToolkit.getDisplay(), window);
 678         } finally {
 679             XToolkit.awtUnlock();
 680         }
 681     }
 682     long getScreenNumber() {
 683         XToolkit.awtLock();
 684         try {
 685             return XlibWrapper.XScreenNumberOfScreen(getScreen());
 686         } finally {
 687             XToolkit.awtUnlock();
 688         }
 689     }
 690 
 691     long getScreen() {
 692         if (screen == -1) { // Not initialized
 693             screen = getScreenOfWindow(window);
 694         }
 695         return screen;
 696     }
 697 
 698     public void xSetBounds(Rectangle bounds) {
 699         xSetBounds(bounds.x, bounds.y, bounds.width, bounds.height);
 700     }
 701 
 702     public void xSetBounds(int x, int y, int width, int height) {
 703         if (getWindow() == 0) {
 704             insLog.warning("Attempt to resize uncreated window");
 705             throw new IllegalStateException("Attempt to resize uncreated window");
 706         }
 707         insLog.fine("Setting bounds on " + this + " to (" + x + ", " + y + "), " + width + "x" + height);
 708         width = Math.max(MIN_SIZE, width);
 709         height = Math.max(MIN_SIZE, height);
 710         XToolkit.awtLock();
 711         try {
 712              XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getWindow(), x,y,width,height);
 713         } finally {
 714             XToolkit.awtUnlock();
 715         }
 716     }
 717 
 718     /**
 719      * Translate coordinates from one window into another.  Optimized
 720      * for XAWT - uses cached data when possible.  Preferable over
 721      * pure XTranslateCoordinates.
 722      * @return coordinates relative to dst, or null if error happened
 723      */
 724     static Point toOtherWindow(long src, long dst, int x, int y) {
 725         Point rpt = new Point(0, 0);
 726 
 727         // Check if both windows belong to XAWT - then no X calls are necessary
 728 
 729         XBaseWindow srcPeer = XToolkit.windowToXWindow(src);
 730         XBaseWindow dstPeer = XToolkit.windowToXWindow(dst);
 731 
 732         if (srcPeer != null && dstPeer != null) {
 733             // (x, y) is relative to src
 734             rpt.x = x + srcPeer.getAbsoluteX() - dstPeer.getAbsoluteX();
 735             rpt.y = y + srcPeer.getAbsoluteY() - dstPeer.getAbsoluteY();
 736         } else if (dstPeer != null && XlibUtil.isRoot(src, dstPeer.getScreenNumber())) {
 737             // from root into peer
 738             rpt.x = x - dstPeer.getAbsoluteX();
 739             rpt.y = y - dstPeer.getAbsoluteY();
 740         } else if (srcPeer != null && XlibUtil.isRoot(dst, srcPeer.getScreenNumber())) {
 741             // from peer into root
 742             rpt.x = x + srcPeer.getAbsoluteX();
 743             rpt.y = y + srcPeer.getAbsoluteY();
 744         } else {
 745             rpt = XlibUtil.translateCoordinates(src, dst, new Point(x, y));
 746         }
 747         return rpt;
 748     }
 749 
 750     /*
 751      * Convert to global coordinates.
 752      */
 753     Rectangle toGlobal(Rectangle rec) {
 754         Point p = toGlobal(rec.getLocation());
 755         Rectangle newRec = new Rectangle(rec);
 756         if (p != null) {
 757             newRec.setLocation(p);
 758         }
 759         return newRec;
 760     }
 761 
 762     Point toGlobal(Point pt) {
 763         Point p = toGlobal(pt.x, pt.y);
 764         if (p != null) {
 765             return p;
 766         } else {
 767             return new Point(pt);
 768         }
 769     }
 770 
 771     Point toGlobal(int x, int y) {
 772         long root;
 773         XToolkit.awtLock();
 774         try {
 775             root = XlibWrapper.RootWindow(XToolkit.getDisplay(),
 776                     getScreenNumber());
 777         } finally {
 778             XToolkit.awtUnlock();
 779         }
 780         Point p = toOtherWindow(getContentWindow(), root, x, y);
 781         if (p != null) {
 782             return p;
 783         } else {
 784             return new Point(x, y);
 785         }
 786     }
 787 
 788     /*
 789      * Convert to local coordinates.
 790      */
 791     Point toLocal(Point pt) {
 792         Point p = toLocal(pt.x, pt.y);
 793         if (p != null) {
 794             return p;
 795         } else {
 796             return new Point(pt);
 797         }
 798     }
 799 
 800     Point toLocal(int x, int y) {
 801         long root;
 802         XToolkit.awtLock();
 803         try {
 804             root = XlibWrapper.RootWindow(XToolkit.getDisplay(),
 805                     getScreenNumber());
 806         } finally {
 807             XToolkit.awtUnlock();
 808         }
 809         Point p = toOtherWindow(root, getContentWindow(), x, y);
 810         if (p != null) {
 811             return p;
 812         } else {
 813             return new Point(x, y);
 814         }
 815     }
 816 
 817     /**
 818      * We should always grab both keyboard and pointer to control event flow
 819      * on popups. This also simplifies synthetic grab implementation.
 820      * The active grab overrides activated automatic grab.
 821      */
 822     public boolean grabInput() {
 823         grabLog.fine("Grab input on {0}", this);
 824 
 825         XToolkit.awtLock();
 826         try {
 827             if (XAwtState.getGrabWindow() == this &&
 828                 XAwtState.isManualGrab())
 829             {
 830                 grabLog.fine("    Already Grabbed");
 831                 return true;
 832             }
 833             //6273031: PIT. Choice drop down does not close once it is right clicked to show a popup menu
 834             //remember previous window having grab and if it's not null ungrab it.
 835             XBaseWindow prevGrabWindow = XAwtState.getGrabWindow();
 836             final int eventMask = (int) (XConstants.ButtonPressMask | XConstants.ButtonReleaseMask
 837                 | XConstants.EnterWindowMask | XConstants.LeaveWindowMask | XConstants.PointerMotionMask
 838                 | XConstants.ButtonMotionMask);
 839             final int ownerEvents = 1;
 840 
 841 
 842             //6714678: IDE (Netbeans, Eclipse, JDeveloper) Debugger hangs
 843             //process on Linux
 844             //The user must pass the sun.awt.disablegrab property to disable
 845             //taking grabs. This prevents hanging of the GUI when a breakpoint
 846             //is hit while a popup window taking the grab is open.
 847             if (!XToolkit.getSunAwtDisableGrab()) {
 848                 int ptrGrab = XlibWrapper.XGrabPointer(XToolkit.getDisplay(),
 849                         getContentWindow(), ownerEvents, eventMask, XConstants.GrabModeAsync,
 850                         XConstants.GrabModeAsync, XConstants.None, (XWM.isMotif() ? XToolkit.arrowCursor : XConstants.None),
 851                         XConstants.CurrentTime);
 852                 // Check grab results to be consistent with X server grab
 853                 if (ptrGrab != XConstants.GrabSuccess) {
 854                     XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime);
 855                     XAwtState.setGrabWindow(null);
 856                     grabLog.fine("    Grab Failure - mouse");
 857                     return false;
 858                 }
 859 
 860                 int keyGrab = XlibWrapper.XGrabKeyboard(XToolkit.getDisplay(),
 861                         getContentWindow(), ownerEvents, XConstants.GrabModeAsync, XConstants.GrabModeAsync,
 862                         XConstants.CurrentTime);
 863                 if (keyGrab != XConstants.GrabSuccess) {
 864                     XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime);
 865                     XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(), XConstants.CurrentTime);
 866                     XAwtState.setGrabWindow(null);
 867                     grabLog.fine("    Grab Failure - keyboard");
 868                     return false;
 869                 }
 870             }
 871             if (prevGrabWindow != null) {
 872                 prevGrabWindow.ungrabInputImpl();
 873             }
 874             XAwtState.setGrabWindow(this);
 875             grabLog.fine("    Grab - success");
 876             return true;
 877         } finally {
 878             XToolkit.awtUnlock();
 879         }
 880     }
 881 
 882     static void ungrabInput() {
 883         XToolkit.awtLock();
 884         try {
 885             XBaseWindow grabWindow = XAwtState.getGrabWindow();
 886             grabLog.fine("UnGrab input on {0}", grabWindow);
 887             if (grabWindow != null) {
 888                 grabWindow.ungrabInputImpl();
 889                 if (!XToolkit.getSunAwtDisableGrab()) {
 890                     XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime);
 891                     XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(), XConstants.CurrentTime);
 892                 }
 893                 XAwtState.setGrabWindow(null);
 894                 // we need to call XFlush() here to force ungrab
 895                 // see 6384219 for details
 896                 XlibWrapper.XFlush(XToolkit.getDisplay());
 897             }
 898         } finally {
 899             XToolkit.awtUnlock();
 900         }
 901     }
 902 
 903     // called from ungrabInput, used in popup windows to hide theirselfs in ungrabbing
 904     void ungrabInputImpl() {
 905     }
 906 
 907     static void checkSecurity() {
 908         if (XToolkit.isSecurityWarningEnabled() && XToolkit.isToolkitThread()) {
 909             StackTraceElement stack[] = (new Throwable()).getStackTrace();
 910             log.warning(stack[1] + ": Security violation: calling user code on toolkit thread");
 911         }
 912     }
 913 
 914     public Set<Long> getChildren() {
 915         synchronized (getStateLock()) {
 916             return new HashSet<Long>(children);
 917         }
 918     }
 919 
 920     // -------------- Event handling ----------------
 921     public void handleMapNotifyEvent(XEvent xev) {
 922         mapped = true;
 923     }
 924     public void handleUnmapNotifyEvent(XEvent xev) {
 925         mapped = false;
 926     }
 927     public void handleReparentNotifyEvent(XEvent xev) {
 928         if (eventLog.isLoggable(PlatformLogger.FINER)) {
 929             XReparentEvent msg = xev.get_xreparent();
 930             eventLog.finer(msg.toString());
 931         }
 932     }
 933     public void handlePropertyNotify(XEvent xev) {
 934         XPropertyEvent msg = xev.get_xproperty();
 935         if (XPropertyCache.isCachingSupported()) {
 936             XPropertyCache.clearCache(window, XAtom.get(msg.get_atom()));
 937         }
 938         if (eventLog.isLoggable(PlatformLogger.FINER)) {
 939             eventLog.finer("{0}", msg);
 940         }
 941     }
 942 
 943     public void handleDestroyNotify(XEvent xev) {
 944         XAnyEvent xany = xev.get_xany();
 945         if (xany.get_window() == getWindow()) {
 946             XToolkit.removeFromWinMap(getWindow(), this);
 947             if (XPropertyCache.isCachingSupported()) {
 948                 XPropertyCache.clearCache(getWindow());
 949             }
 950         }
 951         if (xany.get_window() != getWindow()) {
 952             synchronized (getStateLock()) {
 953                 children.remove(xany.get_window());
 954             }
 955         }
 956     }
 957 
 958     public void handleCreateNotify(XEvent xev) {
 959         XAnyEvent xany = xev.get_xany();
 960         if (xany.get_window() != getWindow()) {
 961             synchronized (getStateLock()) {
 962                 children.add(xany.get_window());
 963             }
 964         }
 965     }
 966 
 967     public void handleClientMessage(XEvent xev) {
 968         if (eventLog.isLoggable(PlatformLogger.FINER)) {
 969             XClientMessageEvent msg = xev.get_xclient();
 970             eventLog.finer(msg.toString());
 971         }
 972     }
 973 
 974     public void handleVisibilityEvent(XEvent xev) {
 975     }
 976     public void handleKeyPress(XEvent xev) {
 977     }
 978     public void handleKeyRelease(XEvent xev) {
 979     }
 980     public void handleExposeEvent(XEvent xev) {
 981     }
 982     /**
 983      * Activate automatic grab on first ButtonPress,
 984      * deactivate on full mouse release
 985      */
 986     public void handleButtonPressRelease(XEvent xev) {
 987         XButtonEvent xbe = xev.get_xbutton();
 988         /*
 989          * Ignore the buttons above 20 due to the bit limit for
 990          * InputEvent.BUTTON_DOWN_MASK.
 991          * One more bit is reserved for FIRST_HIGH_BIT.
 992          */
 993         if (xbe.get_button() > SunToolkit.MAX_BUTTONS_SUPPORTED) {
 994             return;
 995         }
 996         int buttonState = 0;
 997         final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
 998         for (int i = 0; i<buttonsNumber; i++){
 999             buttonState |= (xbe.get_state() & XConstants.buttonsMask[i]);
1000         }
1001         switch (xev.get_type()) {
1002         case XConstants.ButtonPress:
1003             if (buttonState == 0) {
1004                 XWindowPeer parent = getToplevelXWindow();
1005                 // See 6385277, 6981400.
1006                 if (parent != null && parent.isFocusableWindow()) {
1007                     // A click in a client area drops the actual focused window retaining.
1008                     parent.setActualFocusedWindow(null);
1009                     parent.requestWindowFocus(xbe.get_time(), true);
1010                 }
1011                 XAwtState.setAutoGrabWindow(this);
1012             }
1013             break;
1014         case XConstants.ButtonRelease:
1015             if (isFullRelease(buttonState, xbe.get_button())) {
1016                 XAwtState.setAutoGrabWindow(null);
1017             }
1018             break;
1019         }
1020     }
1021     public void handleMotionNotify(XEvent xev) {
1022     }
1023     public void handleXCrossingEvent(XEvent xev) {
1024     }
1025     public void handleConfigureNotifyEvent(XEvent xev) {
1026         XConfigureEvent xe = xev.get_xconfigure();
1027         insLog.finer("Configure, {0}", xe);
1028         x = xe.get_x();
1029         y = xe.get_y();
1030         width = xe.get_width();
1031         height = xe.get_height();
1032     }
1033     /**
1034      * Checks ButtonRelease released all Mouse buttons
1035      */
1036     static boolean isFullRelease(int buttonState, int button) {
1037         final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
1038 
1039         if (button < 0 || button > buttonsNumber) {
1040             return buttonState == 0;
1041         } else {
1042             return buttonState == XConstants.buttonsMask[button - 1];
1043         }
1044     }
1045 
1046     static boolean isGrabbedEvent(XEvent ev, XBaseWindow target) {
1047         switch (ev.get_type()) {
1048           case XConstants.ButtonPress:
1049           case XConstants.ButtonRelease:
1050           case XConstants.MotionNotify:
1051           case XConstants.KeyPress:
1052           case XConstants.KeyRelease:
1053               return true;
1054           case XConstants.LeaveNotify:
1055           case XConstants.EnterNotify:
1056               // We shouldn't dispatch this events to the grabbed components (see 6317481)
1057               // But this logic is important if the grabbed component is top-level (see realSync)
1058               return (target instanceof XWindowPeer);
1059           default:
1060               return false;
1061         }
1062     }
1063     /**
1064      * Dispatches event to the grab Window or event source window depending
1065      * on whether the grab is active and on the event type
1066      */
1067     static void dispatchToWindow(XEvent ev) {
1068         XBaseWindow target = XAwtState.getGrabWindow();
1069         if (target == null || !isGrabbedEvent(ev, target)) {
1070             target = XToolkit.windowToXWindow(ev.get_xany().get_window());
1071         }
1072         if (target != null && target.checkInitialised()) {
1073             target.dispatchEvent(ev);
1074         }
1075     }
1076 
1077     public void dispatchEvent(XEvent xev) {
1078         if (eventLog.isLoggable(PlatformLogger.FINEST)) eventLog.finest(xev.toString());
1079         int type = xev.get_type();
1080 
1081         if (isDisposed()) {
1082             return;
1083         }
1084 
1085         switch (type)
1086         {
1087           case XConstants.VisibilityNotify:
1088               handleVisibilityEvent(xev);
1089               break;
1090           case XConstants.ClientMessage:
1091               handleClientMessage(xev);
1092               break;
1093           case XConstants.Expose :
1094           case XConstants.GraphicsExpose :
1095               handleExposeEvent(xev);
1096               break;
1097           case XConstants.ButtonPress:
1098           case XConstants.ButtonRelease:
1099               handleButtonPressRelease(xev);
1100               break;
1101 
1102           case XConstants.MotionNotify:
1103               handleMotionNotify(xev);
1104               break;
1105           case XConstants.KeyPress:
1106               handleKeyPress(xev);
1107               break;
1108           case XConstants.KeyRelease:
1109               handleKeyRelease(xev);
1110               break;
1111           case XConstants.EnterNotify:
1112           case XConstants.LeaveNotify:
1113               handleXCrossingEvent(xev);
1114               break;
1115           case XConstants.ConfigureNotify:
1116               handleConfigureNotifyEvent(xev);
1117               break;
1118           case XConstants.MapNotify:
1119               handleMapNotifyEvent(xev);
1120               break;
1121           case XConstants.UnmapNotify:
1122               handleUnmapNotifyEvent(xev);
1123               break;
1124           case XConstants.ReparentNotify:
1125               handleReparentNotifyEvent(xev);
1126               break;
1127           case XConstants.PropertyNotify:
1128               handlePropertyNotify(xev);
1129               break;
1130           case XConstants.DestroyNotify:
1131               handleDestroyNotify(xev);
1132               break;
1133           case XConstants.CreateNotify:
1134               handleCreateNotify(xev);
1135               break;
1136         }
1137     }
1138     protected boolean isEventDisabled(XEvent e) {
1139         return false;
1140     }
1141 
1142     int getX() {
1143         return x;
1144     }
1145 
1146     int getY() {
1147         return y;
1148     }
1149 
1150     int getWidth() {
1151         return width;
1152     }
1153 
1154     int getHeight() {
1155         return height;
1156     }
1157 
1158     void setDisposed(boolean d) {
1159         disposed = d;
1160     }
1161 
1162     boolean isDisposed() {
1163         return disposed;
1164     }
1165 
1166     public int getAbsoluteX() {
1167         XBaseWindow pw = getParentWindow();
1168         if (pw != null) {
1169             return pw.getAbsoluteX() + getX();
1170         } else {
1171             // Overridden for top-levels as their (x,y) is Java (x, y), not native location
1172             return getX();
1173         }
1174     }
1175 
1176     public int getAbsoluteY() {
1177         XBaseWindow pw = getParentWindow();
1178         if (pw != null) {
1179             return pw.getAbsoluteY() + getY();
1180         } else {
1181             return getY();
1182         }
1183     }
1184 
1185     public XBaseWindow getParentWindow() {
1186         return parentWindow;
1187     }
1188 
1189     public XWindowPeer getToplevelXWindow() {
1190         XBaseWindow bw = this;
1191         while (bw != null && !(bw instanceof XWindowPeer)) {
1192             bw = bw.getParentWindow();
1193         }
1194         return (XWindowPeer)bw;
1195     }
1196     public String toString() {
1197         return super.toString() + "(" + Long.toString(getWindow(), 16) + ")";
1198     }
1199 
1200     /**
1201      * Returns whether the given point is inside of the window.  Coordinates are local.
1202      */
1203     public boolean contains(int x, int y) {
1204         return x >= 0 && y >= 0 && x < getWidth() && y < getHeight();
1205     }
1206 
1207     /**
1208      * Returns whether the given point is inside of the window.  Coordinates are global.
1209      */
1210     public boolean containsGlobal(int x, int y) {
1211         return x >= getAbsoluteX() && y >= getAbsoluteY() && x < (getAbsoluteX()+getWidth()) && y < (getAbsoluteY()+getHeight());
1212     }
1213 
1214 }