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