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