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