1 /*
   2  * Copyright (c) 2002, 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 package sun.awt.X11;
  26 
  27 import java.awt.*;
  28 
  29 import java.awt.event.ComponentEvent;
  30 import java.awt.event.FocusEvent;
  31 import java.awt.event.WindowEvent;
  32 
  33 import java.awt.peer.ComponentPeer;
  34 import java.awt.peer.WindowPeer;
  35 
  36 import java.io.UnsupportedEncodingException;
  37 
  38 import java.security.AccessController;
  39 import java.security.PrivilegedAction;
  40 
  41 import java.util.ArrayList;
  42 import java.util.HashSet;
  43 import java.util.Iterator;
  44 import java.util.Set;
  45 import java.util.Vector;
  46 
  47 import java.util.concurrent.atomic.AtomicBoolean;
  48 
  49 import sun.util.logging.PlatformLogger;
  50 
  51 import sun.awt.AWTAccessor;
  52 import sun.awt.DisplayChangedListener;
  53 import sun.awt.SunToolkit;
  54 import sun.awt.X11GraphicsDevice;
  55 import sun.awt.X11GraphicsEnvironment;
  56 import sun.awt.IconInfo;
  57 
  58 import sun.java2d.pipe.Region;
  59 
  60 class XWindowPeer extends XPanelPeer implements WindowPeer,
  61                                                 DisplayChangedListener {
  62 
  63     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XWindowPeer");
  64     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XWindowPeer");
  65     private static final PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XWindowPeer");
  66     private static final PlatformLogger grabLog = PlatformLogger.getLogger("sun.awt.X11.grab.XWindowPeer");
  67     private static final PlatformLogger iconLog = PlatformLogger.getLogger("sun.awt.X11.icon.XWindowPeer");
  68 
  69     // should be synchronized on awtLock
  70     private static Set<XWindowPeer> windows = new HashSet<XWindowPeer>();
  71 
  72 
  73     private boolean cachedFocusableWindow;
  74     XWarningWindow warningWindow;
  75 
  76     private boolean alwaysOnTop;
  77     private boolean locationByPlatform;
  78 
  79     Dialog modalBlocker;
  80     boolean delayedModalBlocking = false;
  81     Dimension targetMinimumSize = null;
  82 
  83     private XWindowPeer ownerPeer;
  84 
  85     // used for modal blocking to keep existing z-order
  86     protected XWindowPeer prevTransientFor, nextTransientFor;
  87     // value of WM_TRANSIENT_FOR hint set on this window
  88     private XWindowPeer curRealTransientFor;
  89 
  90     private boolean grab = false; // Whether to do a grab during showing
  91 
  92     private boolean isMapped = false; // Is this window mapped or not
  93     private boolean mustControlStackPosition = false; // Am override-redirect not on top
  94     private XEventDispatcher rootPropertyEventDispatcher = null;
  95 
  96     private static final AtomicBoolean isStartupNotificationRemoved = new AtomicBoolean();
  97 
  98     /*
  99      * Focus related flags
 100      */
 101     private boolean isUnhiding = false;             // Is the window unhiding.
 102     private boolean isBeforeFirstMapNotify = false; // Is the window (being shown) between
 103                                                     //    setVisible(true) & handleMapNotify().
 104 
 105     /**
 106      * The type of the window.
 107      *
 108      * The type is supposed to be immutable while the peer object exists.
 109      * The value gets initialized in the preInit() method.
 110      */
 111     private Window.Type windowType = Window.Type.NORMAL;
 112 
 113     public final Window.Type getWindowType() {
 114         return windowType;
 115     }
 116 
 117     // It need to be accessed from XFramePeer.
 118     protected Vector <ToplevelStateListener> toplevelStateListeners = new Vector<ToplevelStateListener>();
 119     XWindowPeer(XCreateWindowParams params) {
 120         super(params.putIfNull(PARENT_WINDOW, Long.valueOf(0)));
 121     }
 122 
 123     XWindowPeer(Window target) {
 124         super(new XCreateWindowParams(new Object[] {
 125             TARGET, target,
 126             PARENT_WINDOW, Long.valueOf(0)}));
 127     }
 128 
 129     /*
 130      * This constant defines icon size recommended for using.
 131      * Apparently, we should use XGetIconSizes which should
 132      * return icon sizes would be most appreciated by the WM.
 133      * However, XGetIconSizes always returns 0 for some reason.
 134      * So the constant has been introduced.
 135      */
 136     private static final int PREFERRED_SIZE_FOR_ICON = 128;
 137 
 138     /*
 139      * Sometimes XChangeProperty(_NET_WM_ICON) doesn't work if
 140      * image buffer is too large. This constant holds maximum
 141      * length of buffer which can be used with _NET_WM_ICON hint.
 142      * It holds int's value.
 143      */
 144     private static final int MAXIMUM_BUFFER_LENGTH_NET_WM_ICON = (2<<15) - 1;
 145 
 146     void preInit(XCreateWindowParams params) {
 147         target = (Component)params.get(TARGET);
 148         windowType = ((Window)target).getType();
 149         params.put(REPARENTED,
 150                    Boolean.valueOf(isOverrideRedirect() || isSimpleWindow()));
 151         super.preInit(params);
 152         params.putIfNull(BIT_GRAVITY, Integer.valueOf(XConstants.NorthWestGravity));
 153 
 154         long eventMask = 0;
 155         if (params.containsKey(EVENT_MASK)) {
 156             eventMask = ((Long)params.get(EVENT_MASK));
 157         }
 158         eventMask |= XConstants.VisibilityChangeMask;
 159         params.put(EVENT_MASK, eventMask);
 160 
 161         XA_NET_WM_STATE = XAtom.get("_NET_WM_STATE");
 162 
 163 
 164         params.put(OVERRIDE_REDIRECT, Boolean.valueOf(isOverrideRedirect()));
 165 
 166         SunToolkit.awtLock();
 167         try {
 168             windows.add(this);
 169         } finally {
 170             SunToolkit.awtUnlock();
 171         }
 172 
 173         cachedFocusableWindow = isFocusableWindow();
 174 
 175         Font f = target.getFont();
 176         if (f == null) {
 177             f = XWindow.getDefaultFont();
 178             target.setFont(f);
 179             // we should not call setFont because it will call a repaint
 180             // which the peer may not be ready to do yet.
 181         }
 182         Color c = target.getBackground();
 183         if (c == null) {
 184             Color background = SystemColor.window;
 185             target.setBackground(background);
 186             // we should not call setBackGround because it will call a repaint
 187             // which the peer may not be ready to do yet.
 188         }
 189         c = target.getForeground();
 190         if (c == null) {
 191             target.setForeground(SystemColor.windowText);
 192             // we should not call setForeGround because it will call a repaint
 193             // which the peer may not be ready to do yet.
 194         }
 195 
 196         alwaysOnTop = ((Window)target).isAlwaysOnTop() && ((Window)target).isAlwaysOnTopSupported();
 197 
 198         GraphicsConfiguration gc = getGraphicsConfiguration();
 199         ((X11GraphicsDevice)gc.getDevice()).addDisplayChangedListener(this);
 200     }
 201 
 202     protected String getWMName() {
 203         String name = target.getName();
 204         if (name == null || name.trim().equals("")) {
 205             name = " ";
 206         }
 207         return name;
 208     }
 209 
 210     private static native String getLocalHostname();
 211     private static native int getJvmPID();
 212 
 213     @SuppressWarnings("deprecation")
 214     void postInit(XCreateWindowParams params) {
 215         super.postInit(params);
 216 
 217         // Init WM_PROTOCOLS atom
 218         initWMProtocols();
 219 
 220         // Set _NET_WM_PID and WM_CLIENT_MACHINE using this JVM
 221         XAtom.get("WM_CLIENT_MACHINE").setProperty(getWindow(), getLocalHostname());
 222         XAtom.get("_NET_WM_PID").setCard32Property(getWindow(), getJvmPID());
 223 
 224         // Set WM_TRANSIENT_FOR and group_leader
 225         Window t_window = (Window)target;
 226         Window owner = t_window.getOwner();
 227         if (owner != null) {
 228             ownerPeer = (XWindowPeer)owner.getPeer();
 229             if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
 230                 focusLog.finer("Owner is " + owner);
 231                 focusLog.finer("Owner peer is " + ownerPeer);
 232                 focusLog.finer("Owner X window " + Long.toHexString(ownerPeer.getWindow()));
 233                 focusLog.finer("Owner content X window " + Long.toHexString(ownerPeer.getContentWindow()));
 234             }
 235             // as owner window may be an embedded window, we must get a toplevel window
 236             // to set as TRANSIENT_FOR hint
 237             long ownerWindow = ownerPeer.getWindow();
 238             if (ownerWindow != 0) {
 239                 XToolkit.awtLock();
 240                 try {
 241                     // Set WM_TRANSIENT_FOR
 242                     if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
 243                         focusLog.fine("Setting transient on " + Long.toHexString(getWindow())
 244                                       + " for " + Long.toHexString(ownerWindow));
 245                     }
 246                     setToplevelTransientFor(this, ownerPeer, false, true);
 247 
 248                     // Set group leader
 249                     XWMHints hints = getWMHints();
 250                     hints.set_flags(hints.get_flags() | (int)XUtilConstants.WindowGroupHint);
 251                     hints.set_window_group(ownerWindow);
 252                     XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
 253                 }
 254                 finally {
 255                     XToolkit.awtUnlock();
 256                 }
 257             }
 258         }
 259 
 260         if (owner != null || isSimpleWindow()) {
 261             XNETProtocol protocol = XWM.getWM().getNETProtocol();
 262             if (protocol != null && protocol.active()) {
 263                 XToolkit.awtLock();
 264                 try {
 265                     XAtomList net_wm_state = getNETWMState();
 266                     net_wm_state.add(protocol.XA_NET_WM_STATE_SKIP_TASKBAR);
 267                     setNETWMState(net_wm_state);
 268                 } finally {
 269                     XToolkit.awtUnlock();
 270                 }
 271 
 272             }
 273         }
 274 
 275          // Init warning window(for applets)
 276         if (((Window)target).getWarningString() != null) {
 277             // accessSystemTray permission allows to display TrayIcon, TrayIcon tooltip
 278             // and TrayIcon balloon windows without a warning window.
 279             if (!AWTAccessor.getWindowAccessor().isTrayIconWindow((Window)target)) {
 280                 warningWindow = new XWarningWindow((Window)target, getWindow(), this);
 281             }
 282         }
 283 
 284         setSaveUnder(true);
 285 
 286         updateIconImages();
 287 
 288         updateShape();
 289         updateOpacity();
 290         // no need in updateOpaque() as it is no-op
 291     }
 292 
 293     public void updateIconImages() {
 294         Window target = (Window)this.target;
 295         java.util.List<Image> iconImages = target.getIconImages();
 296         XWindowPeer ownerPeer = getOwnerPeer();
 297         winAttr.icons = new ArrayList<IconInfo>();
 298         if (iconImages.size() != 0) {
 299             //read icon images from target
 300             winAttr.iconsInherited = false;
 301             for (Iterator<Image> i = iconImages.iterator(); i.hasNext(); ) {
 302                 Image image = i.next();
 303                 if (image == null) {
 304                     if (log.isLoggable(PlatformLogger.Level.FINEST)) {
 305                         log.finest("XWindowPeer.updateIconImages: Skipping the image passed into Java because it's null.");
 306                     }
 307                     continue;
 308                 }
 309                 IconInfo iconInfo;
 310                 try {
 311                     iconInfo = new IconInfo(image);
 312                 } catch (Exception e){
 313                     if (log.isLoggable(PlatformLogger.Level.FINEST)) {
 314                         log.finest("XWindowPeer.updateIconImages: Perhaps the image passed into Java is broken. Skipping this icon.");
 315                     }
 316                     continue;
 317                 }
 318                 if (iconInfo.isValid()) {
 319                     winAttr.icons.add(iconInfo);
 320                 }
 321             }
 322         }
 323 
 324         // Fix for CR#6425089
 325         winAttr.icons = normalizeIconImages(winAttr.icons);
 326 
 327         if (winAttr.icons.size() == 0) {
 328             //target.icons is empty or all icon images are broken
 329             if (ownerPeer != null) {
 330                 //icon is inherited from parent
 331                 winAttr.iconsInherited = true;
 332                 winAttr.icons = ownerPeer.getIconInfo();
 333             } else {
 334                 //default icon is used
 335                 winAttr.iconsInherited = false;
 336                 winAttr.icons = getDefaultIconInfo();
 337             }
 338         }
 339         recursivelySetIcon(winAttr.icons);
 340     }
 341 
 342     /*
 343      * Sometimes XChangeProperty(_NET_WM_ICON) doesn't work if
 344      * image buffer is too large. This function help us accommodate
 345      * initial list of the icon images to certainly-acceptable.
 346      * It does scale some of these icons to appropriate size
 347      * if it's necessary.
 348      */
 349     static java.util.List<IconInfo> normalizeIconImages(java.util.List<IconInfo> icons) {
 350         java.util.List<IconInfo> result = new ArrayList<IconInfo>();
 351         int totalLength = 0;
 352         boolean haveLargeIcon = false;
 353 
 354         for (IconInfo icon : icons) {
 355             int width = icon.getWidth();
 356             int height = icon.getHeight();
 357             int length = icon.getRawLength();
 358 
 359             if (width > PREFERRED_SIZE_FOR_ICON || height > PREFERRED_SIZE_FOR_ICON) {
 360                 if (haveLargeIcon) {
 361                     continue;
 362                 }
 363                 int scaledWidth = width;
 364                 int scaledHeight = height;
 365                 while (scaledWidth > PREFERRED_SIZE_FOR_ICON ||
 366                        scaledHeight > PREFERRED_SIZE_FOR_ICON) {
 367                     scaledWidth = scaledWidth / 2;
 368                     scaledHeight = scaledHeight / 2;
 369                 }
 370 
 371                 icon.setScaledSize(scaledWidth, scaledHeight);
 372                 length = icon.getRawLength();
 373             }
 374 
 375             if (totalLength + length <= MAXIMUM_BUFFER_LENGTH_NET_WM_ICON) {
 376                 totalLength += length;
 377                 result.add(icon);
 378                 if (width > PREFERRED_SIZE_FOR_ICON || height > PREFERRED_SIZE_FOR_ICON) {
 379                     haveLargeIcon = true;
 380                 }
 381             }
 382         }
 383 
 384         if (iconLog.isLoggable(PlatformLogger.Level.FINEST)) {
 385             iconLog.finest(">>> Length_ of buffer of icons data: " + totalLength +
 386                            ", maximum length: " + MAXIMUM_BUFFER_LENGTH_NET_WM_ICON);
 387         }
 388 
 389         return result;
 390     }
 391 
 392     /*
 393      * Dumps each icon from the list
 394      */
 395     static void dumpIcons(java.util.List<IconInfo> icons) {
 396         if (iconLog.isLoggable(PlatformLogger.Level.FINEST)) {
 397             iconLog.finest(">>> Sizes of icon images:");
 398             for (Iterator<IconInfo> i = icons.iterator(); i.hasNext(); ) {
 399                 iconLog.finest("    {0}", i.next());
 400             }
 401         }
 402     }
 403 
 404     @SuppressWarnings("deprecation")
 405     public void recursivelySetIcon(java.util.List<IconInfo> icons) {
 406         dumpIcons(winAttr.icons);
 407         setIconHints(icons);
 408         Window target = (Window)this.target;
 409         Window[] children = target.getOwnedWindows();
 410         int cnt = children.length;
 411         for (int i = 0; i < cnt; i++) {
 412             ComponentPeer childPeer = children[i].getPeer();
 413             if (childPeer != null && childPeer instanceof XWindowPeer) {
 414                 if (((XWindowPeer)childPeer).winAttr.iconsInherited) {
 415                     ((XWindowPeer)childPeer).winAttr.icons = icons;
 416                     ((XWindowPeer)childPeer).recursivelySetIcon(icons);
 417                 }
 418             }
 419         }
 420     }
 421 
 422     java.util.List<IconInfo> getIconInfo() {
 423         return winAttr.icons;
 424     }
 425     void setIconHints(java.util.List<IconInfo> icons) {
 426         //This does nothing for XWindowPeer,
 427         //It's overriden in XDecoratedPeer
 428     }
 429 
 430     private static ArrayList<IconInfo> defaultIconInfo;
 431     protected synchronized static java.util.List<IconInfo> getDefaultIconInfo() {
 432         if (defaultIconInfo == null) {
 433             defaultIconInfo = new ArrayList<IconInfo>();
 434             if (XlibWrapper.dataModel == 32) {
 435                 defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon32_java_icon16_png.java_icon16_png));
 436                 defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon32_java_icon24_png.java_icon24_png));
 437                 defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon32_java_icon32_png.java_icon32_png));
 438                 defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon32_java_icon48_png.java_icon48_png));
 439             } else {
 440                 defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon64_java_icon16_png.java_icon16_png));
 441                 defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon64_java_icon24_png.java_icon24_png));
 442                 defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon64_java_icon32_png.java_icon32_png));
 443                 defaultIconInfo.add(new IconInfo(sun.awt.AWTIcon64_java_icon48_png.java_icon48_png));
 444             }
 445         }
 446         return defaultIconInfo;
 447     }
 448 
 449     private void updateShape() {
 450         // Shape shape = ((Window)target).getShape();
 451         Shape shape = AWTAccessor.getWindowAccessor().getShape((Window)target);
 452         if (shape != null) {
 453             applyShape(Region.getInstance(shape, null));
 454         }
 455     }
 456 
 457     private void updateOpacity() {
 458         // float opacity = ((Window)target).getOpacity();
 459         float opacity = AWTAccessor.getWindowAccessor().getOpacity((Window)target);
 460         if (opacity < 1.0f) {
 461             setOpacity(opacity);
 462         }
 463     }
 464 
 465     public void updateMinimumSize() {
 466         //This function only saves minimumSize value in XWindowPeer
 467         //Setting WMSizeHints is implemented in XDecoratedPeer
 468         targetMinimumSize = (target.isMinimumSizeSet()) ?
 469             target.getMinimumSize() : null;
 470     }
 471 
 472     public Dimension getTargetMinimumSize() {
 473         return (targetMinimumSize == null) ? null : new Dimension(targetMinimumSize);
 474     }
 475 
 476     public XWindowPeer getOwnerPeer() {
 477         return ownerPeer;
 478     }
 479 
 480     //Fix for 6318144: PIT:Setting Min Size bigger than current size enlarges
 481     //the window but fails to revalidate, Sol-CDE
 482     //This bug is regression for
 483     //5025858: Resizing a decorated frame triggers componentResized event twice.
 484     //Since events are not posted from Component.setBounds we need to send them here.
 485     //Note that this function is overriden in XDecoratedPeer so event
 486     //posting is not changing for decorated peers
 487     public void setBounds(int x, int y, int width, int height, int op) {
 488         XToolkit.awtLock();
 489         try {
 490             Rectangle oldBounds = getBounds();
 491 
 492             super.setBounds(x, y, width, height, op);
 493 
 494             Rectangle bounds = getBounds();
 495 
 496             XSizeHints hints = getHints();
 497             setSizeHints(hints.get_flags() | XUtilConstants.PPosition | XUtilConstants.PSize,
 498                              bounds.x, bounds.y, bounds.width, bounds.height);
 499             XWM.setMotifDecor(this, false, 0, 0);
 500 
 501             boolean isResized = !bounds.getSize().equals(oldBounds.getSize());
 502             boolean isMoved = !bounds.getLocation().equals(oldBounds.getLocation());
 503             if (isMoved || isResized) {
 504                 repositionSecurityWarning();
 505             }
 506             if (isResized) {
 507                 postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_RESIZED));
 508             }
 509             if (isMoved) {
 510                 postEventToEventQueue(new ComponentEvent(getEventSource(), ComponentEvent.COMPONENT_MOVED));
 511             }
 512         } finally {
 513             XToolkit.awtUnlock();
 514         }
 515     }
 516 
 517     void updateFocusability() {
 518         updateFocusableWindowState();
 519         XToolkit.awtLock();
 520         try {
 521             XWMHints hints = getWMHints();
 522             hints.set_flags(hints.get_flags() | (int)XUtilConstants.InputHint);
 523             hints.set_input(false/*isNativelyNonFocusableWindow() ? (0):(1)*/);
 524             XlibWrapper.XSetWMHints(XToolkit.getDisplay(), getWindow(), hints.pData);
 525         }
 526         finally {
 527             XToolkit.awtUnlock();
 528         }
 529     }
 530 
 531     public Insets getInsets() {
 532         return new Insets(0, 0, 0, 0);
 533     }
 534 
 535     // NOTE: This method may be called by privileged threads.
 536     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 537     public void handleIconify() {
 538         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_ICONIFIED));
 539     }
 540 
 541     // NOTE: This method may be called by privileged threads.
 542     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 543     public void handleDeiconify() {
 544         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_DEICONIFIED));
 545     }
 546 
 547     // NOTE: This method may be called by privileged threads.
 548     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 549     public void handleStateChange(int oldState, int newState) {
 550         postEvent(new WindowEvent((Window)target,
 551                                   WindowEvent.WINDOW_STATE_CHANGED,
 552                                   oldState, newState));
 553     }
 554 
 555     /**
 556      * DEPRECATED:  Replaced by getInsets().
 557      */
 558     public Insets insets() {
 559         return getInsets();
 560     }
 561 
 562     boolean isAutoRequestFocus() {
 563         if (XToolkit.isToolkitThread()) {
 564             return AWTAccessor.getWindowAccessor().isAutoRequestFocus((Window)target);
 565         } else {
 566             return ((Window)target).isAutoRequestFocus();
 567         }
 568     }
 569 
 570     /*
 571      * Retrives real native focused window and converts it into Java peer.
 572      */
 573     static XWindowPeer getNativeFocusedWindowPeer() {
 574         XBaseWindow baseWindow = XToolkit.windowToXWindow(xGetInputFocus());
 575         return (baseWindow instanceof XWindowPeer) ? (XWindowPeer)baseWindow :
 576                (baseWindow instanceof XFocusProxyWindow) ?
 577                ((XFocusProxyWindow)baseWindow).getOwner() : null;
 578     }
 579 
 580     /*
 581      * Retrives real native focused window and converts it into Java window.
 582      */
 583     static Window getNativeFocusedWindow() {
 584         XWindowPeer peer = getNativeFocusedWindowPeer();
 585         return peer != null ? (Window)peer.target : null;
 586     }
 587 
 588     boolean isFocusableWindow() {
 589         if (XToolkit.isToolkitThread() || SunToolkit.isAWTLockHeldByCurrentThread())
 590         {
 591             return cachedFocusableWindow;
 592         } else {
 593             return ((Window)target).isFocusableWindow();
 594         }
 595     }
 596 
 597     /* WARNING: don't call client code in this method! */
 598     boolean isFocusedWindowModalBlocker() {
 599         return false;
 600     }
 601 
 602     long getFocusTargetWindow() {
 603         return getContentWindow();
 604     }
 605 
 606     /**
 607      * Returns whether or not this window peer has native X window
 608      * configured as non-focusable window. It might happen if:
 609      * - Java window is non-focusable
 610      * - Java window is simple Window(not Frame or Dialog)
 611      */
 612     boolean isNativelyNonFocusableWindow() {
 613         if (XToolkit.isToolkitThread() || SunToolkit.isAWTLockHeldByCurrentThread())
 614         {
 615             return isSimpleWindow() || !cachedFocusableWindow;
 616         } else {
 617             return isSimpleWindow() || !(((Window)target).isFocusableWindow());
 618         }
 619     }
 620 
 621     public void handleWindowFocusIn_Dispatch() {
 622         if (EventQueue.isDispatchThread()) {
 623             XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target);
 624             WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
 625             SunToolkit.setSystemGenerated(we);
 626             target.dispatchEvent(we);
 627         }
 628     }
 629 
 630     public void handleWindowFocusInSync(long serial) {
 631         WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
 632         XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target);
 633         sendEvent(we);
 634     }
 635     // NOTE: This method may be called by privileged threads.
 636     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 637     public void handleWindowFocusIn(long serial) {
 638         WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_GAINED_FOCUS);
 639         /* wrap in Sequenced, then post*/
 640         XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow((Window) target);
 641         postEvent(wrapInSequenced((AWTEvent) we));
 642     }
 643 
 644     // NOTE: This method may be called by privileged threads.
 645     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 646     public void handleWindowFocusOut(Window oppositeWindow, long serial) {
 647         WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
 648         XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(null);
 649         XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null);
 650         /* wrap in Sequenced, then post*/
 651         postEvent(wrapInSequenced((AWTEvent) we));
 652     }
 653     public void handleWindowFocusOutSync(Window oppositeWindow, long serial) {
 654         WindowEvent we = new WindowEvent((Window)target, WindowEvent.WINDOW_LOST_FOCUS, oppositeWindow);
 655         XKeyboardFocusManagerPeer.getInstance().setCurrentFocusedWindow(null);
 656         XKeyboardFocusManagerPeer.getInstance().setCurrentFocusOwner(null);
 657         sendEvent(we);
 658     }
 659 
 660 /* --- DisplayChangedListener Stuff --- */
 661 
 662     /* Xinerama
 663      * called to check if we've been moved onto a different screen
 664      * Based on checkNewXineramaScreen() in awt_GraphicsEnv.c
 665      */
 666     public void checkIfOnNewScreen(Rectangle newBounds) {
 667         if (!XToolkit.localEnv.runningXinerama()) {
 668             return;
 669         }
 670 
 671         if (log.isLoggable(PlatformLogger.Level.FINEST)) {
 672             log.finest("XWindowPeer: Check if we've been moved to a new screen since we're running in Xinerama mode");
 673         }
 674 
 675         int area = newBounds.width * newBounds.height;
 676         int intAmt, vertAmt, horizAmt;
 677         int largestAmt = 0;
 678         int curScreenNum = ((X11GraphicsDevice)getGraphicsConfiguration().getDevice()).getScreen();
 679         int newScreenNum = 0;
 680         GraphicsDevice gds[] = XToolkit.localEnv.getScreenDevices();
 681         GraphicsConfiguration newGC = null;
 682         Rectangle screenBounds;
 683 
 684         for (int i = 0; i < gds.length; i++) {
 685             screenBounds = gds[i].getDefaultConfiguration().getBounds();
 686             if (newBounds.intersects(screenBounds)) {
 687                 horizAmt = Math.min(newBounds.x + newBounds.width,
 688                                     screenBounds.x + screenBounds.width) -
 689                            Math.max(newBounds.x, screenBounds.x);
 690                 vertAmt = Math.min(newBounds.y + newBounds.height,
 691                                    screenBounds.y + screenBounds.height)-
 692                           Math.max(newBounds.y, screenBounds.y);
 693                 intAmt = horizAmt * vertAmt;
 694                 if (intAmt == area) {
 695                     // Completely on this screen - done!
 696                     newScreenNum = i;
 697                     newGC = gds[i].getDefaultConfiguration();
 698                     break;
 699                 }
 700                 if (intAmt > largestAmt) {
 701                     largestAmt = intAmt;
 702                     newScreenNum = i;
 703                     newGC = gds[i].getDefaultConfiguration();
 704                 }
 705             }
 706         }
 707         if (newScreenNum != curScreenNum) {
 708             if (log.isLoggable(PlatformLogger.Level.FINEST)) {
 709                 log.finest("XWindowPeer: Moved to a new screen");
 710             }
 711             executeDisplayChangedOnEDT(newGC);
 712         }
 713     }
 714 
 715     /**
 716      * Helper method that executes the displayChanged(screen) method on
 717      * the event dispatch thread.  This method is used in the Xinerama case
 718      * and after display mode change events.
 719      */
 720     private void executeDisplayChangedOnEDT(final GraphicsConfiguration gc) {
 721         Runnable dc = new Runnable() {
 722             public void run() {
 723                 AWTAccessor.getComponentAccessor().
 724                     setGraphicsConfiguration(target, gc);
 725             }
 726         };
 727         SunToolkit.executeOnEventHandlerThread(target, dc);
 728     }
 729 
 730     /**
 731      * From the DisplayChangedListener interface; called from
 732      * X11GraphicsDevice when the display mode has been changed.
 733      */
 734     public void displayChanged() {
 735         executeDisplayChangedOnEDT(getGraphicsConfiguration());
 736     }
 737 
 738     /**
 739      * From the DisplayChangedListener interface; top-levels do not need
 740      * to react to this event.
 741      */
 742     public void paletteChanged() {
 743     }
 744 
 745     private Point queryXLocation()
 746     {
 747         return XlibUtil.translateCoordinates(
 748             getContentWindow(),
 749             XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()),
 750             new Point(0, 0));
 751     }
 752 
 753     protected Point getNewLocation(XConfigureEvent xe, int leftInset, int topInset) {
 754         // Bounds of the window
 755         Rectangle targetBounds = AWTAccessor.getComponentAccessor().getBounds(target);
 756 
 757         int runningWM = XWM.getWMID();
 758         Point newLocation = targetBounds.getLocation();
 759         if (xe.get_send_event() || runningWM == XWM.NO_WM || XWM.isNonReparentingWM()) {
 760             // Location, Client size + insets
 761             newLocation = new Point(xe.get_x() - leftInset, xe.get_y() - topInset);
 762         } else {
 763             // ICCCM 4.1.5 states that a real ConfigureNotify will be sent when
 764             // a window is resized but the client can not tell if the window was
 765             // moved or not. The client should consider the position as unkown
 766             // and use TranslateCoordinates to find the actual position.
 767             //
 768             // TODO this should be the default for every case.
 769             switch (runningWM) {
 770                 case XWM.CDE_WM:
 771                 case XWM.MOTIF_WM:
 772                 case XWM.METACITY_WM:
 773                 case XWM.MUTTER_WM:
 774                 case XWM.SAWFISH_WM:
 775                 {
 776                     Point xlocation = queryXLocation();
 777                     if (log.isLoggable(PlatformLogger.Level.FINE)) {
 778                         log.fine("New X location: {0}", xlocation);
 779                     }
 780                     if (xlocation != null) {
 781                         newLocation = xlocation;
 782                     }
 783                     break;
 784                 }
 785                 default:
 786                     break;
 787             }
 788         }
 789         return newLocation;
 790     }
 791 
 792     /*
 793      * Overridden to check if we need to update our GraphicsDevice/Config
 794      * Added for 4934052.
 795      */
 796     @Override
 797     public void handleConfigureNotifyEvent(XEvent xev) {
 798         XConfigureEvent xe = xev.get_xconfigure();
 799         /*
 800          * Correct window location which could be wrong in some cases.
 801          * See getNewLocation() for the details.
 802          */
 803         Point newLocation = getNewLocation(xe, 0, 0);
 804         xe.set_x(newLocation.x);
 805         xe.set_y(newLocation.y);
 806         checkIfOnNewScreen(new Rectangle(xe.get_x(),
 807                                          xe.get_y(),
 808                                          xe.get_width(),
 809                                          xe.get_height()));
 810 
 811         // Don't call super until we've handled a screen change.  Otherwise
 812         // there could be a race condition in which a ComponentListener could
 813         // see the old screen.
 814         super.handleConfigureNotifyEvent(xev);
 815         repositionSecurityWarning();
 816     }
 817 
 818     final void requestXFocus(long time) {
 819         requestXFocus(time, true);
 820     }
 821 
 822     final void requestXFocus() {
 823         requestXFocus(0, false);
 824     }
 825 
 826     /**
 827      * Requests focus to this top-level. Descendants should override to provide
 828      * implementations based on a class of top-level.
 829      */
 830     protected void requestXFocus(long time, boolean timeProvided) {
 831         // Since in XAWT focus is synthetic and all basic Windows are
 832         // override_redirect all we can do is check whether our parent
 833         // is active. If it is - we can freely synthesize focus transfer.
 834         // Luckily, this logic is already implemented in requestWindowFocus.
 835         if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
 836             focusLog.fine("Requesting window focus");
 837         }
 838         requestWindowFocus(time, timeProvided);
 839     }
 840 
 841     public final boolean focusAllowedFor() {
 842         if (isNativelyNonFocusableWindow()) {
 843             return false;
 844         }
 845 /*
 846         Window target = (Window)this.target;
 847         if (!target.isVisible() ||
 848             !target.isEnabled() ||
 849             !target.isFocusable())
 850         {
 851             return false;
 852         }
 853 */
 854         if (isModalBlocked()) {
 855             return false;
 856         }
 857         return true;
 858     }
 859 
 860     public void handleFocusEvent(XEvent xev) {
 861         XFocusChangeEvent xfe = xev.get_xfocus();
 862         FocusEvent fe;
 863         if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
 864             focusLog.fine("{0}", xfe);
 865         }
 866         if (isEventDisabled(xev)) {
 867             return;
 868         }
 869         if (xev.get_type() == XConstants.FocusIn)
 870         {
 871             // If this window is non-focusable don't post any java focus event
 872             if (focusAllowedFor()) {
 873                 if (xfe.get_mode() == XConstants.NotifyNormal // Normal notify
 874                     || xfe.get_mode() == XConstants.NotifyWhileGrabbed) // Alt-Tab notify
 875                 {
 876                     handleWindowFocusIn(xfe.get_serial());
 877                 }
 878             }
 879         }
 880         else
 881         {
 882             if (xfe.get_mode() == XConstants.NotifyNormal // Normal notify
 883                 || xfe.get_mode() == XConstants.NotifyWhileGrabbed) // Alt-Tab notify
 884             {
 885                 // If this window is non-focusable don't post any java focus event
 886                 if (!isNativelyNonFocusableWindow()) {
 887                     XWindowPeer oppositeXWindow = getNativeFocusedWindowPeer();
 888                     Object oppositeTarget = (oppositeXWindow!=null)? oppositeXWindow.getTarget() : null;
 889                     Window oppositeWindow = null;
 890                     if (oppositeTarget instanceof Window) {
 891                         oppositeWindow = (Window) oppositeTarget;
 892                     }
 893                     // Check if opposite window is non-focusable. In that case we don't want to
 894                     // post any event.
 895                     if (oppositeXWindow != null && oppositeXWindow.isNativelyNonFocusableWindow()) {
 896                         return;
 897                     }
 898                     if (this == oppositeXWindow) {
 899                         oppositeWindow = null;
 900                     } else if (oppositeXWindow instanceof XDecoratedPeer) {
 901                         if (((XDecoratedPeer) oppositeXWindow).actualFocusedWindow != null) {
 902                             oppositeXWindow = ((XDecoratedPeer) oppositeXWindow).actualFocusedWindow;
 903                             oppositeTarget = oppositeXWindow.getTarget();
 904                             if (oppositeTarget instanceof Window
 905                                 && oppositeXWindow.isVisible()
 906                                 && oppositeXWindow.isNativelyNonFocusableWindow())
 907                             {
 908                                 oppositeWindow = ((Window) oppositeTarget);
 909                             }
 910                         }
 911                     }
 912                     handleWindowFocusOut(oppositeWindow, xfe.get_serial());
 913                 }
 914             }
 915         }
 916     }
 917 
 918     void setSaveUnder(boolean state) {}
 919 
 920     public void toFront() {
 921         if (isOverrideRedirect() && mustControlStackPosition) {
 922             mustControlStackPosition = false;
 923             removeRootPropertyEventDispatcher();
 924         }
 925         if (isVisible()) {
 926             super.toFront();
 927             if (isFocusableWindow() && isAutoRequestFocus() &&
 928                 !isModalBlocked() && !isWithdrawn())
 929             {
 930                 requestInitialFocus();
 931             }
 932         } else {
 933             setVisible(true);
 934         }
 935     }
 936 
 937     public void toBack() {
 938         XToolkit.awtLock();
 939         try {
 940             if(!isOverrideRedirect()) {
 941                 XlibWrapper.XLowerWindow(XToolkit.getDisplay(), getWindow());
 942             }else{
 943                 lowerOverrideRedirect();
 944             }
 945         }
 946         finally {
 947             XToolkit.awtUnlock();
 948         }
 949     }
 950     private void lowerOverrideRedirect() {
 951         //
 952         // make new hash of toplevels of all windows from 'windows' hash.
 953         // FIXME: do not call them "toplevel" as it is misleading.
 954         //
 955         HashSet<Long> toplevels = new HashSet<>();
 956         long topl = 0, mytopl = 0;
 957 
 958         for (XWindowPeer xp : windows) {
 959             topl = getToplevelWindow( xp.getWindow() );
 960             if( xp.equals( this ) ) {
 961                 mytopl = topl;
 962             }
 963             if( topl > 0 )
 964                 toplevels.add( Long.valueOf( topl ) );
 965         }
 966 
 967         //
 968         // find in the root's tree:
 969         // (1) my toplevel, (2) lowest java toplevel, (3) desktop
 970         // We must enforce (3), (1), (2) order, upward;
 971         // note that nautilus on the next restacking will do (1),(3),(2).
 972         //
 973         long laux,     wDesktop = -1, wBottom = -1;
 974         int  iMy = -1, iDesktop = -1, iBottom = -1;
 975         int i = 0;
 976         XQueryTree xqt = new XQueryTree(XToolkit.getDefaultRootWindow());
 977         try {
 978             if( xqt.execute() > 0 ) {
 979                 int nchildren = xqt.get_nchildren();
 980                 long children = xqt.get_children();
 981                 for(i = 0; i < nchildren; i++) {
 982                     laux = Native.getWindow(children, i);
 983                     if( laux == mytopl ) {
 984                         iMy = i;
 985                     }else if( isDesktopWindow( laux ) ) {
 986                         // we need topmost desktop of them all.
 987                         iDesktop = i;
 988                         wDesktop = laux;
 989                     }else if(iBottom < 0 &&
 990                              toplevels.contains( Long.valueOf(laux) ) &&
 991                              laux != mytopl) {
 992                         iBottom = i;
 993                         wBottom = laux;
 994                     }
 995                 }
 996             }
 997 
 998             if( (iMy < iBottom || iBottom < 0 )&& iDesktop < iMy)
 999                 return; // no action necessary
1000 
1001             long to_restack = Native.allocateLongArray(2);
1002             Native.putLong(to_restack, 0, wBottom);
1003             Native.putLong(to_restack, 1,  mytopl);
1004             XlibWrapper.XRestackWindows(XToolkit.getDisplay(), to_restack, 2);
1005             XlibWrapper.unsafe.freeMemory(to_restack);
1006 
1007 
1008             if( !mustControlStackPosition ) {
1009                 mustControlStackPosition = true;
1010                 // add root window property listener:
1011                 // somebody (eg nautilus desktop) may obscure us
1012                 addRootPropertyEventDispatcher();
1013             }
1014         } finally {
1015             xqt.dispose();
1016         }
1017     }
1018     /**
1019         Get XID of closest to root window in a given window hierarchy.
1020         FIXME: do not call it "toplevel" as it is misleading.
1021         On error return 0.
1022     */
1023     private long getToplevelWindow( long w ) {
1024         long wi = w, ret, root;
1025         do {
1026             ret = wi;
1027             XQueryTree qt = new XQueryTree(wi);
1028             try {
1029                 if (qt.execute() == 0) {
1030                     return 0;
1031                 }
1032                 root = qt.get_root();
1033                 wi = qt.get_parent();
1034             } finally {
1035                 qt.dispose();
1036             }
1037 
1038         } while (wi != root);
1039 
1040         return ret;
1041     }
1042 
1043     private static boolean isDesktopWindow( long wi ) {
1044         return XWM.getWM().isDesktopWindow( wi );
1045     }
1046 
1047     private void updateAlwaysOnTop() {
1048         if (log.isLoggable(PlatformLogger.Level.FINE)) {
1049             log.fine("Promoting always-on-top state {0}", Boolean.valueOf(alwaysOnTop));
1050         }
1051         XWM.getWM().setLayer(this,
1052                              alwaysOnTop ?
1053                              XLayerProtocol.LAYER_ALWAYS_ON_TOP :
1054                              XLayerProtocol.LAYER_NORMAL);
1055     }
1056 
1057     public void updateAlwaysOnTopState() {
1058         this.alwaysOnTop = ((Window) this.target).isAlwaysOnTop();
1059         updateAlwaysOnTop();
1060     }
1061 
1062     boolean isLocationByPlatform() {
1063         return locationByPlatform;
1064     }
1065 
1066     private void promoteDefaultPosition() {
1067         this.locationByPlatform = ((Window)target).isLocationByPlatform();
1068         if (locationByPlatform) {
1069             XToolkit.awtLock();
1070             try {
1071                 Rectangle bounds = getBounds();
1072                 XSizeHints hints = getHints();
1073                 setSizeHints(hints.get_flags() & ~(XUtilConstants.USPosition | XUtilConstants.PPosition),
1074                              bounds.x, bounds.y, bounds.width, bounds.height);
1075             } finally {
1076                 XToolkit.awtUnlock();
1077             }
1078         }
1079     }
1080 
1081     public void setVisible(boolean vis) {
1082         if (!isVisible() && vis) {
1083             isBeforeFirstMapNotify = true;
1084             winAttr.initialFocus = isAutoRequestFocus();
1085             if (!winAttr.initialFocus) {
1086                 /*
1087                  * It's easier and safer to temporary suppress WM_TAKE_FOCUS
1088                  * protocol itself than to ignore WM_TAKE_FOCUS client message.
1089                  * Because we will have to make the difference between
1090                  * the message come after showing and the message come after
1091                  * activation. Also, on Metacity, for some reason, we have _two_
1092                  * WM_TAKE_FOCUS client messages when showing a frame/dialog.
1093                  */
1094                 suppressWmTakeFocus(true);
1095             }
1096         }
1097         updateFocusability();
1098         promoteDefaultPosition();
1099         if (!vis && warningWindow != null) {
1100             warningWindow.setSecurityWarningVisible(false, false);
1101         }
1102         super.setVisible(vis);
1103         if (!vis && !isWithdrawn()) {
1104             // ICCCM, 4.1.4. Changing Window State:
1105             // "Iconic -> Withdrawn - The client should unmap the window and follow it
1106             // with a synthetic UnmapNotify event as described later in this section."
1107             // The same is true for Normal -> Withdrawn
1108             XToolkit.awtLock();
1109             try {
1110                 XUnmapEvent unmap = new XUnmapEvent();
1111                 unmap.set_window(window);
1112                 unmap.set_event(XToolkit.getDefaultRootWindow());
1113                 unmap.set_type(XConstants.UnmapNotify);
1114                 unmap.set_from_configure(false);
1115                 XlibWrapper.XSendEvent(XToolkit.getDisplay(), XToolkit.getDefaultRootWindow(),
1116                         false, XConstants.SubstructureNotifyMask | XConstants.SubstructureRedirectMask,
1117                         unmap.pData);
1118                 unmap.dispose();
1119             }
1120             finally {
1121                 XToolkit.awtUnlock();
1122             }
1123         }
1124         // method called somewhere in parent does not generate configure-notify
1125         // event for override-redirect.
1126         // Ergo, no reshape and bugs like 5085647 in case setBounds was
1127         // called before setVisible.
1128         if (isOverrideRedirect() && vis) {
1129             updateChildrenSizes();
1130         }
1131         repositionSecurityWarning();
1132     }
1133 
1134     protected void suppressWmTakeFocus(boolean doSuppress) {
1135     }
1136 
1137     final boolean isSimpleWindow() {
1138         return !(target instanceof Frame || target instanceof Dialog);
1139     }
1140     boolean hasWarningWindow() {
1141         return ((Window)target).getWarningString() != null;
1142     }
1143 
1144     // The height of menu bar window
1145     int getMenuBarHeight() {
1146         return 0;
1147     }
1148 
1149     // Called when shell changes its size and requires children windows
1150     // to update their sizes appropriately
1151     void updateChildrenSizes() {
1152     }
1153 
1154     public void repositionSecurityWarning() {
1155         // NOTE: On KWin if the window/border snapping option is enabled,
1156         // the Java window may be swinging while it's being moved.
1157         // This doesn't make the application unusable though looks quite ugly.
1158         // Probobly we need to find some hint to assign to our Security
1159         // Warning window in order to exclude it from the snapping option.
1160         // We are not currently aware of existance of such a property.
1161         if (warningWindow != null) {
1162             // We can't use the coordinates stored in the XBaseWindow since
1163             // they are zeros for decorated frames.
1164             AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
1165             int x = compAccessor.getX(target);
1166             int y = compAccessor.getY(target);
1167             int width = compAccessor.getWidth(target);
1168             int height = compAccessor.getHeight(target);
1169             warningWindow.reposition(x, y, width, height);
1170         }
1171     }
1172 
1173     @Override
1174     protected void setMouseAbove(boolean above) {
1175         super.setMouseAbove(above);
1176         updateSecurityWarningVisibility();
1177     }
1178 
1179     @Override
1180     public void setFullScreenExclusiveModeState(boolean state) {
1181         super.setFullScreenExclusiveModeState(state);
1182         updateSecurityWarningVisibility();
1183     }
1184 
1185     public void updateSecurityWarningVisibility() {
1186         if (warningWindow == null) {
1187             return;
1188         }
1189 
1190         if (!isVisible()) {
1191             return; // The warning window should already be hidden.
1192         }
1193 
1194         boolean show = false;
1195 
1196         if (!isFullScreenExclusiveMode()) {
1197             int state = getWMState();
1198 
1199             // getWMState() always returns 0 (Withdrawn) for simple windows. Hence
1200             // we ignore the state for such windows.
1201             if (isVisible() && (state == XUtilConstants.NormalState || isSimpleWindow())) {
1202                 if (XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow() ==
1203                         getTarget())
1204                 {
1205                     show = true;
1206                 }
1207 
1208                 if (isMouseAbove() || warningWindow.isMouseAbove())
1209                 {
1210                     show = true;
1211                 }
1212             }
1213         }
1214 
1215         warningWindow.setSecurityWarningVisible(show, true);
1216     }
1217 
1218     boolean isOverrideRedirect() {
1219         return XWM.getWMID() == XWM.OPENLOOK_WM ||
1220             Window.Type.POPUP.equals(getWindowType());
1221     }
1222 
1223     final boolean isOLWMDecorBug() {
1224         return XWM.getWMID() == XWM.OPENLOOK_WM &&
1225             winAttr.nativeDecor == false;
1226     }
1227 
1228     public void dispose() {
1229         if (isGrabbed()) {
1230             if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
1231                 grabLog.fine("Generating UngrabEvent on {0} because of the window disposal", this);
1232             }
1233             postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
1234         }
1235 
1236         SunToolkit.awtLock();
1237 
1238         try {
1239             windows.remove(this);
1240         } finally {
1241             SunToolkit.awtUnlock();
1242         }
1243 
1244         if (warningWindow != null) {
1245             warningWindow.destroy();
1246         }
1247 
1248         removeRootPropertyEventDispatcher();
1249         mustControlStackPosition = false;
1250         super.dispose();
1251 
1252         /*
1253          * Fix for 6457980.
1254          * When disposing an owned Window we should implicitly
1255          * return focus to its decorated owner because it won't
1256          * receive WM_TAKE_FOCUS.
1257          */
1258         if (isSimpleWindow()) {
1259             if (target == XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow()) {
1260                 Window owner = getDecoratedOwner((Window)target);
1261                 ((XWindowPeer)AWTAccessor.getComponentAccessor().getPeer(owner)).requestWindowFocus();
1262             }
1263         }
1264     }
1265 
1266     boolean isResizable() {
1267         return winAttr.isResizable;
1268     }
1269 
1270     public void handleVisibilityEvent(XEvent xev) {
1271         super.handleVisibilityEvent(xev);
1272         XVisibilityEvent ve = xev.get_xvisibility();
1273         winAttr.visibilityState = ve.get_state();
1274 //         if (ve.get_state() == XlibWrapper.VisibilityUnobscured) {
1275 //             // raiseInputMethodWindow
1276 //         }
1277         repositionSecurityWarning();
1278     }
1279 
1280     void handleRootPropertyNotify(XEvent xev) {
1281         XPropertyEvent ev = xev.get_xproperty();
1282         if( mustControlStackPosition &&
1283             ev.get_atom() == XAtom.get("_NET_CLIENT_LIST_STACKING").getAtom()){
1284             // Restore stack order unhadled/spoiled by WM or some app (nautilus).
1285             // As of now, don't use any generic machinery: just
1286             // do toBack() again.
1287             if(isOverrideRedirect()) {
1288                 toBack();
1289             }
1290         }
1291     }
1292 
1293     private void removeStartupNotification() {
1294         if (isStartupNotificationRemoved.getAndSet(true)) {
1295             return;
1296         }
1297 
1298         final String desktopStartupId = AccessController.doPrivileged(new PrivilegedAction<String>() {
1299             public String run() {
1300                 return XToolkit.getEnv("DESKTOP_STARTUP_ID");
1301             }
1302         });
1303         if (desktopStartupId == null) {
1304             return;
1305         }
1306 
1307         final StringBuilder messageBuilder = new StringBuilder("remove: ID=");
1308         messageBuilder.append('"');
1309         for (int i = 0; i < desktopStartupId.length(); i++) {
1310             if (desktopStartupId.charAt(i) == '"' || desktopStartupId.charAt(i) == '\\') {
1311                 messageBuilder.append('\\');
1312             }
1313             messageBuilder.append(desktopStartupId.charAt(i));
1314         }
1315         messageBuilder.append('"');
1316         messageBuilder.append('\0');
1317         final byte[] message;
1318         try {
1319             message = messageBuilder.toString().getBytes("UTF-8");
1320         } catch (UnsupportedEncodingException cannotHappen) {
1321             return;
1322         }
1323 
1324         XClientMessageEvent req = null;
1325 
1326         XToolkit.awtLock();
1327         try {
1328             final XAtom netStartupInfoBeginAtom = XAtom.get("_NET_STARTUP_INFO_BEGIN");
1329             final XAtom netStartupInfoAtom = XAtom.get("_NET_STARTUP_INFO");
1330 
1331             req = new XClientMessageEvent();
1332             req.set_type(XConstants.ClientMessage);
1333             req.set_window(getWindow());
1334             req.set_message_type(netStartupInfoBeginAtom.getAtom());
1335             req.set_format(8);
1336 
1337             for (int pos = 0; pos < message.length; pos += 20) {
1338                 final int msglen = Math.min(message.length - pos, 20);
1339                 int i = 0;
1340                 for (; i < msglen; i++) {
1341                     XlibWrapper.unsafe.putByte(req.get_data() + i, message[pos + i]);
1342                 }
1343                 for (; i < 20; i++) {
1344                     XlibWrapper.unsafe.putByte(req.get_data() + i, (byte)0);
1345                 }
1346                 XlibWrapper.XSendEvent(XToolkit.getDisplay(),
1347                     XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber()),
1348                     false,
1349                     XConstants.PropertyChangeMask,
1350                     req.pData);
1351                 req.set_message_type(netStartupInfoAtom.getAtom());
1352             }
1353         } finally {
1354             XToolkit.awtUnlock();
1355             if (req != null) {
1356                 req.dispose();
1357             }
1358         }
1359     }
1360 
1361     public void handleMapNotifyEvent(XEvent xev) {
1362         removeStartupNotification();
1363 
1364         // See 6480534.
1365         isUnhiding |= isWMStateNetHidden();
1366 
1367         super.handleMapNotifyEvent(xev);
1368         if (!winAttr.initialFocus) {
1369             suppressWmTakeFocus(false); // restore the protocol.
1370             /*
1371              * For some reason, on Metacity, a frame/dialog being shown
1372              * without WM_TAKE_FOCUS protocol doesn't get moved to the front.
1373              * So, we do it evidently.
1374              */
1375             XToolkit.awtLock();
1376             try {
1377                 XlibWrapper.XRaiseWindow(XToolkit.getDisplay(), getWindow());
1378             } finally {
1379                 XToolkit.awtUnlock();
1380             }
1381         }
1382         if (shouldFocusOnMapNotify()) {
1383             focusLog.fine("Automatically request focus on window");
1384             requestInitialFocus();
1385         }
1386         isUnhiding = false;
1387         isBeforeFirstMapNotify = false;
1388         updateAlwaysOnTop();
1389 
1390         synchronized (getStateLock()) {
1391             if (!isMapped) {
1392                 isMapped = true;
1393             }
1394         }
1395     }
1396 
1397     public void handleUnmapNotifyEvent(XEvent xev) {
1398         super.handleUnmapNotifyEvent(xev);
1399 
1400         // On Metacity UnmapNotify comes before PropertyNotify (for _NET_WM_STATE_HIDDEN).
1401         // So we also check for the property later in MapNotify. See 6480534.
1402         isUnhiding |= isWMStateNetHidden();
1403 
1404         synchronized (getStateLock()) {
1405             if (isMapped) {
1406                 isMapped = false;
1407             }
1408         }
1409     }
1410 
1411     private boolean shouldFocusOnMapNotify() {
1412         boolean res = false;
1413 
1414         if (isBeforeFirstMapNotify) {
1415             res = (winAttr.initialFocus ||          // Window.autoRequestFocus
1416                    isFocusedWindowModalBlocker());
1417         } else {
1418             res = isUnhiding;                       // Unhiding
1419         }
1420         res = res &&
1421             isFocusableWindow() &&                  // General focusability
1422             !isModalBlocked();                      // Modality
1423 
1424         return res;
1425     }
1426 
1427     protected boolean isWMStateNetHidden() {
1428         XNETProtocol protocol = XWM.getWM().getNETProtocol();
1429         return (protocol != null && protocol.isWMStateNetHidden(this));
1430     }
1431 
1432     protected void requestInitialFocus() {
1433         requestXFocus();
1434     }
1435 
1436     public void addToplevelStateListener(ToplevelStateListener l){
1437         toplevelStateListeners.add(l);
1438     }
1439 
1440     public void removeToplevelStateListener(ToplevelStateListener l){
1441         toplevelStateListeners.remove(l);
1442     }
1443 
1444     /**
1445      * Override this methods to get notifications when top-level window state changes. The state is
1446      * meant in terms of ICCCM: WithdrawnState, IconicState, NormalState
1447      */
1448     @Override
1449     protected void stateChanged(long time, int oldState, int newState) {
1450         // Fix for 6401700, 6412803
1451         // If this window is modal blocked, it is put into the transient_for
1452         // chain using prevTransientFor and nextTransientFor hints. However,
1453         // the real WM_TRANSIENT_FOR hint shouldn't be set for windows in
1454         // different WM states (except for owner-window relationship), so
1455         // if the window changes its state, its real WM_TRANSIENT_FOR hint
1456         // should be updated accordingly.
1457         updateTransientFor();
1458 
1459         for (ToplevelStateListener topLevelListenerTmp : toplevelStateListeners) {
1460             topLevelListenerTmp.stateChangedICCCM(oldState, newState);
1461         }
1462 
1463         updateSecurityWarningVisibility();
1464     }
1465 
1466     boolean isWithdrawn() {
1467         return getWMState() == XUtilConstants.WithdrawnState;
1468     }
1469 
1470     boolean hasDecorations(int decor) {
1471         if (!winAttr.nativeDecor) {
1472             return false;
1473         }
1474         else {
1475             int myDecor = winAttr.decorations;
1476             boolean hasBits = ((myDecor & decor) == decor);
1477             if ((myDecor & XWindowAttributesData.AWT_DECOR_ALL) != 0)
1478                 return !hasBits;
1479             else
1480                 return hasBits;
1481         }
1482     }
1483 
1484     void setReparented(boolean newValue) {
1485         super.setReparented(newValue);
1486         XToolkit.awtLock();
1487         try {
1488             if (isReparented() && delayedModalBlocking) {
1489                 addToTransientFors((XDialogPeer) AWTAccessor.getComponentAccessor().getPeer(modalBlocker));
1490                 delayedModalBlocking = false;
1491             }
1492         } finally {
1493             XToolkit.awtUnlock();
1494         }
1495     }
1496 
1497     /*
1498      * Returns a Vector of all Java top-level windows,
1499      * sorted by their current Z-order
1500      */
1501     static Vector<XWindowPeer> collectJavaToplevels() {
1502         Vector<XWindowPeer> javaToplevels = new Vector<XWindowPeer>();
1503         Vector<Long> v = new Vector<Long>();
1504         X11GraphicsEnvironment ge =
1505             (X11GraphicsEnvironment)GraphicsEnvironment.getLocalGraphicsEnvironment();
1506         GraphicsDevice[] gds = ge.getScreenDevices();
1507         if (!ge.runningXinerama() && (gds.length > 1)) {
1508             for (GraphicsDevice gd : gds) {
1509                 int screen = ((X11GraphicsDevice)gd).getScreen();
1510                 long rootWindow = XlibWrapper.RootWindow(XToolkit.getDisplay(), screen);
1511                 v.add(rootWindow);
1512             }
1513         } else {
1514             v.add(XToolkit.getDefaultRootWindow());
1515         }
1516         final int windowsCount = windows.size();
1517         while ((v.size() > 0) && (javaToplevels.size() < windowsCount)) {
1518             long win = v.remove(0);
1519             XQueryTree qt = new XQueryTree(win);
1520             try {
1521                 if (qt.execute() != 0) {
1522                     int nchildren = qt.get_nchildren();
1523                     long children = qt.get_children();
1524                     // XQueryTree returns window children ordered by z-order
1525                     for (int i = 0; i < nchildren; i++) {
1526                         long child = Native.getWindow(children, i);
1527                         XBaseWindow childWindow = XToolkit.windowToXWindow(child);
1528                         // filter out Java non-toplevels
1529                         if ((childWindow != null) && !(childWindow instanceof XWindowPeer)) {
1530                             continue;
1531                         } else {
1532                             v.add(child);
1533                         }
1534                         if (childWindow instanceof XWindowPeer) {
1535                             XWindowPeer np = (XWindowPeer)childWindow;
1536                             javaToplevels.add(np);
1537                             // XQueryTree returns windows sorted by their z-order. However,
1538                             // if WM has not handled transient for hint for a child window,
1539                             // it may appear in javaToplevels before its owner. Move such
1540                             // children after their owners.
1541                             int k = 0;
1542                             XWindowPeer toCheck = javaToplevels.get(k);
1543                             while (toCheck != np) {
1544                                 XWindowPeer toCheckOwnerPeer = toCheck.getOwnerPeer();
1545                                 if (toCheckOwnerPeer == np) {
1546                                     javaToplevels.remove(k);
1547                                     javaToplevels.add(toCheck);
1548                                 } else {
1549                                     k++;
1550                                 }
1551                                 toCheck = javaToplevels.get(k);
1552                             }
1553                         }
1554                     }
1555                 }
1556             } finally {
1557                 qt.dispose();
1558             }
1559         }
1560         return javaToplevels;
1561     }
1562 
1563     public void setModalBlocked(Dialog d, boolean blocked) {
1564         setModalBlocked(d, blocked, null);
1565     }
1566     public void setModalBlocked(Dialog d, boolean blocked,
1567                                 Vector<XWindowPeer> javaToplevels)
1568     {
1569         XToolkit.awtLock();
1570         try {
1571             // State lock should always be after awtLock
1572             synchronized(getStateLock()) {
1573                 XDialogPeer blockerPeer = (XDialogPeer) AWTAccessor.getComponentAccessor().getPeer(d);
1574                 if (blocked) {
1575                     if (log.isLoggable(PlatformLogger.Level.FINE)) {
1576                         log.fine("{0} is blocked by {1}", this, blockerPeer);
1577                     }
1578                     modalBlocker = d;
1579 
1580                     if (isReparented() || XWM.isNonReparentingWM()) {
1581                         addToTransientFors(blockerPeer, javaToplevels);
1582                     } else {
1583                         delayedModalBlocking = true;
1584                     }
1585                 } else {
1586                     if (d != modalBlocker) {
1587                         throw new IllegalStateException("Trying to unblock window blocked by another dialog");
1588                     }
1589                     modalBlocker = null;
1590 
1591                     if (isReparented() || XWM.isNonReparentingWM()) {
1592                         removeFromTransientFors();
1593                     } else {
1594                         delayedModalBlocking = false;
1595                     }
1596                 }
1597 
1598                 updateTransientFor();
1599             }
1600         } finally {
1601             XToolkit.awtUnlock();
1602         }
1603     }
1604 
1605     /*
1606      * Sets the TRANSIENT_FOR hint to the given top-level window. This
1607      *  method is used when a window is modal blocked/unblocked or
1608      *  changed its state from/to NormalState to/from other states.
1609      * If window or transientForWindow are embedded frames, the containing
1610      *  top-level windows are used.
1611      *
1612      * @param window specifies the top-level window that the hint
1613      *  is to be set to
1614      * @param transientForWindow the top-level window
1615      * @param updateChain specifies if next/prevTransientFor fields are
1616      *  to be updated
1617      * @param allStates if set to <code>true</code> then TRANSIENT_FOR hint
1618      *  is set regardless of the state of window and transientForWindow,
1619      *  otherwise it is set only if both are in the same state
1620      */
1621     static void setToplevelTransientFor(XWindowPeer window, XWindowPeer transientForWindow,
1622                                                 boolean updateChain, boolean allStates)
1623     {
1624         if ((window == null) || (transientForWindow == null)) {
1625             return;
1626         }
1627         if (updateChain) {
1628             window.prevTransientFor = transientForWindow;
1629             transientForWindow.nextTransientFor = window;
1630         }
1631         if (window.curRealTransientFor == transientForWindow) {
1632             return;
1633         }
1634         if (!allStates && (window.getWMState() != transientForWindow.getWMState())) {
1635             return;
1636         }
1637         if (window.getScreenNumber() != transientForWindow.getScreenNumber()) {
1638             return;
1639         }
1640         long bpw = window.getWindow();
1641         while (!XlibUtil.isToplevelWindow(bpw) && !XlibUtil.isXAWTToplevelWindow(bpw)) {
1642             bpw = XlibUtil.getParentWindow(bpw);
1643         }
1644         long tpw = transientForWindow.getWindow();
1645         while (!XlibUtil.isToplevelWindow(tpw) && !XlibUtil.isXAWTToplevelWindow(tpw)) {
1646             tpw = XlibUtil.getParentWindow(tpw);
1647         }
1648         XlibWrapper.XSetTransientFor(XToolkit.getDisplay(), bpw, tpw);
1649         window.curRealTransientFor = transientForWindow;
1650     }
1651 
1652     /*
1653      * This method does nothing if this window is not blocked by any modal dialog.
1654      * For modal blocked windows this method looks up for the nearest
1655      *  prevTransiendFor window that is in the same state (Normal/Iconified/Withdrawn)
1656      *  as this one and makes this window transient for it. The same operation is
1657      *  performed for nextTransientFor window.
1658      * Values of prevTransientFor and nextTransientFor fields are not changed.
1659      */
1660     void updateTransientFor() {
1661         int state = getWMState();
1662         XWindowPeer p = prevTransientFor;
1663         while ((p != null) && ((p.getWMState() != state) || (p.getScreenNumber() != getScreenNumber()))) {
1664             p = p.prevTransientFor;
1665         }
1666         if (p != null) {
1667             setToplevelTransientFor(this, p, false, false);
1668         } else {
1669             restoreTransientFor(this);
1670         }
1671         XWindowPeer n = nextTransientFor;
1672         while ((n != null) && ((n.getWMState() != state) || (n.getScreenNumber() != getScreenNumber()))) {
1673             n = n.nextTransientFor;
1674         }
1675         if (n != null) {
1676             setToplevelTransientFor(n, this, false, false);
1677         }
1678     }
1679 
1680     /*
1681      * Removes the TRANSIENT_FOR hint from the given top-level window.
1682      * If window or transientForWindow are embedded frames, the containing
1683      *  top-level windows are used.
1684      *
1685      * @param window specifies the top-level window that the hint
1686      *  is to be removed from
1687      */
1688     private static void removeTransientForHint(XWindowPeer window) {
1689         XAtom XA_WM_TRANSIENT_FOR = XAtom.get(XAtom.XA_WM_TRANSIENT_FOR);
1690         long bpw = window.getWindow();
1691         while (!XlibUtil.isToplevelWindow(bpw) && !XlibUtil.isXAWTToplevelWindow(bpw)) {
1692             bpw = XlibUtil.getParentWindow(bpw);
1693         }
1694         XlibWrapper.XDeleteProperty(XToolkit.getDisplay(), bpw, XA_WM_TRANSIENT_FOR.getAtom());
1695         window.curRealTransientFor = null;
1696     }
1697 
1698     /*
1699      * When a modal dialog is shown, all its blocked windows are lined up into
1700      *  a chain in such a way that each window is a transient_for window for
1701      *  the next one. That allows us to keep the modal dialog above all its
1702      *  blocked windows (even if there are some another modal dialogs between
1703      *  them).
1704      * This method adds this top-level window to the chain of the given modal
1705      *  dialog. To keep the current relative z-order, we should use the
1706      *  XQueryTree to find the place to insert this window to. As each window
1707      *  can be blocked by only one modal dialog (such checks are performed in
1708      *  shared code), both this and blockerPeer are on the top of their chains
1709      *  (chains may be empty).
1710      * If this window is a modal dialog and has its own chain, these chains are
1711      *  merged according to the current z-order (XQueryTree is used again).
1712      *  Below are some simple examples (z-order is from left to right, -- is
1713      *  modal blocking).
1714      *
1715      * Example 0:
1716      *     T (current chain of this, no windows are blocked by this)
1717      *  W1---B (current chain of blockerPeer, W2 is blocked by blockerPeer)
1718      *  Result is:
1719      *  W1-T-B (merged chain, all the windows are blocked by blockerPeer)
1720      *
1721      * Example 1:
1722      *  W1-T (current chain of this, W1 is blocked by this)
1723      *       W2-B (current chain of blockerPeer, W2 is blocked by blockerPeer)
1724      *  Result is:
1725      *  W1-T-W2-B (merged chain, all the windows are blocked by blockerPeer)
1726      *
1727      * Example 2:
1728      *  W1----T (current chain of this, W1 is blocked by this)
1729      *     W2---B (current chain of blockerPeer, W2 is blocked by blockerPeer)
1730      *  Result is:
1731      *  W1-W2-T-B (merged chain, all the windows are blocked by blockerPeer)
1732      *
1733      * This method should be called under the AWT lock.
1734      *
1735      * @see #removeFromTransientFors
1736      * @see #setModalBlocked
1737      */
1738     private void addToTransientFors(XDialogPeer blockerPeer) {
1739         addToTransientFors(blockerPeer, null);
1740     }
1741 
1742     private void addToTransientFors(XDialogPeer blockerPeer, Vector<XWindowPeer> javaToplevels)
1743     {
1744         // blockerPeer chain iterator
1745         XWindowPeer blockerChain = blockerPeer;
1746         while (blockerChain.prevTransientFor != null) {
1747             blockerChain = blockerChain.prevTransientFor;
1748         }
1749         // this window chain iterator
1750         // each window can be blocked no more than once, so this window
1751         //   is on top of its chain
1752         XWindowPeer thisChain = this;
1753         while (thisChain.prevTransientFor != null) {
1754             thisChain = thisChain.prevTransientFor;
1755         }
1756         // if there are no windows blocked by modalBlocker, simply add this window
1757         //  and its chain to blocker's chain
1758         if (blockerChain == blockerPeer) {
1759             setToplevelTransientFor(blockerPeer, this, true, false);
1760         } else {
1761             // Collect all the Java top-levels, if required
1762             if (javaToplevels == null) {
1763                 javaToplevels = collectJavaToplevels();
1764             }
1765             // merged chain tail
1766             XWindowPeer mergedChain = null;
1767             for (XWindowPeer w : javaToplevels) {
1768                 XWindowPeer prevMergedChain = mergedChain;
1769                 if (w == thisChain) {
1770                     if (thisChain == this) {
1771                         if (prevMergedChain != null) {
1772                             setToplevelTransientFor(this, prevMergedChain, true, false);
1773                         }
1774                         setToplevelTransientFor(blockerChain, this, true, false);
1775                         break;
1776                     } else {
1777                         mergedChain = thisChain;
1778                         thisChain = thisChain.nextTransientFor;
1779                     }
1780                 } else if (w == blockerChain) {
1781                     mergedChain = blockerChain;
1782                     blockerChain = blockerChain.nextTransientFor;
1783                 } else {
1784                     continue;
1785                 }
1786                 if (prevMergedChain == null) {
1787                     mergedChain.prevTransientFor = null;
1788                 } else {
1789                     setToplevelTransientFor(mergedChain, prevMergedChain, true, false);
1790                     mergedChain.updateTransientFor();
1791                 }
1792                 if (blockerChain == blockerPeer) {
1793                     setToplevelTransientFor(thisChain, mergedChain, true, false);
1794                     setToplevelTransientFor(blockerChain, this, true, false);
1795                     break;
1796                 }
1797             }
1798         }
1799 
1800         XToolkit.XSync();
1801     }
1802 
1803     static void restoreTransientFor(XWindowPeer window) {
1804         XWindowPeer ownerPeer = window.getOwnerPeer();
1805         if (ownerPeer != null) {
1806             setToplevelTransientFor(window, ownerPeer, false, true);
1807         } else {
1808             removeTransientForHint(window);
1809         }
1810     }
1811 
1812     /*
1813      * When a window is modally unblocked, it should be removed from its blocker
1814      *  chain, see {@link #addToTransientFor addToTransientFors} method for the
1815      *  chain definition.
1816      * The problem is that we cannot simply restore window's original
1817      *  TRANSIENT_FOR hint (if any) and link prevTransientFor and
1818      *  nextTransientFor together as the whole chain could be created as a merge
1819      *  of two other chains in addToTransientFors. In that case, if this window is
1820      *  a modal dialog, it would lost all its own chain, if we simply exclude it
1821      *  from the chain.
1822      * The correct behaviour of this method should be to split the chain, this
1823      *  window is currently in, into two chains. First chain is this window own
1824      *  chain (i. e. all the windows blocked by this one, directly or indirectly),
1825      *  if any, and the rest windows from the current chain.
1826      *
1827      * Example:
1828      *  Original state:
1829      *   W1-B1 (window W1 is blocked by B1)
1830      *   W2-B2 (window W2 is blocked by B2)
1831      *  B3 is shown and blocks B1 and B2:
1832      *   W1-W2-B1-B2-B3 (a single chain after B1.addToTransientFors() and B2.addToTransientFors())
1833      *  If we then unblock B1, the state should be:
1834      *   W1-B1 (window W1 is blocked by B1)
1835      *   W2-B2-B3 (window W2 is blocked by B2 and B2 is blocked by B3)
1836      *
1837      * This method should be called under the AWT lock.
1838      *
1839      * @see #addToTransientFors
1840      * @see #setModalBlocked
1841      */
1842     private void removeFromTransientFors() {
1843         // the head of the chain of this window
1844         XWindowPeer thisChain = this;
1845         // the head of the current chain
1846         // nextTransientFor is always not null as this window is in the chain
1847         XWindowPeer otherChain = nextTransientFor;
1848         // the set of blockers in this chain: if this dialog blocks some other
1849         // modal dialogs, their blocked windows should stay in this dialog's chain
1850         Set<XWindowPeer> thisChainBlockers = new HashSet<XWindowPeer>();
1851         thisChainBlockers.add(this);
1852         // current chain iterator in the order from next to prev
1853         XWindowPeer chainToSplit = prevTransientFor;
1854         while (chainToSplit != null) {
1855             XWindowPeer blocker = (XWindowPeer) AWTAccessor.getComponentAccessor().getPeer(chainToSplit.modalBlocker);
1856             if (thisChainBlockers.contains(blocker)) {
1857                 // add to this dialog's chain
1858                 setToplevelTransientFor(thisChain, chainToSplit, true, false);
1859                 thisChain = chainToSplit;
1860                 thisChainBlockers.add(chainToSplit);
1861             } else {
1862                 // leave in the current chain
1863                 setToplevelTransientFor(otherChain, chainToSplit, true, false);
1864                 otherChain = chainToSplit;
1865             }
1866             chainToSplit = chainToSplit.prevTransientFor;
1867         }
1868         restoreTransientFor(thisChain);
1869         thisChain.prevTransientFor = null;
1870         restoreTransientFor(otherChain);
1871         otherChain.prevTransientFor = null;
1872         nextTransientFor = null;
1873 
1874         XToolkit.XSync();
1875     }
1876 
1877     boolean isModalBlocked() {
1878         return modalBlocker != null;
1879     }
1880 
1881     static Window getDecoratedOwner(Window window) {
1882         while ((null != window) && !(window instanceof Frame || window instanceof Dialog)) {
1883             window = (Window) AWTAccessor.getComponentAccessor().getParent(window);
1884         }
1885         return window;
1886     }
1887 
1888     public boolean requestWindowFocus(XWindowPeer actualFocusedWindow) {
1889         setActualFocusedWindow(actualFocusedWindow);
1890         return requestWindowFocus();
1891     }
1892 
1893     public boolean requestWindowFocus() {
1894         return requestWindowFocus(0, false);
1895     }
1896 
1897     public boolean requestWindowFocus(long time, boolean timeProvided) {
1898         focusLog.fine("Request for window focus");
1899         // If this is Frame or Dialog we can't assure focus request success - but we still can try
1900         // If this is Window and its owner Frame is active we can be sure request succedded.
1901         Window ownerWindow  = XWindowPeer.getDecoratedOwner((Window)target);
1902         Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
1903         Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
1904 
1905         if (isWMStateNetHidden()) {
1906             focusLog.fine("The window is unmapped, so rejecting the request");
1907             return false;
1908         }
1909         if (activeWindow == ownerWindow) {
1910             focusLog.fine("Parent window is active - generating focus for this window");
1911             handleWindowFocusInSync(-1);
1912             return true;
1913         }
1914         focusLog.fine("Parent window is not active");
1915 
1916         XDecoratedPeer wpeer = (XDecoratedPeer)AWTAccessor.getComponentAccessor().getPeer(ownerWindow);
1917         if (wpeer != null && wpeer.requestWindowFocus(this, time, timeProvided)) {
1918             focusLog.fine("Parent window accepted focus request - generating focus for this window");
1919             return true;
1920         }
1921         focusLog.fine("Denied - parent window is not active and didn't accept focus request");
1922         return false;
1923     }
1924 
1925     // This method is to be overriden in XDecoratedPeer.
1926     void setActualFocusedWindow(XWindowPeer actualFocusedWindow) {
1927     }
1928 
1929     /**
1930      * Applies the current window type.
1931      */
1932     private void applyWindowType() {
1933         XNETProtocol protocol = XWM.getWM().getNETProtocol();
1934         if (protocol == null) {
1935             return;
1936         }
1937 
1938         XAtom typeAtom = null;
1939 
1940         switch (getWindowType())
1941         {
1942             case NORMAL:
1943                 typeAtom = (ownerPeer == null) ?
1944                                protocol.XA_NET_WM_WINDOW_TYPE_NORMAL :
1945                                protocol.XA_NET_WM_WINDOW_TYPE_DIALOG;
1946                 break;
1947             case UTILITY:
1948                 typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_UTILITY;
1949                 break;
1950             case POPUP:
1951                 typeAtom = protocol.XA_NET_WM_WINDOW_TYPE_POPUP_MENU;
1952                 break;
1953         }
1954 
1955         if (typeAtom != null) {
1956             XAtomList wtype = new XAtomList();
1957             wtype.add(typeAtom);
1958             protocol.XA_NET_WM_WINDOW_TYPE.
1959                 setAtomListProperty(getWindow(), wtype);
1960         } else {
1961             protocol.XA_NET_WM_WINDOW_TYPE.
1962                 DeleteProperty(getWindow());
1963         }
1964     }
1965 
1966     @Override
1967     public void xSetVisible(boolean visible) {
1968         if (log.isLoggable(PlatformLogger.Level.FINE)) {
1969             log.fine("Setting visible on " + this + " to " + visible);
1970         }
1971         XToolkit.awtLock();
1972         try {
1973             this.visible = visible;
1974             if (visible) {
1975                 applyWindowType();
1976                 XlibWrapper.XMapRaised(XToolkit.getDisplay(), getWindow());
1977             } else {
1978                 XlibWrapper.XUnmapWindow(XToolkit.getDisplay(), getWindow());
1979             }
1980             XlibWrapper.XFlush(XToolkit.getDisplay());
1981         }
1982         finally {
1983             XToolkit.awtUnlock();
1984         }
1985     }
1986 
1987     // should be synchronized on awtLock
1988     private int dropTargetCount = 0;
1989 
1990     public void addDropTarget() {
1991         XToolkit.awtLock();
1992         try {
1993             if (dropTargetCount == 0) {
1994                 long window = getWindow();
1995                 if (window != 0) {
1996                     XDropTargetRegistry.getRegistry().registerDropSite(window);
1997                 }
1998             }
1999             dropTargetCount++;
2000         } finally {
2001             XToolkit.awtUnlock();
2002         }
2003     }
2004 
2005     public void removeDropTarget() {
2006         XToolkit.awtLock();
2007         try {
2008             dropTargetCount--;
2009             if (dropTargetCount == 0) {
2010                 long window = getWindow();
2011                 if (window != 0) {
2012                     XDropTargetRegistry.getRegistry().unregisterDropSite(window);
2013                 }
2014             }
2015         } finally {
2016             XToolkit.awtUnlock();
2017         }
2018     }
2019     void addRootPropertyEventDispatcher() {
2020         if( rootPropertyEventDispatcher == null ) {
2021             rootPropertyEventDispatcher = new XEventDispatcher() {
2022                 public void dispatchEvent(XEvent ev) {
2023                     if( ev.get_type() == XConstants.PropertyNotify ) {
2024                         handleRootPropertyNotify( ev );
2025                     }
2026                 }
2027             };
2028             XlibWrapper.XSelectInput( XToolkit.getDisplay(),
2029                                       XToolkit.getDefaultRootWindow(),
2030                                       XConstants.PropertyChangeMask);
2031             XToolkit.addEventDispatcher(XToolkit.getDefaultRootWindow(),
2032                                                 rootPropertyEventDispatcher);
2033         }
2034     }
2035     void removeRootPropertyEventDispatcher() {
2036         if( rootPropertyEventDispatcher != null ) {
2037             XToolkit.removeEventDispatcher(XToolkit.getDefaultRootWindow(),
2038                                                 rootPropertyEventDispatcher);
2039             rootPropertyEventDispatcher = null;
2040         }
2041     }
2042     public void updateFocusableWindowState() {
2043         cachedFocusableWindow = isFocusableWindow();
2044     }
2045 
2046     XAtom XA_NET_WM_STATE;
2047     XAtomList net_wm_state;
2048     public XAtomList getNETWMState() {
2049         if (net_wm_state == null) {
2050             net_wm_state = XA_NET_WM_STATE.getAtomListPropertyList(this);
2051         }
2052         return net_wm_state;
2053     }
2054 
2055     public void setNETWMState(XAtomList state) {
2056         net_wm_state = state;
2057         if (state != null) {
2058             XA_NET_WM_STATE.setAtomListProperty(this, state);
2059         }
2060     }
2061 
2062     public PropMwmHints getMWMHints() {
2063         if (mwm_hints == null) {
2064             mwm_hints = new PropMwmHints();
2065             if (!XWM.XA_MWM_HINTS.getAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS)) {
2066                 mwm_hints.zero();
2067             }
2068         }
2069         return mwm_hints;
2070     }
2071 
2072     public void setMWMHints(PropMwmHints hints) {
2073         mwm_hints = hints;
2074         if (hints != null) {
2075             XWM.XA_MWM_HINTS.setAtomData(getWindow(), mwm_hints.pData, MWMConstants.PROP_MWM_HINTS_ELEMENTS);
2076         }
2077     }
2078 
2079     protected void updateDropTarget() {
2080         XToolkit.awtLock();
2081         try {
2082             if (dropTargetCount > 0) {
2083                 long window = getWindow();
2084                 if (window != 0) {
2085                     XDropTargetRegistry.getRegistry().unregisterDropSite(window);
2086                     XDropTargetRegistry.getRegistry().registerDropSite(window);
2087                 }
2088             }
2089         } finally {
2090             XToolkit.awtUnlock();
2091         }
2092     }
2093 
2094     public void setGrab(boolean grab) {
2095         this.grab = grab;
2096         if (grab) {
2097             pressTarget = this;
2098             grabInput();
2099         } else {
2100             ungrabInput();
2101         }
2102     }
2103 
2104     public boolean isGrabbed() {
2105         return grab && XAwtState.getGrabWindow() == this;
2106     }
2107 
2108     public void handleXCrossingEvent(XEvent xev) {
2109         XCrossingEvent xce = xev.get_xcrossing();
2110         if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
2111             grabLog.fine("{0}, when grabbed {1}, contains {2}",
2112                          xce, isGrabbed(), containsGlobal(xce.get_x_root(), xce.get_y_root()));
2113         }
2114         if (isGrabbed()) {
2115             // When window is grabbed, all events are dispatched to
2116             // it.  Retarget them to the corresponding windows (notice
2117             // that XBaseWindow.dispatchEvent does the opposite
2118             // translation)
2119             // Note that we need to retarget XCrossingEvents to content window
2120             // since it generates MOUSE_ENTERED/MOUSE_EXITED for frame and dialog.
2121             // (fix for 6390326)
2122             XBaseWindow target = XToolkit.windowToXWindow(xce.get_window());
2123             if (grabLog.isLoggable(PlatformLogger.Level.FINER)) {
2124                 grabLog.finer("  -  Grab event target {0}", target);
2125             }
2126             if (target != null && target != this) {
2127                 target.dispatchEvent(xev);
2128                 return;
2129             }
2130         }
2131         super.handleXCrossingEvent(xev);
2132     }
2133 
2134     public void handleMotionNotify(XEvent xev) {
2135         XMotionEvent xme = xev.get_xmotion();
2136         if (grabLog.isLoggable(PlatformLogger.Level.FINER)) {
2137             grabLog.finer("{0}, when grabbed {1}, contains {2}",
2138                           xme, isGrabbed(), containsGlobal(xme.get_x_root(), xme.get_y_root()));
2139         }
2140         if (isGrabbed()) {
2141             boolean dragging = false;
2142             final int buttonsNumber = XToolkit.getNumberOfButtonsForMask();
2143 
2144             for (int i = 0; i < buttonsNumber; i++){
2145                 // here is the bug in WM: extra buttons doesn't have state!=0 as they should.
2146                 if ((i != 4) && (i != 5)){
2147                     dragging = dragging || ((xme.get_state() & XlibUtil.getButtonMask(i + 1)) != 0);
2148                 }
2149             }
2150             // When window is grabbed, all events are dispatched to
2151             // it.  Retarget them to the corresponding windows (notice
2152             // that XBaseWindow.dispatchEvent does the opposite
2153             // translation)
2154             XBaseWindow target = XToolkit.windowToXWindow(xme.get_window());
2155             if (dragging && pressTarget != target) {
2156                 // for some reasons if we grab input MotionNotify for drag is reported with target
2157                 // to underlying window, not to window on which we have initiated drag
2158                 // so we need to retarget them.  Here I use simplified logic which retarget all
2159                 // such events to source of mouse press (or the grabber).  It helps with fix for 6390326.
2160                 // So, I do not want to implement complicated logic for better retargeting.
2161                 target = pressTarget.isVisible() ? pressTarget : this;
2162                 xme.set_window(target.getWindow());
2163                 Point localCoord = target.toLocal(xme.get_x_root(), xme.get_y_root());
2164                 xme.set_x(localCoord.x);
2165                 xme.set_y(localCoord.y);
2166             }
2167             if (grabLog.isLoggable(PlatformLogger.Level.FINER)) {
2168                 grabLog.finer("  -  Grab event target {0}", target);
2169             }
2170             if (target != null) {
2171                 if (target != getContentXWindow() && target != this) {
2172                     target.dispatchEvent(xev);
2173                     return;
2174                 }
2175             }
2176 
2177             // note that we need to pass dragging events to the grabber (6390326)
2178             // see comment above for more inforamtion.
2179             if (!containsGlobal(xme.get_x_root(), xme.get_y_root()) && !dragging) {
2180                 // Outside of Java
2181                 return;
2182             }
2183         }
2184         super.handleMotionNotify(xev);
2185     }
2186 
2187     // we use it to retarget mouse drag and mouse release during grab.
2188     private XBaseWindow pressTarget = this;
2189 
2190     public void handleButtonPressRelease(XEvent xev) {
2191         XButtonEvent xbe = xev.get_xbutton();
2192 
2193         /*
2194          * Ignore the buttons above 20 due to the bit limit for
2195          * InputEvent.BUTTON_DOWN_MASK.
2196          * One more bit is reserved for FIRST_HIGH_BIT.
2197          */
2198         if (xbe.get_button() > SunToolkit.MAX_BUTTONS_SUPPORTED) {
2199             return;
2200         }
2201         if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
2202             grabLog.fine("{0}, when grabbed {1}, contains {2} ({3}, {4}, {5}x{6})",
2203                          xbe, isGrabbed(), containsGlobal(xbe.get_x_root(), xbe.get_y_root()), getAbsoluteX(), getAbsoluteY(), getWidth(), getHeight());
2204         }
2205         if (isGrabbed()) {
2206             // When window is grabbed, all events are dispatched to
2207             // it.  Retarget them to the corresponding windows (notice
2208             // that XBaseWindow.dispatchEvent does the opposite
2209             // translation)
2210             XBaseWindow target = XToolkit.windowToXWindow(xbe.get_window());
2211             try {
2212                 if (grabLog.isLoggable(PlatformLogger.Level.FINER)) {
2213                     grabLog.finer("  -  Grab event target {0} (press target {1})", target, pressTarget);
2214                 }
2215                 if (xbe.get_type() == XConstants.ButtonPress
2216                     && xbe.get_button() == XConstants.buttons[0])
2217                 {
2218                     // need to keep it to retarget mouse release
2219                     pressTarget = target;
2220                 } else if (xbe.get_type() == XConstants.ButtonRelease
2221                            && xbe.get_button() == XConstants.buttons[0]
2222                            && pressTarget != target)
2223                 {
2224                     // during grab we do receive mouse release on different component (not on the source
2225                     // of mouse press).  So we need to retarget it.
2226                     // see 6390326 for more information.
2227                     target = pressTarget.isVisible() ? pressTarget : this;
2228                     xbe.set_window(target.getWindow());
2229                     Point localCoord = target.toLocal(xbe.get_x_root(), xbe.get_y_root());
2230                     xbe.set_x(localCoord.x);
2231                     xbe.set_y(localCoord.y);
2232                     pressTarget = this;
2233                 }
2234                 if (target != null && target != getContentXWindow() && target != this) {
2235                     target.dispatchEvent(xev);
2236                     return;
2237                 }
2238             } finally {
2239                 if (target != null) {
2240                     // Target is either us or our content window -
2241                     // check that event is inside.  'Us' in case of
2242                     // shell will mean that this will also filter out press on title
2243                     if ((target == this || target == getContentXWindow()) && !containsGlobal(xbe.get_x_root(), xbe.get_y_root())) {
2244                         // Outside this toplevel hierarchy
2245                         // According to the specification of UngrabEvent, post it
2246                         // when press occurs outside of the window and not on its owned windows
2247                         if (xbe.get_type() == XConstants.ButtonPress) {
2248                             if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
2249                                 grabLog.fine("Generating UngrabEvent on {0} because not inside of shell", this);
2250                             }
2251                             postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
2252                             return;
2253                         }
2254                     }
2255                     // First, get the toplevel
2256                     XWindowPeer toplevel = target.getToplevelXWindow();
2257                     if (toplevel != null) {
2258                         Window w = (Window)toplevel.target;
2259                         while (w != null && toplevel != this && !(toplevel instanceof XDialogPeer)) {
2260                             w = (Window) AWTAccessor.getComponentAccessor().getParent(w);
2261                             if (w != null) {
2262                                 toplevel = (XWindowPeer) AWTAccessor.getComponentAccessor().getPeer(w);
2263                             }
2264                         }
2265                         if (w == null || (w != this.target && w instanceof Dialog)) {
2266                             // toplevel == null - outside of
2267                             // hierarchy, toplevel is Dialog - should
2268                             // send ungrab (but shouldn't for Window)
2269                             if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
2270                                 grabLog.fine("Generating UngrabEvent on {0} because hierarchy ended", this);
2271                             }
2272                             postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
2273                         }
2274                     } else {
2275                         // toplevel is null - outside of hierarchy
2276                         if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
2277                             grabLog.fine("Generating UngrabEvent on {0} because toplevel is null", this);
2278                         }
2279                         postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
2280                         return;
2281                     }
2282                 } else {
2283                     // target doesn't map to XAWT window - outside of hierarchy
2284                     if (grabLog.isLoggable(PlatformLogger.Level.FINE)) {
2285                         grabLog.fine("Generating UngrabEvent on because target is null {0}", this);
2286                     }
2287                     postEventToEventQueue(new sun.awt.UngrabEvent(getEventSource()));
2288                     return;
2289                 }
2290             }
2291         }
2292         super.handleButtonPressRelease(xev);
2293     }
2294 
2295     public void print(Graphics g) {
2296         // We assume we print the whole frame,
2297         // so we expect no clip was set previously
2298         Shape shape = AWTAccessor.getWindowAccessor().getShape((Window)target);
2299         if (shape != null) {
2300             g.setClip(shape);
2301         }
2302         super.print(g);
2303     }
2304 
2305     @Override
2306     public void setOpacity(float opacity) {
2307         final long maxOpacity = 0xffffffffl;
2308         long iOpacity = (long)(opacity * maxOpacity);
2309         if (iOpacity < 0) {
2310             iOpacity = 0;
2311         }
2312         if (iOpacity > maxOpacity) {
2313             iOpacity = maxOpacity;
2314         }
2315 
2316         XAtom netWmWindowOpacityAtom = XAtom.get("_NET_WM_WINDOW_OPACITY");
2317 
2318         if (iOpacity == maxOpacity) {
2319             netWmWindowOpacityAtom.DeleteProperty(getWindow());
2320         } else {
2321             netWmWindowOpacityAtom.setCard32Property(getWindow(), iOpacity);
2322         }
2323     }
2324 
2325     @Override
2326     public void setOpaque(boolean isOpaque) {
2327         // no-op
2328     }
2329 
2330     @Override
2331     public void updateWindow() {
2332         // no-op
2333     }
2334 }