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