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