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