1 /*
   2  * Copyright 2003-2008 Sun Microsystems, Inc.  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.  Sun designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22  * CA 95054 USA or visit www.sun.com if you need additional information or
  23  * have any questions.
  24  */
  25 
  26 package sun.awt.X11;
  27 
  28 import java.awt.*;
  29 import sun.awt.*;
  30 import java.util.logging.*;
  31 import java.util.*;
  32 
  33 public class XBaseWindow {
  34     private static final Logger log = Logger.getLogger("sun.awt.X11.XBaseWindow");
  35     private static final Logger insLog = Logger.getLogger("sun.awt.X11.insets.XBaseWindow");
  36     private static final Logger eventLog = Logger.getLogger("sun.awt.X11.event.XBaseWindow");
  37     private static final Logger focusLog = Logger.getLogger("sun.awt.X11.focus.XBaseWindow");
  38     private static final Logger grabLog = Logger.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 = XConstants.None;
  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(Level.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.log(Level.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                 
 336                 Rectangle bounds = (Rectangle)params.get(BOUNDS);
 337                 this.x = bounds.x;
 338                 this.y = bounds.y;
 339                 this.width = bounds.width;
 340                 this.height = bounds.height;
 341 
 342                 Integer depth = (Integer)params.get(DEPTH);
 343                 Integer visual_class = (Integer)params.get(VISUAL_CLASS);
 344                 Long visual = (Long)params.get(VISUAL);
 345                 Boolean overrideRedirect = (Boolean)params.get(OVERRIDE_REDIRECT);
 346                 if (overrideRedirect != null) {
 347                     xattr.set_override_redirect(overrideRedirect.booleanValue());
 348                     value_mask |= XConstants.CWOverrideRedirect;
 349                 }
 350 
 351                 Boolean saveUnder = (Boolean)params.get(SAVE_UNDER);
 352                 if (saveUnder != null) {
 353                     xattr.set_save_under(saveUnder.booleanValue());
 354                     value_mask |= XConstants.CWSaveUnder;
 355                 }
 356 
 357                 Integer backingStore = (Integer)params.get(BACKING_STORE);
 358                 if (backingStore != null) {
 359                     xattr.set_backing_store(backingStore.intValue());
 360                     value_mask |= XConstants.CWBackingStore;
 361                 }
 362 
 363                 Integer bitGravity = (Integer)params.get(BIT_GRAVITY);
 364                 if (bitGravity != null) {
 365                     xattr.set_bit_gravity(bitGravity.intValue());
 366                     value_mask |= XConstants.CWBitGravity;
 367                 }
 368 
 369                 if (log.isLoggable(Level.FINE)) {
 370                     log.fine("Creating window for " + this + " with the following attributes: \n" + params);
 371                 }
 372                 window = XlibWrapper.XCreateWindow(XToolkit.getDisplay(),
 373                                    parentWindow.longValue(),
 374                                    bounds.x, bounds.y, // location
 375                                    bounds.width, bounds.height, // size
 376                                    0, // border
 377                                    depth.intValue(), // depth
 378                                    visual_class.intValue(), // class
 379                                    visual.longValue(), // visual
 380                                    value_mask,  // value mask
 381                                    xattr.pData); // attributes
 382 
 383                 if (window == 0) {
 384                     throw new IllegalStateException("Couldn't create window because of wrong parameters. Run with NOISY_AWT to see details");
 385                 }
 386                 XToolkit.addToWinMap(window, this);
 387             } finally {
 388                 xattr.dispose();
 389             }
 390         } finally {
 391             XToolkit.awtUnlock();
 392         }
 393     }
 394 
 395     public XCreateWindowParams getDelayedParams() {
 396         return delayedParams;
 397     }
 398 
 399     protected String getWMName() {
 400         return XToolkit.getCorrectXIDString(getClass().getName());
 401     }
 402 
 403     protected void initClientLeader() {
 404         XToolkit.awtLock();
 405         try {
 406             if (wm_client_leader == null) {
 407                 wm_client_leader = XAtom.get("WM_CLIENT_LEADER");
 408             }
 409             wm_client_leader.setWindowProperty(this, getXAWTRootWindow());
 410         } finally {
 411             XToolkit.awtUnlock();
 412         }
 413     }
 414 
 415     static XRootWindow getXAWTRootWindow() {
 416         return XRootWindow.getInstance();
 417     }
 418 
 419     void destroy() {
 420         XToolkit.awtLock();
 421         try {
 422             if (hints != null) {
 423                 XlibWrapper.XFree(hints.pData);
 424                 hints = null;
 425             }
 426             XToolkit.removeFromWinMap(getWindow(), this);
 427             XlibWrapper.XDestroyWindow(XToolkit.getDisplay(), getWindow());
 428             if (XPropertyCache.isCachingSupported()) {
 429                 XPropertyCache.clearCache(window);
 430             }
 431             window = -1;
 432             if( !isDisposed() ) {
 433                 setDisposed( true );
 434             }
 435 
 436             XAwtState.getGrabWindow(); // Magic - getGrabWindow clear state if grabbing window is disposed of.
 437         } finally {
 438             XToolkit.awtUnlock();
 439         }
 440     }
 441 
 442     void flush() {
 443         XToolkit.awtLock();
 444         try {
 445             XlibWrapper.XFlush(XToolkit.getDisplay());
 446         } finally {
 447             XToolkit.awtUnlock();
 448         }
 449     }
 450 
 451     /**
 452      * Helper function to set W
 453      */
 454     public final void setWMHints(XWMHints hints) {
 455         XToolkit.awtLock();
 456         try {
 457             XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
 458         } finally {
 459             XToolkit.awtUnlock();
 460         }
 461     }
 462 
 463     public XWMHints getWMHints() {
 464         if (wmHints == null) {
 465             wmHints = new XWMHints(XlibWrapper.XAllocWMHints());
 466 //              XlibWrapper.XGetWMHints(XToolkit.getDisplay(),
 467 //                                      getWindow(),
 468 //                                      wmHints.pData);
 469         }
 470         return wmHints;
 471     }
 472 
 473 
 474     /*
 475      * Call this method under AWTLock.
 476      * The lock should be acquired untill all operations with XSizeHints are completed.
 477      */
 478     public XSizeHints getHints() {
 479         if (hints == null) {
 480             long p_hints = XlibWrapper.XAllocSizeHints();
 481             hints = new XSizeHints(p_hints);
 482 //              XlibWrapper.XGetWMNormalHints(XToolkit.getDisplay(), getWindow(), p_hints, XlibWrapper.larg1);
 483             // TODO: Shouldn't we listen for WM updates on this property?
 484         }
 485         return hints;
 486     }
 487 
 488     public void setSizeHints(long flags, int x, int y, int width, int height) {
 489         if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting hints, flags " + XlibWrapper.hintsToString(flags));
 490         XToolkit.awtLock();
 491         try {
 492             XSizeHints hints = getHints();
 493             // Note: if PPosition is not set in flags this means that
 494             // we want to reset PPosition in hints.  This is necessary
 495             // for locationByPlatform functionality
 496             if ((flags & XUtilConstants.PPosition) != 0) {
 497                 hints.set_x(x);
 498                 hints.set_y(y);
 499             }
 500             if ((flags & XUtilConstants.PSize) != 0) {
 501                 hints.set_width(width);
 502                 hints.set_height(height);
 503             } else if ((hints.get_flags() & XUtilConstants.PSize) != 0) {
 504                 flags |= XUtilConstants.PSize;
 505             }
 506             if ((flags & XUtilConstants.PMinSize) != 0) {
 507                 hints.set_min_width(width);
 508                 hints.set_min_height(height);
 509             } else if ((hints.get_flags() & XUtilConstants.PMinSize) != 0) {
 510                 flags |= XUtilConstants.PMinSize;
 511                 //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
 512                 //We don't need to reset minimum size if it's already set
 513             }
 514             if ((flags & XUtilConstants.PMaxSize) != 0) {
 515                 if (maxBounds != null) {
 516                     if (maxBounds.width != Integer.MAX_VALUE) {
 517                         hints.set_max_width(maxBounds.width);
 518                     } else {
 519                         hints.set_max_width(XToolkit.getDefaultScreenWidth());
 520                     }
 521                     if (maxBounds.height != Integer.MAX_VALUE) {
 522                         hints.set_max_height(maxBounds.height);
 523                     } else {
 524                         hints.set_max_height(XToolkit.getDefaultScreenHeight());
 525                     }
 526                 } else {
 527                     hints.set_max_width(width);
 528                     hints.set_max_height(height);
 529                 }
 530             } else if ((hints.get_flags() & XUtilConstants.PMaxSize) != 0) {
 531                 flags |= XUtilConstants.PMaxSize;
 532                 if (maxBounds != null) {
 533                     if (maxBounds.width != Integer.MAX_VALUE) {
 534                         hints.set_max_width(maxBounds.width);
 535                     } else {
 536                         hints.set_max_width(XToolkit.getDefaultScreenWidth());
 537                     }
 538                     if (maxBounds.height != Integer.MAX_VALUE) {
 539                         hints.set_max_height(maxBounds.height);
 540                     } else {
 541                         hints.set_max_height(XToolkit.getDefaultScreenHeight());
 542                     }
 543                 } else {
 544                     // Leave intact
 545                 }
 546             }
 547             flags |= XUtilConstants.PWinGravity;
 548             hints.set_flags(flags);
 549             hints.set_win_gravity((int)XConstants.NorthWestGravity);
 550             if (insLog.isLoggable(Level.FINER)) insLog.finer("Setting hints, resulted flags " + XlibWrapper.hintsToString(flags) +
 551                                                              ", values " + hints);
 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(Level.FINER)) focusLog.finer("XSetInputFocus on " + Long.toHexString(getWindow()) + " with time " + time);
 603             XlibWrapper.XSetInputFocus2(XToolkit.getDisplay(), getWindow(), time);
 604         } finally {
 605             XToolkit.awtUnlock();
 606         }
 607     }
 608     public void xRequestFocus() {
 609         XToolkit.awtLock();
 610         try {
 611             if (focusLog.isLoggable(Level.FINER)) focusLog.finer("XSetInputFocus on " + Long.toHexString(getWindow()));
 612              XlibWrapper.XSetInputFocus(XToolkit.getDisplay(), getWindow());
 613         } finally {
 614             XToolkit.awtUnlock();
 615         }
 616     }
 617 
 618     public static long xGetInputFocus() {
 619         XToolkit.awtLock();
 620         try {
 621             return XlibWrapper.XGetInputFocus(XToolkit.getDisplay());
 622         } finally {
 623             XToolkit.awtUnlock();
 624         }
 625     }
 626 
 627     public void xSetVisible(boolean visible) {
 628         if (log.isLoggable(Level.FINE)) log.fine("Setting visible on " + this + " to " + visible);
 629         XToolkit.awtLock();
 630         try {
 631             this.visible = visible;
 632             if (visible) {
 633                 XlibWrapper.XMapWindow(XToolkit.getDisplay(), getWindow());
 634             }
 635             else {
 636                 XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), getWindow());
 637             }
 638             XlibWrapper.XFlush(XToolkit.getDisplay());
 639         } finally {
 640             XToolkit.awtUnlock();
 641         }
 642     }
 643 
 644     boolean isMapped() {
 645         return mapped;
 646     }
 647 
 648     void updateWMName() {
 649         String name = getWMName();
 650         XToolkit.awtLock();
 651         try {
 652             if (name == null) {
 653                 name = " ";
 654             }
 655             XAtom nameAtom = XAtom.get(XAtom.XA_WM_NAME);
 656             nameAtom.setProperty(getWindow(), name);
 657             XAtom netNameAtom = XAtom.get("_NET_WM_NAME");
 658             netNameAtom.setPropertyUTF8(getWindow(), name);
 659         } finally {
 660             XToolkit.awtUnlock();
 661         }
 662     }
 663     void setWMClass(String[] cl) {
 664         if (cl.length != 2) {
 665             throw new IllegalArgumentException("WM_CLASS_NAME consists of exactly two strings");
 666         }
 667         XToolkit.awtLock();
 668         try {
 669             XAtom xa = XAtom.get(XAtom.XA_WM_CLASS);
 670             xa.setProperty8(getWindow(), cl[0] + '\0' + cl[1]);
 671         } finally {
 672             XToolkit.awtUnlock();
 673         }
 674     }
 675 
 676     boolean isVisible() {
 677         return visible;
 678     }
 679 
 680     static long getScreenOfWindow(long window) {
 681         XToolkit.awtLock();
 682         try {
 683             return XlibWrapper.getScreenOfWindow(XToolkit.getDisplay(), window);
 684         } finally {
 685             XToolkit.awtUnlock();
 686         }
 687     }
 688     long getScreenNumber() {
 689         XToolkit.awtLock();
 690         try {
 691             return XlibWrapper.XScreenNumberOfScreen(getScreen());
 692         } finally {
 693             XToolkit.awtUnlock();
 694         }
 695     }
 696 
 697     long getScreen() {
 698         if (screen == -1) { // Not initialized
 699             screen = getScreenOfWindow(window);
 700         }
 701         return screen;
 702     }
 703 
 704     public void xSetBounds(Rectangle bounds) {
 705         xSetBounds(bounds.x, bounds.y, bounds.width, bounds.height);
 706     }
 707 
 708     public void xSetBounds(int x, int y, int width, int height) {
 709         if (getWindow() == 0) {
 710             insLog.warning("Attempt to resize uncreated window");
 711             throw new IllegalStateException("Attempt to resize uncreated window");
 712         }
 713         insLog.fine("Setting bounds on " + this + " to (" + x + ", " + y + "), " + width + "x" + height);
 714         if (width <= 0) {
 715             width = 1;
 716         }
 717         if (height <= 0) {
 718             height = 1;
 719         }
 720         XToolkit.awtLock();
 721         try {
 722              XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getWindow(), x,y,width,height);
 723         } finally {
 724             XToolkit.awtUnlock();
 725         }
 726     }
 727 
 728     /**
 729      * Translate coordinates from one window into another.  Optimized
 730      * for XAWT - uses cached data when possible.  Preferable over
 731      * pure XTranslateCoordinates.
 732      * @return coordinates relative to dst, or null if error happened
 733      */
 734     static Point toOtherWindow(long src, long dst, int x, int y) {
 735         Point rpt = new Point(0, 0);
 736 
 737         // Check if both windows belong to XAWT - then no X calls are necessary
 738 
 739         XBaseWindow srcPeer = XToolkit.windowToXWindow(src);
 740         XBaseWindow dstPeer = XToolkit.windowToXWindow(dst);
 741 
 742         if (srcPeer != null && dstPeer != null) {
 743             // (x, y) is relative to src
 744             rpt.x = x + srcPeer.getAbsoluteX() - dstPeer.getAbsoluteX();
 745             rpt.y = y + srcPeer.getAbsoluteY() - dstPeer.getAbsoluteY();
 746         } else if (dstPeer != null && XlibUtil.isRoot(src, dstPeer.getScreenNumber())) {
 747             // from root into peer
 748             rpt.x = x - dstPeer.getAbsoluteX();
 749             rpt.y = y - dstPeer.getAbsoluteY();
 750         } else if (srcPeer != null && XlibUtil.isRoot(dst, srcPeer.getScreenNumber())) {
 751             // from peer into root
 752             rpt.x = x + srcPeer.getAbsoluteX();
 753             rpt.y = y + srcPeer.getAbsoluteY();
 754         } else {
 755             rpt = XlibUtil.translateCoordinates(src, dst, new Point(x, y));
 756         }
 757         return rpt;
 758     }
 759 
 760     /*
 761      * Convert to global coordinates.
 762      */
 763     Rectangle toGlobal(Rectangle rec) {
 764         Point p = toGlobal(rec.getLocation());
 765         Rectangle newRec = new Rectangle(rec);
 766         if (p != null) {
 767             newRec.setLocation(p);
 768         }
 769         return newRec;
 770     }
 771 
 772     Point toGlobal(Point pt) {
 773         Point p = toGlobal(pt.x, pt.y);
 774         if (p != null) {
 775             return p;
 776         } else {
 777             return new Point(pt);
 778         }
 779     }
 780 
 781     Point toGlobal(int x, int y) {
 782         long root;
 783         XToolkit.awtLock();
 784         try {
 785             root = XlibWrapper.RootWindow(XToolkit.getDisplay(),
 786                     getScreenNumber());
 787         } finally {
 788             XToolkit.awtUnlock();
 789         }
 790         Point p = toOtherWindow(getContentWindow(), root, x, y);
 791         if (p != null) {
 792             return p;
 793         } else {
 794             return new Point(x, y);
 795         }
 796     }
 797 
 798     /*
 799      * Convert to local coordinates.
 800      */
 801     Point toLocal(Point pt) {
 802         Point p = toLocal(pt.x, pt.y);
 803         if (p != null) {
 804             return p;
 805         } else {
 806             return new Point(pt);
 807         }
 808     }
 809 
 810     Point toLocal(int x, int y) {
 811         long root;
 812         XToolkit.awtLock();
 813         try {
 814             root = XlibWrapper.RootWindow(XToolkit.getDisplay(),
 815                     getScreenNumber());
 816         } finally {
 817             XToolkit.awtUnlock();
 818         }
 819         Point p = toOtherWindow(root, getContentWindow(), x, y);
 820         if (p != null) {
 821             return p;
 822         } else {
 823             return new Point(x, y);
 824         }
 825     }
 826 
 827     /**
 828      * We should always grab both keyboard and pointer to control event flow
 829      * on popups. This also simplifies synthetic grab implementation.
 830      * The active grab overrides activated automatic grab.
 831      */
 832     public boolean grabInput() {
 833         grabLog.log(Level.FINE, "Grab input on {0}", new Object[] {this});
 834 
 835         XToolkit.awtLock();
 836         try {
 837             if (XAwtState.getGrabWindow() == this &&
 838                 XAwtState.isManualGrab())
 839             {
 840                 grabLog.fine("    Already Grabbed");
 841                 return true;
 842             }
 843             //6273031: PIT. Choice drop down does not close once it is right clicked to show a popup menu
 844             //remember previous window having grab and if it's not null ungrab it.
 845             XBaseWindow prevGrabWindow = XAwtState.getGrabWindow();
 846             final int eventMask = (int) (XConstants.ButtonPressMask | XConstants.ButtonReleaseMask
 847                 | XConstants.EnterWindowMask | XConstants.LeaveWindowMask | XConstants.PointerMotionMask
 848                 | XConstants.ButtonMotionMask);
 849             final int ownerEvents = 1;
 850 
 851 
 852             //6714678: IDE (Netbeans, Eclipse, JDeveloper) Debugger hangs
 853             //process on Linux
 854             //The user must pass the sun.awt.disablegrab property to disable
 855             //taking grabs. This prevents hanging of the GUI when a breakpoint
 856             //is hit while a popup window taking the grab is open.
 857             if (!XToolkit.getSunAwtDisableGrab()) {
 858                 int ptrGrab = XlibWrapper.XGrabPointer(XToolkit.getDisplay(),
 859                         getContentWindow(), ownerEvents, eventMask, XConstants.GrabModeAsync,
 860                         XConstants.GrabModeAsync, XConstants.None, (XWM.isMotif() ? XToolkit.arrowCursor : XConstants.None),
 861                         XConstants.CurrentTime);
 862                 // Check grab results to be consistent with X server grab
 863                 if (ptrGrab != XConstants.GrabSuccess) {
 864                     XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime);
 865                     XAwtState.setGrabWindow(null);
 866                     grabLog.fine("    Grab Failure - mouse");
 867                     return false;
 868                 }
 869 
 870                 int keyGrab = XlibWrapper.XGrabKeyboard(XToolkit.getDisplay(),
 871                         getContentWindow(), ownerEvents, XConstants.GrabModeAsync, XConstants.GrabModeAsync,
 872                         XConstants.CurrentTime);
 873                 if (keyGrab != XConstants.GrabSuccess) {
 874                     XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime);
 875                     XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(), XConstants.CurrentTime);
 876                     XAwtState.setGrabWindow(null);
 877                     grabLog.fine("    Grab Failure - keyboard");
 878                     return false;
 879                 }
 880             }
 881             if (prevGrabWindow != null) {
 882                 prevGrabWindow.ungrabInputImpl();
 883             }
 884             XAwtState.setGrabWindow(this);
 885             grabLog.fine("    Grab - success");
 886             return true;
 887         } finally {
 888             XToolkit.awtUnlock();
 889         }
 890     }
 891 
 892     static void ungrabInput() {
 893         XToolkit.awtLock();
 894         try {
 895             XBaseWindow grabWindow = XAwtState.getGrabWindow();
 896             grabLog.log(Level.FINE, "UnGrab input on {0}", new Object[] {grabWindow});
 897             if (grabWindow != null) {
 898                 grabWindow.ungrabInputImpl();
 899                 if (!XToolkit.getSunAwtDisableGrab()) {
 900                     XlibWrapper.XUngrabPointer(XToolkit.getDisplay(), XConstants.CurrentTime);
 901                     XlibWrapper.XUngrabKeyboard(XToolkit.getDisplay(), XConstants.CurrentTime);
 902                 }
 903                 XAwtState.setGrabWindow(null);
 904                 // we need to call XFlush() here to force ungrab
 905                 // see 6384219 for details
 906                 XlibWrapper.XFlush(XToolkit.getDisplay());
 907             }
 908         } finally {
 909             XToolkit.awtUnlock();
 910         }
 911     }
 912 
 913     // called from ungrabInput, used in popup windows to hide theirselfs in ungrabbing
 914     void ungrabInputImpl() {
 915     }
 916 
 917     static void checkSecurity() {
 918         if (XToolkit.isSecurityWarningEnabled() && XToolkit.isToolkitThread()) {
 919             StackTraceElement stack[] = (new Throwable()).getStackTrace();
 920             log.warning(stack[1] + ": Security violation: calling user code on toolkit thread");
 921         }
 922     }
 923 
 924     public Set<Long> getChildren() {
 925         synchronized (getStateLock()) {
 926             return new HashSet<Long>(children);
 927         }
 928     }
 929 
 930     // -------------- Event handling ----------------
 931     public void handleMapNotifyEvent(XEvent xev) {
 932         if (xev.get_xany().get_window() == getWindow()) {
 933             mapped = true;
 934         }
 935     }
 936     public void handleUnmapNotifyEvent(XEvent xev) {
 937         if (xev.get_xany().get_window() == getWindow()) {
 938             mapped = false;
 939         }
 940     }
 941     public void handleReparentNotifyEvent(XEvent xev) {
 942         if (eventLog.isLoggable(Level.FINER)) {
 943             XReparentEvent msg = xev.get_xreparent();
 944             eventLog.finer(msg.toString());
 945         }
 946     }
 947     public void handlePropertyNotify(XEvent xev) {
 948         XPropertyEvent msg = xev.get_xproperty();
 949         if (XPropertyCache.isCachingSupported()) {
 950             XPropertyCache.clearCache(window, XAtom.get(msg.get_atom()));
 951         }
 952         if (eventLog.isLoggable(Level.FINER)) {
 953             eventLog.log(Level.FINER, "{0}", new Object[] {msg});
 954         }
 955     }
 956 
 957     public void handleDestroyNotify(XEvent xev) {
 958         XAnyEvent xany = xev.get_xany();
 959         if (xany.get_window() == getWindow()) {
 960             XToolkit.removeFromWinMap(getWindow(), this);
 961             if (XPropertyCache.isCachingSupported()) {
 962                 XPropertyCache.clearCache(getWindow());
 963             }
 964         }
 965         if (xany.get_window() != getWindow()) {
 966             synchronized (getStateLock()) {
 967                 children.remove(xany.get_window());
 968             }
 969         }
 970     }
 971 
 972     public void handleCreateNotify(XEvent xev) {
 973         XAnyEvent xany = xev.get_xany();
 974         if (xany.get_window() != getWindow()) {
 975             synchronized (getStateLock()) {
 976                 children.add(xany.get_window());
 977             }
 978         }
 979     }
 980 
 981     public void handleClientMessage(XEvent xev) {
 982         if (eventLog.isLoggable(Level.FINER)) {
 983             XClientMessageEvent msg = xev.get_xclient();
 984             eventLog.finer(msg.toString());
 985         }
 986     }
 987 
 988     public void handleVisibilityEvent(XEvent xev) {
 989     }
 990     public void handleKeyPress(XEvent xev) {
 991     }
 992     public void handleKeyRelease(XEvent xev) {
 993     }
 994     public void handleExposeEvent(XEvent xev) {
 995     }
 996     /**
 997      * Activate automatic grab on first ButtonPress,
 998      * deactivate on full mouse release
 999      */
1000     public void handleButtonPressRelease(XEvent xev) {
1001         XButtonEvent xbe = xev.get_xbutton();
1002         /*
1003          * Ignore the buttons above 20 due to the bit limit for
1004          * InputEvent.BUTTON_DOWN_MASK.
1005          * One more bit is reserved for FIRST_HIGH_BIT.
1006          */
1007         if (xbe.get_button() > SunToolkit.MAX_BUTTONS_SUPPORTED) {
1008             return;
1009         }
1010         int buttonState = 0;
1011         final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
1012         for (int i = 0; i<buttonsNumber; i++){
1013             // A bug in WM implementation: extra buttons doesn't have state!=0 as they should on Release message.
1014             if ((i != 4) && (i != 5)){
1015                 buttonState |= (xbe.get_state() & XConstants.buttonsMask[i]);
1016             }
1017         }
1018         switch (xev.get_type()) {
1019         case XConstants.ButtonPress:
1020             if (buttonState == 0) {
1021                 XAwtState.setAutoGrabWindow(this);
1022             }
1023             break;
1024         case XConstants.ButtonRelease:
1025             if (isFullRelease(buttonState, xbe.get_button())) {
1026                 XAwtState.setAutoGrabWindow(null);
1027             }
1028             break;
1029         }
1030     }
1031     public void handleMotionNotify(XEvent xev) {
1032     }
1033     public void handleXCrossingEvent(XEvent xev) {
1034     }
1035     public void handleConfigureNotifyEvent(XEvent xev) {
1036         XConfigureEvent xe = xev.get_xconfigure();
1037         insLog.log(Level.FINER, "Configure, {0}",
1038                    new Object[] {xe});
1039 
1040         if (xe.get_window() != getWindow()) {
1041             return;
1042         }
1043 
1044         x = xe.get_x();
1045         y = xe.get_y();
1046         width = xe.get_width();
1047         height = xe.get_height();
1048     }
1049     /**
1050      * Checks ButtonRelease released all Mouse buttons
1051      */
1052     static boolean isFullRelease(int buttonState, int button) {
1053         final int buttonsNumber = ((SunToolkit)(Toolkit.getDefaultToolkit())).getNumberOfButtons();
1054 
1055         if (button < 0 || button > buttonsNumber) {
1056             return buttonState == 0;
1057         } else {
1058             return buttonState == XConstants.buttonsMask[button - 1];
1059         }
1060     }
1061 
1062     static boolean isGrabbedEvent(XEvent ev, XBaseWindow target) {
1063         switch (ev.get_type()) {
1064           case XConstants.ButtonPress:
1065           case XConstants.ButtonRelease:
1066           case XConstants.MotionNotify:
1067           case XConstants.KeyPress:
1068           case XConstants.KeyRelease:
1069               return true;
1070           case XConstants.LeaveNotify:
1071           case XConstants.EnterNotify:
1072               // We shouldn't dispatch this events to the grabbed components (see 6317481)
1073               // But this logic is important if the grabbed component is top-level (see realSync)
1074               return (target instanceof XWindowPeer);
1075           default:
1076               return false;
1077         }
1078     }
1079     /**
1080      * Dispatches event to the grab Window or event source window depending
1081      * on whether the grab is active and on the event type
1082      */
1083     static void dispatchToWindow(XEvent ev) {
1084         XBaseWindow target = XAwtState.getGrabWindow();
1085         if (target == null || !isGrabbedEvent(ev, target)) {
1086             target = XToolkit.windowToXWindow(ev.get_xany().get_window());
1087         }
1088         if (target != null && target.checkInitialised()) {
1089             target.dispatchEvent(ev);
1090         }
1091     }
1092 
1093     public void dispatchEvent(XEvent xev) {
1094         if (eventLog.isLoggable(Level.FINEST)) eventLog.finest(xev.toString());
1095         int type = xev.get_type();
1096 
1097         if (isDisposed()) {
1098             return;
1099         }
1100 
1101         switch (type)
1102         {
1103           case XConstants.VisibilityNotify:
1104               handleVisibilityEvent(xev);
1105               break;
1106           case XConstants.ClientMessage:
1107               handleClientMessage(xev);
1108               break;
1109           case XConstants.Expose :
1110           case XConstants.GraphicsExpose :
1111               handleExposeEvent(xev);
1112               break;
1113           case XConstants.ButtonPress:
1114           case XConstants.ButtonRelease:
1115               handleButtonPressRelease(xev);
1116               break;
1117 
1118           case XConstants.MotionNotify:
1119               handleMotionNotify(xev);
1120               break;
1121           case XConstants.KeyPress:
1122               handleKeyPress(xev);
1123               break;
1124           case XConstants.KeyRelease:
1125               handleKeyRelease(xev);
1126               break;
1127           case XConstants.EnterNotify:
1128           case XConstants.LeaveNotify:
1129               handleXCrossingEvent(xev);
1130               break;
1131           case XConstants.ConfigureNotify:
1132               handleConfigureNotifyEvent(xev);
1133               break;
1134           case XConstants.MapNotify:
1135               handleMapNotifyEvent(xev);
1136               break;
1137           case XConstants.UnmapNotify:
1138               handleUnmapNotifyEvent(xev);
1139               break;
1140           case XConstants.ReparentNotify:
1141               handleReparentNotifyEvent(xev);
1142               break;
1143           case XConstants.PropertyNotify:
1144               handlePropertyNotify(xev);
1145               break;
1146           case XConstants.DestroyNotify:
1147               handleDestroyNotify(xev);
1148               break;
1149           case XConstants.CreateNotify:
1150               handleCreateNotify(xev);
1151               break;
1152         }
1153     }
1154     protected boolean isEventDisabled(XEvent e) {
1155         return false;
1156     }
1157 
1158     int getX() {
1159         return x;
1160     }
1161 
1162     int getY() {
1163         return y;
1164     }
1165 
1166     int getWidth() {
1167         return width;
1168     }
1169 
1170     int getHeight() {
1171         return height;
1172     }
1173 
1174     void setDisposed(boolean d) {
1175         disposed = d;
1176     }
1177 
1178     boolean isDisposed() {
1179         return disposed;
1180     }
1181 
1182     public int getAbsoluteX() {
1183         XBaseWindow pw = getParentWindow();
1184         if (pw != null) {
1185             return pw.getAbsoluteX() + getX();
1186         } else {
1187             // Overridden for top-levels as their (x,y) is Java (x, y), not native location
1188             return getX();
1189         }
1190     }
1191 
1192     public int getAbsoluteY() {
1193         XBaseWindow pw = getParentWindow();
1194         if (pw != null) {
1195             return pw.getAbsoluteY() + getY();
1196         } else {
1197             return getY();
1198         }
1199     }
1200 
1201     public XBaseWindow getParentWindow() {
1202         return parentWindow;
1203     }
1204 
1205     public XWindowPeer getToplevelXWindow() {
1206         XBaseWindow bw = this;
1207         while (bw != null && !(bw instanceof XWindowPeer)) {
1208             bw = bw.getParentWindow();
1209         }
1210         return (XWindowPeer)bw;
1211     }
1212     public String toString() {
1213         return super.toString() + "(" + Long.toString(getWindow(), 16) + ")";
1214     }
1215 
1216     /**
1217      * Returns whether the given point is inside of the window.  Coordinates are local.
1218      */
1219     public boolean contains(int x, int y) {
1220         return x >= 0 && y >= 0 && x < getWidth() && y < getHeight();
1221     }
1222 
1223     /**
1224      * Returns whether the given point is inside of the window.  Coordinates are global.
1225      */
1226     public boolean containsGlobal(int x, int y) {
1227         return x >= getAbsoluteX() && y >= getAbsoluteY() && x < (getAbsoluteX()+getWidth()) && y < (getAbsoluteY()+getHeight());
1228     }
1229 
1230 }