1 /*
   2  * Copyright (c) 2002, 2016, 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.InvocationEvent;
  31 import java.awt.event.WindowEvent;
  32 import java.util.Collections;
  33 import java.util.HashMap;
  34 import java.util.Map;
  35 
  36 import sun.awt.IconInfo;
  37 import sun.util.logging.PlatformLogger;
  38 
  39 import sun.awt.AWTAccessor;
  40 import sun.awt.SunToolkit;
  41 
  42 abstract class XDecoratedPeer extends XWindowPeer {
  43     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XDecoratedPeer");
  44     private static final PlatformLogger insLog = PlatformLogger.getLogger("sun.awt.X11.insets.XDecoratedPeer");
  45     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XDecoratedPeer");
  46     private static final PlatformLogger iconLog = PlatformLogger.getLogger("sun.awt.X11.icon.XDecoratedPeer");
  47 
  48     // Set to true when we get the first ConfigureNotify after being
  49     // reparented - indicates that WM has adopted the top-level.
  50     boolean configure_seen;
  51     boolean insets_corrected;
  52 
  53     XIconWindow iconWindow;
  54     WindowDimensions dimensions;
  55     XContentWindow content;
  56     Insets currentInsets;
  57     XFocusProxyWindow focusProxy;
  58     static final Map<Class<?>,Insets> lastKnownInsets =
  59                                    Collections.synchronizedMap(new HashMap<>());
  60 
  61     XDecoratedPeer(Window target) {
  62         super(target);
  63     }
  64 
  65     XDecoratedPeer(XCreateWindowParams params) {
  66         super(params);
  67     }
  68 
  69     public long getShell() {
  70         return window;
  71     }
  72 
  73     public long getContentWindow() {
  74         return (content == null) ? window : content.getWindow();
  75     }
  76 
  77     void preInit(XCreateWindowParams params) {
  78         super.preInit(params);
  79         winAttr.initialFocus = true;
  80 
  81         currentInsets = new Insets(0,0,0,0);
  82         if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
  83             currentInsets = lastKnownInsets.get(getClass());
  84         }
  85         applyGuessedInsets();
  86 
  87         Rectangle bounds = (Rectangle)params.get(BOUNDS);
  88         dimensions = new WindowDimensions(bounds, getRealInsets(), false);
  89         params.put(BOUNDS, dimensions.getClientRect());
  90         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
  91             insLog.fine("Initial dimensions {0}", dimensions);
  92         }
  93 
  94         // Deny default processing of these events on the shell - proxy will take care of
  95         // them instead
  96         Long eventMask = (Long)params.get(EVENT_MASK);
  97         params.add(EVENT_MASK, Long.valueOf(eventMask.longValue() & ~(XConstants.FocusChangeMask | XConstants.KeyPressMask | XConstants.KeyReleaseMask)));
  98     }
  99 
 100     void postInit(XCreateWindowParams params) {
 101         // The size hints must be set BEFORE mapping the window (see 6895647)
 102         updateSizeHints(dimensions);
 103 
 104         // The super method maps the window if it's visible on the shared level
 105         super.postInit(params);
 106 
 107         // The lines that follow need to be in a postInit, so they
 108         // happen after the X window is created.
 109         initResizability();
 110         XWM.requestWMExtents(getWindow());
 111 
 112         content = XContentWindow.createContent(this);
 113 
 114         if (warningWindow != null) {
 115             warningWindow.toFront();
 116         }
 117         focusProxy = createFocusProxy();
 118     }
 119 
 120     void setIconHints(java.util.List<IconInfo> icons) {
 121         if (!XWM.getWM().setNetWMIcon(this, icons)) {
 122             if (icons.size() > 0) {
 123                 if (iconWindow == null) {
 124                     iconWindow = new XIconWindow(this);
 125                 }
 126                 iconWindow.setIconImages(icons);
 127             }
 128         }
 129     }
 130 
 131     public void updateMinimumSize() {
 132         XToolkit.awtLock();
 133         try {
 134             super.updateMinimumSize();
 135             updateMinSizeHints();
 136         } finally {
 137             XToolkit.awtUnlock();
 138         }
 139     }
 140 
 141     private void updateMinSizeHints() {
 142         if (isResizable()) {
 143             Dimension minimumSize = getTargetMinimumSize();
 144             if (minimumSize != null) {
 145                 Insets insets = getRealInsets();
 146                 int minWidth = minimumSize.width - insets.left - insets.right;
 147                 int minHeight = minimumSize.height - insets.top - insets.bottom;
 148                 if (minWidth < 0) minWidth = 0;
 149                 if (minHeight < 0) minHeight = 0;
 150                 setSizeHints(XUtilConstants.PMinSize | (isLocationByPlatform()?0:(XUtilConstants.PPosition | XUtilConstants.USPosition)),
 151                              getX(), getY(), minWidth, minHeight);
 152                 if (isVisible()) {
 153                     Rectangle bounds = getShellBounds();
 154                     int nw = (bounds.width < minWidth) ? minWidth : bounds.width;
 155                     int nh = (bounds.height < minHeight) ? minHeight : bounds.height;
 156                     if (nw != bounds.width || nh != bounds.height) {
 157                         setShellSize(new Rectangle(0, 0, nw, nh));
 158                     }
 159                 }
 160             } else {
 161                 boolean isMinSizeSet = isMinSizeSet();
 162                 XWM.removeSizeHints(this, XUtilConstants.PMinSize);
 163                 /* Some WMs need remap to redecorate the window */
 164                 if (isMinSizeSet && isShowing() && XWM.needRemap(this)) {
 165                     /*
 166                      * Do the re/mapping at the Xlib level.  Since we essentially
 167                      * work around a WM bug we don't want this hack to be exposed
 168                      * to Intrinsics (i.e. don't mess with grabs, callbacks etc).
 169                      */
 170                     xSetVisible(false);
 171                     XToolkit.XSync();
 172                     xSetVisible(true);
 173                 }
 174             }
 175         }
 176     }
 177 
 178     XFocusProxyWindow createFocusProxy() {
 179         return new XFocusProxyWindow(this);
 180     }
 181 
 182     protected XAtomList getWMProtocols() {
 183         XAtomList protocols = super.getWMProtocols();
 184         protocols.add(wm_delete_window);
 185         protocols.add(wm_take_focus);
 186         return protocols;
 187     }
 188 
 189     public Graphics getGraphics() {
 190         AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
 191         return getGraphics(content.surfaceData,
 192                            compAccessor.getForeground(target),
 193                            compAccessor.getBackground(target),
 194                            compAccessor.getFont(target));
 195     }
 196 
 197     public void setTitle(String title) {
 198         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 199             log.fine("Title is " + title);
 200         }
 201         winAttr.title = title;
 202         updateWMName();
 203     }
 204 
 205     protected String getWMName() {
 206         if (winAttr.title == null || winAttr.title.trim().equals("")) {
 207             return " ";
 208         } else {
 209             return winAttr.title;
 210         }
 211     }
 212 
 213     void updateWMName() {
 214         super.updateWMName();
 215         String name = getWMName();
 216         XToolkit.awtLock();
 217         try {
 218             if (name == null || name.trim().equals("")) {
 219                 name = "Java";
 220             }
 221             XAtom iconNameAtom = XAtom.get(XAtom.XA_WM_ICON_NAME);
 222             iconNameAtom.setProperty(getWindow(), name);
 223             XAtom netIconNameAtom = XAtom.get("_NET_WM_ICON_NAME");
 224             netIconNameAtom.setPropertyUTF8(getWindow(), name);
 225         } finally {
 226             XToolkit.awtUnlock();
 227         }
 228     }
 229 
 230     // NOTE: This method may be called by privileged threads.
 231     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 232     public void handleIconify() {
 233         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_ICONIFIED));
 234     }
 235 
 236     // NOTE: This method may be called by privileged threads.
 237     //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
 238     public void handleDeiconify() {
 239         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_DEICONIFIED));
 240     }
 241 
 242     public void handleFocusEvent(XEvent xev) {
 243         super.handleFocusEvent(xev);
 244         XFocusChangeEvent xfe = xev.get_xfocus();
 245 
 246         // If we somehow received focus events forward it instead to proxy
 247         // FIXME: Shouldn't we instead check for inferrior?
 248         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
 249             focusLog.finer("Received focus event on shell: " + xfe);
 250         }
 251 //         focusProxy.xRequestFocus();
 252    }
 253 
 254 /***************************************************************************************
 255  *                             I N S E T S   C O D E
 256  **************************************************************************************/
 257 
 258     protected boolean isInitialReshape() {
 259         return false;
 260     }
 261 
 262     private static Insets difference(Insets i1, Insets i2) {
 263         return new Insets(i1.top-i2.top, i1.left - i2.left, i1.bottom-i2.bottom, i1.right-i2.right);
 264     }
 265 
 266     private static boolean isNull(Insets i) {
 267         return (i == null) || ((i.left | i.top | i.right | i.bottom) == 0);
 268     }
 269 
 270     private static Insets copy(Insets i) {
 271         return new Insets(i.top, i.left, i.bottom, i.right);
 272     }
 273 
 274     private Insets copyAndScaleDown(Insets i) {
 275         return new Insets(scaleDown(i.top), scaleDown(i.left),
 276                           scaleDown(i.bottom), scaleDown(i.right));
 277     }
 278 
 279 
 280     // insets which we get from WM (e.g from _NET_FRAME_EXTENTS)
 281     private Insets wm_set_insets;
 282 
 283     private Insets getWMSetInsets(XAtom changedAtom) {
 284         if (isEmbedded()) {
 285             return null;
 286         }
 287 
 288         if (wm_set_insets != null) {
 289             return wm_set_insets;
 290         }
 291 
 292         if (changedAtom == null) {
 293             wm_set_insets = XWM.getInsetsFromExtents(getWindow());
 294         } else {
 295             wm_set_insets = XWM.getInsetsFromProp(getWindow(), changedAtom);
 296         }
 297 
 298         if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 299             insLog.finer("FRAME_EXTENTS: {0}", wm_set_insets);
 300         }
 301 
 302         if (wm_set_insets != null) {
 303             wm_set_insets = copyAndScaleDown(wm_set_insets);
 304         }
 305         return wm_set_insets;
 306     }
 307 
 308     private void resetWMSetInsets() {
 309         if (XWM.getWMID() != XWM.UNITY_COMPIZ_WM) {
 310             currentInsets = new Insets(0, 0, 0, 0);
 311             wm_set_insets = null;
 312         } else {
 313             insets_corrected = false;
 314         }
 315     }
 316 
 317     public void handlePropertyNotify(XEvent xev) {
 318         super.handlePropertyNotify(xev);
 319 
 320         XPropertyEvent ev = xev.get_xproperty();
 321         if( !insets_corrected && isReparented() &&
 322                                          XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
 323             int state = XWM.getWM().getState(this);
 324             if ((state & Frame.MAXIMIZED_BOTH) ==  Frame.MAXIMIZED_BOTH) {
 325                 // Stop ignoring ConfigureNotify because no extents will be sent
 326                 // by WM for initially maximized decorated window.
 327                 // Re-request window bounds to ensure actual dimensions and
 328                 // notify the target with the initial size.
 329                 insets_corrected = true;
 330                 XlibWrapper.XConfigureWindow(XToolkit.getDisplay(),
 331                                                              getWindow(), 0, 0);
 332             }
 333         }
 334         if (ev.get_atom() == XWM.XA_KDE_NET_WM_FRAME_STRUT.getAtom()
 335             || ev.get_atom() == XWM.XA_NET_FRAME_EXTENTS.getAtom())
 336         {
 337             if (XWM.getWMID() != XWM.UNITY_COMPIZ_WM) {
 338                 getWMSetInsets(XAtom.get(ev.get_atom()));
 339             } else {
 340                 if (!isReparented()) {
 341                     return;
 342                 }
 343                 XToolkit.awtLock();
 344                 try {
 345                     wm_set_insets = null;
 346                     Insets in = getWMSetInsets(XAtom.get(ev.get_atom()));
 347                     if (isNull(in)) {
 348                         return;
 349                     }
 350                     if (!isEmbedded() && !isTargetUndecorated()) {
 351                         lastKnownInsets.put(getClass(), in);
 352                     }
 353                     if (!in.equals(dimensions.getInsets())) {
 354                         if (insets_corrected || isMaximized()) {
 355                             currentInsets = in;
 356                             insets_corrected = true;
 357                             // insets were changed by WM. To handle this
 358                             // situation re-request window bounds because the
 359                             // current dimensions may be not actual as well.
 360                             XlibWrapper.XConfigureWindow(XToolkit.getDisplay(),
 361                                     getWindow(), 0, 0);
 362                         } else {
 363                             // recalculate dimensions when window is just
 364                             // created and the initially guessed insets were
 365                             // wrong
 366                             handleCorrectInsets(in);
 367                         }
 368                     } else if (!insets_corrected ||
 369                             !dimensions.isClientSizeSet()) {
 370                         insets_corrected = true;
 371                         // initial insets were guessed correctly. Re-request
 372                         // frame bounds because they may be changed by WM if
 373                         // the initial window position overlapped desktop's
 374                         // toolbars. This should initiate the final
 375                         // ConfigureNotify upon which the target will be
 376                         // notified with the final size.
 377                         XlibWrapper.XConfigureWindow(XToolkit.getDisplay(),
 378                                 getWindow(), 0, 0);
 379                     }
 380                 } finally {
 381                     XToolkit.awtUnlock();
 382                 }
 383             }
 384         }
 385     }
 386 
 387     long reparent_serial = 0;
 388 
 389     public void handleReparentNotifyEvent(XEvent xev) {
 390         XReparentEvent  xe = xev.get_xreparent();
 391         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 392             insLog.fine(xe.toString());
 393         }
 394         reparent_serial = xe.get_serial();
 395         XToolkit.awtLock();
 396         try {
 397             long root = XlibWrapper.RootWindow(XToolkit.getDisplay(), getScreenNumber());
 398 
 399             if (isEmbedded()) {
 400                 setReparented(true);
 401                 insets_corrected = true;
 402                 return;
 403             }
 404             Component t = target;
 405             if (getDecorations() == XWindowAttributesData.AWT_DECOR_NONE) {
 406                 setReparented(true);
 407                 insets_corrected = true;
 408                 reshape(dimensions, SET_SIZE, false);
 409             } else if (xe.get_parent() == root) {
 410                 configure_seen = false;
 411                 insets_corrected = false;
 412 
 413                 /*
 414                  * We can be repareted to root for two reasons:
 415                  *   . setVisible(false)
 416                  *   . WM exited
 417                  */
 418                 if (isVisible()) { /* WM exited */
 419                     /* Work around 4775545 */
 420                     XWM.getWM().unshadeKludge(this);
 421                     insLog.fine("- WM exited");
 422                 } else {
 423                     insLog.fine(" - reparent due to hide");
 424                 }
 425             } else { /* reparented to WM frame, figure out our insets */
 426                 setReparented(true);
 427                 insets_corrected = false;
 428                 if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
 429                     return;
 430                 }
 431 
 432                 // Check if we have insets provided by the WM
 433                 Insets correctWM = getWMSetInsets(null);
 434                 if (correctWM != null) {
 435                     if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 436                         insLog.finer("wm-provided insets {0}", correctWM);
 437                     }
 438                     // If these insets are equal to our current insets - no actions are necessary
 439                     Insets dimInsets = dimensions.getInsets();
 440                     if (correctWM.equals(dimInsets)) {
 441                         insLog.finer("Insets are the same as estimated - no additional reshapes necessary");
 442                         no_reparent_artifacts = true;
 443                         insets_corrected = true;
 444                         applyGuessedInsets();
 445                         return;
 446                     }
 447                 } else {
 448                     correctWM = XWM.getWM().getInsets(this, xe.get_window(), xe.get_parent());
 449                     if (correctWM != null) {
 450                         correctWM = copyAndScaleDown(correctWM);
 451                     }
 452 
 453                     if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 454                         if (correctWM != null) {
 455                             insLog.finer("correctWM {0}", correctWM);
 456                         } else {
 457                             insLog.finer("correctWM insets are not available, waiting for configureNotify");
 458                         }
 459                     }
 460                 }
 461 
 462                 if (correctWM != null) {
 463                     handleCorrectInsets(correctWM);
 464                 }
 465             }
 466         } finally {
 467             XToolkit.awtUnlock();
 468         }
 469     }
 470 
 471     protected void handleCorrectInsets(Insets correctWM) {
 472         XToolkit.awtLock();
 473         try {
 474             /*
 475              * Ok, now see if we need adjust window size because
 476              * initial insets were wrong (most likely they were).
 477              */
 478             Insets correction = difference(correctWM, currentInsets);
 479             if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
 480                 insLog.finest("Corrention {0}", correction);
 481             }
 482             if (!isNull(correction)) {
 483                 currentInsets = copy(correctWM);
 484                 applyGuessedInsets();
 485 
 486                 //Fix for 6318109: PIT: Min Size is not honored properly when a
 487                 //smaller size is specified in setSize(), XToolkit
 488                 //update minimum size hints
 489                 updateMinSizeHints();
 490             }
 491             if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 492                 insLog.finer("Dimensions before reparent: " + dimensions);
 493             }
 494 
 495             dimensions.setInsets(getRealInsets());
 496             insets_corrected = true;
 497 
 498             if (isMaximized()) {
 499                 return;
 500             }
 501 
 502             /*
 503              * If this window has been sized by a pack() we need
 504              * to keep the interior geometry intact.  Since pack()
 505              * computed width and height with wrong insets, we
 506              * must adjust the target dimensions appropriately.
 507              */
 508             if ((getHints().get_flags() & (XUtilConstants.USPosition | XUtilConstants.PPosition)) != 0) {
 509                 reshape(dimensions, SET_BOUNDS, false);
 510             } else {
 511                 reshape(dimensions, SET_SIZE, false);
 512             }
 513         } finally {
 514             XToolkit.awtUnlock();
 515         }
 516     }
 517 
 518     public void handleMoved(WindowDimensions dims) {
 519         Point loc = dims.getLocation();
 520         AWTAccessor.getComponentAccessor().setLocation(target, loc.x, loc.y);
 521         postEvent(new ComponentEvent(target, ComponentEvent.COMPONENT_MOVED));
 522     }
 523 
 524 
 525     protected Insets guessInsets() {
 526         if (isEmbedded() || isTargetUndecorated()) {
 527             return new Insets(0, 0, 0, 0);
 528         } else {
 529             if (!isNull(currentInsets)) {
 530                 /* insets were set on wdata by System Properties */
 531                 return copy(currentInsets);
 532             } else {
 533                 Insets res = getWMSetInsets(null);
 534                 if (res == null) {
 535                     res = XWM.getWM().guessInsets(this);
 536                     if (res != null) {
 537                         res = copyAndScaleDown(res);
 538                     }
 539                 }
 540                 return res;
 541             }
 542         }
 543     }
 544 
 545     private void applyGuessedInsets() {
 546         Insets guessed = guessInsets();
 547         currentInsets = copy(guessed);
 548     }
 549 
 550     public void revalidate() {
 551         XToolkit.executeOnEventHandlerThread(target, new Runnable() {
 552                 public void run() {
 553                     target.invalidate();
 554                     target.validate();
 555                 }
 556             });
 557     }
 558 
 559     Insets getRealInsets() {
 560         if (isNull(currentInsets)) {
 561             applyGuessedInsets();
 562         }
 563         return currentInsets;
 564     }
 565 
 566     public Insets getInsets() {
 567         Insets in = copy(getRealInsets());
 568         in.top += getMenuBarHeight();
 569         if (insLog.isLoggable(PlatformLogger.Level.FINEST)) {
 570             insLog.finest("Get insets returns {0}", in);
 571         }
 572         return in;
 573     }
 574 
 575     boolean gravityBug() {
 576         return XWM.configureGravityBuggy();
 577     }
 578 
 579     // The height of area used to display current active input method
 580     int getInputMethodHeight() {
 581         return 0;
 582     }
 583 
 584     void updateSizeHints(WindowDimensions dims) {
 585         Rectangle rec = dims.getClientRect();
 586         checkShellRect(rec);
 587         updateSizeHints(rec.x, rec.y, rec.width, rec.height);
 588     }
 589 
 590     void updateSizeHints() {
 591         updateSizeHints(dimensions);
 592     }
 593 
 594     // Coordinates are that of the target
 595     // Called only on Toolkit thread
 596     public void reshape(WindowDimensions newDimensions, int op,
 597                         boolean userReshape)
 598     {
 599         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 600             insLog.fine("Reshaping " + this + " to " + newDimensions + " op " + op + " user reshape " + userReshape);
 601         }
 602         if (userReshape) {
 603             // We handle only userReshape == true cases. It means that
 604             // if the window manager or any other part of the windowing
 605             // system sets inappropriate size for this window, we can
 606             // do nothing but accept it.
 607             Rectangle newBounds = newDimensions.getBounds();
 608             Insets insets = newDimensions.getInsets();
 609             // Inherit isClientSizeSet from newDimensions
 610             if (newDimensions.isClientSizeSet()) {
 611                 newBounds = new Rectangle(newBounds.x, newBounds.y,
 612                                           newBounds.width - insets.left - insets.right,
 613                                           newBounds.height - insets.top - insets.bottom);
 614             }
 615             newDimensions = new WindowDimensions(newBounds, insets, newDimensions.isClientSizeSet());
 616         }
 617         XToolkit.awtLock();
 618         try {
 619             if (!isReparented() || !isVisible()) {
 620                 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 621                     insLog.fine("- not reparented({0}) or not visible({1}), default reshape",
 622                            Boolean.valueOf(isReparented()), Boolean.valueOf(visible));
 623                 }
 624 
 625                 // Fix for 6323293.
 626                 // This actually is needed to preserve compatibility with previous releases -
 627                 // some of licensees are expecting componentMoved event on invisible one while
 628                 // its location changes.
 629                 Point oldLocation = getLocation();
 630 
 631                 Point newLocation = new Point(AWTAccessor.getComponentAccessor().getX(target),
 632                                               AWTAccessor.getComponentAccessor().getY(target));
 633 
 634                 if (!newLocation.equals(oldLocation)) {
 635                     handleMoved(newDimensions);
 636                 }
 637 
 638                 dimensions = new WindowDimensions(newDimensions);
 639                 updateSizeHints(dimensions);
 640                 Rectangle client = dimensions.getClientRect();
 641                 checkShellRect(client);
 642                 setShellBounds(client);
 643                 if (content != null &&
 644                     !content.getSize().equals(newDimensions.getSize()))
 645                 {
 646                     reconfigureContentWindow(newDimensions);
 647                 }
 648                 return;
 649             }
 650 
 651             int wm = XWM.getWMID();
 652             updateChildrenSizes();
 653             applyGuessedInsets();
 654 
 655             Rectangle shellRect = newDimensions.getClientRect();
 656 
 657             if (gravityBug()) {
 658                 Insets in = newDimensions.getInsets();
 659                 shellRect.translate(in.left, in.top);
 660             }
 661 
 662             if ((op & NO_EMBEDDED_CHECK) == 0 && isEmbedded()) {
 663                 shellRect.setLocation(0, 0);
 664             }
 665 
 666             checkShellRectSize(shellRect);
 667             if (!isEmbedded()) {
 668                 checkShellRectPos(shellRect);
 669             }
 670 
 671             op = op & ~NO_EMBEDDED_CHECK;
 672 
 673             if (op == SET_LOCATION) {
 674                 setShellPosition(shellRect);
 675             } else if (isResizable()) {
 676                 if (op == SET_BOUNDS) {
 677                     setShellBounds(shellRect);
 678                 } else {
 679                     setShellSize(shellRect);
 680                 }
 681             } else {
 682                 XWM.setShellNotResizable(this, newDimensions, shellRect, true);
 683                 if (op == SET_BOUNDS) {
 684                     setShellPosition(shellRect);
 685                 }
 686             }
 687 
 688             reconfigureContentWindow(newDimensions);
 689         } finally {
 690             XToolkit.awtUnlock();
 691         }
 692     }
 693 
 694     /**
 695      * @param x, y, width, heith - dimensions of the window with insets
 696      */
 697     private void reshape(int x, int y, int width, int height, int operation,
 698                          boolean userReshape)
 699     {
 700         XToolkit.awtLock();
 701         try {
 702             WindowDimensions dims = new WindowDimensions(dimensions);
 703             switch (operation & (~NO_EMBEDDED_CHECK)) {
 704                 case SET_LOCATION:
 705                     // Set location always sets bounds location. However, until the window is mapped we
 706                     // should use client coordinates
 707                     dims.setLocation(x, y);
 708                     break;
 709                 case SET_SIZE:
 710                     // Set size sets bounds size. However, until the window is mapped we
 711                     // should use client coordinates
 712                     dims.setSize(width, height);
 713                     break;
 714                 case SET_CLIENT_SIZE: {
 715                     // Sets client rect size. Width and height contain insets.
 716                     Insets in = currentInsets;
 717                     width -= in.left + in.right;
 718                     height -= in.top + in.bottom;
 719                     dims.setClientSize(width, height);
 720                     break;
 721                 }
 722                 case SET_BOUNDS:
 723                 default:
 724                     dims.setLocation(x, y);
 725                     dims.setSize(width, height);
 726                     break;
 727             }
 728             if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 729                 insLog.fine("For the operation {0} new dimensions are {1}",
 730                         operationToString(operation), dims);
 731             }
 732 
 733             reshape(dims, operation, userReshape);
 734         } finally {
 735             XToolkit.awtUnlock();
 736         }
 737     }
 738 
 739     // This method gets overriden in XFramePeer & XDialogPeer.
 740     abstract boolean isTargetUndecorated();
 741 
 742     /**
 743      * @see java.awt.peer.ComponentPeer#setBounds
 744      */
 745     public void setBounds(int x, int y, int width, int height, int op) {
 746         // TODO: Rewrite with WindowDimensions
 747         reshape(x, y, width, height, op, true);
 748         validateSurface();
 749     }
 750 
 751     // Coordinates are that of the shell
 752     void reconfigureContentWindow(WindowDimensions dims) {
 753         if (content == null) {
 754             insLog.fine("WARNING: Content window is null");
 755             return;
 756         }
 757         content.setContentBounds(dims);
 758     }
 759 
 760     boolean no_reparent_artifacts = false;
 761     public void handleConfigureNotifyEvent(XEvent xev) {
 762         if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM && !insets_corrected) {
 763             return;
 764         }
 765         assert (SunToolkit.isAWTLockHeldByCurrentThread());
 766         XConfigureEvent xe = xev.get_xconfigure();
 767         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 768             insLog.fine("Configure notify {0}", xe);
 769         }
 770 
 771         // XXX: should really only consider synthetic events, but
 772         if (isReparented()) {
 773             configure_seen = true;
 774         }
 775         XToolkit.awtLock();
 776         try {
 777             if (!isMaximized()
 778                     && (xe.get_serial() == reparent_serial
 779                     || xe.get_window() != getShell())
 780                     && !no_reparent_artifacts) {
 781                 insLog.fine("- reparent artifact, skipping");
 782                 return;
 783             }
 784             no_reparent_artifacts = false;
 785 
 786             /**
 787              * When there is a WM we receive some CN before being visible and
 788              * after. We should skip all CN which are before being visible,
 789              * because we assume the gravity is in action while it is not yet.
 790              *
 791              * When there is no WM we receive CN only _before_ being visible.
 792              * We should process these CNs.
 793              */
 794             if (!isVisible() && XWM.getWMID() != XWM.NO_WM) {
 795                 insLog.fine(" - not visible, skipping");
 796                 return;
 797             }
 798 
 799         /*
 800          * Some window managers configure before we are reparented and
 801          * the send event flag is set! ugh... (Enlighetenment for one,
 802          * possibly MWM as well).  If we haven't been reparented yet
 803          * this is just the WM shuffling us into position.  Ignore
 804          * it!!!! or we wind up in a bogus location.
 805          */
 806             int runningWM = XWM.getWMID();
 807             if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 808                 insLog.fine("reparented={0}, visible={1}, WM={2}, " +
 809                       "decorations={3}", isReparented(), isVisible(),
 810                                                    runningWM, getDecorations());
 811             }
 812             if (!isReparented() && isVisible() && runningWM != XWM.NO_WM
 813                        && !XWM.isNonReparentingWM() && getDecorations() !=
 814                                          XWindowAttributesData.AWT_DECOR_NONE) {
 815                 insLog.fine("- visible but not reparented, skipping");
 816                 return;
 817             }
 818             //Last chance to correct insets
 819             if (!insets_corrected && getDecorations() !=
 820                                          XWindowAttributesData.AWT_DECOR_NONE) {
 821                 long parent = XlibUtil.getParentWindow(window);
 822                 Insets correctWM = (parent != -1) ? XWM.getWM().
 823                                          getInsets(this, window, parent) : null;
 824                 if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 825                     if (correctWM != null) {
 826                         insLog.finer("Configure notify - insets : "
 827                                                                    + correctWM);
 828                     } else {
 829                         insLog.finer("Configure notify - insets are still " +
 830                                 "                               not available");
 831                     }
 832                 }
 833                 if (correctWM != null) {
 834                     handleCorrectInsets(copyAndScaleDown(correctWM));
 835                 } else {
 836                     //Only one attempt to correct insets is made (to lower risk)
 837                     //if insets are still not available we simply set the flag
 838                     insets_corrected = true;
 839                 }
 840             }
 841 
 842             updateChildrenSizes();
 843 
 844             Point newLocation = getNewLocation(xe, currentInsets.left,
 845                                                              currentInsets.top);
 846             WindowDimensions newDimensions =
 847                     new WindowDimensions(newLocation,
 848                             new Dimension(scaleDown(xe.get_width()),
 849                                     scaleDown(xe.get_height())),
 850                             copy(currentInsets), true);
 851 
 852             if (insLog.isLoggable(PlatformLogger.Level.FINER)) {
 853                 insLog.finer("Insets are {0}, new dimensions {1}",
 854                         currentInsets, newDimensions);
 855             }
 856 
 857             checkIfOnNewScreen(newDimensions.getBounds());
 858 
 859             Point oldLocation = getLocation();
 860             dimensions = newDimensions;
 861             if (!newLocation.equals(oldLocation)) {
 862                 handleMoved(newDimensions);
 863             }
 864             reconfigureContentWindow(newDimensions);
 865             updateChildrenSizes();
 866 
 867             repositionSecurityWarning();
 868         } finally {
 869             XToolkit.awtUnlock();
 870         }
 871     }
 872 
 873     private void checkShellRectSize(Rectangle shellRect) {
 874         shellRect.width = Math.max(MIN_SIZE, shellRect.width);
 875         shellRect.height = Math.max(MIN_SIZE, shellRect.height);
 876     }
 877 
 878     private void checkShellRectPos(Rectangle shellRect) {
 879         int wm = XWM.getWMID();
 880         if (wm == XWM.MOTIF_WM || wm == XWM.CDE_WM) {
 881             if (shellRect.x == 0 && shellRect.y == 0) {
 882                 shellRect.x = shellRect.y = 1;
 883             }
 884         }
 885     }
 886 
 887     private void checkShellRect(Rectangle shellRect) {
 888         checkShellRectSize(shellRect);
 889         checkShellRectPos(shellRect);
 890     }
 891 
 892     public void setShellBounds(Rectangle rec) {
 893         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 894             insLog.fine("Setting shell bounds on " + this + " to " + rec);
 895         }
 896         XToolkit.awtLock();
 897         try {
 898             updateSizeHints(rec.x, rec.y, rec.width, rec.height);
 899             XlibWrapper.XMoveResizeWindow(XToolkit.getDisplay(), getShell(),
 900                                           scaleUp(rec.x), scaleUp(rec.y),
 901                                           scaleUp(rec.width), scaleUp(rec.height));
 902         }
 903         finally {
 904             XToolkit.awtUnlock();
 905         }
 906     }
 907     public void setShellSize(Rectangle rec) {
 908         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 909             insLog.fine("Setting shell size on " + this + " to " + rec);
 910         }
 911         XToolkit.awtLock();
 912         try {
 913             updateSizeHints(rec.x, rec.y, rec.width, rec.height);
 914             XlibWrapper.XResizeWindow(XToolkit.getDisplay(), getShell(),
 915                                       scaleUp(rec.width), scaleUp(rec.height));
 916         }
 917         finally {
 918             XToolkit.awtUnlock();
 919         }
 920     }
 921     public void setShellPosition(Rectangle rec) {
 922         if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
 923             insLog.fine("Setting shell position on " + this + " to " + rec);
 924         }
 925         XToolkit.awtLock();
 926         try {
 927             updateSizeHints(rec.x, rec.y, rec.width, rec.height);
 928             XlibWrapper.XMoveWindow(XToolkit.getDisplay(), getShell(),
 929                                     scaleUp(rec.x), scaleUp(rec.y));
 930         }
 931         finally {
 932             XToolkit.awtUnlock();
 933         }
 934     }
 935 
 936     void initResizability() {
 937         setResizable(winAttr.initialResizability);
 938     }
 939     public void setResizable(boolean resizable) {
 940         XToolkit.awtLock();
 941         try {
 942             int fs = winAttr.functions;
 943             if (!isResizable() && resizable) {
 944                 resetWMSetInsets();
 945                 if (!isEmbedded()) {
 946                     setReparented(false);
 947                 }
 948                 winAttr.isResizable = resizable;
 949                 if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
 950                     fs &= ~(MWMConstants.MWM_FUNC_RESIZE
 951                           | MWMConstants.MWM_FUNC_MAXIMIZE);
 952                 } else {
 953                     fs |= (MWMConstants.MWM_FUNC_RESIZE
 954                          | MWMConstants.MWM_FUNC_MAXIMIZE);
 955                 }
 956                 winAttr.functions = fs;
 957                 XWM.setShellResizable(this);
 958             } else if (isResizable() && !resizable) {
 959                 resetWMSetInsets();
 960                 if (!isEmbedded()) {
 961                     setReparented(false);
 962                 }
 963                 winAttr.isResizable = resizable;
 964                 if ((fs & MWMConstants.MWM_FUNC_ALL) != 0) {
 965                     fs |= (MWMConstants.MWM_FUNC_RESIZE
 966                          | MWMConstants.MWM_FUNC_MAXIMIZE);
 967                 } else {
 968                     fs &= ~(MWMConstants.MWM_FUNC_RESIZE
 969                           | MWMConstants.MWM_FUNC_MAXIMIZE);
 970                 }
 971                 winAttr.functions = fs;
 972                 XWM.setShellNotResizable(this, dimensions,
 973                         XWM.getWMID() == XWM.UNITY_COMPIZ_WM && configure_seen ?
 974                         dimensions.getScreenBounds() :
 975                         dimensions.getBounds(), false);
 976             }
 977         } finally {
 978             XToolkit.awtUnlock();
 979         }
 980     }
 981 
 982     Rectangle getShellBounds() {
 983         return dimensions.getClientRect();
 984     }
 985 
 986     public Rectangle getBounds() {
 987         return dimensions.getBounds();
 988     }
 989 
 990     public Dimension getSize() {
 991         return dimensions.getSize();
 992     }
 993 
 994     public int getX() {
 995         return dimensions.getLocation().x;
 996     }
 997 
 998     public int getY() {
 999         return dimensions.getLocation().y;
1000     }
1001 
1002     public Point getLocation() {
1003         return dimensions.getLocation();
1004     }
1005 
1006     public int getAbsoluteX() {
1007         // NOTE: returning this peer's location which is shell location
1008         return dimensions.getScreenBounds().x;
1009     }
1010 
1011     public int getAbsoluteY() {
1012         // NOTE: returning this peer's location which is shell location
1013         return dimensions.getScreenBounds().y;
1014     }
1015 
1016     public int getWidth() {
1017         return getSize().width;
1018     }
1019 
1020     public int getHeight() {
1021         return getSize().height;
1022     }
1023 
1024     public final WindowDimensions getDimensions() {
1025         return dimensions;
1026     }
1027 
1028     public Point getLocationOnScreen() {
1029         XToolkit.awtLock();
1030         try {
1031             if (configure_seen) {
1032                 return toGlobal(0,0);
1033             } else {
1034                 Point location = target.getLocation();
1035                 if (insLog.isLoggable(PlatformLogger.Level.FINE)) {
1036                     insLog.fine("getLocationOnScreen {0} not reparented: {1} ",
1037                                 this, location);
1038                 }
1039                 return location;
1040             }
1041         } finally {
1042             XToolkit.awtUnlock();
1043         }
1044     }
1045 
1046 
1047 /***************************************************************************************
1048  *              END            OF             I N S E T S   C O D E
1049  **************************************************************************************/
1050 
1051     protected boolean isEventDisabled(XEvent e) {
1052         switch (e.get_type()) {
1053             // Do not generate MOVED/RESIZED events since we generate them by ourselves
1054           case XConstants.ConfigureNotify:
1055               return true;
1056           case XConstants.EnterNotify:
1057           case XConstants.LeaveNotify:
1058               // Disable crossing event on outer borders of Frame so
1059               // we receive only one set of cross notifications(first set is from content window)
1060               return true;
1061           default:
1062               return super.isEventDisabled(e);
1063         }
1064     }
1065 
1066     int getDecorations() {
1067         return winAttr.decorations;
1068     }
1069 
1070     int getFunctions() {
1071         return winAttr.functions;
1072     }
1073 
1074     public void setVisible(boolean vis) {
1075         if (log.isLoggable(PlatformLogger.Level.FINER)) {
1076             log.finer("Setting {0} to visible {1}", this, Boolean.valueOf(vis));
1077         }
1078         if (vis && !isVisible()) {
1079             XWM.setShellDecor(this);
1080             super.setVisible(vis);
1081             if (winAttr.isResizable) {
1082                 //Fix for 4320050: Minimum size for java.awt.Frame is not being enforced.
1083                 //We need to update frame's minimum size, not to reset it
1084                 XWM.removeSizeHints(this, XUtilConstants.PMaxSize);
1085                 updateMinimumSize();
1086             }
1087         } else {
1088             super.setVisible(vis);
1089         }
1090     }
1091 
1092     protected void suppressWmTakeFocus(boolean doSuppress) {
1093         XAtomList protocols = getWMProtocols();
1094         if (doSuppress) {
1095             protocols.remove(wm_take_focus);
1096         } else {
1097             protocols.add(wm_take_focus);
1098         }
1099         wm_protocols.setAtomListProperty(this, protocols);
1100     }
1101 
1102     public void dispose() {
1103         if (content != null) {
1104             content.destroy();
1105         }
1106         focusProxy.destroy();
1107 
1108         if (iconWindow != null) {
1109             iconWindow.destroy();
1110         }
1111 
1112         super.dispose();
1113     }
1114 
1115     public void handleClientMessage(XEvent xev) {
1116         super.handleClientMessage(xev);
1117         XClientMessageEvent cl = xev.get_xclient();
1118         if ((wm_protocols != null) && (cl.get_message_type() == wm_protocols.getAtom())) {
1119             if (cl.get_data(0) == wm_delete_window.getAtom()) {
1120                 handleQuit();
1121             } else if (cl.get_data(0) == wm_take_focus.getAtom()) {
1122                 handleWmTakeFocus(cl);
1123             }
1124         }
1125     }
1126 
1127     private void handleWmTakeFocus(XClientMessageEvent cl) {
1128         if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1129             focusLog.fine("WM_TAKE_FOCUS on {0}", this);
1130         }
1131 
1132         if (XWM.getWMID() == XWM.UNITY_COMPIZ_WM) {
1133             // JDK-8159460
1134             Window focusedWindow = XKeyboardFocusManagerPeer.getInstance()
1135                     .getCurrentFocusedWindow();
1136             Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
1137             if (activeWindow != target) {
1138                 requestWindowFocus(cl.get_data(1), true);
1139             } else {
1140                 WindowEvent we = new WindowEvent(focusedWindow,
1141                         WindowEvent.WINDOW_GAINED_FOCUS);
1142                 sendEvent(we);
1143             }
1144         } else {
1145             requestWindowFocus(cl.get_data(1), true);
1146         }
1147     }
1148 
1149     /**
1150      * Requests focus to this decorated top-level by requesting X input focus
1151      * to the shell window.
1152      */
1153     protected void requestXFocus(long time, boolean timeProvided) {
1154         // We have proxied focus mechanism - instead of shell the focus is held
1155         // by "proxy" - invisible mapped window. When we want to set X input focus to
1156         // toplevel set it on proxy instead.
1157         if (focusProxy == null) {
1158             if (focusLog.isLoggable(PlatformLogger.Level.WARNING)) {
1159                 focusLog.warning("Focus proxy is null for " + this);
1160             }
1161         } else {
1162             if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1163                 focusLog.fine("Requesting focus to proxy: " + focusProxy);
1164             }
1165             if (timeProvided) {
1166                 focusProxy.xRequestFocus(time);
1167             } else {
1168                 focusProxy.xRequestFocus();
1169             }
1170         }
1171     }
1172 
1173     XFocusProxyWindow getFocusProxy() {
1174         return focusProxy;
1175     }
1176 
1177     public void handleQuit() {
1178         postEvent(new WindowEvent((Window)target, WindowEvent.WINDOW_CLOSING));
1179     }
1180 
1181     final void dumpMe() {
1182         System.err.println(">>> Peer: " + x + ", " + y + ", " + width + ", " + height);
1183     }
1184 
1185     final void dumpTarget() {
1186         AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
1187         int getWidth = compAccessor.getWidth(target);
1188         int getHeight = compAccessor.getHeight(target);
1189         int getTargetX = compAccessor.getX(target);
1190         int getTargetY = compAccessor.getY(target);
1191         System.err.println(">>> Target: " + getTargetX + ", " + getTargetY + ", " + getWidth + ", " + getHeight);
1192     }
1193 
1194     final void dumpShell() {
1195         dumpWindow("Shell", getShell());
1196     }
1197     final void dumpContent() {
1198         dumpWindow("Content", getContentWindow());
1199     }
1200     final void dumpParent() {
1201         long parent = XlibUtil.getParentWindow(getShell());
1202         if (parent != 0)
1203         {
1204             dumpWindow("Parent", parent);
1205         }
1206         else
1207         {
1208             System.err.println(">>> NO PARENT");
1209         }
1210     }
1211 
1212     final void dumpWindow(String id, long window) {
1213         XWindowAttributes pattr = new XWindowAttributes();
1214         try {
1215             XToolkit.awtLock();
1216             try {
1217                 int status =
1218                     XlibWrapper.XGetWindowAttributes(XToolkit.getDisplay(),
1219                                                      window, pattr.pData);
1220             }
1221             finally {
1222                 XToolkit.awtUnlock();
1223             }
1224             System.err.println(">>>> " + id + ": " + pattr.get_x()
1225                                + ", " + pattr.get_y() + ", " + pattr.get_width()
1226                                + ", " + pattr.get_height());
1227         } finally {
1228             pattr.dispose();
1229         }
1230     }
1231 
1232     final void dumpAll() {
1233         dumpTarget();
1234         dumpMe();
1235         dumpParent();
1236         dumpShell();
1237         dumpContent();
1238     }
1239 
1240     boolean isMaximized() {
1241         return false;
1242     }
1243 
1244     @Override
1245     boolean isOverrideRedirect() {
1246         return Window.Type.POPUP.equals(getWindowType());
1247     }
1248 
1249     public boolean requestWindowFocus(long time, boolean timeProvided) {
1250         focusLog.fine("Request for decorated window focus");
1251         // If this is Frame or Dialog we can't assure focus request success - but we still can try
1252         // If this is Window and its owner Frame is active we can be sure request succedded.
1253         Window focusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
1254         Window activeWindow = XWindowPeer.getDecoratedOwner(focusedWindow);
1255 
1256         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
1257             focusLog.finer("Current window is: active={0}, focused={1}",
1258                        Boolean.valueOf(target == activeWindow),
1259                        Boolean.valueOf(target == focusedWindow));
1260         }
1261 
1262         XWindowPeer toFocus = this;
1263         while (toFocus.nextTransientFor != null) {
1264             toFocus = toFocus.nextTransientFor;
1265         }
1266         if (toFocus == null || !toFocus.focusAllowedFor()) {
1267             // This might change when WM will have property to determine focus policy.
1268             // Right now, because policy is unknown we can't be sure we succedded
1269             return false;
1270         }
1271         if (this == toFocus) {
1272             if (isWMStateNetHidden()) {
1273                 focusLog.fine("The window is unmapped, so rejecting the request");
1274                 return false;
1275             }
1276             if (target == activeWindow && target != focusedWindow) {
1277                 // Happens when an owned window is currently focused
1278                 focusLog.fine("Focus is on child window - transferring it back to the owner");
1279                 handleWindowFocusInSync(-1);
1280                 return true;
1281             }
1282             Window realNativeFocusedWindow = XWindowPeer.getNativeFocusedWindow();
1283             if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
1284                 focusLog.finest("Real native focused window: " + realNativeFocusedWindow +
1285                             "\nKFM's focused window: " + focusedWindow);
1286             }
1287 
1288             // A workaround for Metacity. See 6522725, 6613426, 7147075.
1289             if (target == realNativeFocusedWindow && XWM.getWMID() == XWM.METACITY_WM) {
1290                 if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1291                     focusLog.fine("The window is already natively focused.");
1292                 }
1293                 return true;
1294             }
1295         }
1296         if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
1297             focusLog.fine("Requesting focus to " + (this == toFocus ? "this window" : toFocus));
1298         }
1299 
1300         if (timeProvided) {
1301             toFocus.requestXFocus(time);
1302         } else {
1303             toFocus.requestXFocus();
1304         }
1305         return (this == toFocus);
1306     }
1307 
1308     XWindowPeer actualFocusedWindow = null;
1309     void setActualFocusedWindow(XWindowPeer actualFocusedWindow) {
1310         synchronized(getStateLock()) {
1311             this.actualFocusedWindow = actualFocusedWindow;
1312         }
1313     }
1314 
1315     boolean requestWindowFocus(XWindowPeer actualFocusedWindow,
1316                                long time, boolean timeProvided)
1317     {
1318         setActualFocusedWindow(actualFocusedWindow);
1319         return requestWindowFocus(time, timeProvided);
1320     }
1321     public void handleWindowFocusIn(long serial) {
1322         if (null == actualFocusedWindow) {
1323             super.handleWindowFocusIn(serial);
1324         } else {
1325             /*
1326              * Fix for 6314575.
1327              * If this is a result of clicking on one of the Frame's component
1328              * then 'actualFocusedWindow' shouldn't be focused. A decision of focusing
1329              * it or not should be made after the appropriate Java mouse event (if any)
1330              * is handled by the component where 'actualFocusedWindow' value may be reset.
1331              *
1332              * The fix is based on the empiric fact consisting in that the component
1333              * receives native mouse event nearly at the same time the Frame receives
1334              * WM_TAKE_FOCUS (when FocusIn is generated via XSetInputFocus call) but
1335              * definetely before the Frame gets FocusIn event (when this method is called).
1336              */
1337             postEvent(new InvocationEvent(target, new Runnable() {
1338                 public void run() {
1339                     XWindowPeer fw = null;
1340                     synchronized (getStateLock()) {
1341                         fw = actualFocusedWindow;
1342                         actualFocusedWindow = null;
1343                         if (null == fw || !fw.isVisible() || !fw.isFocusableWindow()) {
1344                             fw = XDecoratedPeer.this;
1345                         }
1346                     }
1347                     fw.handleWindowFocusIn_Dispatch();
1348                 }
1349             }));
1350         }
1351     }
1352 
1353     public void handleWindowFocusOut(Window oppositeWindow, long serial) {
1354         Window actualFocusedWindow = XKeyboardFocusManagerPeer.getInstance().getCurrentFocusedWindow();
1355 
1356         // If the actual focused window is not this decorated window then retain it.
1357         if (actualFocusedWindow != null && actualFocusedWindow != target) {
1358             Window owner = XWindowPeer.getDecoratedOwner(actualFocusedWindow);
1359 
1360             if (owner != null && owner == target) {
1361                 setActualFocusedWindow(AWTAccessor.getComponentAccessor().getPeer(actualFocusedWindow));
1362             }
1363         }
1364         super.handleWindowFocusOut(oppositeWindow, serial);
1365     }
1366 }