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

Save This Page
Home » openjdk-7 » sun » awt » X11 » [javadoc | source]