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