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