1 /*
   2  * Copyright (c) 2002, 2014, 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.AWTEvent;
  28 import java.awt.AWTException;
  29 import java.awt.BufferCapabilities;
  30 import java.awt.Color;
  31 import java.awt.Component;
  32 import java.awt.Container;
  33 import java.awt.Cursor;
  34 import java.awt.Dimension;
  35 import java.awt.Font;
  36 import java.awt.FontMetrics;
  37 import java.awt.Graphics;
  38 import java.awt.GraphicsConfiguration;
  39 import java.awt.Image;
  40 import java.awt.Insets;
  41 import java.awt.Rectangle;
  42 import java.awt.SystemColor;
  43 import java.awt.Toolkit;
  44 import java.awt.Window;
  45 import java.awt.dnd.DropTarget;
  46 import java.awt.dnd.peer.DropTargetPeer;
  47 import java.awt.event.FocusEvent;
  48 import java.awt.event.InputEvent;
  49 import java.awt.event.InputMethodEvent;
  50 import java.awt.event.KeyEvent;
  51 import java.awt.event.MouseEvent;
  52 import java.awt.event.MouseWheelEvent;
  53 import java.awt.event.PaintEvent;
  54 import java.awt.event.WindowEvent;
  55 import java.awt.event.InvocationEvent;
  56 import java.awt.image.ImageObserver;
  57 import java.awt.image.ImageProducer;
  58 import java.awt.image.VolatileImage;
  59 import java.awt.peer.ComponentPeer;
  60 import java.awt.peer.ContainerPeer;
  61 import java.lang.reflect.*;
  62 import java.security.*;
  63 import java.util.Collection;
  64 import java.util.Objects;
  65 import java.util.Set;
  66 import sun.util.logging.PlatformLogger;
  67 import sun.awt.*;
  68 import sun.awt.event.IgnorePaintEvent;
  69 import sun.awt.image.SunVolatileImage;
  70 import sun.awt.image.ToolkitImage;
  71 import sun.java2d.BackBufferCapsProvider;
  72 import sun.java2d.pipe.Region;
  73 
  74 
  75 public class XComponentPeer extends XWindow implements ComponentPeer, DropTargetPeer,
  76     BackBufferCapsProvider
  77 {
  78     private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.X11.XComponentPeer");
  79     private static final PlatformLogger buffersLog = PlatformLogger.getLogger("sun.awt.X11.XComponentPeer.multibuffer");
  80     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.X11.focus.XComponentPeer");
  81     private static final PlatformLogger fontLog = PlatformLogger.getLogger("sun.awt.X11.font.XComponentPeer");
  82     private static final PlatformLogger enableLog = PlatformLogger.getLogger("sun.awt.X11.enable.XComponentPeer");
  83     private static final PlatformLogger shapeLog = PlatformLogger.getLogger("sun.awt.X11.shape.XComponentPeer");
  84 
  85     boolean paintPending = false;
  86     boolean isLayouting = false;
  87     private boolean enabled;
  88 
  89     // Actually used only by XDecoratedPeer
  90     protected int boundsOperation;
  91 
  92     Color foreground;
  93     Color background;
  94 
  95     // Colors calculated as on Motif using MotifColorUtilties.
  96     // If you use these, call updateMotifColors() in the peer's Constructor and
  97     // setBackground().  Examples are XCheckboxPeer and XButtonPeer.
  98     Color darkShadow;
  99     Color lightShadow;
 100     Color selectColor;
 101 
 102     Font font;
 103     private long backBuffer = 0;
 104     private VolatileImage xBackBuffer = null;
 105 
 106     static Color[] systemColors;
 107 
 108     XComponentPeer() {
 109     }
 110 
 111     XComponentPeer (XCreateWindowParams params) {
 112         super(params);
 113     }
 114 
 115     XComponentPeer(Component target, long parentWindow, Rectangle bounds) {
 116         super(target, parentWindow, bounds);
 117     }
 118 
 119     /**
 120      * Standard peer constructor, with corresponding Component
 121      */
 122     XComponentPeer(Component target) {
 123         super(target);
 124     }
 125 
 126 
 127     void preInit(XCreateWindowParams params) {
 128         super.preInit(params);
 129         boundsOperation = DEFAULT_OPERATION;
 130     }
 131     void postInit(XCreateWindowParams params) {
 132         super.postInit(params);
 133 
 134         pSetCursor(target.getCursor());
 135 
 136         foreground = target.getForeground();
 137         background = target.getBackground();
 138         font = target.getFont();
 139 
 140         if (isInitialReshape()) {
 141             Rectangle r = target.getBounds();
 142             reshape(r.x, r.y, r.width, r.height);
 143         }
 144 
 145         setEnabled(target.isEnabled());
 146 
 147         if (target.isVisible()) {
 148             setVisible(true);
 149         }
 150     }
 151 
 152     protected boolean isInitialReshape() {
 153         return true;
 154     }
 155 
 156     public void reparent(ContainerPeer newNativeParent) {
 157         XComponentPeer newPeer = (XComponentPeer)newNativeParent;
 158         XToolkit.awtLock();
 159         try {
 160             XlibWrapper.XReparentWindow(XToolkit.getDisplay(), getWindow(), newPeer.getContentWindow(), x, y);
 161             parentWindow = newPeer;
 162         } finally {
 163             XToolkit.awtUnlock();
 164         }
 165     }
 166     public boolean isReparentSupported() {
 167         return System.getProperty("sun.awt.X11.XComponentPeer.reparentNotSupported", "false").equals("false");
 168     }
 169 
 170     public boolean isObscured() {
 171         Container container  = (target instanceof Container) ?
 172             (Container)target : target.getParent();
 173 
 174         if (container == null) {
 175             return true;
 176         }
 177 
 178         Container parent;
 179         while ((parent = container.getParent()) != null) {
 180             container = parent;
 181         }
 182 
 183         if (container instanceof Window) {
 184             XWindowPeer wpeer = (XWindowPeer)(container.getPeer());
 185             if (wpeer != null) {
 186                 return (wpeer.winAttr.visibilityState !=
 187                         XWindowAttributesData.AWT_UNOBSCURED);
 188             }
 189         }
 190         return true;
 191     }
 192 
 193     public boolean canDetermineObscurity() {
 194         return true;
 195     }
 196 
 197     /*************************************************
 198      * FOCUS STUFF
 199      *************************************************/
 200 
 201     /**
 202      * Keeps the track of focused state of the _NATIVE_ window
 203      */
 204     boolean bHasFocus = false;
 205 
 206     /**
 207      * Descendants should use this method to determine whether or not native window
 208      * has focus.
 209      */
 210     final public boolean hasFocus() {
 211         return bHasFocus;
 212     }
 213 
 214     /**
 215      * Called when component receives focus
 216      */
 217     public void focusGained(FocusEvent e) {
 218         if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
 219             focusLog.fine("{0}", e);
 220         }
 221         bHasFocus = true;
 222     }
 223 
 224     /**
 225      * Called when component loses focus
 226      */
 227     public void focusLost(FocusEvent e) {
 228         if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
 229             focusLog.fine("{0}", e);
 230         }
 231         bHasFocus = false;
 232     }
 233 
 234     public boolean isFocusable() {
 235         /* should be implemented by other sub-classes */
 236         return false;
 237     }
 238 
 239     private static Class<?> seClass;
 240     private static Constructor<?> seCtor;
 241 
 242     final static AWTEvent wrapInSequenced(AWTEvent event) {
 243         try {
 244             if (seClass == null) {
 245                 seClass = Class.forName("java.awt.SequencedEvent");
 246             }
 247 
 248             if (seCtor == null) {
 249                 seCtor = AccessController.doPrivileged(new
 250                     PrivilegedExceptionAction<Constructor<?>>() {
 251                         public Constructor<?> run() throws Exception {
 252                             Constructor<?> ctor = seClass.getConstructor(
 253                                 new Class<?>[] { AWTEvent.class });
 254                             ctor.setAccessible(true);
 255                             return ctor;
 256                         }
 257                     });
 258             }
 259 
 260             return (AWTEvent) seCtor.newInstance(new Object[] { event });
 261         }
 262         catch (ClassNotFoundException e) {
 263             throw new NoClassDefFoundError("java.awt.SequencedEvent.");
 264         }
 265         catch (PrivilegedActionException ex) {
 266             throw new NoClassDefFoundError("java.awt.SequencedEvent.");
 267         }
 268         catch (InstantiationException e) {
 269             assert false;
 270         }
 271         catch (IllegalAccessException e) {
 272             assert false;
 273         }
 274         catch (InvocationTargetException e) {
 275             assert false;
 276         }
 277 
 278         return null;
 279     }
 280 
 281     // TODO: consider moving it to KeyboardFocusManagerPeerImpl
 282     final public boolean requestFocus(Component lightweightChild, boolean temporary,
 283                                       boolean focusedWindowChangeAllowed, long time,
 284                                       CausedFocusEvent.Cause cause)
 285     {
 286         if (XKeyboardFocusManagerPeer.
 287             processSynchronousLightweightTransfer(target, lightweightChild, temporary,
 288                                                   focusedWindowChangeAllowed, time))
 289         {
 290             return true;
 291         }
 292 
 293         int result = XKeyboardFocusManagerPeer.
 294             shouldNativelyFocusHeavyweight(target, lightweightChild,
 295                                            temporary, focusedWindowChangeAllowed,
 296                                            time, cause);
 297 
 298         switch (result) {
 299           case XKeyboardFocusManagerPeer.SNFH_FAILURE:
 300               return false;
 301           case XKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
 302               // Currently we just generate focus events like we deal with lightweight instead of calling
 303               // XSetInputFocus on native window
 304               if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
 305                   focusLog.finer("Proceeding with request to " +
 306                                  lightweightChild + " in " + target);
 307               }
 308               /**
 309                * The problems with requests in non-focused window arise because shouldNativelyFocusHeavyweight
 310                * checks that native window is focused while appropriate WINDOW_GAINED_FOCUS has not yet
 311                * been processed - it is in EventQueue. Thus, SNFH allows native request and stores request record
 312                * in requests list - and it breaks our requests sequence as first record on WGF should be the last
 313                * focus owner which had focus before WLF. So, we should not add request record for such requests
 314                * but store this component in mostRecent - and return true as before for compatibility.
 315                */
 316               Window parentWindow = SunToolkit.getContainingWindow(target);
 317               if (parentWindow == null) {
 318                   return rejectFocusRequestHelper("WARNING: Parent window is null");
 319               }
 320               XWindowPeer wpeer = (XWindowPeer)parentWindow.getPeer();
 321               if (wpeer == null) {
 322                   return rejectFocusRequestHelper("WARNING: Parent window's peer is null");
 323               }
 324               /*
 325                * Passing null 'actualFocusedWindow' as we don't want to restore focus on it
 326                * when a component inside a Frame is requesting focus.
 327                * See 6314575 for details.
 328                */
 329               boolean res = wpeer.requestWindowFocus(null);
 330 
 331               if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
 332                   focusLog.finer("Requested window focus: " + res);
 333               }
 334               // If parent window can be made focused and has been made focused(synchronously)
 335               // then we can proceed with children, otherwise we retreat.
 336               if (!(res && parentWindow.isFocused())) {
 337                   return rejectFocusRequestHelper("Waiting for asynchronous processing of the request");
 338               }
 339               return XKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
 340                                                             target,
 341                                                             temporary,
 342                                                             focusedWindowChangeAllowed,
 343                                                             time, cause);
 344               // Motif compatibility code
 345           case XKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
 346               // Either lightweight or excessive request - all events are generated.
 347               return true;
 348         }
 349         return false;
 350     }
 351 
 352     private boolean rejectFocusRequestHelper(String logMsg) {
 353         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
 354             focusLog.finer(logMsg);
 355         }
 356         XKeyboardFocusManagerPeer.removeLastFocusRequest(target);
 357         return false;
 358     }
 359 
 360     void handleJavaFocusEvent(AWTEvent e) {
 361         if (focusLog.isLoggable(PlatformLogger.Level.FINER)) {
 362             focusLog.finer(e.toString());
 363         }
 364         if (e.getID() == FocusEvent.FOCUS_GAINED) {
 365             focusGained((FocusEvent)e);
 366         } else {
 367             focusLost((FocusEvent)e);
 368         }
 369     }
 370 
 371     void handleJavaWindowFocusEvent(AWTEvent e) {
 372     }
 373 
 374     /*************************************************
 375      * END OF FOCUS STUFF
 376      *************************************************/
 377 
 378 
 379 
 380     public void setVisible(boolean b) {
 381         xSetVisible(b);
 382     }
 383 
 384     public void hide() {
 385         setVisible(false);
 386     }
 387 
 388     /**
 389      * @see java.awt.peer.ComponentPeer
 390      */
 391     public void setEnabled(final boolean value) {
 392         if (enableLog.isLoggable(PlatformLogger.Level.FINE)) {
 393             enableLog.fine("{0}ing {1}", (value ? "Enabl" : "Disabl"), this);
 394         }
 395         boolean status = value;
 396         // If any of our heavyweight ancestors are disable, we should be too
 397         // See 6176875 for more information
 398         final Container cp = SunToolkit.getNativeContainer(target);
 399         if (cp != null) {
 400             status &= ((XComponentPeer) cp.getPeer()).isEnabled();
 401         }
 402         synchronized (getStateLock()) {
 403             if (enabled == status) {
 404                 return;
 405             }
 406             enabled = status;
 407         }
 408 
 409         if (target instanceof Container) {
 410             final Component[] list = ((Container) target).getComponents();
 411             for (final Component child : list) {
 412                 final ComponentPeer p = child.getPeer();
 413                 if (p != null) {
 414                     p.setEnabled(status && child.isEnabled());
 415                 }
 416             }
 417         }
 418         repaint();
 419     }
 420 
 421     //
 422     // public so aw/Window can call it
 423     //
 424     public final boolean isEnabled() {
 425         synchronized (getStateLock()) {
 426             return enabled;
 427         }
 428     }
 429 
 430     @Override
 431     public void paint(final Graphics g) {
 432         super.paint(g);
 433         // allow target to change the picture
 434         target.paint(g);
 435     }
 436 
 437     public Graphics getGraphics() {
 438         return getGraphics(surfaceData, getPeerForeground(), getPeerBackground(), getPeerFont());
 439     }
 440     public void print(Graphics g) {
 441         // clear rect here to emulate X clears rect before Expose
 442         g.setColor(target.getBackground());
 443         g.fillRect(0, 0, target.getWidth(), target.getHeight());
 444         g.setColor(target.getForeground());
 445         // paint peer
 446         paintPeer(g);
 447         // allow target to change the picture
 448         target.print(g);
 449     }
 450 
 451     public void setBounds(int x, int y, int width, int height, int op) {
 452         this.x = x;
 453         this.y = y;
 454         this.width = width;
 455         this.height = height;
 456         xSetBounds(x,y,width,height);
 457         validateSurface();
 458         layout();
 459     }
 460 
 461     public void reshape(int x, int y, int width, int height) {
 462         setBounds(x, y, width, height, SET_BOUNDS);
 463     }
 464 
 465     public void coalescePaintEvent(PaintEvent e) {
 466         Rectangle r = e.getUpdateRect();
 467         if (!(e instanceof IgnorePaintEvent)) {
 468             paintArea.add(r, e.getID());
 469         }
 470         if (true) {
 471             switch(e.getID()) {
 472               case PaintEvent.UPDATE:
 473                   if (log.isLoggable(PlatformLogger.Level.FINER)) {
 474                       log.finer("XCP coalescePaintEvent : UPDATE : add : x = " +
 475                             r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height);
 476                   }
 477                   return;
 478               case PaintEvent.PAINT:
 479                   if (log.isLoggable(PlatformLogger.Level.FINER)) {
 480                       log.finer("XCP coalescePaintEvent : PAINT : add : x = " +
 481                             r.x + ", y = " + r.y + ", width = " + r.width + ",height = " + r.height);
 482                   }
 483                   return;
 484             }
 485         }
 486     }
 487 
 488     XWindowPeer getParentTopLevel() {
 489         AWTAccessor.ComponentAccessor compAccessor = AWTAccessor.getComponentAccessor();
 490         Container parent = (target instanceof Container) ? ((Container)target) : (compAccessor.getParent(target));
 491         // Search for parent window
 492         while (parent != null && !(parent instanceof Window)) {
 493             parent = compAccessor.getParent(parent);
 494         }
 495         if (parent != null) {
 496             return (XWindowPeer)compAccessor.getPeer(parent);
 497         } else {
 498             return null;
 499         }
 500     }
 501 
 502     /* This method is intended to be over-ridden by peers to perform user interaction */
 503     void handleJavaMouseEvent(MouseEvent e) {
 504         switch (e.getID()) {
 505           case MouseEvent.MOUSE_PRESSED:
 506               if (target == e.getSource() &&
 507                   !target.isFocusOwner() &&
 508                   XKeyboardFocusManagerPeer.shouldFocusOnClick(target))
 509               {
 510                   XWindowPeer parentXWindow = getParentTopLevel();
 511                   Window parentWindow = ((Window)parentXWindow.getTarget());
 512                   // Simple windows are non-focusable in X terms but focusable in Java terms.
 513                   // As X-non-focusable they don't receive any focus events - we should generate them
 514                   // by ourselfves.
 515 //                   if (parentXWindow.isFocusableWindow() /*&& parentXWindow.isSimpleWindow()*/ &&
 516 //                       !(getCurrentNativeFocusedWindow() == parentWindow))
 517 //                   {
 518 //                       setCurrentNativeFocusedWindow(parentWindow);
 519 //                       WindowEvent wfg = new WindowEvent(parentWindow, WindowEvent.WINDOW_GAINED_FOCUS);
 520 //                       parentWindow.dispatchEvent(wfg);
 521 //                   }
 522                   XKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);
 523               }
 524               break;
 525         }
 526     }
 527 
 528     /* This method is intended to be over-ridden by peers to perform user interaction */
 529     void handleJavaKeyEvent(KeyEvent e) {
 530     }
 531 
 532     /* This method is intended to be over-ridden by peers to perform user interaction */
 533     void handleJavaMouseWheelEvent(MouseWheelEvent e) {
 534     }
 535 
 536 
 537     /* This method is intended to be over-ridden by peers to perform user interaction */
 538     void handleJavaInputMethodEvent(InputMethodEvent e) {
 539     }
 540 
 541     void handleF10JavaKeyEvent(KeyEvent e) {
 542         if (e.getID() == KeyEvent.KEY_PRESSED && e.getKeyCode() == KeyEvent.VK_F10) {
 543             XWindowPeer winPeer = this.getToplevelXWindow();
 544             if (winPeer instanceof XFramePeer) {
 545                 XMenuBarPeer mPeer = ((XFramePeer)winPeer).getMenubarPeer();
 546                 if (mPeer != null) {
 547                     mPeer.handleF10KeyPress(e);
 548                 }
 549             }
 550         }
 551     }
 552 
 553     @SuppressWarnings("fallthrough")
 554     public void handleEvent(java.awt.AWTEvent e) {
 555         if ((e instanceof InputEvent) && !((InputEvent)e).isConsumed() && target.isEnabled())  {
 556             if (e instanceof MouseEvent) {
 557                 if (e instanceof MouseWheelEvent) {
 558                     handleJavaMouseWheelEvent((MouseWheelEvent) e);
 559                 }
 560                 else
 561                     handleJavaMouseEvent((MouseEvent) e);
 562             }
 563             else if (e instanceof KeyEvent) {
 564                 handleF10JavaKeyEvent((KeyEvent)e);
 565                 handleJavaKeyEvent((KeyEvent)e);
 566             }
 567         }
 568         else if (e instanceof KeyEvent && !((InputEvent)e).isConsumed()) {
 569             // even if target is disabled.
 570             handleF10JavaKeyEvent((KeyEvent)e);
 571         }
 572         else if (e instanceof InputMethodEvent) {
 573             handleJavaInputMethodEvent((InputMethodEvent) e);
 574         }
 575 
 576         int id = e.getID();
 577 
 578         switch(id) {
 579           case PaintEvent.PAINT:
 580               // Got native painting
 581               paintPending = false;
 582               // Fallthrough to next statement
 583           case PaintEvent.UPDATE:
 584               // Skip all painting while layouting and all UPDATEs
 585               // while waiting for native paint
 586               if (!isLayouting && !paintPending) {
 587                   paintArea.paint(target,false);
 588               }
 589               return;
 590           case FocusEvent.FOCUS_LOST:
 591           case FocusEvent.FOCUS_GAINED:
 592               handleJavaFocusEvent(e);
 593               break;
 594           case WindowEvent.WINDOW_LOST_FOCUS:
 595           case WindowEvent.WINDOW_GAINED_FOCUS:
 596               handleJavaWindowFocusEvent(e);
 597               break;
 598           default:
 599               break;
 600         }
 601 
 602     }
 603 
 604     public Dimension getMinimumSize() {
 605         return target.getSize();
 606     }
 607 
 608     public Dimension getPreferredSize() {
 609         return getMinimumSize();
 610     }
 611 
 612     public void layout() {}
 613 
 614     void updateMotifColors(Color bg) {
 615         int red = bg.getRed();
 616         int green = bg.getGreen();
 617         int blue = bg.getBlue();
 618 
 619         darkShadow = new Color(MotifColorUtilities.calculateBottomShadowFromBackground(red,green,blue));
 620         lightShadow = new Color(MotifColorUtilities.calculateTopShadowFromBackground(red,green,blue));
 621         selectColor= new Color(MotifColorUtilities.calculateSelectFromBackground(red,green,blue));
 622     }
 623 
 624     /*
 625      * Draw a 3D rectangle using the Motif colors.
 626      * "Normal" rectangles have shadows on the bottom.
 627      * "Depressed" rectangles (such as pressed buttons) have shadows on the top,
 628      * in which case true should be passed for topShadow.
 629      */
 630     public void drawMotif3DRect(Graphics g,
 631                                           int x, int y, int width, int height,
 632                                           boolean topShadow) {
 633         g.setColor(topShadow ? darkShadow : lightShadow);
 634         g.drawLine(x, y, x+width, y);       // top
 635         g.drawLine(x, y+height, x, y);      // left
 636 
 637         g.setColor(topShadow ? lightShadow : darkShadow );
 638         g.drawLine(x+1, y+height, x+width, y+height); // bottom
 639         g.drawLine(x+width, y+height, x+width, y+1);  // right
 640     }
 641 
 642     @Override
 643     public void setBackground(Color c) {
 644         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 645             log.fine("Set background to " + c);
 646         }
 647         synchronized (getStateLock()) {
 648             if (Objects.equals(background, c)) {
 649                 return;
 650             }
 651             background = c;
 652         }
 653         super.setBackground(c);
 654         repaint();
 655     }
 656 
 657     @Override
 658     public void setForeground(Color c) {
 659         if (log.isLoggable(PlatformLogger.Level.FINE)) {
 660             log.fine("Set foreground to " + c);
 661         }
 662         synchronized (getStateLock()) {
 663             if (Objects.equals(foreground, c)) {
 664                 return;
 665             }
 666             foreground = c;
 667         }
 668         repaint();
 669     }
 670 
 671     /**
 672      * Gets the font metrics for the specified font.
 673      * @param font the font for which font metrics is to be
 674      *      obtained
 675      * @return the font metrics for <code>font</code>
 676      * @see       #getFont
 677      * @see       #getPeer
 678      * @see       java.awt.peer.ComponentPeer#getFontMetrics(Font)
 679      * @see       Toolkit#getFontMetrics(Font)
 680      * @since     JDK1.0
 681      */
 682     public FontMetrics getFontMetrics(Font font) {
 683         if (fontLog.isLoggable(PlatformLogger.Level.FINE)) {
 684             fontLog.fine("Getting font metrics for " + font);
 685         }
 686         return sun.font.FontDesignMetrics.getMetrics(font);
 687     }
 688 
 689     @Override
 690     public void setFont(Font f) {
 691         if (f == null) {
 692             f = XWindow.getDefaultFont();
 693         }
 694         synchronized (getStateLock()) {
 695             if (f.equals(font)) {
 696                 return;
 697             }
 698             font = f;
 699         }
 700         // as it stands currently we don't need to do layout since
 701         // layout is done in the Component upon setFont.
 702         //layout();
 703         repaint();
 704     }
 705 
 706     public Font getFont() {
 707         return font;
 708     }
 709 
 710     public void updateCursorImmediately() {
 711         XGlobalCursorManager.getCursorManager().updateCursorImmediately();
 712     }
 713 
 714     public final void pSetCursor(Cursor cursor) {
 715         this.pSetCursor(cursor, true);
 716     }
 717 
 718     /*
 719      * The method changes the cursor.
 720      * @param cursor - a new cursor to change to.
 721      * @param ignoreSubComponents - if {@code true} is passed then
 722      *                              the new cursor will be installed on window.
 723      *                              if {@code false} is passed then
 724      *                              subsequent components will try to handle
 725      *                              this request and install their cursor.
 726      */
 727     //ignoreSubComponents not used here
 728     public void pSetCursor(Cursor cursor, boolean ignoreSubComponents) {
 729         XToolkit.awtLock();
 730         try {
 731             long xcursor = XGlobalCursorManager.getCursor(cursor);
 732 
 733             XSetWindowAttributes xwa = new XSetWindowAttributes();
 734             xwa.set_cursor(xcursor);
 735 
 736             long valuemask = XConstants.CWCursor;
 737 
 738             XlibWrapper.XChangeWindowAttributes(XToolkit.getDisplay(),getWindow(),valuemask,xwa.pData);
 739             XlibWrapper.XFlush(XToolkit.getDisplay());
 740             xwa.dispose();
 741         } finally {
 742             XToolkit.awtUnlock();
 743         }
 744     }
 745 
 746     public Image createImage(ImageProducer producer) {
 747         return new ToolkitImage(producer);
 748     }
 749 
 750     public Image createImage(int width, int height) {
 751         return graphicsConfig.createAcceleratedImage(target, width, height);
 752     }
 753 
 754     public VolatileImage createVolatileImage(int width, int height) {
 755         return new SunVolatileImage(target, width, height);
 756     }
 757 
 758     public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
 759         return Toolkit.getDefaultToolkit().prepareImage(img, w, h, o);
 760     }
 761 
 762     public int checkImage(Image img, int w, int h, ImageObserver o) {
 763         return Toolkit.getDefaultToolkit().checkImage(img, w, h, o);
 764     }
 765 
 766     public Dimension preferredSize() {
 767         return getPreferredSize();
 768     }
 769 
 770     public Dimension minimumSize() {
 771         return getMinimumSize();
 772     }
 773 
 774     public Insets getInsets() {
 775         return new Insets(0, 0, 0, 0);
 776     }
 777 
 778     public void beginValidate() {
 779     }
 780 
 781     public void endValidate() {
 782     }
 783 
 784 
 785     /**
 786      * DEPRECATED:  Replaced by getInsets().
 787      */
 788 
 789     public Insets insets() {
 790         return getInsets();
 791     }
 792 
 793     // Returns true if we are inside begin/endLayout and
 794     // are waiting for native painting
 795     public boolean isPaintPending() {
 796         return paintPending && isLayouting;
 797     }
 798 
 799     public boolean handlesWheelScrolling() {
 800         return false;
 801     }
 802 
 803     public void beginLayout() {
 804         // Skip all painting till endLayout
 805         isLayouting = true;
 806 
 807     }
 808 
 809     public void endLayout() {
 810         if (!paintPending && !paintArea.isEmpty()
 811             && !AWTAccessor.getComponentAccessor().getIgnoreRepaint(target))
 812         {
 813             // if not waiting for native painting repaint damaged area
 814             postEvent(new PaintEvent(target, PaintEvent.PAINT,
 815                                      new Rectangle()));
 816         }
 817         isLayouting = false;
 818     }
 819 
 820     public Color getWinBackground() {
 821         return getPeerBackground();
 822     }
 823 
 824     static int[] getRGBvals(Color c) {
 825 
 826         int rgbvals[] = new int[3];
 827 
 828         rgbvals[0] = c.getRed();
 829         rgbvals[1] = c.getGreen();
 830         rgbvals[2] = c.getBlue();
 831 
 832         return rgbvals;
 833     }
 834 
 835     static final int BACKGROUND_COLOR = 0;
 836     static final int HIGHLIGHT_COLOR = 1;
 837     static final int SHADOW_COLOR = 2;
 838     static final int FOREGROUND_COLOR = 3;
 839 
 840     public Color[] getGUIcolors() {
 841         Color c[] = new Color[4];
 842         float backb, highb, shadowb, hue, saturation;
 843         c[BACKGROUND_COLOR] = getWinBackground();
 844         if (c[BACKGROUND_COLOR] == null) {
 845             c[BACKGROUND_COLOR] = super.getWinBackground();
 846         }
 847         if (c[BACKGROUND_COLOR] == null) {
 848             c[BACKGROUND_COLOR] = Color.lightGray;
 849         }
 850 
 851         int[] rgb = getRGBvals(c[BACKGROUND_COLOR]);
 852 
 853         float[] hsb = Color.RGBtoHSB(rgb[0],rgb[1],rgb[2],null);
 854 
 855         hue = hsb[0];
 856         saturation = hsb[1];
 857         backb = hsb[2];
 858 
 859 
 860 /*      Calculate Highlight Brightness  */
 861 
 862         highb = backb + 0.2f;
 863         shadowb = backb - 0.4f;
 864         if ((highb > 1.0) ) {
 865             if  ((1.0 - backb) < 0.05) {
 866                 highb = shadowb + 0.25f;
 867             } else {
 868                 highb = 1.0f;
 869             }
 870         } else {
 871             if (shadowb < 0.0) {
 872                 if ((backb - 0.0) < 0.25) {
 873                     highb = backb + 0.75f;
 874                     shadowb = highb - 0.2f;
 875                 } else {
 876                     shadowb = 0.0f;
 877                 }
 878             }
 879         }
 880         c[HIGHLIGHT_COLOR] = Color.getHSBColor(hue,saturation,highb);
 881         c[SHADOW_COLOR] = Color.getHSBColor(hue,saturation,shadowb);
 882 
 883 
 884 /*
 885   c[SHADOW_COLOR] = c[BACKGROUND_COLOR].darker();
 886   int r2 = c[SHADOW_COLOR].getRed();
 887   int g2 = c[SHADOW_COLOR].getGreen();
 888   int b2 = c[SHADOW_COLOR].getBlue();
 889 */
 890 
 891         c[FOREGROUND_COLOR] = getPeerForeground();
 892         if (c[FOREGROUND_COLOR] == null) {
 893             c[FOREGROUND_COLOR] = Color.black;
 894         }
 895 /*
 896   if ((c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR]))
 897   && (c[BACKGROUND_COLOR].equals(c[SHADOW_COLOR]))) {
 898   c[SHADOW_COLOR] = new Color(c[BACKGROUND_COLOR].getRed() + 75,
 899   c[BACKGROUND_COLOR].getGreen() + 75,
 900   c[BACKGROUND_COLOR].getBlue() + 75);
 901   c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR].brighter();
 902   } else if (c[BACKGROUND_COLOR].equals(c[HIGHLIGHT_COLOR])) {
 903   c[HIGHLIGHT_COLOR] = c[SHADOW_COLOR];
 904   c[SHADOW_COLOR] = c[SHADOW_COLOR].darker();
 905   }
 906 */
 907         if (! isEnabled()) {
 908             c[BACKGROUND_COLOR] = c[BACKGROUND_COLOR].darker();
 909             // Reduce the contrast
 910             // Calculate the NTSC gray (NB: REC709 L* might be better!)
 911             // for foreground and background; then multiply the foreground
 912             // by the average lightness
 913 
 914 
 915             Color tc = c[BACKGROUND_COLOR];
 916             int bg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11;
 917 
 918             tc = c[FOREGROUND_COLOR];
 919             int fg = tc.getRed() * 30 + tc.getGreen() * 59 + tc.getBlue() * 11;
 920 
 921             float ave = (float) ((fg + bg) / 51000.0);
 922             // 255 * 100 * 2
 923 
 924             Color newForeground = new Color((int) (tc.getRed() * ave),
 925                                             (int) (tc.getGreen() * ave),
 926                                             (int) (tc.getBlue() * ave));
 927 
 928             if (newForeground.equals(c[FOREGROUND_COLOR])) {
 929                 // This probably means the foreground color is black or white
 930                 newForeground = new Color(ave, ave, ave);
 931             }
 932             c[FOREGROUND_COLOR] = newForeground;
 933 
 934         }
 935 
 936 
 937         return c;
 938     }
 939 
 940     /**
 941      * Returns an array of Colors similar to getGUIcolors(), but using the
 942      * System colors.  This is useful if pieces of a Component (such as
 943      * the integrated scrollbars of a List) should retain the System color
 944      * instead of the background color set by Component.setBackground().
 945      */
 946     static Color[] getSystemColors() {
 947         if (systemColors == null) {
 948             systemColors = new Color[4];
 949             systemColors[BACKGROUND_COLOR] = SystemColor.window;
 950             systemColors[HIGHLIGHT_COLOR] = SystemColor.controlLtHighlight;
 951             systemColors[SHADOW_COLOR] = SystemColor.controlShadow;
 952             systemColors[FOREGROUND_COLOR] = SystemColor.windowText;
 953         }
 954         return systemColors;
 955     }
 956 
 957     /**
 958      * Draw a 3D oval.
 959      */
 960     public void draw3DOval(Graphics g, Color colors[],
 961                            int x, int y, int w, int h, boolean raised)
 962         {
 963         Color c = g.getColor();
 964         g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]);
 965         g.drawArc(x, y, w, h, 45, 180);
 966         g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]);
 967         g.drawArc(x, y, w, h, 225, 180);
 968         g.setColor(c);
 969     }
 970 
 971     public void draw3DRect(Graphics g, Color colors[],
 972                            int x, int y, int width, int height, boolean raised)
 973         {
 974             Color c = g.getColor();
 975             g.setColor(raised ? colors[HIGHLIGHT_COLOR] : colors[SHADOW_COLOR]);
 976             g.drawLine(x, y, x, y + height);
 977             g.drawLine(x + 1, y, x + width - 1, y);
 978             g.setColor(raised ? colors[SHADOW_COLOR] : colors[HIGHLIGHT_COLOR]);
 979             g.drawLine(x + 1, y + height, x + width, y + height);
 980             g.drawLine(x + width, y, x + width, y + height - 1);
 981             g.setColor(c);
 982         }
 983 
 984     /*
 985      * drawXXX() methods are used to print the native components by
 986      * rendering the Motif look ourselves.
 987      * ToDo(aim): needs to query native motif for more accurate color
 988      * information.
 989      */
 990     void draw3DOval(Graphics g, Color bg,
 991                     int x, int y, int w, int h, boolean raised)
 992         {
 993             Color c = g.getColor();
 994             Color shadow = bg.darker();
 995             Color highlight = bg.brighter();
 996 
 997             g.setColor(raised ? highlight : shadow);
 998             g.drawArc(x, y, w, h, 45, 180);
 999             g.setColor(raised ? shadow : highlight);
1000             g.drawArc(x, y, w, h, 225, 180);
1001             g.setColor(c);
1002         }
1003 
1004     void draw3DRect(Graphics g, Color bg,
1005                     int x, int y, int width, int height,
1006                     boolean raised) {
1007         Color c = g.getColor();
1008         Color shadow = bg.darker();
1009         Color highlight = bg.brighter();
1010 
1011         g.setColor(raised ? highlight : shadow);
1012         g.drawLine(x, y, x, y + height);
1013         g.drawLine(x + 1, y, x + width - 1, y);
1014         g.setColor(raised ? shadow : highlight);
1015         g.drawLine(x + 1, y + height, x + width, y + height);
1016         g.drawLine(x + width, y, x + width, y + height - 1);
1017         g.setColor(c);
1018     }
1019 
1020     void drawScrollbar(Graphics g, Color bg, int thickness, int length,
1021                int min, int max, int val, int vis, boolean horizontal) {
1022         Color c = g.getColor();
1023         double f = (double)(length - 2*(thickness-1)) / Math.max(1, ((max - min) + vis));
1024         int v1 = thickness + (int)(f * (val - min));
1025         int v2 = (int)(f * vis);
1026         int w2 = thickness-4;
1027         int tpts_x[] = new int[3];
1028         int tpts_y[] = new int[3];
1029 
1030         if (length < 3*w2 ) {
1031             v1 = v2 = 0;
1032             if (length < 2*w2 + 2) {
1033                 w2 = (length-2)/2;
1034             }
1035         } else  if (v2 < 7) {
1036             // enforce a minimum handle size
1037             v1 = Math.max(0, v1 - ((7 - v2)>>1));
1038             v2 = 7;
1039         }
1040 
1041         int ctr   = thickness/2;
1042         int sbmin = ctr - w2/2;
1043         int sbmax = ctr + w2/2;
1044 
1045         // paint the background slightly darker
1046         {
1047             Color d = new Color((int) (bg.getRed()   * 0.85),
1048                                 (int) (bg.getGreen() * 0.85),
1049                                 (int) (bg.getBlue()  * 0.85));
1050 
1051             g.setColor(d);
1052             if (horizontal) {
1053                 g.fillRect(0, 0, length, thickness);
1054             } else {
1055                 g.fillRect(0, 0, thickness, length);
1056             }
1057         }
1058 
1059         // paint the thumb and arrows in the normal background color
1060         g.setColor(bg);
1061         if (v1 > 0) {
1062             if (horizontal) {
1063                 g.fillRect(v1, 3, v2, thickness-3);
1064             } else {
1065                 g.fillRect(3, v1, thickness-3, v2);
1066             }
1067         }
1068 
1069         tpts_x[0] = ctr;    tpts_y[0] = 2;
1070         tpts_x[1] = sbmin;  tpts_y[1] = w2;
1071         tpts_x[2] = sbmax;  tpts_y[2] = w2;
1072         if (horizontal) {
1073             g.fillPolygon(tpts_y, tpts_x, 3);
1074         } else {
1075             g.fillPolygon(tpts_x, tpts_y, 3);
1076         }
1077 
1078         tpts_y[0] = length-2;
1079         tpts_y[1] = length-w2;
1080         tpts_y[2] = length-w2;
1081         if (horizontal) {
1082             g.fillPolygon(tpts_y, tpts_x, 3);
1083         } else {
1084             g.fillPolygon(tpts_x, tpts_y, 3);
1085         }
1086 
1087         Color highlight = bg.brighter();
1088 
1089         // // // // draw the "highlighted" edges
1090         g.setColor(highlight);
1091 
1092         // outline & arrows
1093         if (horizontal) {
1094             g.drawLine(1, thickness, length - 1, thickness);
1095             g.drawLine(length - 1, 1, length - 1, thickness);
1096 
1097             // arrows
1098             g.drawLine(1, ctr, w2, sbmin);
1099             g.drawLine(length - w2, sbmin, length - w2, sbmax);
1100             g.drawLine(length - w2, sbmin, length - 2, ctr);
1101 
1102         } else {
1103             g.drawLine(thickness, 1, thickness, length - 1);
1104             g.drawLine(1, length - 1, thickness, length - 1);
1105 
1106             // arrows
1107             g.drawLine(ctr, 1, sbmin, w2);
1108             g.drawLine(sbmin, length - w2, sbmax, length - w2);
1109             g.drawLine(sbmin, length - w2, ctr, length - 2);
1110         }
1111 
1112         // thumb
1113         if (v1 > 0) {
1114             if (horizontal) {
1115                 g.drawLine(v1, 2, v1 + v2, 2);
1116                 g.drawLine(v1, 2, v1, thickness-3);
1117             } else {
1118                 g.drawLine(2, v1, 2, v1 + v2);
1119                 g.drawLine(2, v1, thickness-3, v1);
1120             }
1121         }
1122 
1123         Color shadow = bg.darker();
1124 
1125         // // // // draw the "shadowed" edges
1126         g.setColor(shadow);
1127 
1128         // outline && arrows
1129         if (horizontal) {
1130             g.drawLine(0, 0, 0, thickness);
1131             g.drawLine(0, 0, length - 1, 0);
1132 
1133             // arrows
1134             g.drawLine(w2, sbmin, w2, sbmax);
1135             g.drawLine(w2, sbmax, 1, ctr);
1136             g.drawLine(length-2, ctr, length-w2, sbmax);
1137 
1138         } else {
1139             g.drawLine(0, 0, thickness, 0);
1140             g.drawLine(0, 0, 0, length - 1);
1141 
1142             // arrows
1143             g.drawLine(sbmin, w2, sbmax, w2);
1144             g.drawLine(sbmax, w2, ctr, 1);
1145             g.drawLine(ctr, length-2, sbmax, length-w2);
1146         }
1147 
1148         // thumb
1149         if (v1 > 0) {
1150             if (horizontal) {
1151                 g.drawLine(v1 + v2, 2, v1 + v2, thickness-2);
1152                 g.drawLine(v1, thickness-2, v1 + v2, thickness-2);
1153             } else {
1154                 g.drawLine(2, v1 + v2, thickness-2, v1 + v2);
1155                 g.drawLine(thickness-2, v1, thickness-2, v1 + v2);
1156             }
1157         }
1158         g.setColor(c);
1159     }
1160 
1161     /**
1162      * The following multibuffering-related methods delegate to our
1163      * associated GraphicsConfig (X11 or GLX) to handle the appropriate
1164      * native windowing system specific actions.
1165      */
1166 
1167     private BufferCapabilities backBufferCaps;
1168 
1169     public void createBuffers(int numBuffers, BufferCapabilities caps)
1170       throws AWTException
1171     {
1172         if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1173             buffersLog.fine("createBuffers(" + numBuffers + ", " + caps + ")");
1174         }
1175         // set the caps first, they're used when creating the bb
1176         backBufferCaps = caps;
1177         backBuffer = graphicsConfig.createBackBuffer(this, numBuffers, caps);
1178         xBackBuffer = graphicsConfig.createBackBufferImage(target,
1179                                                            backBuffer);
1180     }
1181 
1182     @Override
1183     public BufferCapabilities getBackBufferCaps() {
1184         return backBufferCaps;
1185     }
1186 
1187     public void flip(int x1, int y1, int x2, int y2,
1188                      BufferCapabilities.FlipContents flipAction)
1189     {
1190         if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1191             buffersLog.fine("flip(" + flipAction + ")");
1192         }
1193         if (backBuffer == 0) {
1194             throw new IllegalStateException("Buffers have not been created");
1195         }
1196         graphicsConfig.flip(this, target, xBackBuffer,
1197                             x1, y1, x2, y2, flipAction);
1198     }
1199 
1200     public Image getBackBuffer() {
1201         if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1202             buffersLog.fine("getBackBuffer()");
1203         }
1204         if (backBuffer == 0) {
1205             throw new IllegalStateException("Buffers have not been created");
1206         }
1207         return xBackBuffer;
1208     }
1209 
1210     public void destroyBuffers() {
1211         if (buffersLog.isLoggable(PlatformLogger.Level.FINE)) {
1212             buffersLog.fine("destroyBuffers()");
1213         }
1214         graphicsConfig.destroyBackBuffer(backBuffer);
1215         backBuffer = 0;
1216         xBackBuffer = null;
1217     }
1218 
1219     // End of multi-buffering
1220 
1221     public void notifyTextComponentChange(boolean add){
1222         Container parent = AWTAccessor.getComponentAccessor().getParent(target);
1223         while(!(parent == null ||
1224                 parent instanceof java.awt.Frame ||
1225                 parent instanceof java.awt.Dialog)) {
1226             parent = AWTAccessor.getComponentAccessor().getParent(parent);
1227         }
1228 
1229 /*      FIX ME - FIX ME need to implement InputMethods
1230     if (parent instanceof java.awt.Frame ||
1231         parent instanceof java.awt.Dialog) {
1232         if (add)
1233         ((MInputMethodControl)parent.getPeer()).addTextComponent((MComponentPeer)this);
1234         else
1235         ((MInputMethodControl)parent.getPeer()).removeTextComponent((MComponentPeer)this);
1236     }
1237 */
1238     }
1239 
1240     /**
1241      * Returns true if this event is disabled and shouldn't be processed by window
1242      * Currently if target component is disabled the following event will be disabled on window:
1243      * ButtonPress, ButtonRelease, KeyPress, KeyRelease, EnterNotify, LeaveNotify, MotionNotify
1244      */
1245     protected boolean isEventDisabled(XEvent e) {
1246         if (enableLog.isLoggable(PlatformLogger.Level.FINEST)) {
1247             enableLog.finest("Component is {1}, checking for disabled event {0}", e, (isEnabled()?"enabled":"disable"));
1248         }
1249         if (!isEnabled()) {
1250             switch (e.get_type()) {
1251               case XConstants.ButtonPress:
1252               case XConstants.ButtonRelease:
1253               case XConstants.KeyPress:
1254               case XConstants.KeyRelease:
1255               case XConstants.EnterNotify:
1256               case XConstants.LeaveNotify:
1257               case XConstants.MotionNotify:
1258                   if (enableLog.isLoggable(PlatformLogger.Level.FINER)) {
1259                       enableLog.finer("Event {0} is disable", e);
1260                   }
1261                   return true;
1262             }
1263         }
1264         switch(e.get_type()) {
1265           case XConstants.MapNotify:
1266           case XConstants.UnmapNotify:
1267               return true;
1268         }
1269         return super.isEventDisabled(e);
1270     }
1271 
1272     Color getPeerBackground() {
1273         return background;
1274     }
1275 
1276     Color getPeerForeground() {
1277         return foreground;
1278     }
1279 
1280     Font getPeerFont() {
1281         return font;
1282     }
1283 
1284     Dimension getPeerSize() {
1285         return new Dimension(width,height);
1286     }
1287 
1288     public void setBoundsOperation(int operation) {
1289         synchronized(getStateLock()) {
1290             if (boundsOperation == DEFAULT_OPERATION) {
1291                 boundsOperation = operation;
1292             } else if (operation == RESET_OPERATION) {
1293                 boundsOperation = DEFAULT_OPERATION;
1294             }
1295         }
1296     }
1297 
1298     static String operationToString(int operation) {
1299         switch (operation) {
1300           case SET_LOCATION:
1301               return "SET_LOCATION";
1302           case SET_SIZE:
1303               return "SET_SIZE";
1304           case SET_CLIENT_SIZE:
1305               return "SET_CLIENT_SIZE";
1306           default:
1307           case SET_BOUNDS:
1308               return "SET_BOUNDS";
1309         }
1310     }
1311 
1312     /**
1313      * Lowers this component at the bottom of the above HW peer. If the above parameter
1314      * is null then the method places this component at the top of the Z-order.
1315      */
1316     public void setZOrder(ComponentPeer above) {
1317         long aboveWindow = (above != null) ? ((XComponentPeer)above).getWindow() : 0;
1318 
1319         XToolkit.awtLock();
1320         try{
1321             XlibWrapper.SetZOrder(XToolkit.getDisplay(), getWindow(), aboveWindow);
1322         }finally{
1323             XToolkit.awtUnlock();
1324         }
1325     }
1326 
1327     private void addTree(Collection<Long> order, Set<Long> set, Container cont) {
1328         for (int i = 0; i < cont.getComponentCount(); i++) {
1329             Component comp = cont.getComponent(i);
1330             ComponentPeer peer = comp.getPeer();
1331             if (peer instanceof XComponentPeer) {
1332                 Long window = Long.valueOf(((XComponentPeer)peer).getWindow());
1333                 if (!set.contains(window)) {
1334                     set.add(window);
1335                     order.add(window);
1336                 }
1337             } else if (comp instanceof Container) {
1338                 // It is lightweight container, it might contain heavyweight components attached to this
1339                 // peer
1340                 addTree(order, set, (Container)comp);
1341             }
1342         }
1343     }
1344 
1345     /****** DropTargetPeer implementation ********************/
1346 
1347     public void addDropTarget(DropTarget dt) {
1348         Component comp = target;
1349         while(!(comp == null || comp instanceof Window)) {
1350             comp = comp.getParent();
1351         }
1352 
1353         if (comp instanceof Window) {
1354             XWindowPeer wpeer = (XWindowPeer)(comp.getPeer());
1355             if (wpeer != null) {
1356                 wpeer.addDropTarget();
1357             }
1358         }
1359     }
1360 
1361     public void removeDropTarget(DropTarget dt) {
1362         Component comp = target;
1363         while(!(comp == null || comp instanceof Window)) {
1364             comp = comp.getParent();
1365         }
1366 
1367         if (comp instanceof Window) {
1368             XWindowPeer wpeer = (XWindowPeer)(comp.getPeer());
1369             if (wpeer != null) {
1370                 wpeer.removeDropTarget();
1371             }
1372         }
1373     }
1374 
1375     /**
1376      * Applies the shape to the X-window.
1377      * @since 1.7
1378      */
1379     public void applyShape(Region shape) {
1380         if (XlibUtil.isShapingSupported()) {
1381             if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) {
1382                 shapeLog.finer(
1383                         "*** INFO: Setting shape: PEER: " + this
1384                         + "; WINDOW: " + getWindow()
1385                         + "; TARGET: " + target
1386                         + "; SHAPE: " + shape);
1387             }
1388             XToolkit.awtLock();
1389             try {
1390                 if (shape != null) {
1391                     XlibWrapper.SetRectangularShape(
1392                             XToolkit.getDisplay(),
1393                             getWindow(),
1394                             shape.getLoX(), shape.getLoY(),
1395                             shape.getHiX(), shape.getHiY(),
1396                             (shape.isRectangular() ? null : shape)
1397                             );
1398                 } else {
1399                     XlibWrapper.SetRectangularShape(
1400                             XToolkit.getDisplay(),
1401                             getWindow(),
1402                             0, 0,
1403                             0, 0,
1404                             null
1405                             );
1406                 }
1407             } finally {
1408                 XToolkit.awtUnlock();
1409             }
1410         } else {
1411             if (shapeLog.isLoggable(PlatformLogger.Level.FINER)) {
1412                 shapeLog.finer("*** WARNING: Shaping is NOT supported!");
1413             }
1414         }
1415     }
1416 
1417     public boolean updateGraphicsData(GraphicsConfiguration gc) {
1418         int oldVisual = -1, newVisual = -1;
1419 
1420         if (graphicsConfig != null) {
1421             oldVisual = graphicsConfig.getVisual();
1422         }
1423         if (gc != null && gc instanceof X11GraphicsConfig) {
1424             newVisual = ((X11GraphicsConfig)gc).getVisual();
1425         }
1426 
1427         // If the new visual differs from the old one, the peer must be
1428         // recreated because X11 does not allow changing the visual on the fly.
1429         // So we even skip the initGraphicsConfiguration() call.
1430         // The initial assignment should happen though, hence the != -1 thing.
1431         if (oldVisual != -1 && oldVisual != newVisual) {
1432             return true;
1433         }
1434 
1435         initGraphicsConfiguration();
1436         doValidateSurface();
1437         return false;
1438     }
1439 }