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