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