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