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