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