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